読者です 読者をやめる 読者になる 読者になる

Minecraftとタートルと僕

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

シルクタッチで回転式直下掘りプログラム(MoreTurtles Mod使用)

はじめに

前回は、Nokiyen氏のMoreTurtles Modに入っているSilkTouch Mining Turtleを紹介しました。

前々回に紹介した回転式直下掘りプログラムを、シルクタッチを使うよう改造しましょう。

f:id:hevohevo:20140218013131p:plain:w400

最終的なソースコードはこの記事の最後に挙げるとして、
まず改造のポイントを抑えていきます。

改造のポイント

  • ポイント1)標準の turtle.dig()を、digSilkTouch()に置き換える。
  • ポイント2)燃料消費の激しさを考慮したパラメータ調整
  • ポイント3)ついでに、採掘結果を最後に表示する
  • ポイント4)その他、エラー処理など

主にこの4点を改造しました。
それぞれ具体的に見ていきましょう。

ソースコード解説

ポイント1)標準の turtle.dig()を、digSilkTouch()に置き換える。

ソースコード内、L19-27

local silkP = peripheral.wrap("right")
if silkP and silkP.digSilkTouch then
  print("Boring with SilkTouch!")
  turtle.dig_org = turtle.dig_org or turtle.dig
  turtle.dig= silkP.digSilkTouch
 
  turtle.digDown_org = turtle.digDown_org or turtle.digDown
  turtle.digDown = silkP.digSilkTouchDown
end
  • 右側に装着した周辺機器から、シルクタッチ関数を入手(peripheral.wrap)
  • もし、問題なく周辺機器からシルクタッチ関数を手に入れることができたなら、「シルクタッチで穴掘るぜ!」という宣言をして置き換え処理開始
  • 標準の turtle.dig関数を turtle.dig_org関数へとバックアップをとり
  • digSilkTouch関数を、turtle.dig関数へと置き換えしています。

関数の置き換えですが、なぜこのようなことができるのかできるだけ簡単に説明するならば、
Luaの関数はすべてが無名関数を変数に代入したものだからです。
つまり「turtle.dig」は変数名であり、中には実際に穴を掘る関数(function)オブジェクトが代入されています。「turtle.dig()」とすることで変数内に入っている関数を実行します。
このあたりの詳しい話は以下の記事をどうぞ。


そしてもう一つ。以下の構文をはじめて見た人は戸惑うかもしれません。

turtle.dig_org = turtle.dig_org or turtle.dig

これは代入文ですが、変数 = 条件式1 or 条件式2 と解釈し、「=」の右側から処理します。
条件式1が「偽(nil/false)ではないとき」に条件式1をそのまま変数に代入します。
逆に条件式1が「偽のとき」には条件式2の結果を変数に代入します。
Luaでは、そもそも存在しない変数を参照すると偽(false)というルールがあるので、
この構文は、変数(条件式1)がすでにあるときにはその値を使って、まだ未定義ならば初期値(条件式2)を設定するという、よくある慣用表現となっています。

つまり今回は、このプログラムをCCコンピュータを再起動せずに何度も実行したときに、オリジナルdig_org()をさらに上書きしてしまうことを防いでいます。すでにdig_org()バックアップがあるなら、もうそれにはもう触らないようにしているのです。

さあこれで、単純に turtle.dig()/turtle.digDown()するだけで、シルクタッチができるようになりました。

ポイント2)燃料消費の激しさを考慮したパラメータ調整

シルクタッチ採掘をするたびに燃料を1消費することに注意しなくてはなりません。
そのために、燃料に関するパラメータを調整しています。具体的には以下の2箇所。

  • L10: MIN_FUEL_LEVEの値を増やしています。
  • L58: revolve()関数の中で、燃料が足りなくなったら途中で採掘をやめる処理がありますが、余裕を持たせるために上に戻るために必要な燃料に+10しています。

ポイント3)ついでに、採掘結果を最後に表示する

採掘終了後に、残った現在の燃料といくつ掘ったのかを報告します。
そのため掘ったブロックのカウント用に、L49でグローバル変数Countを用意し、
L52とL56でdig()に成功したらカウントを増やしています。

ポイント4)その他、エラー処理など

採掘開始時、穴にフタをする(CLOSE_HOLEフラグがtrue)予定なのに、フタ用のブロックをインベントリに入れていない場合はエラーを返してプログラムを終了するようにしました。

このエラー処理に、Luaの「assert」関数を使っています。

第1引数が偽のときに、エラーメッセージを表示してプログラムを緊急終了する。
assert( boolean, message )

つまり、L86-89によって、「CLOSE_HOLE_FLAGがtrue」のときに、フタ用ブロックが5個未満ならエラーで停止し、エラーメッセージを表示します。
f:id:hevohevo:20140218012705p:plain:w400


なお、フタ用ブロックをスロット1に入れておけば、問題なく採掘を開始します。
f:id:hevohevo:20140218012743p:plain:w400

不満点

燃料やフタ用アイテムを入れてから、手動でプログラム名を入力して実行、という手順が非常に面倒です。

次回は、
startupなどでプログラムを自動起動後に、必要アイテムがインベントリ内に入っていないことがわかったら、入れられるまで待つというプログラムを検討してみます。

つまり、以下のようなプログラムだと色々と楽ですよね?

  • 現在) タートル設置→必要アイテムを挿入→プログラム名を手動入力して実行→作業開始
  • これから) タートル設置→必要アイテムを挿入→作業開始

ソースコード

http://pastebin.com/NLjiz6Mv