自分の跡をたどる
仲間を直接見るのでなく、地面に置かれた痕跡を読んで動く決め方がある。各点は踏んだマスに痕跡を足し、少し前方の濃さを嗅いで濃い方へ向きを切る。濃い跡に寄ると跡がさらに濃くなり、線が太く育つ。
スティグマジー(stigmergy)。環境に痕跡を残し、その痕跡を介して間接的にやりとりする仕組み。アリのフェロモン経路が代表例。粘菌の配線網をこの形でモデル化したのが Jeff Jones の Physarum モデルで、三つの操作からなる。各点が踏んだマスへ痕跡を足す deposit、痕跡格子を毎フレームぼかして一定率で薄める diffuse-decay、各点が前方の濃さを嗅いで濃い方へ向きを切る sense-rotate。濃い跡へ集まると跡がさらに濃くなる正のフィードバックが、配線網のような筋を立てる。
痕跡を置く器を用意する。trail は一辺 g マスの濃さを並べた一次元配列で、座標 (x, y) をその添字へ畳むのが at。盤からはみ出した座標は縁に丸める。
const trail = new Float32Array(g * g)
const at = (x, y) => {
let gx = x | 0
let gy = y | 0
if (gx < 0) gx = 0
else if (gx >= g) gx = g - 1
if (gy < 0) gy = 0
else if (gy >= g) gy = g - 1
return gy * g + gx
}deposit だけを入れる。点は嗅がずにまっすぐ進み、踏んだマスの濃さを +1 する。trail の各マスの濃さを、そのまま濃淡の四角で描く。
直進した点の通り道が、踏まれたぶんだけ濃くなって残る。一度濃くなったマスは消えないので、画面はそのうち固いスジで埋まる。痕跡が育つだけで薄れないと、場としては動かない。
痕跡を毎フレーム少しぼかして、少し薄める(diffuse-decay)。各マスを上下左右と自分の5点で平均すると濃さが滲んで広がり、その値に 1 未満を掛けると全体が褪せる。0.2 が5マス平均、後ろの 0.9 が寿命のつまみ。
// 上下左右+自分の平均でぼかし、0.9 を掛けて薄める next[i] = (trail[i] + trail[xm] + trail[xp] + trail[ym] + trail[yp]) * 0.2 * 0.9
deposit にこのぼかしと減衰を足したのが下。
スジが柔らかくなり、踏まれ続ける所だけ濃く残り、通らなくなった所は溶けて消える。痕跡が薄れる場になる。点はまだまっすぐ進むだけで、この場を読んでいない。
嗅ぐ動きを足す。各点が自分の少し前方の左・正面・右の3マスで濃さを読んで、いちばん濃い方へ向きを切る(sense-rotate)。sa が触角の開き、ta が一度に曲がる量。3つとも同じくらいなら、乱数で散らす。
const cF = trail[at(x + Math.cos(head) * sense, y + Math.sin(head) * sense)] const cL = trail[at(x + Math.cos(head - sa) * sense, y + Math.sin(head - sa) * sense)] const cR = trail[at(x + Math.cos(head + sa) * sense, y + Math.sin(head + sa) * sense)] let nh = head if (cF >= cL && cF >= cR) nh = head else if (cL > cR) nh = head - ta else if (cR > cL) nh = head + ta else nh = head + (Math.random() - 0.5) * ta * 2
ばらばらに散っていた点が、嗅いで・曲がって・置いてを繰り返すうちに、自分たちの痕跡を伝う配線網の筋を引きはじめる。濃い跡へ寄ると跡がもっと濃くなる正のフィードバックで、細い筋がいくつかの太い線へまとまっていく。ta(曲がる量)を大きくすると神経質にうねり、sense(触角の長さ)を伸ばすと網目が粗くなる。ぼかしの後ろの 0.9 が痕跡の寿命で、1 に近づけるほど跡が消えず画面が埋まる。