海と森の生成（アレフガルド in マインクラフト Part5）

# はじめに
　[Part4](https://qiita.com/yamamorisoba/items/fdd1dfdc42510e64af5a)まででメルキド地方の地形はおおむね完成しましたが、草原と岩山のみで海と森は生成されていない状態でした。今回はPart4までに生成した地形に海と森を作ってみたいと思います。完成図は以下のようになります。
 
![Minecraft Education 2024_04_30 18_12_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/375f8740-ba8f-9edd-3745-af0eec4601f9.png)


 # 海の生成
 　今回、地形データのベースとして参照しているドラゴンクエストビルダースでは、海が2つのパターンに分かれています。

1. 徒歩で移動可能な浅瀬（深さ1）
1. 踏み込むとダメージとともに手前に引き戻される海（進入不可のため深さ不明）

　浅瀬というパターンが増えているものの、基本的には進入不可能になっているという意味で、FC版のドラゴンクエストの海の特性を引きついでいます。一方で、マインクラフトでは、プレイヤーは海（水中）に自由に出入りできる仕様となっています。したがって、マインクラフト上にアレフガルドを再現する際に、海を単純に水で満たすだけでは、プレイヤーは海を渡ることができてしまい、本来の地形の特性を再現することができなくなってしまいます。
　今回は、プレイヤーの海への進入を防ぐ方法として、バリアブロックを用いることにします[^1]。進入不可能な海のエリアの海上を、十分な高さのバリアブロックで満たすことで、陸地や浅瀬からの海への進入を防ぐことができるはずです。
[^1]:Education Editionには、バリアブロックの他に、ボーダーというブロックが用意されています。ボーダーもプレイヤーの移動境界を定めるのに利用可能ですが、Education Edition限定のブロックとなっています。今回は、統合版でも応用可能なつくりとするために、バリアブロックを採用します。
　浅瀬と海とで、プレイヤーの進入可否が異なるので、海の生成は以下の二つの条件を考慮してコードを生成します。
 1. 浅瀬は、深さ1の水で満たす（バリアブロックは置かず、プレイヤーが出入りできるようにする）
 1. 海は、海面の高さまでを水で満たした上、海面から一定の高さまでバリアブロックを設置し、プレイヤーが進入できないようにする

　なお、ゲームモードがクリエイティブ、サバイバルの場合には、バリアブロックの輪郭が表示され、不可視ブロックの存在が示唆されますが、アドベンチャーにすると輪郭表示もなくなり、単純に進入不可の状態となります。

 ![Minecraft Education 2024_04_30 23_36_40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/fad55d25-68c4-5a33-f1e6-886afd81fedb.png)
クリエイティブモードで輪郭が表示されるバリアブロック
 
# 森の生成
## 植林の密度の検討
　森を作りたいエリアには、適切な密度で「苗木」を植えることで森を形成することができます。例えば樫の木であれば、16x16のエリア内に平均的に4本程度の木をはやすことができれば、森を作ることができそうです。Excelで用意している地形データの中で、森を生成するエリアを表現する方法としては、セルのフォントカラーを利用することにします[^2]。`$Worksheet.Cells.Item(<row>,<col>).Font.Color()`を用いることで、フォントカラーを数値データとして取り出すことができます。特定のフォントカラーが設定されたセルを森エリアと判定して、森エリア16x16に4本という密度で苗木を植えるための、コード生成ロジックは以下のようにしています。

[^2]:セルの背景色は、その座標に設置するブロックの種類を定義するのに使ってしまっているため、森かどうかの判定を行うための情報としては、背景色以外のセルの属性としてフォントカラーを採用することにしました。


 ```powershell
for ($i = 1; $i -le $r_max; $i++) {
    for ($j = 1; $j -le $c_max; $j++) {

        $Value = $Worksheet.Cells.Item($i,$j+2).Value()
        $FontColor = $Worksheet.Cells.Item($i,$j+2).Font.Color()
        if($FontColor -eq 255){
            $Random = Get-Random -Minimum 0 -Maximum 63
            $x = $x_base + $j - 1
            $z = $z_base + $i - 1
            $GroundLevel = $Value + $y_base + 1
            if( $Random -le 1 ){
                echo "blocks.place(<SAPLING_ID>, world($x, $GroundLevel, $z))"    
            }
        }
    }
}
 ```
　このコードにおいて、`r_max`と`c_max`は、マインクラフト上で地形を生成する際の、x軸方向とz軸方向の幅です。`x_base`と`z_base`は地形を生成する起点となる座標、`y_base`は地形を生成する基準の高さを調節するためのパラメータです（高いところに地形を生成したい場合には`y_base`に大きい値を設定します）。`Value`は`y_base`からの差分で表現される座標の高さです。16x16に4本という密度で木を植える場合、平均的に1/64の確率で苗木を植えられれば良いので、0～63の範囲で乱数を生成し、生成された乱数が1以下である場合に苗木を植えるというコードになっています。マインクラフトで苗木を植える場合には、地面の1つ上の高さを指定する必要があるため、`GroundLevel`という変数で、苗木を植える高さを定義しています。植える苗木の種類は`<SAPLING_ID>`で指定します。

## 苗木の種類の検討
　マインクラフトには、植えられる樹木が複数種類存在しています。FC版ドラゴンクエストでは、森はあくまで森であって、樹木の種類までは表現されていませんが、マインクラフトに森を実装しようとする場合には、樹木の種類を指定する必要があります。Wikipediaによると、樹木の種類に応じた生息分布地域は以下のようになっています。

|種類|苗木の名前|分布|
|:-:|:-:|:-|
|樫|OAK_SAPLING|温帯南部の湿潤地域[^3]|
|トウヒ|SPRUCE_SAPLING|海抜1,500-2,500 mにかけての亜高山帯[^4]|
|白樺|BIRCH_SAPLING|北半球の温帯から亜寒帯地方[^5]|
|アカシア|ACACIA_SAPLING|熱帯から温帯。年間を通してほとんど降水が無い砂漠に自生[^6]
|ジャングルの木|JUNGLE_SAPLING|-(種類が不明だが、ジャングルなので熱帯か)
|マングローブ|MANGROVE_PROPAGULE|熱帯および亜熱帯地域の河口汽水域の塩性湿地[^7]|

[^3]:https://ja.wikipedia.org/wiki/%E3%82%AB%E3%82%B7
[^4]:https://ja.wikipedia.org/wiki/%E3%83%88%E3%82%A6%E3%83%92
[^5]:https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%A9%E3%82%AB%E3%83%B3%E3%83%90
[^6]:https://ja.wikipedia.org/wiki/%E3%82%A2%E3%82%AB%E3%82%B7%E3%82%A2
[^7]:https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%82%B0%E3%83%AD%E3%83%BC%E3%83%96

　メルキド地方は、アレフガルドの中では南の方に位置しています。アレフガルドが日本と同様、北が寒く、南が温かい気候になっていると仮定する場合、メルキド周辺に生える樹木の候補は、樫かジャングルの木と考えられます。アカシアやマングローブも緯度的にはマッチしそうですが、アカシアは乾燥地帯、マングローブは湿地帯に生えるという特性を考えると、メルキド地方の森を構成する樹木としては不適切に思われます[^8]。

[^8]:マングローブは、メルキドのさらに南にあるロトの紋章が手に入る沼地周辺あたりで採用するのがよさそうです。またアカシアは、ドムドーラの砂漠地帯の周辺の森林エリアに採用するのがよさそうです。

　今回は、いったん樫の木を配置してみることにしました（ドラゴンクエストのフィールドマップの森アイコンと木の形も似ていますし）。FC版のメルキド周辺の森の配置を参考に、メルキドの街から岩山地帯との間が森となるように森エリアを定義し、前述したコードを用いて苗木を配置します。MakeCodeのプログラムを介して苗木を植える場合、プレイヤー自身は遠く離れていても、苗を植えることが可能です。ただし、苗木が木に成長するためには、ある程度プレイヤーが苗木に近づく必要があります。マインクラフトEducation Editionでは演算距離が既定値で4チャンク[^9]なので、64ブロック以内に近づいていないと苗木は成長しません。今回は、苗木を植えるところまでをコードで実行しておき、ティック速度を速めた状態で苗木の周辺を移動し、森を形成しました。

[^9]:ワールド生成時に設定され、生成後の変更は不可。

# 海と森の生成結果
　これまでに生成した地形に、海と森を追加した状態が冒頭の写真です。再掲します。

![Minecraft Education 2024_04_30 18_12_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297527/fad996ce-4785-f717-45f7-cf7f9135d828.png)
 
 メルキドの街周辺が森のようになり、海ができたことで、宙に浮いたように見えていた陸地も本来のドラゴンクエストのマップイメージに近づいたように感じます。岩山の高さに比べて、木々が思ったよりも大きく成長したため、岩山はもう少し高く形成してもよいかもしれません。このあたりの最終的なバランス調整は、全体が完成した後で別途行いたいと思います。

# おまけ：メルキド地方全体をコードで生成してみた
　これまで、測量した範囲を順次生成してきたメルキド地方ですが、今回の記事で全体のコード化が完了しました。そこで、何もない状態から、MakeCodeのコードのみでメルキド地方を生成することを試してみました。その結果が以下の動画です。10倍速で再生されるようになっています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/H_jvtToqoG0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>