ComputerCraftでQuarryのような何かを実装した(MC1.7.10 CC1.65)
はじめに
というわけで、greg環境でBCのクァーリーのコストが異常に高騰しているので、コストの安いComputerCraftのMinningTrutleに露天掘りさせるプログラムを書きました。
はじめてluaを書いたんですが、簡単でいいですね、これ。今度、ルーター*1で動かす何かでも書きたいなーとか少し思いました。
あと動作保障は一切ないので何が起きても文句言わないでください。
使い方
仕様
- パラメータで指定した範囲を掘りぬく
- 燃料がなくなると戻ってきて補充する
- インベントリが残り3枠を切ると戻ってきてチェストに納品
- 納品や燃料補充がうまくいかないと一時停止してユーザの入力を待つ
- 掘りぬいたら戻ってくる
- MOBに当たるなどして引っかかるとリトライする
- 何度リトライしてもダメなら停止する
- 当たり前だけどチャンクロード範囲外に出るとプログラムごと終了する
設置方法
タートルの後ろに空のアイテム搬出用チェスト。下のチェストには燃料の木炭とか突っ込んでください。ただ念のため1スタック以上の空きスペースを作ってください*2。
また、最初の燃料をタートルの一番右下のインベントリに入れてください。
コマンド
pestbinからとってきて保存したファイルを実行してください。コマンドライン・パラメータとして「奥行き」「横幅」「掘る深さ」の三つのパラメータを入力してください。
途中で止まった時
アイテムをチェストに搬出したり、チェストから燃料補充をしますが、これに失敗すると一時停止します。チェストの中身をチェックして処置してから、タートルのシェルで何かキーを入力すれば再開します。
実際に掘る姿
これは4x4の範囲を掘っている姿です。
設置場所の1マス前方を左に向かって指定領域を掘ります。
ソースコード
------------------------------------ -- Quarry modoki -- by yoshizawa81 -- version 0.1 -- Set backside chest empty. Turtle dump items this chest. -- Set underchest fuel. Need one (or lager) empty slot in this chest. -- Set turtle's inventory 16th slot (the lower right) fuel. -- This program need just 3 parameters.(depth width hight) -- Enjoy minecraft ! ------------------------------------ ------------------------------------ -- config ------------------------------------ refuel_level = 1024 fuel_inventory = 16 max_x = 64 max_y = 64 max_z = 128 -- moving config retry = 10 wait = 3 ------------------------------------ -- global vars ------------------------------------ -- turtle position x = 0 --depth y = 0 --width z = 0 --hight face = 0 --0:forword 1:right 2:back 3:left -- digging position dx = 0 --depth dy = 0 --width dz = 0 --hight dface = 0 --0:forword 1:right 2:back 3:left -- target position tgt_x = 0 tgt_y = 0 tgt_z = 0 ------------------------------------ -- command line parameter include ------------------------------------ args = {...} ------------------------------------ -- functions ------------------------------------ -- command line parameter check function cmdline_check() if #args > 3 then print("This program need just 3 parameters. depth width hight") os.queueEvent("terminate") sleep(1) --bad know haw... end tgt_x = tonumber(args[1]) tgt_y = tonumber(args[2]) tgt_z = tonumber(args[3]) if tgt_x > max_x then print("Set depth less than "..max_x) os.queueEvent("terminate") sleep(1) --bad know haw... end if tgt_y > max_y then print("Set width less than "..max_y) os.queueEvent("terminate") sleep(1) --bad know haw... end if tgt_z > max_z then print("Set hight less than "..max_z) os.queueEvent("terminate") sleep(1) --bad know haw... end tgt_y = tgt_y - 1 end function my_forword() local tf = true local cause = "string" local i = 0 tf,cause=turtle.forward() if tf==false then if cause=="Movement obstructed" then while i < retry do tf=turtle.forward() if tf == true then break end sleep(wait) i = i + 1 end if tf == false then print("Error. Obstructed.") os.queueEvent("terminate") sleep(1) --bad know haw... end end end end -- Came back home position. function back_home() while z > 0 do turtle.up() z = z - 1 end if face == 0 then turtle.turnRight() face = 1 while y > 0 do my_forword() y = y - 1 end elseif face == 1 then while y > 0 do my_forword() y = y - 1 end elseif face == 2 then turtle.turnLeft() face = 1 while y > 0 do my_forword() y = y - 1 end elseif face == 3 then turtle.turnRight() turtle.turnRight() face = 1 while y > 0 do my_forword() y = y - 1 end end turtle.turnRight() face = 2 while x > 0 do my_forword() x = x - 1 end end function my_down() local tf = true local cause = "string" local i = 0 tf,cause=turtle.down() if tf==false then if cause=="Movement obstructed" then while i < retry do tf=turtle.down() if tf == true then break end end sleep(wait) i = i + 1 end if tf == false then back_home() print("Error. Obstructed? End?") os.queueEvent("terminate") sleep(1) --bad know haw... end end end -- Go digging position. function go_digpos() turtle.turnRight() turtle.turnRight() face = 0 while x < dx do my_forword() x = x + 1 end turtle.turnLeft() face = 3 while y < dy do my_forword() y = y + 1 end while z < dz do my_down() z = z + 1 end if dface==0 then turtle.turnRight() face=0 elseif dface==1 then turtle.turnRight() turtle.turnRight() face=1 elseif dface==2 then turtle.turnLeft() face=2 end end -- Get fuel from chest. function get_fuel() turtle.select(fuel_inventory) local tf = false local cause = "string" tf,cause = turtle.dropDown() if tf == false and cause == "Inventory full" then print("After check chests, hit any key.") os.pullEvent(key) get_fuel() end if turtle.suckDown() == false then print("After check chests, hit any key.") os.pullEvent(key) get_fuel() end end -- Dump items to chest. function dump_items() local i = 1 while i < 16 do turtle.select(i) turtle.drop() i = i + 1 end if not(turtle.getItemSpace(15) == 64 and turtle.getItemSpace(14) == 64 and turtle.getItemSpace(13) == 64) then print("After check chests, hit any key.") os.pullEvent(key) dump_items() end end -- error trap of empty fuel or full items. function error_trap() if (x == 0 and y ==0 and z == 0) then print("After check chests, hit any key.") os.pullEvent(key) else back_home() end dump_items() get_fuel() go_digpos() end -- refuel from inventory function refuel_inv() turtle.select(fuel_inventory) while turtle.getFuelLevel() < refuel_level do if turtle.refuel(1) == false then error_trap() end end turtle.select(1) end -- Check inventry space. function check_inv() if not(turtle.getItemSpace(15) == 64 and turtle.getItemSpace(14) == 64 and turtle.getItemSpace(13) == 64) then error_trap() end turtle.select(1) end ------------------------------------ -- main program ------------------------------------ cmdline_check() while z <= tgt_z do while y <= tgt_y do if face == 0 then while x < tgt_x do refuel_inv() check_inv() turtle.dig() my_forword() x = x+1 dx=dx+1 end end if y == tgt_y then break end if face == 0 then turtle.turnLeft() face=3 dface=3 turtle.dig() my_forword() y = y + 1 dy = dy + 1 turtle.turnLeft() face=2 dface=2 end if face == 2 then while x > 1 do refuel_inv() check_inv() turtle.dig() my_forword() x = x - 1 dx = dx - 1 end end if y == tgt_y then break end if face == 2 then turtle.turnRight() face=3 dface=3 turtle.dig() my_forword() y = y + 1 dy = dy + 1 turtle.turnRight() face=0 dface=0 end end if z == tgt_z then break end turtle.digDown() my_down() z=z+1 dz=dz+1 turtle.turnRight() turtle.turnRight() if face == 0 then face=2 dface=2 elseif face == 2 then face=0 dface=0 end while y >= 0 do if face == 0 then while x < tgt_x do refuel_inv() check_inv() turtle.dig() my_forword() x = x + 1 dx = dx + 1 end end if y == 0 then break end if face == 0 then turtle.turnRight() face=1 dface=1 turtle.dig() my_forword() y = y - 1 dy = dy - 1 turtle.turnRight() face=2 dface=2 end if face == 2 then while x > 1 do refuel_inv() check_inv() turtle.dig() my_forword() x = x-1 dx = dx - 1 end end if y == 0 then break end if face == 2 then turtle.turnLeft() face=1 dface=1 turtle.dig() my_forword() y = y - 1 dy = dy - 1 turtle.turnLeft() face=0 dface=0 end end if z == tgt_z then break end turtle.digDown() my_down() z = z + 1 dz = dz + 1 turtle.turnRight() turtle.turnRight() if face == 0 then face=2 dface=2 elseif face == 2 then face=0 dface=0 end end back_home()
謝辞
id:hevohevo氏の記事をいろいろと参考にしました。多謝。