Minecraftとタートルと僕

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

採掘タートルで整地する: (2)【補足】なぜ砂/砂利処理時間が正面と真上で違うのか

前回の問題点

前回(第1回目)は、

  • 真正面に砂/砂利の山があったとしても全て採掘して前進するプログラム
  • 真上から砂/砂利が落ちてきたとしても全て採掘して上昇するプログラム

という2つの簡単なプログラムを紹介しました。

2つのプログラムの違いは、真上の方だけ、whileループの中にos.sleep(0.4)というウエイトを入れている点です。 少しだけ採掘を遅らせることで、連続で砂を採掘できるようになります。

しかしなぜ、「真上の砂を掘るのになぜ0.4秒の待機時間が必要」なのでしょうか。

今回は整地に関する話題から少しだけ離れて、この内容を検討してみましょう。

なぜ真上の砂/砂利採掘に失敗するのか

マインクラフトの世界は1m四方の「ブロック」を基本に構成されていることは周知の通りですが、

マインクラフトプログラムは、世界の中で動き回るオブジェクトを「エンティティ」と呼んで特別に処理します。

モンスターや動物などのいわゆるMob、あるいは撃ち出した矢などもエンティティです。

また、砂/砂利はブロックですが、下に支えるものがなくなると、ブロック→下に落下するエンティティ→落下後はブロック、というふうに処理されます。

ここで注意したいのが、タートルの採掘turtle.dig()は、ブロックに対してしか行うことはできないということです。 そしてブロックを検出する関数turtle.detect()もブロックがあるときにしかtrueを返しません。

そのため、whileループでturtle.dig()を繰り返すプログラムを書いたとき、turtle.dig()を繰り返すタイミングが早すぎると、落下中のエンティティに対してturtle.dig()することになり、whileループを抜け出してしまうのです。

つまり、真上の採掘で指定した0.4秒の待ち時間は早すぎる関数実行の対策であり、0.4秒という待ち時間によって、落下中のエンティティに触れることなく正面に出現しつづけるブロックを連続して掘ることができるのです。

でもおかしいですよね?

エンティティには全て加速度が設定されており、さきほど挙げた参考ページによると落下する砂ブロック(エンティティ)には16m/s2の加速度が一律設定されているようです。

ここで、「あれ?」っと思った方は鋭い。

落下するブロックは一律同じ加速度なのですから、真上だろうが正面だろうが、ブロック→落下中のエンティティ→ブロック という移り変わりの時間は全く同じはずなのです。

しかしタートルの真上のときだけ0.4秒の待ち時間が必要であることが、試行錯誤の結果わかっています。

原因を探る

正面に落下する砂、タートルの真上に落下する砂。

違いは何でしょう?

最も大きな違いは、「砂が何の上に落下するか」ということです。

正面の砂はブロックの上に落下します。タートルの真上の砂はタートルの上に落下します。

ん? 「タートルの真上に落下すると時間がかかる?」 これが問題なのでしょうか。見比べてみましょう。

f:id:hevohevo:20140712004315j:plain

タートル真上の砂と(石)ブロック真上の砂。見比べるとタートルの真上には隙間が開いていることがわかります。

この隙間があやしぃ・・・。

1m未満のブロックを試す

マイクラ世界では、1ブロックは1辺1mの立方体です。

しかし手持ちのブロックの中には高さが1m未満のブロックがいくつもあります。

たとえば半ブロックやチェスト、そして今回のタートルなどなど。

なお、ブロックの高さを調べるにはF3キーを押して表示される情報が便利です。

f:id:hevohevo:20140712012017j:plain

上記は、高さ(Y座標)4の地面の上にタートルを設置して、その上に乗った状態の画像です。

足元位置のY座標が4.875と表示されていますが、Y座標4を差し引いて、タートルの高さが0.875mであることがわかります。

なお、0.875mというのは覚えにくいので、7/8mとこれからは呼びましょう。

ブロックの高さ

参考として、以下に測定したブロックの高さ一覧を示します。

ブロックの種類 高さ 上から砂を落とすと
石など通常のブロック 1m 上に積み重なる
タートル 7/8m 上に積み重なる
チェスト 7/8m 上に積み重なる
半ブロック 1/2m 砂はアイテム化

また、雪(snow)なども面白いですね。

雪はとても薄いブロックですが、最大8枚まで重ねることができます。

雪を積む枚数と高さの関係を以下に示します。

