はじめに
前回は「MoreTurtles」Modで追加されるFortune Mining Turtleについて紹介しました。
燃料を1消費するかわりに、フォーチュン付きでブロックを掘ってくれるすばらしいタートルです。 鉱石ブロックを幸運付きで破壊することで入手素材を飛躍的に増やすことができますね。
とはいえ、私の環境では工業系のModをいろいろと入れているため、鉱石ブロックをシルクタッチで持ち帰って機械で粉砕したほうが得られる素材が増えることも多いのですよね。 そのため、以前紹介したシルクタッチ採掘タートル(SilkTouch Mining Turtle)に比べると、出番は少なめです。
しかし、一部の鉱石ブロックは、上位機械*1が必要だったりそもそも機械が対応していなかったりで、幸運付き破壊の方がお得だったりします。
たとえば私の環境でいうと、以下の鉱石はまだ幸運付きの方がお得です。
- ダイヤモンド鉱石(Diamond Ore)
- Power Ore(DartCraftによる追加鉱石)
- Certus Quartz Ore (Applied Energisticsによる追加鉱石)
うん、少ないですね。
基本は全ての鉱石ブロックをシルクタッチで持ち帰り、これらブロックのみフォーチュン採掘で破壊するようにしましょう。
そのために、フォーチュン付き採掘を使って鉱石ブロックを破壊し入手素材を増やす、
フォーチュン付きブロックブレイカープログラムを紹介します。
今回は初心者向けに、できるだけシンプルでわかりやすいプログラムを心がけてみました。
フォーチュン付きブロックブレイカー
イメージ画像を先に紹介しましょう。タートルの上のチェストに破壊したい鉱石ブロックを入れておきます。破壊して手に入れた素材アイテムは下のチェストに落とします。
上のチェストから鉱石ブロックを手に入れて、「正面に設置&フォーチュン付き破壊」を入手ブロック数だけ繰り返し、下のチェストに入手アイテムを全部ドロップというのが基本的な流れになります。
この基本アイデアをシンプルに実現したのが今回のプログラムです。
なお今回のプログラミングは、assert()関数を使うことでどれだけ手抜きができるかということにチャレンジしてみました:P
assert()関数とは次のような関数です。
- assert(boolean, error_message)
- 第1引数はブーリアン。真なら何もしない。偽(false, nil)ならエラーメッセージを表示してプログラム終了。
- 第2引数はエラー時に表示するメッセージ。省略可能。
たとえば、turtle.place()
は選択スロットにあるブロックを正面に設置しますが、設置に成功するとtrue、失敗するとfalseを返します。
そのため、assert(turtle.place())
とすることで、ブロック設置に失敗したら、そのエラーメッセージを表示してプログラムを終了するようにできます。
プログラム内の重要な箇所でassertを使うことで、プログラム実行中に問題が発生したらassertでプログラムを強制終了してしまえという手抜きをしているわけです。
プログラム
インストール方法
「bb」というファイル名でプログラムをダウンロード&保存する。
> pastebin get FAg2hgy8 bb
ソースコード
プログラム解説
設定(cofig)部分
- FUEL_SLOT: 燃料アイテムを入れるスロット番号
- BLOCK_SLOT: 鉱石ブロックを入手するときに使うスロット番号
またこの箇所で、(タートルの右手に装着している赤い)周辺機器からフォーチュン採掘関数を入手しています。
そしてFortune Mining Turtle以外のタートルが使われていたらプログラムを強制終了します。
具体的には、周辺機器から何らかの関数テーブルを入手できていること、かつ、関数テーブル中にフォーチュン採掘関数が含まれていることを確認しています。
もしフォーチュン採掘関数が存在しなかったら、このタートルはそもそもFortune Mining Turtleではなかったということなので、assert()を使うことで強制終了しています。
メイン(main)部分
メイン部分を一目見るだけで、何をやっているのかだいたいわかるというのが良いプログラムだと思います。
まず自分で定義した関数を紹介。
- myRefuel(): FUEL_SLOTにある燃料アイテムを補給します。
- suckBlock(): 上のチェストから1スタック分のブロックを入手しようとします。入手成功か失敗かによってtrue/falseを返します。
- placeDig(繰り返し回数): ブロックの設置&破壊を行う関数で、引数は繰り返し回数です。
- dropAll(開始slot, 終了slot): インベントリ内のアイテムをドロップします。 開始slotから終了slotまで順番に落としていきます。
以上を踏まえて、解説。
myRefuel() while suckBlock() do placeDig(turtle.getItemCount(BLOCK_SLOT)) dropAll(1,16) end print("Finished: fuel ",turtle.getFuelLevel())
- プログラムスタートしたらまず燃料補給
- whileループによって、アイテム入手→設置&破壊の繰り返し→アイテムドロップという1セットの動作を繰り返すようにしています。
- まずsuckBlock()に成功するかどうかを条件式としており、入手に成功したらループの繰り返し、失敗したら次へ進みプログラムを完了します。
- ループ内部では、
turtle.getItemCount()
関数を使っていくつ鉱石ブロックを入手したのかを調べ、その回数だけplace() dig()
を繰り返しています。 - 手持ちの鉱石ブロックをすべて処理終えたらアイテムを全てドロップすることで、1セットの動作を終了し、suckBlock()という条件式の実行と判断へと戻ります。
- プログラム終了時には、燃料がいくつ残っているかを表示します。
プログラミング初心者にとって、ループの入れ子が多いと見づらいと思うので、placeDig()に繰り返し回数を指定できるようにすることで入れ子を一つ消してみました。いかがでしょうか。
自分で定義した関数の説明
注意すべきことは、各関数において、まずturtle.select()を実行していることです。
これはタートルプログラミングのコツの一つです。何か行動をさせる直前に選択スロットを明確に指定しておくことによって、「いまの選択スロットって何だっけ?」というような混乱を防ぐことができます。
myRefuel():
FUEL_SLOTにある燃料アイテムを補給します。
suckBlock():
上のチェストから1スタック分のブロックを入手しようとします。入手成功か失敗かによってtrue/falseを返します。
return turtle.suckUp()
と関数の最後に書くことで、turtle.suckUp()
の成否をそのままこの関数の返値として利用できます。
placeDig(繰り返し回数):
ブロックの設置&破壊を行う関数で、引数は繰り返し回数です。
turtle.place()をassert()で囲むことで、ブロック設置を失敗したときにプログラムを強制終了します。 たとえば、上の鉱石ブロック用チェストに変なアイテム(たとえばブロックとして設置できない種など)を間違えて入れてしまったときに、このassert()関数で強制終了させます。
またフォーチュン採掘は1回ごとに燃料を1消費しますが、燃料が足りないときにはdigFortune()関数がfalseを返します。これをそのままassert()で拾うことでプログラム自体を強制します。
dropAll(開始slot, 終了slot):
インベントリ内のアイテムをドロップします。 開始slotから終了slotまで順番に落としていきます。
for文で開始スロットから終了スロットまで順番に選択スロットを切り替え、ドロップしているだけです。
まとめ
これで一通り動くプログラムができました。
assert()を使うことで、燃料が足りなくなったり、上の鉱石チェストに設置できないアイテムを入れてしまったときにプログラムを強制終了するようになっています。
とはいえ問題点がないわけではありません。 たとえば燃料不足によって強制終了すると、その状況を立て直してまたプログラムを再開させるのが少しだけ面倒です。
たとえば、ダイヤ鉱石を正面に設置→破壊しようとしたけれど燃料不足で強制終了という状況を考えましょう。
強制終了後、気を取り直して燃料をインベントリに入れて再度プログラムを再開しようとします。
しかしすでにダイヤ鉱石が設置してあるので設置エラーが発生してプログラムをすすめることができません。
何らかの方法で正面のダイヤブロックを取り除かなくてはならないのです。うん、めんd。
次回はこの対策として、燃料が足りなくなったら強制終了するのではなく、その場で燃料補給待ちするようなプログラムを検討してみましょう。
*1:たとえばGreg-techの Industrial Grinderなど