game_of_life.ecal 4.8 KB

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