規模が大きくなることで顕在化する問題ってありますよね（アレフガルド in マインクラフト Part11）

# はじめに
　これまでに紹介した方法で、ドラゴンクエストビルダーズのアレフガルド測量→マインクラフトでの再現を繰り返し、アレフガルド南西地方をカバーできる程度には再現マップが広がってきました。ただ、技術的に新しいトピックスが何もない状況（既存の手法を横展しているだけ）で、ただの進捗報告的な投稿をするのもQiitaっぽくないということで、「マップがここまで広がったよ」的な進捗は、別途Noteに記録をつけていくことにしました。今回は、アレフガルド南西地方全域のフィールドマップをマインクラフト上に生成する際、ちょっとした技術トピックスになりそうなネタを見つけましたので、それを紹介しようと思います。

 # アレフガルド南西地方
 　ドムドーラからメルキドまでつながる一体を、アレフガルド南西地方と呼ぶことにします。過去の投稿ではドムドーラ周辺やメルキド周辺を単一のマップとして再現していましたが、ドラゴンクエスト上で地続きとなっている部分をつなぎ合わせて、一枚の大きなマップにしました。エクセルのセル数でいうと縦×横=606x1166程度の広さになっています。

![map1-4_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/6fc8d9e9-b5be-8f7a-03dc-94ac0ec5ece2.jpeg)

　右上の白い部分は、迷路のように細い道が入り組んだ岩山地帯ですが、今の時点では陸地の外周部分だけを測量した白地図の状態です。この地形データをもとに、マインクラフト上で生成した地形がこちらです。
 ![Minecraft Education 2024_10_21 0_44_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/97ee8616-3cd9-f0bf-909e-0ea16e6db881.png)

　マップ同士をつなぎ合わせた部分や、本家のドラゴンクエストから変わってしまった地形の修正が途中なので、細かい部分ではおかしなところがありますが、全体的にはアレフガルドの南西地方を形作ることができてきました。今回紹介する事象は、この地形を生成する際に起こったのです。

# 発生した事象
　今回生成する地形は砂ブロックで構成される砂漠地帯を含んでいます。マインクラフトの砂ブロックは、そのままでは空中に配置しても落下してしまうため、地形全体の「底」となる部分に岩盤ブロックを敷き詰めることで砂の落下を防ぐようにしています。今回は、上に掲載したアレフガルド南西地方のマップ全体を読み込んで地形生成のコマンド群をつくり（PowerShellで実施）、そのコマンド群をマインクラフトエデュケーションのコードビルダー上で実行する形で地形生成を試みました。

 　ところが、実際にコマンドを実行してみると、「底」となるはずの岩盤ブロックが生成されず、その上に配置される砂ブロックだけが生成され、砂が落下してしまうという事象が発生したのです。
  ![Minecraft Education 2024_10_20 7_52_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/1063347c-3d9e-e76e-b64a-dec87804cb7a.png)

　生成されないのは岩盤ブロックだけで、上に配置される各種のブロックは生成されています。岩盤ブロックについては、生成されている場所とされていない場所がありました。

# 事象の分析
 　発生した事象の原因を突き止めるにあたり、今回実施している地形生成の仕組みについて簡単に整理します。
  1. 地形データを上から順に１行ずつ生成している
  1. 各行において、最初に岩盤の層を端から端までfillコマンドで生成する
  1. 同じ種類のブロックが同じ高さで続く範囲に区切り、それぞれの区画をfillコマンドで生成する

　例えば、草ブロック(grass)と砂ブロック(sand)が続く、なだらかな勾配がある地形の一行は、以下の図の①～⑩のような単位に分割されてコマンドが実行されるのです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/0cf56029-4b1a-e5e2-6e6f-d6b99457e285.png)

　また、岩盤層が生成されないという事象については、再現を繰り返す中で、以下のような特徴があることがわかりました。
 1. 層が生成されない場合は、行単位で全く生成されない
 1. プレイヤーの位置が生成範囲の中央に近い時には生成に成功することが多い
 1. プレイヤーが同じ場所いる場合でも、ビデオ設定の「描画距離」を小さくすると岩盤層が生成されなくなる

3つ目の特徴については、何度も再現する中で、描画処理の重さでPCのファンがブンブン回っているのを不憫に思い、少しでも処理の負担をさげようと描画距離を狭くしたことが、功を奏した結果となりました。

　地形生成の仕組みと発生した事象の特徴を組み合わせて考えると、今回発生した事象については以下のような仮説を立てることができそうです。

- 岩盤層の生成を行うコマンドは、他の地形生成のコマンドと比べて、fillコマンドの始点と終点が大きく離れている（生成するマップの東西方向の広さに比例）
- 岩盤層生成を実行する際に、コマンドの始点と終点のいずれかが、ビデオ設定の「描画距離」の限界を超えていた時には、コマンド自体が失敗する


