game_of_life.ecal 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. Conway's Game of Life
  3. A zero-player game that evolves based on its initial state.
  4. https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
  5. Some examples:
  6. grid := [ # Normally evolving
  7. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  8. [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ],
  9. [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
  10. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  11. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  12. [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ],
  13. [ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ],
  14. [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ],
  15. [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
  16. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
  17. ]
  18. grid := [ # Blinker oscillator
  19. [ 0, 0, 0, 0, 0 ],
  20. [ 0, 0, 1, 0, 0 ],
  21. [ 0, 0, 1, 0, 0 ],
  22. [ 0, 0, 1, 0, 0 ],
  23. [ 0, 0, 0, 0, 0 ],
  24. ]
  25. grid := [ # Still life
  26. [ 0, 0, 0, 0, 0, 0 ],
  27. [ 0, 0, 1, 1, 0, 0 ],
  28. [ 0, 1, 0, 0, 1, 0 ],
  29. [ 0, 0, 1, 1, 0, 0 ],
  30. [ 0, 0, 0, 0, 0, 0 ],
  31. ]
  32. grid := [ # Glider spaceship
  33. [ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],
  34. [ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 ],
  35. [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],
  36. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  37. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  38. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  39. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  40. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  41. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  42. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
  43. ]
  44. */
  45. grid := [ # Penta-decathlon oscillator
  46. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  47. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  48. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  49. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  50. [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
  51. [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
  52. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
  53. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
  54. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
  55. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ]
  56. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
  57. [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
  58. [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
  59. [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
  60. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  61. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  62. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  63. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  64. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
  65. [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
  66. ]
  67. /*
  68. output displays a given grid.
  69. */
  70. func output(grid) {
  71. for row in grid {
  72. displayRow := []
  73. for i in row {
  74. if i == 0 {
  75. i := ' '
  76. } else {
  77. i := '*'
  78. }
  79. displayRow := add(displayRow, i)
  80. }
  81. log("{{displayRow}}")
  82. }
  83. }
  84. /*
  85. newGrid allocates a new grid.
  86. */
  87. func newGrid() {
  88. result := []
  89. for row in range(0, len(grid)-1) {
  90. newrow := []
  91. for col in range(0, len(grid[0])-1) {
  92. newrow := add(newrow, 0)
  93. }
  94. result := add(result, newrow)
  95. }
  96. return result
  97. }
  98. /*
  99. compareGrids compares two grids and returns a delta of differences.
  100. */
  101. func compareGrids(g1, g2) {
  102. delta := 0
  103. for row in range(0, len(grid)-1) {
  104. for col in range(0, len(grid[0])-1) {
  105. if g1[row][col] != g2[row][col] {
  106. delta := delta + 1
  107. }
  108. }
  109. }
  110. return delta
  111. }
  112. /*
  113. nextGen calculates the next generation for a given grid.
  114. */
  115. func nextGen() {
  116. future := newGrid()
  117. for row in range(0, len(grid)-1) {
  118. for col in range(0, len(grid[0])-1) {
  119. # Finding number of neighbours that are alive
  120. aliveNeighbours := 0
  121. for i in range(-1, 1) {
  122. for j in range(-1, 1) {
  123. try {
  124. aliveNeighbours := aliveNeighbours + grid[row + i][col + j]
  125. } except {
  126. # Don't care about out of bounds errors
  127. }
  128. }
  129. }
  130. # Subtract the cell itself if alive
  131. aliveNeighbours := aliveNeighbours - grid[row][col];
  132. # Apply the rules
  133. if grid[row][col] == 1 and aliveNeighbours < 2 {
  134. # Cell is lonely and dies
  135. } elif grid[row][col] == 1 and aliveNeighbours > 3 {
  136. # Cell dies due to over population
  137. } elif grid[row][col] == 0 and aliveNeighbours == 3 {
  138. # A new cell is born
  139. future[row][col] := 1
  140. } else {
  141. # Unchanged
  142. future[row][col] := grid[row][col]
  143. }
  144. # log("row: {{row}} col: {{col}} val: {{grid[row][col]}} aliveNeighbours:{{aliveNeighbours}} -> {{future[row][col]}}")
  145. }
  146. }
  147. return future
  148. }
  149. output(grid)
  150. # Evolve the grid for 33 generations
  151. for i in range(1, 33) {
  152. next := nextGen()
  153. delta := compareGrids(grid, next)
  154. if delta == 0 {
  155. delta := "0 (still life)"
  156. }
  157. log("Gen: {{i}} - delta {{delta}}")
  158. output(next)
  159. grid := next
  160. }