User:Kyaco11/村の仕組み

村の仕組み
Minecraftでは「村」と呼ばれる仕組みがあり、村人を繁殖させたり、 ゴーレムTTを作ったりするためにはその仕組みを理解しておく必要がある. このページでは村の仕組みについてできるだけ詳細に解説していく.

概観
マインクラフトにおける村の仕組みは主に2つの機能によって成り立っている. 1つは村人のAIによる機能で、もう1つはVillageCollectionと呼ばれる、村の情報を集中的に管理する機能である.

前者は村人のいる場所を後者に知らせる働きをしている.

後者の働きは順に書くと次のようになる.
 * 既存の村に働きかけて村情報の更新やゴーレムのスポーンを行わせる
 * 村人が知らせてきた場所をもとにドアを検索する
 * 見つかったドアに対して村への登録情報の更新や既存の村への登録、新規の村を作成をする

//要画像:フローチャート

2つの機能をつなぎ合わせるために、VillageCollectionは村人のいる場所を記憶しておくキューを持っている. このキューに村人は自分のいる場所を登録する. VillageCollectionはキューから村人のいる場所の座標を取り出して様々な処理を行う.

//要画像:キューの概念

村人のAIによる処理
VillageCollectionは村人のブロック座標を64個まで保持できるキューを持っており、村人が渡してきたブロックの座標をキューの末尾に追加する. ただし、村人が渡してきたブロックの座標と同じ座標がキューの中にある場合は追加しない.
 * 1) 自身のいるブロック座標をVillageCollectionに渡す
 * 2) 村人と村の中心が[村の半径]+32m以下である村の中で、一番近い村の中心を自分のホームポジションに設定する（ランダムウォークなどで使われる）
 * 3) 次にこの処理を行うまでの待機時間を70～120tick=3.5～6秒の間でランダムに設定する

//要画像:ホームポジション

//要画像:キューへの登録の流れ

各村についての処理
それぞれの村は村の中心や半径、村人やゴーレムの数、自身に属するドアの座標、 ドアの有効期限に関する情報を保管している. VillageCollectionは村に働きかけてそれらの情報を更新させる. その際ゴーレムのスポーン処理も行われる.

破壊されたドアや有効期限（ドアの検索の項で後述）の切れたドアを村の登録から外す
管理しているドアの座標にドアがなかったり、有効期限がきれたりする場合、 そのドアの情報を削除する.

村の中心と半径を更新する
全てのドアの座標について平均の座標を平均し、小数点以下を切り捨てた座標が村の中心となる. 座標の正負によらず小数点以下を単に切り捨てた座標となる点に注意.

例)
 * 平均座標(10.5, 64, 20.25)→村の中心(10, 64, 20)
 * 平均座標(-10.5, 66.75, -20.25)→村の中心(-10, 66, -20)
 * 平均座標(-22.5, 180, -0.925)→村の中心(-22, 180, 0)

//要画像:象限ごとの平均座標と中心座標のずれかた

村人とゴーレムの数の更新
村の中心を中心として、x軸とz軸方向に村の半径の2倍、y軸方向に8mの直方体に、 ヒットボックスが一部でも重なる村人・ゴーレムの数を数える. 村人数の更新は20tickに1度、ゴーレム数の更新は30tickに1度行われる.

//要画像:直方体のサイズ

ゴーレムのスポーン処理
ゴーレムの数が村人の数の十の位の数字より少なくドアが21枚以上ある村について 、1/7000の確率でスポーン抽選が行われる. 抽選はスポーンできる場所がヒットするまで10回を限度に繰り返し行われる. スポーンできる場所の条件は次の通り. //要画像:ゴーレムが沸くブロックの配置、条件に付いて
 * 1) 村の中心を中心とする16×6×16の直方体の範囲内である
 * 2) ゴーレムの足場となるその場所の真下のブロックについて、isFullyOpaque関数が真を返す
 * 3) ゴーレムの沸く空間となる範囲（その場所との相対座標で、(-1,0,-1)と(0,4,0)を頂点に持つ軸平行境界ボックス内部の8ブロック）すべてについてisNormalCubeが偽を返す
 * isFullyOqaque関数の戻り値の一覧へのリンク
 * isNormalCube関数の戻り値の一覧へのリンク

ドアのなくなった村情報の削除
ドアの数が0になった村の情報を削除する

ドアの検索
村人の場所を記憶しているキューから1つ座標を取り出し、 その座標を中心に32×8×32の範囲でドアを探す.

ドアを探す順番は、x=-16,y=-4,z=-16から始めてzを増やしてz=15になるまで繰り返す. 次にyを1つ増やして同じことをし、yが3になるまで繰り返す. 次にxを1つ増やして同じことを4?、xが15になるまで繰り返す.

ドアが見つかると順番にリストに登録され、次項のドアを村に登録する処理へ移る.

//要画像

【Minecraft】ボタン1つで村を45個作る装置と村の仕組み（ニコニコ動画）で視覚的に解説してある.

ドアを村に登録する
前項で見つかったドアのリストの順にドアを村に登録する. 見つかったドアがすでにいずれかの村に登録されているときは有効期限を1分に再設定する. どの村にも登録されていないときには、既存の村に登録するか新たに村を作るかの処理が行われる.

既存の村に登録するか新たに村を作るかの部分は、Minecraft Version1.8でアルゴリズムが変更された.

1.8以降の処理
村の中心からドアまでの距離が[村の半径]+32m以下であるような村の中で、 村の中心とドアの距離が一番短い村に登録される. このような村が1つもなければそのドアを中心とする村を新たに作る.

1.8以前の処理
村の中心からドアまでの距離が[村の半径]+32m以下であるような村の中で、 できたのが一番古い村に登録される. このような村が1つもなければそのドアを中心とする村を新たに作る.

トリビア

 * 村人がいる座標が大量に（120ヶ所以上）あるときは村人の座標を記憶しておくキューがあふれてしまうことがある
 * レッドストーンブロックや上付きの半ブロックはゴーレムが沸く足場の条件とゴーレムが沸く空間の条件のどちらも満たしている. つまりゴーレムの沸き抽選の行われる範囲をいずれかのブロックで埋めるとブロックに埋まってゴーレムがスポーンする.