見出し画像

#01 ライフゲーム

プログラミングの勉強のため、一瞬fortranを勉強していた時に作成したものです。だいぶ前につくったものですが、面白かったので。

ライフゲームとは

1970年にケンブリッジ大のコンウェイが発明したセルオートマトン。初期条件を与えれば一定の規則で世代が進み、生と死を表すセルが更新されていく。Wikipediaわかりやすい


本を探すと以下のものくらいしか見つからなかった。気がする。
1974年にはTime誌が「ライフゲイムの大群が数百万ドルの貴重なコンピュータ時間を食ってしまっている」と苦言を呈したほど流行ったらしい。


代表的なパターン

白いセルが「生(1)」を、黒いセルが「死(0)」を表していて、初期条件を与えれば、あとは世代を追って一定規則でころころ変わる。
個人的にはたった5つの「生」でスタートして、ランダムそうな模様を展開するR pentominoが面白い。名前がついているのもまたいい。

例1 Nebula

初期条件は以下のように与える。Nebulaの例。

例1 Nebulaの初期条件

他にも例をいくつか。

例2 R pentomino
例3 Glider(周期境界条件)

ソースコード

プログラムは以下の記事を大いに参考にさせていただいています。

Fortranで実装、gnuplotで描画しました。もうgnuplotなんて全然使ってない。。
描画領域を正方形にして、初期条件を乱数ではなく、Excelで作成した init_field.txt から読み込ませてます。境界の条件はcshiftとeoshiftを使い分けて、固定境界か周期境界かを選べるようにしました。

! Conway's Game of Life

  module lifegame
      implicit none
      integer :: n
      integer, allocatable :: field( : , :  )
      integer, allocatable :: neighbors( : , :  )    
  contains

      subroutine init_field( size )
          integer, intent( in ) :: size
          integer i
          integer ios
          n = size
          allocate( field( n, n ) )
          allocate( neighbors( n, n ) )
          open(10, file="init_field.txt")
          do i=0, n
              read(10, *, iostat=ios) field
              if (ios .lt. 0) exit
          end do
          close(10)
      end subroutine init_field

      subroutine print_field()
          implicit none
          integer :: i
          do i = 1, n
            write (*, '( * ( i0, :, " " ) )' ) field( :, i )
          end do
      end subroutine print_field

      subroutine one_epoch
          implicit none
          integer :: dx, dy, i
          neighbors = 0
          do concurrent ( dx = -1 : 1, dy = -1 : 1 )
            ! 周期境界条件(cshift)
              neighbors = neighbors + cshift( cshift(field, dx, 1), dy, 2 )
            ! 固定境界条件(eoshift, 境界の外は死(0))
            ! neighbors = neighbors + eoshift( eoshift(field, dx, 0, 1), dy, 0, 2 ) 
          end do
          where( neighbors == 3 )
              field = 1
          elsewhere( neighbors == 4 )
              field = field
          elsewhere
              field = 0
          endwhere
      end subroutine one_epoch

  end module lifegame


  ! MainProgram
  program main
      use lifegame
      implicit none
      integer :: epoch, size
      integer :: i

      write( *, * ) "# size?"
      read( *, * ) size
      write( *, * ) "# epoch?"
      read( *, * ) epoch

      call init_field( size )
      call print_field

      do i = 1, epoch
          call one_epoch
          write (*, *)
          call print_field
      end do

      stop
  end program main

gifアニメの出力はgnuplotで。

reset

set term gif animate size 560, 400    # 出力をgifアニメに設定
set output "field.gif"                # 出力ファイル名

set size square
set nozeroaxis
set notics
unset colorbox

set palette grey                      # gray0 = 黒
set title font "Arial,30"
set key below

do for [n=0:1000:1] {
   plot "field.log" index n matrix with image title sprintf("generation %d", n)
}

fortran

fortranは以下の本とか読んでいました。
今ならchatgpt使って、最近のプログラムにも簡単に書き換えられるのかもと思いつつ。chatgptもいろいろ試して、記事書いてみたい。

コンパイラ

GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0


準備があればさくっとかける。どんどんかくぞ。


2023/4/12追記

調べたら記事たくさんあった!レベル違う。奥が深い。


chatgptなら、プログラムの書き換えだけじゃなくてこういう使い方もあるのか。そんなに詳しくない言語もなんとかなりそう。

この記事が気に入ったらサポートをしてみませんか?