DAPPLE Example: life

Source code:

// life -- parallel, 2-dimensional, cellular automaton. // according to the rules of the game of life. // written using the Data-Parallel Programming Library for Education (DAPPLE) // // Each cell in the array is either occupied or not. At each iteration // (generation), every cell counts its neighbors. This is done for all // cells in parallel. Then, simple rules determine which cells are occupied // in the next generation. After each generation we map the array to a // character array, and print it. Boundaries are assumed to have unoccupied // neighbors off the edge, rather than cyclic boundary conditions. // // The initial state is kinda boring. // // David Kotz 1994 // $Id: life.cc,v 2.13 94/09/29 12:18:04 dfk Exp $ #include #include #include "dapple.h" const int N = 10; const int ITERATIONS = 5; // which VP am I? useful for VP-specific math const intVector VP(N, Identity); // which row or column am I? useful for VP-specific math const intMatrix VProw(N, N, IdentityR); const intMatrix VPcol(N, N, IdentityC); int mapchar(const int c) { // map it to something printable return (c == 0 ? '.' : 'O'); } int main(int argc, char **argv) { // 1 means life there, 0 means nothing // so this initializes a 2x3 square in the center, to 1s, the rest 0s intMatrix cells( (VProw >= N/2-1 && VProw <= N/2+1) && (VPcol >= N/2-1 && VPcol <= N/2+1)); intMatrix neighbors(N,N); cells[6][_] = 1; // and fill a solid row cells[_][6] = 1; // and fill a full column cout << "Initial:" << endl; cout << charMatrix(apply(mapchar, cells)) << endl; // note that because we use shift(), we assume boundaries of 0 // if we used rotate, we would get periodic boundary conditions (torus) for (int i = 0; i < ITERATIONS; i++) { neighbors = ( shift(cells, 0, -1) + shift(cells, 0, 1) + shift(cells, -1, -1) + shift(cells, -1, 0) + shift(cells, -1, 1) + shift(cells, 1, -1) + shift(cells, 1, 0) + shift(cells, 1, 1)); // cout << "neighbors:" << endl; // cout << neighbors << endl; // The Rules: // If an organism has 0 or 1 neighbors, it dies of loneliness. // If an organism has 2 or 3 neighbors, it survives. // If an organism has 4 or more neighbors, it dies of overcrowding. // If an empty cell has exactly 3 neighbors, a new organism is born. ifp (neighbors != 2) ifp (neighbors == 3) cells = 1; // either existing survives, or new is born else cells = 0; // either lonely or overcrowded else ; // no change with two neighbors cout << "Generation " << i+1 << endl; cout << charMatrix(apply(mapchar, cells)) << endl; } return(0); }

Demonstration:

life Initial: ......O... ......O... ......O... ......O... ....OOO... ....OOO... OOOOOOOOOO ......O... ......O... ......O... Generation 1 .......... .....OOO.. .....OOO.. ......OO.. ....O..O.. .OO.....O. .OOO....O. .OOOO...O. .....OOO.. .......... Generation 2 ......O... .....O.O.. ........O. ........O. ......OOO. .O.....OO. O...O..OOO .O..OOO.O. ..OOOOOO.. ......O... Generation 3 ......O... ......OO.. .......OO. ........OO ......O..O .......... OO..O....O .OO......O ..OO...... ...OO.OO.. Generation 4 ......OO.. ......O.O. ......O..O .........O ........OO .......... OOO....... O......... .O..O..... ..OOO..... Generation 5 ......OO.. .....OO.O. .......OOO .........O ........OO .O........ OO........ O.O....... .OO.O..... ..OOO.....