隣の数え方
(N + i) % N で端を反対側へ巻くと、マス目の上下と左右がつながって、紙が筒になる。筒の口どうしもつながってドーナツ状(トーラス)になる。端のマスを特別扱いせずに済み、模様が画面の縁で途切れない。
隣の集め方には二通りある。上下左右の4マスだけ足す von と、斜めも入れて8マス足す moore。8マスのほうは二重ループで自分 (0, 0) だけ飛ばして、まわりの8マスを足す。どちらも idx でトーラスの巻きを通すので、端のマスでも8方向きっちり拾える。
// 4近傍: 上下左右だけ足す
const von = (g, x, y) => idx(g, x - 1, y) + idx(g, x + 1, y) + idx(g, x, y - 1) + idx(g, x, y + 1)
// 8近傍: 斜めも足す。自分(0,0)だけ飛ばす
const moore = (g, x, y) => {
let sum = 0
for (let dy = -1; dy <= 1; dy++) {
for (let dx = -1; dx <= 1; dx++) {
if (dx === 0 && dy === 0) continue
sum += idx(g, x + dx, y + dy)
}
}
return sum
}中央の1マスだけ立てて、「立っている隣がひとつでもあれば自分も立つ」というルールで広げる。左は4近傍、右は8近傍。同じ初期値・同じルールで、隣の数え方だけが違う。
4近傍は中央から菱形に、8近傍は四角に育つ。grow に渡す数え方の関数を von から moore に替えただけで、波面の形が変わる。
上下左右の4マスを見る数え方が von Neumann 近傍、斜めも入れて8マス見る数え方が Moore 近傍。名前はそれぞれ John von Neumann と Edward Moore に由来する。von Neumann 近傍は1ステップで届く範囲がマンハッタン距離1の集合なので菱形に、Moore 近傍はチェビシェフ距離1の集合なので正方形に広がる。何を隣と認めるかが、そのまま拡散の波面の対称性を決める。
「自分と近傍の数から次の状態を決める関数」を差し替えると、同じ土台のまま別のものが立ち上がる。