Created
October 20, 2014 20:41
-
-
Save sobels/aa7ee8271f3ceda2ea75 to your computer and use it in GitHub Desktop.
Conway's Game of Life, using D metaprogramming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
enum height = 5; | |
enum width = 5; | |
enum iterations = 20; | |
enum initialState = [ | |
0, 1, 0, 1, 1, | |
0, 0, 0, 0, 1, | |
1, 1, 0, 0, 0, | |
1, 1, 1, 1, 1, | |
0, 0, 0, 0, 0 | |
]; | |
// Returns the cell at state[i, j]. Here i is the row and j is the column. This function returns 0 for out of bounds values. | |
auto at(State)(State state, size_t i, size_t j) { | |
if(i >= height) { | |
return 0; | |
} | |
if(j >= width) { | |
return 0; | |
} | |
return state[i*width + j]; | |
} | |
// Returns the number of alive cells surrounding the cell at state[i, j]. | |
uint alive(State)(State state, size_t i, size_t j) { | |
//This loop assumes that if i-1 or j-1 underflows, the result is out of bounds. Ergo, we need to assert this condition | |
static assert(width < size_t.max); | |
static assert(height < size_t.max); | |
uint sum = 0; | |
for(int m = -1; m < 2; m++) { | |
for(int n = -1; n < 2; n++) { | |
if(m == 0 && n == 0) { | |
continue; | |
} | |
sum += state.at(i+m, j+n); | |
} | |
} | |
return sum; | |
} | |
// Returns the next state for the cell at state[i, j]. | |
auto transfer(State)(State state, size_t i, size_t j) { | |
auto liveNeighbors = state.alive(i, j); | |
if(state.at(i, j) == 1) { | |
if(liveNeighbors < 2 || liveNeighbors > 3) { | |
return 0; | |
} | |
return 1; | |
} else { | |
if(liveNeighbors == 3) { | |
return 1; | |
} | |
return 0; | |
} | |
} | |
// Returns the next game state. | |
auto nextState(State)(State state) { | |
State next; | |
next.length = state.length; | |
for(size_t i = 0; i < height; i++) { | |
for(size_t j = 0; j < width; j++) { | |
next[i*width + j] = state.transfer(i, j); | |
} | |
} | |
return next; | |
} | |
void printBoard(State)(State state) { | |
import std.stdio; | |
for(size_t i = 0; i < height; i++) { | |
state[i*width..(i+1)*width].writeln; | |
} | |
} | |
template game(alias seed, int generations) { | |
static if(generations == 0) { | |
enum game = [seed]; | |
} else { | |
enum game = [seed] ~ game!(seed.nextState(), generations - 1); | |
} | |
} | |
void main() { | |
import std.stdio; | |
enum computedGame = game!(initialState, iterations); // Computed at compile-time | |
// pragma(msg, computedGame); // Uncomment this line to see the computed game in your terminal on compilation | |
foreach(state; computedGame) { | |
state.printBoard(); | |
"".writeln(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment