Skip to content

Instantly share code, notes, and snippets.

@sobels
Created October 20, 2014 20:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sobels/aa7ee8271f3ceda2ea75 to your computer and use it in GitHub Desktop.
Save sobels/aa7ee8271f3ceda2ea75 to your computer and use it in GitHub Desktop.
Conway's Game of Life, using D metaprogramming
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