Minecraftとタートルと僕

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

こちらのページは更新が滞っており、情報が古くなりつつあります。新しいCC情報サイトをはじめましたので、もしよければご参照ください。今後ともよろしくお願い申し上げます。

「百億のマインクラフトと千億のタートル」(https://hevo2.hatenablog.com/)

クラフティタートルプログラミング チュートリアル(7)

クラフティタートルの続き

Redstone APIやMFR2のRednetCableの説明で回り道をしてしまったけれど、
クラフティタートルを生産ラインに組み込むケースについて、最終的な自動クラフトプログラムを紹介・解説しましょう。

チュートリアル(5)の自動クラフトプログラムと根本的に異なる点は、材料が絶えず流れてくるのでプログラムの終了条件は無いということです。
そのため、プログラムのmain部分は、「while true do ~ end」ループで構成しています。

プログラム概要

自動クラフトプログラム(Applied Energistics利用版)

  • Applied Energisticsを使った生産ラインにクラフティタートルを組み込む
    • 生産ライン: 農場や鉱石粉砕機などから、材料アイテムが一定量ずつ流れこんでくる
  • クラフティタートルは、あらかじめ決められたレシピを使って材料アイテムをクラフトし続ける。
  • 途中で材料が足りなくなってしまったら、一定時間停止して、材料が十分に溜まるのを待つ。
  • この停止時間については、生産ラインのアイテム流量ごとに各自調整すること

アルゴリズム概要

ME Export Busは、MEネットワーク中の材料アイテムをクラフティタートルの真上のチェストに排出しています。真上のチェストは材料アイテムを一時的に蓄積するバッファの働きをします。
以下アルゴリズムの概要です。

  • f:id:hevohevo:20131215014221p:plain:w400
  1. クラフティタートルによるクラフト開始。
  2. クラフト中は、ME Export Busにレッドストーン信号を当てて、排出を一時停止する。
  3. クラフティタートルは、あらかじめ決められたレシピを使って、材料チェストが空になるまでクラフトを続ける。
  4. クラフトによる完成品および材料の端数は、真下のME InterfaceによりMEネットワーク中に入る。
  5. 材料チェストが空になったらクラフトを一時停止し、レッドストーン信号をOFFにすることで材料チェストへの蓄積を開始する。
  6. 「SUSPENDED_TIME」秒後にクラフトを再開する(1.に戻る)

プログラム

(2013/12/17 21:30 ミスがあったので修正)

プログラム解説

設定項目やタートルの設置方法についてコメントを入れたので、ソースの分量は大幅に増えています。
しかしプログラム自体は前回のものとそれほど変わりありません。
(なお、コメントの英語のひどさについては自覚しているので突っ込みは不要です><)

プログラム解説は以下の4点に分けて行います。

  1. 設定項目(config)
  2. メイン(main)部分の解説
  3. distMaterials()について
  4. sleep(0)について

設定項目について

スロットの定義やレシピの登録については説明済みなので、ここでは省略します。

  • L26)「SUSPENDED_TIME」は、材料が切れたときに一時停止する時間(秒)です。生産ラインのアイテム流量によって各自でこの値を調整してください。
    • なお、30分に一度まとめてクラフトさせるという使い方もできます。この場合は値を1800にしましょう。もちろん、バッファとなる材料チェストは、容量大きめのものにしておく必要があります。
  • L30-31)RednetCableの設定項目ですが、タートルの左から信号を出す、白色ケーブルということだけ抑えておけば、特に記述を書き換える必要はありません。

メイン(main)部分について

  • L108-119) 「while true do ~ end」ループで構成しているので、このプログラムを止めるためには「CTRL+T」を使う必要があります。
  • L109) 最初に、rs.setBundledOutpu()関数で、レッドストーン信号を出し、ExportBusによる排出を止めています。
  • L111-115) 次のwhileループは、チェストから材料がなくなるまでクラフトし続ける部分です。
  • L111) 「getMaterials()」が「true」を返し、なおかつ「distMaterials()」が「true」を返す限り、ひたすらクラフトを続けます。
    • つまり、「チェストから材料をゲットでき」、なおかつ「その材料を問題なくレシピ位置に配置できる」限り、ということ。
  • L117-118)材料がなくなったら、レッドストーン信号をOFFにし、「SUSPENDED_TIME」秒のsleepに入ります。

L67-81)distMaterials()について

この関数は前回のプログラムから少しだけ修正を加えています。
これまで問題としてきた「材料をゲットしたけど1個なので2x2レシピでクラフトできない」という状況は、次のnの値で判別できます。

n = nTotal/(#slots)

4つのスロットに等分配しなければならないのに、材料4個未満なので分配できないという状況では、nの値は1未満です(たとえば1個しかないときにはn=0.25)。
そのためこの関数では、nが1以上のときには等分配に成功するので「true」。そうでなければ失敗するので「false」を返すようにしています。

sleep(0)について

これを見て、「は?スリープしないの?」と思った人がいるかもしれません。
そうではなく、これで0.05秒のスリープを行っています。
もともとこのプログラムでは、「メリハリのある」クラフトを目指していました。
つまり、クラフトを開始したら全力かつ最速のクラフトを、逆に停止するときは材料が溜まるまで長めの停止時間をという方針です。

しかし、クラフト中にはできるだけsleepを入れたくない、でもwhileループでsleepを入れないとプログラム自体がエラーで動かない、というジレンマががが。

このジレンマを解消するためには、最短時間のスリープを入れれば良いですよね。
色々と資料をあさってみた結果、sleep()はtic単位で動くことがわかりました。

  • 【基本知識】 tic(チック)とは
    • ゲーム内の最小時間単位。実時間1秒=20tic。言い換えると0.05秒=1tic

そのため、sleep(0.06)とsleep(0.07)は、実際の挙動としては同じで、2ticのスリープとなります。また、sleep(0)はsleep(0.05)と同じで1ticのスリープとなり、これが最短時間のスリープです。

(2014/01/05 注記) TurtleAPIを使っているので、どうやらsleep(0)無しでも問題なく動くようです。そのため、このプログラム中のsleep(0)は全て削ってもかまいません。この件について詳しくはこちら

まとめ

以上、AEを用いた生産ラインにクラフティタートルを組み込むケースについて試行錯誤してみました。
実際にうちの拠点では、1x1レシピを担当するタートルが各種のキビを処理し、3x3ドーナツ型レシピを担当するタートルがオークの葉とIC2ゴムの葉の処理を行っています。
またプログラムを「startup」というファイル名にすることで、ゲーム開始と同時に動き出すようにしています。


クラフティタートルについてのチュートリアルはこれでひと段落としますが、工夫次第でもっと便利な使い方ができるるはずです。
もっと複雑なレシピへの対応。BCやAE以外のアイテム転送パイプとの連携などなど。
あなたの利用方法やプログラムをぜひ教えてください(他力本願)。

次回のチュートリアルテーマについては、……実は迷っています。
予定ではMeleeタートルを進めるつもりでしたが、このあたりでCCのイベント(Event)について深く掘り下げておくのもいいかなと。
あるいはこれ以外の案についても、リクエストがあればぜひコメントください。

それではまた次回。