ラングトンのアリ
- 引き続きLÖVEで遊んでいます。
- いろんな言語をとっかえひっかえ試しては形にならずに放置していましたが、取りあえず今回はこのLÖVEとLuaで前にQB64で大雑把に作ったシーケンサーの骨組みから完成させるまで作ってみようと自分に課しました。
- まあでも最初は公式Wikiのチュートリアルを写経するわけです。
- 写経ついでにちょっとアレンジしたりして勉強するのが速いですよね。下みたいに点を打つついでに動かしてみるとか。
- 写経だけっていうのも飽きてきて、そろそろゼロから何か書こうかということで、目標アプリではテノリオンみたいな感じにしたいので取りあえずみんな大好きライフゲームでも、と思ったんですが、ふと思いついて同じセル・オートマトンでもラングトンのアリを書くことにしました。簡単だし。
- それでやってみたらサクッと書けました。まだこのレベルならLuaとLÖVEで引っかかることは無いですね。配列が1始まりなのが変わっているくらい?
- Wikiを見るとセルの色でのバリエーションが研究されているみたいだけど、アリの歩く幅を色々変化せてみたりしました。
- 向きによって歩く幅が違うようにしつつ、縦横での一定の比率にするとか、ある一方向だけ他の方向と違う歩幅にするとか。
- で、やってみた結果
- 縦横の歩幅の比が整数の場合はオリジナルと同じような挙動の場合が多いようです。
- 縦横比が整数でない場合、一方向だけ異なる値の場合、はパターンを描きながら直進するパターンが多いようです。
- ただし、どういう理屈でそうなるのか判らないのですが、突如後戻りしたり曲がりだしたりするので油断がならない。
- そうとう大きいフィールドを作らないと詳しく調べられないので、このプログラムでは探索に限界がありそう。
- 全くのランダム、カオスなパターンというのは今のところは出てきてません。
- オリジナルのパターンでも10000ステップ超えたあたりで必ず直進パターンに移行するとか、直進開始後に適切なパターンに衝突すると巻き戻しが起こるとか、ライフゲームに負けず劣らず面白い挙動をするラングトンのアリですが、バリエーションも探すと色々面白そう。
- 見てて面白かったパターンのソースを晒してみます。LÖVE0.10.1なら動くはず。
- 最初見ていて予想するのとは違う展開になると思います。
- Web上でも動きますがかなり遅いので100倍速にしています。
- 本当は必要なところだけ画面を書き換えればいいんだよな。
- http://lovefiddle.com/FHFYFHgN3b44GiC9s
--ラングトンのアリ・バリエーション for LÖVE0.10.1 function love.load() -- width = 198 height = 148 -- ant = {} ant.x = width / 2 ant.y = height / 2 ant.direction = 1 -- map = {} for i=1, width do map[i] = {} for j=1, height do map[i][j] = 0 end end end function love.update() for i=1, 20 do if map[ant.x][ant.y] == 0 then map[ant.x][ant.y] = 1 ant.direction = ant.direction + 1 if ant.direction > 4 then ant.direction = 1 end next_pos(ant.direction) else map[ant.x][ant.y] = 0 ant.direction = ant.direction - 1 if ant.direction < 1 then ant.direction = 4 end next_pos(ant.direction) end end end function love.draw() for x=1, width do for y=1, height do if map[x][y] == 0 then love.graphics.rectangle("line", x * 4, y * 4, 4, 4) else love.graphics.rectangle("fill", x * 4, y * 4, 4, 4) end end end end function next_pos(a) -- if a == 1 then ant.x = ant.x - 2 elseif a == 2 then ant.y = ant.y + 1 elseif a == 3 then ant.x = ant.x + 1 elseif a == 4 then ant.y = ant.y - 1 end -- if ant.x < 1 then ant.x = width end if ant.x > width then ant.x = 1 end if ant.y < 1 then ant.y = height end if ant.y > height then ant.y = 1 end end