3. ライフゲームモデルの作成

3.1. ライフゲームの準備

ライフゲームは次のようなルールで組み立てられます。

  1. 四角格子空間にエージェント(以下、セルと呼びます)を隙間なく並べる

  2. 各セルは生と死という2つの状態をとる

  3. 各セルは(チェビシェフ距離で)周囲の8セルの状態に応じて、自分の状態を変える

    • 生きているセルは、周囲のセルのうち2個または3個が生きていれば生き続けるが、それ以外の場合は死ぬ

    • 死んでいるセルは、周囲のセルのうち3個が生きているときのみ生きる状態になる(誕生する)が 、それ以外の場合は死んだまま

それではモデルを作成していきます。
まず、Universeの下に空間fieldをつくります。空間種別を四角格子空間にし、大きさは25×25にしておきます。その他の設定はデフォルトのままにします。
そして空間fieldの下にエージェントcellをつくってください。cellの下にはセルの色を指定するための変数colorを追加します。また、次の状態を保存するための変数next_colorと周りのエージェントを格納しておく変数neighborsも追加しておきましょう。さらに、Universe直下の変数としてall_cellも作成してください。
次にマップ出力の設定に移ります。罫線表示はチェス型にし、cellのエージェント表示色は「変数指定」を選び、colorを選択してください。エージェントのマーカーは「四角」を選択しておくと見た目がきれいです。

これで準備は完了です。

3.2. ルールを作成する

ライフゲームがどんな動きになるかは初期状態(各セルの生と死)によって決まります。ここでは初期状態をランダムに決めます。
初期状態を決めるuniv_initのルールは以下のようになります。

def univ_init(self):
    for x in range(25):
        for y in range(25):
            one = create_agt(Universe.field.cell)
            one.x = x
            one.y = y
            # 0.2の確率で「生」になるように初期設定
            if rand() < 0.2:
                one.color = COLOR_CYAN
                one.next_color = COLOR_CYAN
            else:
                one.color = COLOR_WHITE
                one.next_color = COLOR_WHITE
    # 全てのセルの集合をall_cellに代入 
    self.all_cell = make_agtset()
    # 全てのセルについて隣接するセルの集合をneighborsに代入
    for one in self.all_cell:
        one.neighbors = one.make_agtset_around_own_sqgrid(1, False)

続いて、エージェントのルールを書きましょう。各cellエージェントは周囲のcellの状態を見て自分の状態を決めるため、前のページで学んだ、状態の変更を保存しておきステップの最後で一斉に変更する方法を使います。

def agt_step(self):
    if count_step() > 1: # 初期状態もマップ出力されるように2ステップ目から状態が変わるようにする
        alive = 0 # 生きているセルをカウントするための変数
        for one in self.neighbors:
            if one.color == COLOR_CYAN:
                alive += 1
        if self.color == COLOR_CYAN: # 自分が生きている場合
            if alive == 2 or alive == 3:
                self.next_color = COLOR_CYAN # 生きたまま
            else:
                self.next_color = COLOR_WHITE # 死ぬ
        else: # 1期前に自分が死んでいる場合
            if alive == 3:
                self.next_color = COLOR_CYAN # 生き返る
            else:
                self.next_color = COLOR_WHITE # 死んだまま

最後に、univ_step_endに状態を置き換えるルールを追加します。

def univ_step_end(self):
    for one in self.all_cell:
        one.color = one.next_color

これでライフゲームは完成です。モデルを実行して人工生命の様々な動きを楽しんでみてください。生と死という2つのみの状態による単純なルールですが、何度再生しても毎回違った動きを楽しめることでしょう。

../../_images/tutorial3-3.gif

何度か実行してみると、すべてのセルが死んでしまう場合、生きているセルはあるけれど動きがなくなってしまう場合といった状態が現れるかと思います。
各ステップの最後にすべてのセルについて1ステップ前の状態と現在の状態が等しければ、もうそれ以上変化が起こることはありません。
このような場合に自動でシミュレーションを停止させるためにルールを修正しましょう。

def univ_step_end(self):
    if count_step() > 1:
        stop = True
        for one in self.all_cell:
            # stopがTrueかつ、colorとnext_colorが異なる色ならstopはFalseに変更
            if stop and one.color != one.next_color:
                stop = False
            one.color = one.next_color
        if stop:
            print(count_step(), "ステップで終了しました。")
            exit_simulation() # シミュレーションを終了

上記のルールでは、エージェントのcolorを置き換える前にcolorとnext_colorが同じかどうかを調べます。もし1つでも直前と状態が異なるセルが見つかれば、stopにFalseを代入してシミュレーションを続行します。全てのセルでcolorとnext_colorが同じであればstopはTrueとなりシミュレーションは停止します。
if count_step() > 1:としたのは、このモデルではセルのnext_colorを2ステップ目以降変更しており、1ステップ目では必ずcolorとnext_colorが等しくなってシミュレーションが止まってしまうからです。
今回はシミュレーション終了条件とcolorの置き換えのルールを同じfor文の中で書きました。このような工夫をすることで、不必要にエージェントを調べたりforループを回したりということはなるべく避けるように心がけましょう。ルールが長くなればなるほど、調べるエージェントが多くなればなるほど、シミュレーションの実行は遅くなってしまいます。

これで第3部は終了です。ライフゲームは大変有名なモデルですが、artisoc Cloudではたったこれだけのルールで作成することができます。ライフゲームには興味深い動きをする有名なモデルがありますので、初期値を変えてそのようなモデルを再現してみるのも面白いかもしれません。

3.3. 参考

この章のサンプルモデルは次の通りです。

チュートリアル3-3(ライフゲーム)