Minecraftとタートルと僕

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

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

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

農業タートルプログラミング チュートリアル(4)

さて前回は気になる引きをしたけれど
プログラムを動かしてみると、すぐにプログラムの問題点に気づくよね?

定期的に収穫物を下のチェストにドロップするのだけど、
そのときに少量の骨粉もドロップしてしまうんだ。

  • 収穫物用チェストに骨粉が混じるのが気持ち悪い
  • 貴重な骨粉を無駄にしたくない。使い切りたい

という意図で、今回はこれを修正したいと思う。

原因と対策

この原因は、手持ちの骨粉が2~3個残っている状態で
真上のチェストから1スタック取ってきてしまうことだよね。
64個を超えてしまって、後のほうのスロットに骨粉がはみ出してしまう。

ではどうすればいいのか。

一番の正攻法は、骨粉が0個になったのを確認してから骨粉を取ってくればいいよね。
これまでは、骨粉を振り掛けるときに、turtle.place()を連続3回まとめてやっているけれど、
毎回振り掛ける前に自分の骨粉の個数を確認すればいい。
0なら骨粉を取りにいくわけ。

そして実装したのが以下のプログラム
促成栽培プログラムはこれで一応完成のつもりだよ。

プログラム

-- ########################
-- cultivate <n>
-- version 0.4
-- http://hevohevo.hatenablog.com/
-- ########################

-- #############
-- config
ARGS = {...}
MAX = ARGS[1]
SEED_SLOT = 1
MEAL_SLOT = 2

-- ##################
-- define functions
function plantSeed()
  turtle.select(SEED_SLOT)
  if turtle.place() then
    return true
  else
    print('failed: plantSeed')
    return false
  end
end

function dropItems(begin_slot, end_slot)
  print('drop items: slots ',begin_slot,'-',end_slot)
  for i=begin_slot, end_slot do
    turtle.select(i)
    turtle.dropDown()
  end
  turtle.select(1)
end
  
function useOneMeal()
  if (turtle.getItemCount(MEAL_SLOT) ==0) and (turtle.suckUp()==false) then
    print('failed: suckUp, and meal = 0')
    return false
  else
    turtle.select(MEAL_SLOT)
    turtle.place()
    return true
  end
end

function useMeals()
  local flag = true
  for i=1,3 do
    if useOneMeal() == false then
      flag = false
      break
    end
  end
  return flag
end

function harvest()
  turtle.select(SEED_SLOT)
  turtle.dig()
end

-- ##################
-- Main
turtle.dig() 
for i=1,MAX do
  print(i,'/',MAX)

  if plantSeed() == false then break end
  if useMeals() == false then break end

  harvest()

  if i%50==0 then dropItems(3,16) end

end
dropItems(3,16)

プログラムの解説

  • 以前あった、 getMeals()関数は全削除だよ。代わりに useOneMeal()関数を新しく作って、その中で骨粉補給もこなしている。
  • useOneMeal()は、実行前に骨粉の個数を調べ、0なら補給しようと試みるよ。補給に失敗したらエラーを返すんだ。
  • それに伴い、useMeals()関数も全面的に書き換えているよ。useOneMeal()が3回連続成功(trueを返す)ならそのまま収穫作業を続け、途中1回でも補給に失敗し(falseを返し)たらすぐにループを抜けて、終了するんだ。

まとめ

前回よりもプログラムの文量は減っているよね?
3回振りかけという大雑把な作業単位よりも、1回振りかけというさらに細かい作業単位にモジュール化したほうが、プログラム全体でわかりやすくなっている。

とりあえず動くプログラムを作って動かして、タートルをじっくり観察する。問題を発見したら、やりたい作業をどんどん細かく分けてモジュール化することで機能を修正・追加していく。
このような行き当たりばったりのプログラミング方法は、動きがすぐに見えて問題点が目に見えてわかるというタートルならではだよね。
このようなツギハギプログラミングによる試行錯誤と、最終的に思ったとおりに動くタートルのかわいさ。これが、僕がComputerCraftに感じる魅力なんだ。

これからもこんな感じで行き当たりばったりでBlogを続けていくつもりだよ。