雪を積む枚数 高さ 上から砂を落とすと
雪1/8 0m 雪は潰れて消失
雪2/8 1/8m 雪は潰れて消失
雪3/8 2/8m 雪は潰れて消失
雪4/8 3/8m 雪は潰れて消失
雪5/8 4/8m 雪は潰れて消失
雪6/8 5/8m 上に積み重なる
雪7/8 6/8m 上に積み重なる
雪8/8 7/8m 上に積み重なる

雪についてのポイントをまとめると以下の通り。

  • 雪1/8枚は、高さ0
  • 1枚から5枚までは、上から砂を落とすと雪は潰れて消失する。
  • 最大の8枚積んだとき、外見は石ブロックと同じ1mの高さに見えるけれど、実際の当たり判定(高さ)は、チェストやタートルと同じ7/8m

つまり落下距離が違うんですよ

普通のブロック(1m)の上に砂ブロックが積み重なっているとき、一番下の砂ブロックを採掘(dig)すると、すぐ上の砂ブロックは1mだけ落下します。

それに対して、タートル(7/8m)の上に砂ブロックが積み重なっているとき、その一番下のブロックを採掘すると、すぐ上の砂ブロックは1m+1/8m、すなわち1.125m落下することになるのです。

ゲーム画面でその様子を実際に見ると、一瞬だけ砂ブロックがタートルにめり込んで、その後すぐに引き戻されてタートルの上に積み重なるような挙動をしています。

以下のスロー映像で見ると一目瞭然ですね。

落下距離が長いなら、その分だけ砂の落下時間も長いわけで、その落下中にturtle.dig()しようとしても失敗してしまいます。

また、映像をみるとわかるように反発して引き戻されるまでの時間も加味しなくてはなりません。

そのため連続して落下してくる砂を採掘しようと思うなら、スリープ時間も多めにとらなくてはならないのです。

つまり、下が7/8mのブロックならば、0.4秒のスリープですね。

それではもっと低いブロックなら?

雪ブロックを積み重ねることで、タートルよりも低いブロックを実現できます。

たとえば、6枚重ねることで、5/8mのブロックができます。スロー映像で見てみましょう。

微妙な差ですが、右の6/8雪側の方が、タートル側よりも深く砂がめり込んでいますね。

なお、7/8mのタートルのときは0.4秒のスリープでよかったのですが、5/8mである雪の場合は0.6秒のスリープが必要となります。

まとめ

1mよりも低いブロックの上に砂/砂利の山があるとき、以下のコードでは砂/砂利を全て取り除くことはできません。

while turtle.dig() do end

タートルもまた1mより低いので、以下のコードでタートルの真上にある砂/砂利を全て取り除くことはできません。

while turtle.digUp() do end

なぜならば、1mに足りない分だけ逆に砂の落下距離が増え、余分に落下した砂が反発して引き戻されるからです。その余分な時間中に採掘しようとして空振りしてしまいます。

適切なスリープ時間を入れましょう。たとえば、タートルの真上を掘るならば、以下のようにos.sleep(0.4)が必要です。

while turtle.digUp() do
  os.sleep(0.4)
end

以下は、ブロックの高さと、その上に砂を落とすとどうなるか。そしてその上に砂/砂利が積み重なっているときに何秒のスリープが必要かをまとめた表です(ブロックの高さが低い順)。 参考までに。

ブロックの種類 高さ 上から砂を落とすと 落下距離 必要なsleep時間
雪1/8 0m 雪は潰れて消失 2m 0.6s (*1)
雪2/8 1/8m 雪は潰れて消失 2m 0.6s (*1)
雪3/8 2/8m 雪は潰れて消失 2m 0.6s (*1)
雪4/8 3/8m 雪は潰れて消失 2m 0.6s (*1)
雪5/8 4/8m 雪は潰れて消失 2m 0.6s (*1)
半ブロック 1/2m 砂はアイテム化 1.5m - (*2)
雪6/8 5/8m 上に積み重なる 1m+3/8m 0.6s
雪7/8 6/8m 上に積み重なる 1m+2/8m 0.4s (*3)
雪8/8 7/8m 上に積み重なる 1m+1/8m 0.4s
タートル 7/8m 上に積み重なる 1m+1/8m 0.4s
チェスト 7/8m 上に積み重なる 1m+1/8m 0.4s
石など通常のブロック 1m 上に積み重なる 1m 0s
  • *1 雪は潰れて消えるので、実質的に2m落下することに
  • *2 半ブロックの上に落ちた砂はアイテム化するのでsleep意味無し
  • *3 0.5秒ではないので注意。