ライフゲームの話とともに,ラングトンのアリも紹介されていたので実装してみた。この先生蟻コロニー最適化も本の中で紹介してるしアリ好きだな(笑)。というか本の中でアリを飼っている話が出てきていた。
1.ラングトンのアリ
詳細はWikipediaがあるので引用。平面が格子状に構成され、各マスが白または黒で塗られる。ここで、1つのマスを「アリ」とする。アリは各ステップで上下左右のいずれかのマスに移動することができる。アリは以下の規則に従って移動する。ルールが非常に単純(プログラム書くのも簡単)。なのに結構複雑な動きをする。まさに複雑系(よく理解していないケド)。
この単純な規則で驚くほど複雑な動作をする。
- 黒いマスにアリがいた場合、90°右に方向転換し、そのマスの色を反転させ、1マス前進する。
- 白いマスにアリがいた場合、90°左に方向転換し、そのマスの色を反転させ、1マス前進する。
実際の動画はこんな感じ。
ラングトンのアリやってみた。黒いマスなら色を変えて右へ,そうでなければ色を変えて左へ進む。チューリング完全なら好きな絵を描かせられるかもしれないけどどうなんだろう。 pic.twitter.com/45yYSGxoub
— TonyMooori (@TonyMooori) 2016, 1月 7
ツイートにも書いたけど,これで自由に絵がかけたら面白いんだけれどなぁ。Wikipediaには二次元チューリングマシンって書いてあるけれど,チューリング完全ってことで良いのだろうか。もし仮にそうならば,ある程度絵がかけるとは思うけど……まぁ良いや。追記
巻き戻す方向にルールを決めてやればいいだけの話でした。
2.プログラム
こちらのサイトを参考にしました。
ライフゲーム - 人工知能に関する断創録
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#coding:utf-8 | |
import pygame | |
from pygame.locals import * | |
import numpy as np | |
""" | |
参考: | |
ライフゲーム - 人工知能に関する断創録 | |
http://aidiary.hatenablog.com/entry/20080914/1281748797 | |
""" | |
# Windowの大きさ | |
SCR_RECT = Rect(0, 0, 800, 600) | |
# セルの大きさ | |
CS = 5 | |
# セルの横の数,縦の数 | |
W = SCR_RECT.width / CS | |
H = SCR_RECT.height / CS | |
class Langtons_Ant: | |
def __init__(self): | |
# 準備 | |
pygame.init()# ウィンドウを初期化 | |
screen = pygame.display.set_mode(SCR_RECT.size) # 大きさを指定 | |
pygame.display.set_caption("Langton's Ant") # タイトル | |
self.font = pygame.font.SysFont(None, 16) # フォント | |
# 変数宣言 | |
self.board = np.zeros((W,H)).astype(np.int) # ボード | |
self.x = W / 2 # 蟻のx座標 | |
self.y = H / 2 # 蟻のy座標 | |
self.vx = 1 # 蟻のx方向速度 | |
self.vy = 0 # 蟻のy方向速度 | |
self.run = True # 実行中か否か | |
self.speed = 200 # 1フレームですすめるステップ数 | |
while True: | |
# 実行中ならすすめる | |
if self.run: | |
for i in range(self.speed): | |
self.update() | |
# 描画 | |
self.draw(screen) | |
pygame.display.update() | |
for event in pygame.event.get(): | |
if event.type == QUIT: | |
pygame.quit() | |
exit(0) | |
elif event.type == KEYDOWN: | |
if event.key == K_s: # sキーで停止・再生 | |
self.run = not self.run | |
elif event.key == K_u: # uキーでスピードアップ | |
self.speed = self.speed + 1 | |
elif event.key == K_d: # dキーでスピードダウン | |
self.speed = self.speed - 1 | |
if self.speed < 0: | |
self.speed = 0 | |
def update(self): | |
""" 更新 """ | |
if self.board[self.x,self.y] == 0: | |
# 右に方向転換 | |
temp = self.vx | |
self.vx = -self.vy | |
self.vy = temp | |
else: | |
# 左に方向転換 | |
temp = self.vx | |
self.vx = self.vy | |
self.vy = -temp | |
# 色を反転 | |
self.board[self.x,self.y] = 1 - self.board[self.x,self.y] | |
# アリを移動 | |
self.x = ( self.x + self.vx ) % W | |
self.y = ( self.y + self.vy ) % H | |
def draw(self,screen): | |
""" セルの描画関数 """ | |
for x in range(W): | |
for y in range(H): | |
rect = Rect(x*CS,y*CS,CS,CS) | |
if self.board[x,y] == 1: | |
pygame.draw.rect(screen, (0,255,0), rect) | |
else: | |
pygame.draw.rect(screen, (0,0,0), rect) | |
# ゲーム情報を描画 | |
screen.blit(self.font.render("s : start/stop", True, (255,255,255)), (0,0)) | |
screen.blit(self.font.render("u : speed up", True, (255,255,255)), (0,12)) | |
screen.blit(self.font.render("d : speed down", True, (255,255,255)), (0,24)) | |
screen.blit(self.font.render("speed : " + str(self.speed) , True, (255,255,255)), (0,36)) | |
# ラングトンのアリを実行 | |
Langtons_Ant() |