Minecraftとタートルと僕

PCゲームMinecraftのMOD「ComputerCraft」の情報を集めたニッチなブログです。

回転式直下掘りプログラムの修正

はじめに

前回は回転式直下掘りプログラムを紹介しましたがいくつか不満点がありました。

今回はプログラムを修正し、機能を付け加えましょう。

問題点

燃料の問題

最も問題となるのは直下掘り中に燃料が切れるパターンです。地下深くまで回収しに行くのは非常に面倒ですよね。
改修案として、以下の2つの安全策をとります。

  1. プログラムの最初に規定以上の燃料が入っていることを確認する。入っていなかったら燃料アイテムがインベントリに入るまで待つ。
  2. 下に移動するたびに現在の燃料値を確認し、燃料が切れそうになったら途中で採掘をやめて戻ってくる。

また同時に、燃料アイテムはどのスロットに入れても良いようにしましょう。

掘り終わった穴が危険

掘り終って戻ってくるのは良いのですが、そこには致死性の落とし穴が!
f:id:hevohevo:20140215130421p:plain:w400
落とし穴製造プログラムなんですね。わかります。


掘り終わって戻ってきたら穴にフタをするようにしましょう。
f:id:hevohevo:20140215130634p:plain:w400
ただし、場合によってはフタが必要ないときもあるので、プログラム起動時にフタをするかどうかを指定できるようにもします。

プログラム

ソースコード

http://pastebin.com/TFvw7usW


プログラム解説

ソースコードの解説は、以下の順に行います。

  1. 設定項目(config)の解説。 ユーザーが書き換えできる各種パラメータです。
  2. メイン部分の解説。メイン部分を見るだけで、おおよそ何をやっているかがわかるのが理想です。
  3. 関数定義部分の解説。メイン部分で使っている関数を詳細に見ていきます。

設定項目の解説

L6-9
  • これら3つのパラメータは、プログラム利用者が自分の好きなように値を書き換えることを想定しています。
    • MIN_FUEL_LEVEL: 最低でもこの値だけ燃料が入っていなければ動きません。
    • CLOSE_HOLE_FLAG: ブーリアンです。trueだと掘り終ったあとにフタをします。
    • LID_BLOCK_SLOT: フタをするために使うブロックを入れておくスロット番号です。
  • 基本的に、大文字を使って変数名を目立たせています。グローバル変数です。
L11-15

プログラム実行時に、引数(arguments)をつけて実行することができます。
たとえばこのプログラムを「boring」という名前で保存したとしましょう。
タートルのターミナル画面で、次のように入力し、エンターキーを押せば実行できます。

> boring


このときに、半角スペースを後ろに一つ入れて、「hevo」のような文字を打ち込んでからエンターキーを押すと、boringプログラムに「hevo」という引数を与えた上で実行できます。
半角スペースで区切れば、後ろにいくつでも好きなだけ引数を与えることができます。

> boring hevo


この引数をプログラム中で利用するためには、以下の構文を使います。

local args = {...} -- 与えられた引数をテーブルの形でローカル変数argsに代入する。

変数argsは、配列(テーブル)であり、与えられた引数をargs[1]、args[2]のように指定して利用できます。なお、前述の「hevo」は1番目の引数なので、args[1]で利用できます。

if #args > 0 then
  CLOSE_HOLE_FLAG = not CLOSE_HOLE_FLAG
end

変数argsは配列であり、#argsは配列の要素の個数を返します。
そのため上記は、プログラム実行時の引数が(何であろうと)1つでもあったら、CLOSE_HOLE_FLAGの値を反転(true → false)するというプログラムです。

つまりこのプログラムは、プログラム実行時に引数を何も与えずそのまま実行したらフタをします。何らかの引数を与えるとフタをしません。
基本的にはフタをするけれど、特別な場合にはフタをしないという運用に適しています。もし基本が逆の方が良いならば、CLOSE_HOLE_FLAGパラメータの値を逆にしてください。

メイン(main)部分の解説

(L72-81)

myRefuel()
 
local depth = 0
while revolve(depth) do
  depth = depth +1
end
 
backToHome(depth)
if CLOSE_HOLE_FLAG then closeHole() end

まず燃料関係(myRefuel())を処理して、変数depthで掘った深さを管理しつつ、直下掘り(revolve())していく。
岩盤や燃料不足などで直下掘りに失敗したら、スタート位置に戻って(backToHome())くる。
最後に、穴を塞ぐフラグがtrueならば蓋をする。
というプログラムです。

関数定義部分の解説

L18-36: myRefuel()

燃料関係を処理する関数です。挙動を説明すると以下のようになります。

  1. まず、スロット1から16までにある全ての燃料アイテムを使って燃料補給する。
  2. 最低燃料値よりも燃料が多いなら選択スロットを1に戻してこの関数を終了。
  3. 最低燃料値よりも燃料が少ないならば、インベントリに何かアイテムが入るまで待ち、入ってきたら燃料補給します。最低燃料値に達するまでこれを繰り返します。
  • 関数内の先頭で、ローカル関数(サブ関数)であるrefuelAll()を定義しています。これは、スロット1から16までの燃料アイテムを補給する関数です。
  • while構文で、最低燃料値MIN_FUEL_LEVELよりも現在燃料値が少ないときに処理を繰り返します。
  • os.pullEvent("turtle_inventory")は、タートルのインベントリに変化(アイテム増えた/減った)があるまで待つ関数です。
  • 燃料補給によって選択スロットが16へと移動しているため、この関数の最後で念のため選択スロット1に戻しています。
L38-51: revolve(depth)

その場で回転しつつ四方を掘り、真下を掘り、真下に移動。この一連の行動をまとめたのがrevolve()です。
この関数は一連の行動を問題なく終了したらtrue、何か問題が生じたらfalseを返します。

  • L39-42は、四方を掘り、真下を掘るという部分です。
  • L46-50によって、もし燃料が不足した場合の処理を行っています。スタート位置に戻るだけの燃料を常に意識し、燃料が足りなくなったらその場で採掘を打ち切ってfalseを返します(つまりスタート位置に戻りはじめます)。
    • 現在の深さ、すなわちスタート位置に戻るまでに必要な燃料数を知るために、変数depthを引数として必要としています。
L53-64: closeHole()

CLOSE_HOLE_FLAGの値がtrueならば穴にフタをします。

  • LID_BLOCK_SLOTにあるブロックを使って、真下に十字型のフタを作ります。
  • 1つ下に下がって四方にブロック設置、1つ上に上がって真下にブロック設置
L66-70: backToHome(n)

引数n(つまりdepth)の値だけ上に戻ります。つまりスタート地点に戻るための関数です。

まとめ

これで一通り動くプログラムが完成しました。
次回からは、シルクタッチ機能がついたタートルを紹介して、このプログラムでシルクタッチ付きの採掘ができるようにしましょう。

Nokiyen氏作成の「More Turtles」Modを使う予定です。