こんにちはマイコン制御

May FORTH be with you.

ラングトンのアリ

  • 引き続きLÖVEで遊んでいます。
  • いろんな言語をとっかえひっかえ試しては形にならずに放置していましたが、取りあえず今回はこのLÖVEとLuaで前にQB64で大雑把に作ったシーケンサーの骨組みから完成させるまで作ってみようと自分に課しました。
    • なんか、今の自分にとっては出来る事とやりたい事とやるべき事のバランスがLÖVEだとちょうどいい感じがします。
    • 作りたいのはテノリオン+グルーヴ地獄Vみたいなの。
      • そこはDEPTHにしておけよ、という話もありますが。
  • まあでも最初は公式Wikiチュートリアルを写経するわけです。
    • 写経ついでにちょっとアレンジしたりして勉強するのが速いですよね。下みたいに点を打つついでに動かしてみるとか。
  • 写経だけっていうのも飽きてきて、そろそろゼロから何か書こうかということで、目標アプリではテノリオンみたいな感じにしたいので取りあえずみんな大好きライフゲームでも、と思ったんですが、ふと思いついて同じセル・オートマトンでもラングトンのアリを書くことにしました。簡単だし。
  • それでやってみたらサクッと書けました。まだこのレベルならLuaとLÖVEで引っかかることは無いですね。配列が1始まりなのが変わっているくらい?
    • 途中までライフゲーム作るつもりだったので効率が悪いコードですが、Luaに慣れるためなので、まあいいでしょうということで。
    • 上のWikipediaの画像はかなり早回しで、これを1セルずつの書き換えにすると非常にかったるいので20倍速にしました。

f:id:SenjiNiban:20161010161307j:plain

  • Wikiを見るとセルの色でのバリエーションが研究されているみたいだけど、アリの歩く幅を色々変化せてみたりしました。
    • 向きによって歩く幅が違うようにしつつ、縦横での一定の比率にするとか、ある一方向だけ他の方向と違う歩幅にするとか。
  • で、やってみた結果
    • 縦横の歩幅の比が整数の場合はオリジナルと同じような挙動の場合が多いようです。
    • 縦横比が整数でない場合、一方向だけ異なる値の場合、はパターンを描きながら直進するパターンが多いようです。
      • ただし、どういう理屈でそうなるのか判らないのですが、突如後戻りしたり曲がりだしたりするので油断がならない。
      • そうとう大きいフィールドを作らないと詳しく調べられないので、このプログラムでは探索に限界がありそう。
    • 全くのランダム、カオスなパターンというのは今のところは出てきてません。
  • オリジナルのパターンでも10000ステップ超えたあたりで必ず直進パターンに移行するとか、直進開始後に適切なパターンに衝突すると巻き戻しが起こるとか、ライフゲームに負けず劣らず面白い挙動をするラングトンのアリですが、バリエーションも探すと色々面白そう。

f:id:SenjiNiban:20161010164852j:plain
f:id:SenjiNiban:20161010164905j:plain

  • 見てて面白かったパターンのソースを晒してみます。LÖVE0.10.1なら動くはず。
    • 最初見ていて予想するのとは違う展開になると思います。
    • Web上でも動きますがかなり遅いので100倍速にしています。
--ラングトンのアリ・バリエーション 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