地図/気まぐれ/プロシージャル生成

酔歩で掘る

盤面の全マスを一斉に均すのでなく、一匹の酔っぱらいを放って歩いた跡だけを床に掘る。ランダムウォーカーが上下左右へよろよろ進み、踏んだマスを床にする。床の割合が目標に届いたら止める。

ランダムウォーク(酔歩)。各ステップで進む向きを毎回乱数で選ぶ。掘り跡が一筆書きの線になるので、面を均すCAが塊を作るのに対して、酔歩はくねった通路を引く。素のランダムウォークは原点から平均で √歩数 ぶんしか離れないため壁際で時間を浪費しやすく、たまに中心へ引き戻すバイアスを混ぜると偏りが抑えられる。止め条件を歩数でなく床率に取ると、盤面の大小によらず開け具合が揃う。

ウォーカーが毎ステップ上下左右のどれか一つへ一マス動く。踏んだマスを床に立て、踏んだことのある床を明るく塗る。dirXdirY1-1 を入れて片方だけ動かすと、四方向の酔歩になる。盤の各所に数匹撒くと、それぞれの踏みあとが伸びて床の筋になる。

明るい頭が酔ってよろめき、通ったあとに細い床の筋が伸びる。一匹だけだと中心から離れにくく、壁にぶつかって跳ねながら同じあたりを行き来して盤の片側に偏った塊を残す。向きの抽選に中心へ寄せる項を混ぜると、頭が遠くへ逃げる前に引き戻される。toCenter < 0.16 のとき x を中心方向へ、< 0.32 のとき y を中心方向へ動かし、残りは素の四方向にする。

// 約3割を中心方向へのバイアスに割り当てる
const toCenter = Math.random()
if (toCenter < 0.16) dirX = wx < nx / 2 ? 1 : -1
else if (toCenter < 0.32) dirY = wy < ny / 2 ? 1 : -1
else if (toCenter < 0.66) dirX = Math.random() < 0.5 ? 1 : -1
else dirY = Math.random() < 0.5 ? 1 : -1

掘ったマスの数 carved を数えて、全マスの目標割合 target に届いたら盤を初期化して掘り直す。床率で止めるので、盤が広くても狭くても開け具合が揃う。ウォーカーを盤全体に数匹撒いて、それぞれが四方向の酔歩で踏んだマスを掘る。明るい頭が踏みあとを残し、複数の軌跡が出会って一つの通路網に繋がる。

くねった通路が枝分かれして広がり、target0.5 に届いたところで盤がまっさらに戻って掘り直す。CAの洞窟は近傍の多数決で面を均すので塊が丸くまとまり、酔歩は軌跡をなぞるので細い通路が有機的に絡む。target を上げると床が増えて開けた空間に、下げると掘り跡が細い迷路寄りになる。ウォーカーの数を増やすと枝が同時に伸びて早く埋まる。一匹だけにして中心バイアスを混ぜると、上の :::code のように一筆書きの通路が中心寄りに留まる掘り方になる。