# 仮説の検証
## 検証方法
　前節で述べた仮説を検証するために、簡単なブロック配置コマンド群を用意して検証を行いました。検証内容は以下の通りです。
 1. プレイヤーの位置を中心として400x400の範囲に5ブロック間隔でブロックを生成していくコマンド群を実行する
 1. ビデオ設定の描画距離を、5チャンク（設定上の最小値）から10チャンクまで1チャンクずつ増やし、上述の処理を実行する

　コマンド群を生成するためにやっつけで作ったPowershellがこちらです。プレイヤーは水平方向には座標0,0の原点にいる前提です。
 ```powershell
$r_max = 400
$c_max = 400
$y = -59
$d = 5


echo "player.onChat(""run$k"", function () {"
for ($i = 1; $i -le $r_max; $i++) {
    $z = $i - 200
    for ($j = 1; $j -le $c_max; $j++) {
        $x = $j - 200
        if($i%$d + $j%$d -eq 0 ){
            echo "blocks.fill(DIAMOND_BLOCK,world($x, $y, $z),world($x, $y, $z),FillOperation.Replace)"
        }
    }
}

echo "blocks.fill(BEDROCK,world(0, $y, 0),world(0, $y, 0),FillOperation.Replace)"
echo "})"
 ```
　全てのコマンド群が実行されれば、80x80のブロックが正方形に配置されます。もし仮説が正しければ、描画距離が異なる試行に対して、ブロックの配置される範囲がかわるはずです。

## 検証結果
　描画距離が5チャンクで、コマンド群を実行した結果がこちらです。中心から5チャンクの範囲内しかブロックの生成コマンドが実行されていないことがわかります。
 ![d5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/f18e3f7d-af89-fa71-1d77-68ffc5071c76.png)

　描画距離を6チャンクに増やした場合は、もう少し広い範囲にブロックが生成されました。
　![d6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/c6fc0be7-3b2b-c59d-a2f9-d28b79f5c132.png)

　7チャンクから10チャンクまでは続けて載せてしまいます。
 ![d7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/0d12b5c5-078d-0b79-8918-afa0ec131526.png)
![d8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/c2e9ab58-1ac4-9f19-16fc-08e183bbe60b.png)
![d9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/cdc2a2a3-8927-1497-3fcf-8887c0ded616.png)
![d10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/63b9993c-91e1-8538-a865-605fa4dfead0.png)

　仮説が期待する通り、描画距離で指定したチャンク数に応じて、コマンドが成功する範囲は広がっていくこと、描画距離よりも遠いところに、始点・終点があるコマンドは実行されないことが確認できました。

# まとめ
　以上の検証を踏まえ、今回起こった事象の発生原因と経緯をまとめると以下のようになります。
- マインクラフトエデュケーションのコードビルダーで実行されるblocks.fillの処理は、fillの始点と終点が描画距離に収まっていないとコマンドの実行に失敗する特徴があった
- これまで実行してきた地形生成では、マップの大きさに対して描画距離が十分に大きかったため、コマンドが失敗することはなかった
- 複数の地域を繋ぎ合わせ地形生成対象となるマップ自体の大きさが広がったことで、block.fillの始点・終点が描画距離の限界を超えるケースが発生しうる状態となった
- 始点と終点の差が最も大きくなる岩盤層の生成コマンドで、真っ先にこの事象が顕在化した

　この事象を回避するためには、①描画距離を十分に大きくとるか、②一度に実行する地形生成の範囲を十分に小さくするかのどちらかになりそうです。ただ、描画距離を大きくすると
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/be638ac2-cf88-af76-a899-72c9c064b12d.png)
ということらしいので、①と②のバランスを取りながら地形生成を進めていくことになりそうです。

# おまけ
これまでの投稿をまとめておきます。
 |No.|内容|
 |:--:|:--|
 |Part1|[マインクラフトでの地形生成](https://qiita.com/yamamorisoba/items/a8736bfe8acb802dd2ae)|
 |Part2|[町の再現①](https://qiita.com/yamamorisoba/items/5e059388ac9db6037fb2)|
 |Part3|[メルキド as Code](https://qiita.com/yamamorisoba/items/26905b328cff581102d0)|
 |Part4|[住民との会話システム](https://qiita.com/yamamorisoba/items/fdd1dfdc42510e64af5a)|
 |Part5|[海と森の生成](https://qiita.com/yamamorisoba/items/f27bc50be589953ce696)|
 |Part6|[森の生成方法の改良](https://qiita.com/yamamorisoba/items/2e6fb100b4ed73d77a27)|
 |Part7|[ドムドーラ地方の生成](https://qiita.com/yamamorisoba/items/1d059817551834c3d14f)|
 |Part8|[ドムドーラの町づくり](https://qiita.com/yamamorisoba/items/dc8f73cef64785c97471)|
 |Part9|[マイクラ版ロト装備の検討](https://qiita.com/yamamorisoba/items/5cd64a9de29b5bb743a0)|
 |Part10|[毒の沼地のつくり方](https://qiita.com/yamamorisoba/items/a7b6ac2c74ea7730b0b8)|

Note版の進捗報告はこちら
https://note.com/search?context=note&q=from%3A%40yamamorisoba