123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- /*
- Conway's Game of Life
- A zero-player game that evolves based on its initial state.
- https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
- Some examples:
- grid := [ # Normally evolving
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- ]
- grid := [ # Blinker oscillator
- [ 0, 0, 0, 0, 0 ],
- [ 0, 0, 1, 0, 0 ],
- [ 0, 0, 1, 0, 0 ],
- [ 0, 0, 1, 0, 0 ],
- [ 0, 0, 0, 0, 0 ],
- ]
- grid := [ # Still life
- [ 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 1, 1, 0, 0 ],
- [ 0, 1, 0, 0, 1, 0 ],
- [ 0, 0, 1, 1, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0 ],
- ]
- grid := [ # Glider spaceship
- [ 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 1, 1, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- ]
- */
- grid := [ # Penta-decathlon oscillator
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ]
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
- [ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ],
- [ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
- ]
- /*
- output displays a given grid.
- */
- func output(grid) {
- for row in grid {
- displayRow := []
- for i in row {
- if i == 0 {
- i := ' '
- } else {
- i := '*'
- }
- displayRow := add(displayRow, i)
- }
- log("{{displayRow}}")
- }
- }
- /*
- newGrid allocates a new grid.
- */
- func newGrid() {
- result := []
- for row in range(0, len(grid)-1) {
- newrow := []
- for col in range(0, len(grid[0])-1) {
- newrow := add(newrow, 0)
- }
- result := add(result, newrow)
- }
- return result
- }
- /*
- compareGrids compares two grids and returns a delta of differences.
- */
- func compareGrids(g1, g2) {
- delta := 0
- for row in range(0, len(grid)-1) {
- for col in range(0, len(grid[0])-1) {
- if g1[row][col] != g2[row][col] {
- delta := delta + 1
- }
- }
- }
- return delta
- }
- /*
- nextGen calculates the next generation for a given grid.
- */
- func nextGen() {
- future := newGrid()
- for row in range(0, len(grid)-1) {
- for col in range(0, len(grid[0])-1) {
- # Finding number of neighbours that are alive
-
- aliveNeighbours := 0
- for i in range(-1, 1) {
- for j in range(-1, 1) {
- try {
- aliveNeighbours := aliveNeighbours + grid[row + i][col + j]
- } except {
- # Don't care about out of bounds errors
- }
- }
- }
- # Subtract the cell itself if alive
- aliveNeighbours := aliveNeighbours - grid[row][col];
- # Apply the rules
- if grid[row][col] == 1 and aliveNeighbours < 2 {
- # Cell is lonely and dies
- } elif grid[row][col] == 1 and aliveNeighbours > 3 {
- # Cell dies due to over population
- } elif grid[row][col] == 0 and aliveNeighbours == 3 {
- # A new cell is born
- future[row][col] := 1
- } else {
- # Unchanged
- future[row][col] := grid[row][col]
- }
- # log("row: {{row}} col: {{col}} val: {{grid[row][col]}} aliveNeighbours:{{aliveNeighbours}} -> {{future[row][col]}}")
- }
- }
- return future
- }
- output(grid)
- # Evolve the grid for 33 generations
- for i in range(1, 33) {
- next := nextGen()
-
- delta := compareGrids(grid, next)
- if delta == 0 {
- delta := "0 (still life)"
- }
-
- log("Gen: {{i}} - delta {{delta}}")
-
- output(next)
- grid := next
- }
|