|
| 1 | +# Conway's Game of Life |
| 2 | + |
| 3 | +This example implements the famous [Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) devised by British mathematician [John Conway](https://en.wikipedia.org/wiki/John_Horton_Conway). |
| 4 | + |
| 5 | +It is an example of a *zero-player game*, where after setting initial rules the simulation plays out algorithmically on its own without need for human intervention. |
| 6 | + |
| 7 | +The original game as devised by Conway was for pen and gridded paper. Starting with any combination of cells in the grid either filled in (alive) or not (dead), the following rules were applied: |
| 8 | + |
| 9 | +1. Any live cell with 2-3 neighbors survives |
| 10 | +2. Any dead cell with exactly 3 neighbors becomes alive |
| 11 | +3. All other cells die or stay dead |
| 12 | + |
| 13 | +There are now hundreds of implementations in many programming languages. The game of life is an example of [cellular automata](https://en.wikipedia.org/wiki/Cellular_automaton). Techniques are explored in a variety of applicatons including game design, studying [biology](https://en.wikipedia.org/wiki/Cellular_automaton#Biology), chemistry, physics, music, and computer science. |
| 14 | + |
| 15 | +This program implements a basic version of the simulation. Press space bar to begin. You can click on individual cells to toggle their state, or draw directly on the grid. Pressing 'r' resets and pauses the game. |
| 16 | + |
| 17 | + |
| 18 | + |
| 19 | +```lua |
| 20 | +require("L5") |
| 21 | + |
| 22 | +-- Conway's Game of Life in L5 |
| 23 | +-- Click to toggle cells, press SPACE to pause/unpause, press R to reset |
| 24 | + |
| 25 | +local cols, rows |
| 26 | +local cellSize = 10 |
| 27 | +local grid = {} |
| 28 | +local nextGrid = {} |
| 29 | +local paused = true |
| 30 | + |
| 31 | +function setup() |
| 32 | + size(800, 600) |
| 33 | + windowTitle("Conway's Game of Life") |
| 34 | + frameRate(10) |
| 35 | + |
| 36 | + -- Calculate grid dimensions |
| 37 | + cols = floor(width / cellSize) |
| 38 | + rows = floor(height / cellSize) |
| 39 | + |
| 40 | + -- Initialize grids |
| 41 | + initGrid() |
| 42 | + |
| 43 | + describe("Conway's Game of Life. Click to toggle cells. Press SPACE to start/pause. Press R to reset.") |
| 44 | +end |
| 45 | + |
| 46 | +function initGrid() |
| 47 | + -- Create empty grids |
| 48 | + for i = 1, cols do |
| 49 | + grid[i] = {} |
| 50 | + nextGrid[i] = {} |
| 51 | + for j = 1, rows do |
| 52 | + grid[i][j] = 0 |
| 53 | + nextGrid[i][j] = 0 |
| 54 | + end |
| 55 | + end |
| 56 | + |
| 57 | + -- Add initial random cells |
| 58 | + for i = 1, cols do |
| 59 | + for j = 1, rows do |
| 60 | + if random(1) < 0.2 then |
| 61 | + grid[i][j] = 1 |
| 62 | + end |
| 63 | + end |
| 64 | + end |
| 65 | +end |
| 66 | + |
| 67 | +function draw() |
| 68 | + background(20) |
| 69 | + |
| 70 | + -- Draw grid |
| 71 | + for i = 1, cols do |
| 72 | + for j = 1, rows do |
| 73 | + local x = (i - 1) * cellSize |
| 74 | + local y = (j - 1) * cellSize |
| 75 | + |
| 76 | + if grid[i][j] == 1 then |
| 77 | + fill(255) |
| 78 | + else |
| 79 | + fill(50) |
| 80 | + end |
| 81 | + |
| 82 | + stroke(30) |
| 83 | + strokeWeight(1) |
| 84 | + rect(x, y, cellSize, cellSize) |
| 85 | + end |
| 86 | + end |
| 87 | + |
| 88 | + -- Update grid if not paused |
| 89 | + if not paused then |
| 90 | + computeNextGeneration() |
| 91 | + end |
| 92 | + |
| 93 | + -- Draw status text |
| 94 | + fill(255) |
| 95 | + noStroke() |
| 96 | + textSize(16) |
| 97 | + textAlign(LEFT, TOP) |
| 98 | + local status = paused and "PAUSED - Press SPACE to start" or "RUNNING - Press SPACE to pause" |
| 99 | + text(status, 10, 10) |
| 100 | + text("Click to toggle cells | Press R to reset", 10, 30) |
| 101 | +end |
| 102 | + |
| 103 | +function keyPressed() |
| 104 | + -- Toggle pause with spacebar |
| 105 | + if key == 'space' then |
| 106 | + paused = not paused |
| 107 | + end |
| 108 | + |
| 109 | + -- Reset with R |
| 110 | + if key == 'r' then |
| 111 | + initGrid() |
| 112 | + paused = true |
| 113 | + end |
| 114 | +end |
| 115 | + |
| 116 | +function computeNextGeneration() |
| 117 | + -- Calculate next generation |
| 118 | + for i = 1, cols do |
| 119 | + for j = 1, rows do |
| 120 | + local neighbors = countNeighbors(i, j) |
| 121 | + |
| 122 | + -- Conway's rules: |
| 123 | + -- 1. Any live cell with 2-3 neighbors survives |
| 124 | + -- 2. Any dead cell with exactly 3 neighbors becomes alive |
| 125 | + -- 3. All other cells die or stay dead |
| 126 | + |
| 127 | + if grid[i][j] == 1 then |
| 128 | + -- Cell is alive |
| 129 | + if neighbors == 2 or neighbors == 3 then |
| 130 | + nextGrid[i][j] = 1 |
| 131 | + else |
| 132 | + nextGrid[i][j] = 0 |
| 133 | + end |
| 134 | + else |
| 135 | + -- Cell is dead |
| 136 | + if neighbors == 3 then |
| 137 | + nextGrid[i][j] = 1 |
| 138 | + else |
| 139 | + nextGrid[i][j] = 0 |
| 140 | + end |
| 141 | + end |
| 142 | + end |
| 143 | + end |
| 144 | + |
| 145 | + -- Copy next generation to current grid |
| 146 | + for i = 1, cols do |
| 147 | + for j = 1, rows do |
| 148 | + grid[i][j] = nextGrid[i][j] |
| 149 | + end |
| 150 | + end |
| 151 | +end |
| 152 | + |
| 153 | +function countNeighbors(x, y) |
| 154 | + local count = 0 |
| 155 | + |
| 156 | + -- Check all 8 neighbors |
| 157 | + for i = -1, 1 do |
| 158 | + for j = -1, 1 do |
| 159 | + -- Skip the center cell |
| 160 | + if not (i == 0 and j == 0) then |
| 161 | + -- Wrap around edges (toroidal topology) |
| 162 | + local col = ((x - 1 + i) % cols) + 1 |
| 163 | + local row = ((y - 1 + j) % rows) + 1 |
| 164 | + |
| 165 | + count = count + grid[col][row] |
| 166 | + end |
| 167 | + end |
| 168 | + end |
| 169 | + |
| 170 | + return count |
| 171 | +end |
| 172 | + |
| 173 | +function mousePressed() |
| 174 | + -- Toggle cell on click |
| 175 | + local col = floor(mouseX / cellSize) + 1 |
| 176 | + local row = floor(mouseY / cellSize) + 1 |
| 177 | + |
| 178 | + if col >= 1 and col <= cols and row >= 1 and row <= rows then |
| 179 | + if grid[col][row] == 0 then |
| 180 | + grid[col][row] = 1 |
| 181 | + else |
| 182 | + grid[col][row] = 0 |
| 183 | + end |
| 184 | + end |
| 185 | +end |
| 186 | + |
| 187 | +function mouseDragged() |
| 188 | + -- Allow drawing by dragging |
| 189 | + local col = floor(mouseX / cellSize) + 1 |
| 190 | + local row = floor(mouseY / cellSize) + 1 |
| 191 | + |
| 192 | + if col >= 1 and col <= cols and row >= 1 and row <= rows then |
| 193 | + grid[col][row] = 1 |
| 194 | + end |
| 195 | +end |
| 196 | +``` |
| 197 | + |
| 198 | +## Related References |
| 199 | + |
| 200 | +* [if](/reference/if) |
| 201 | +* [for](/reference/for) |
| 202 | +* [function](/reference/function) |
| 203 | +* [local](/reference/local) |
| 204 | +* [mouseDragged()](/reference/mouseDragged) |
0 commit comments