#define CURSES 0
#include <stdio.h>
#include <stdlib.h>
#if CURSES
#include <curses.h>
#endif
#include "simple.h"
#define LIFE_GRID 20 // Defines the width x height of the arrays used.
//#define N 5 // Defines the number of generations the program should simulate.
int N;
typedef int byte;
#define TRUE 1
#define FALSE 0
#define LASTROW (my_rank == (LIFE_GRID-1))
#define FIRSTROW (my_rank == 0)
void load_init (unsigned int, byte[LIFE_GRID][LIFE_GRID]);
// Function to setup initial generation.
void step_generation (byte [], int);
// Function to move forward one generation.
void print_grid (byte [LIFE_GRID][LIFE_GRID]);
// Function to print the array.
int neighbors ();
// Function to figure the number of neighbors for a given cell.
void copy_array ();
// Function to copy the contents of one array to another.
byte grid[LIFE_GRID][LIFE_GRID];
int main (int argc, char *argv[])
{
byte *myrow;
// byte grid[LIFE_GRID][LIFE_GRID];
int i;
unsigned int seed; // Holds the user entered seed for the random number generator.
int my_rank, p;
Init (&argc, &argv);
my_rank = GetRank ();
myrow = &grid[my_rank][0];
p = GetSize ();
if (p != LIFE_GRID )
{
if (my_rank == 0)
{
fprintf (stderr, "Wrong number of processes.\nUse -np %d\n", LIFE_GRID );
}
Finalize ();
exit (1);
}
if (argc != 3)
{
if (my_rank == 0)
{
fprintf (stderr,
"Input number of generations and seed\nUse %s <no.gen.> <seed>\n",
argv[0]);
}
Finalize ();
exit (2);
}
// Get a unsigned int from the user and use it to seed the random number generator.
if (0 == my_rank)
{
sscanf (argv[1],"%u", &N);
sscanf (argv[2],"%u", &seed);
// Print a message to the screen and run load_init to setup the initial generation.
printf ("\nGenerating initial grid...\n");
load_init (seed, grid);
}
else
{
Recv (INT, myrow, LIFE_GRID, 0);
}
Bcast(INT,&N,1,0);
// Loop to cycle through the different generations.
for (i = 1; i <= N; i++)
{
step_generation (myrow, my_rank); // Call step_generation to generate the next generation.
if(my_rank != 0) Send (INT, myrow, LIFE_GRID, 0);
Barrier();
if (0==my_rank)
{
#if CURSES
sleep(1);
move (0, 0);
printw ("\nGeneration: %i\n\n", i); // Print the generation number on the screen.
#else
printf ("\nGeneration: %i\n\n", i); // Print the generation number on the screen.
#endif
print_grid (grid); // Call print_grid to display the contents of the array.
}
Barrier();
}
#if CURSES
if (0 == my_rank)
{
sleep(3);
endwin();
printf("\nDone.\n");
}
#endif
Finalize ();
return 0;
}
/*
* load_init() is passed the address of an array of characters. It moves through
* each cell in the array, based on a random number provided by the rand() function
* it places a * or a space in the given cell of the array.
*/
void load_init (unsigned int seed, byte grid[LIFE_GRID][LIFE_GRID])
{
int y, x, z;
byte cell;
srand (seed);
#if CURSES
initscr();
printw ("\nGeneration: %i\n\n", 0); // Print the generation number on the screen.
#else
printf ("\nGeneration: %i\n\n", 0); // Print the generation number on the screen.
#endif
#if CURSES
// Print column numbers left to right.
printw (" ");
for (x = 0; x < LIFE_GRID; x++)
printw ("%i ", x);
printw ("\n");
#endif
for (y = 0; y < LIFE_GRID; y++)
{
#if CURSES
printw ("%i ", y);
#endif
for (x = 0; x < LIFE_GRID; x++)
{
z = (int) (10.0 * rand () / RAND_MAX + 1.0); // Generates a random number between 0 and 10.
if (z < 5)
grid[y][x] = FALSE;
else
grid[y][x] = TRUE;
#if CURSES
printw("%d ",grid[y][x]);
#else
printf("%d ",grid[y][x]);
#endif
}
if (y>0)
{
Send (INT, &grid[y][0], LIFE_GRID, y );
}
#if CURSES
printw("\n");
#else
printf("\n");
#endif
}
#if CURSES
refresh();
sleep(1);
#endif
}
/*
* step_generation() is passed the address of an array of characters. It also sets
* up an array of the exact same size as the one whose address was passed. The
* function moves through each cell in the array, calling neighbors() to get
* the number of neighbors the current cell has. Based on the data from neighbors()
* and the rules of Life, it either places a * or space in the corresponding cell
* of the second array. Once the function has finished, it calls copy_array() to
* copy the contents of the second array into the first array.
*/
void step_generation (byte *myrow, int my_rank)
{
int x, i;
byte *prevrow, *nextrow, newrow[LIFE_GRID];
prevrow = myrow - LIFE_GRID;
nextrow = myrow + LIFE_GRID;
if (!FIRSTROW)
{
// printf("Process %d sending info to process %d\n",my_rank,my_rank-1);
Send (INT, myrow, LIFE_GRID, my_rank - 1);
// printf("Process %d sent info to process %d\n",my_rank,my_rank-1);
Recv (INT, prevrow, LIFE_GRID, my_rank - 1);
// printf("Process %d received info from process %d\n",my_rank,my_rank-1);
}
if (!LASTROW)
{
// printf("Process %d sending info to process %d\n",my_rank,my_rank+1);
Send (INT, myrow, LIFE_GRID, my_rank + 1);
// printf("Process %d sent info to process %d\n",my_rank,my_rank+1);
Recv (INT, nextrow, LIFE_GRID, my_rank + 1);
// printf("Process %d received info from process %d\n",my_rank,my_rank+1);
}
// now, count the neighbors
for(i=0; i < LIFE_GRID; i++)
{
x = 0;
if (!FIRSTROW)
{
if(i!=0) x+=prevrow[i-1];
x+=prevrow[i];
if(i!=LIFE_GRID-1) x+=prevrow[i+1];
}
if (!LASTROW)
{
if(i!=0) x+=nextrow[i-1];
x+=nextrow[i];
if(i!=LIFE_GRID-1) x+=nextrow[i+1];
}
if(i!=0) x+=myrow[i-1];
if(i!=LIFE_GRID-1) x+=myrow[i+1];
if (myrow[i] == TRUE) // If the cell has an organism in it now.
{
if ((x == 2) || (x == 3))
newrow[i] = TRUE;
else
newrow[i] = FALSE;
}
else // If the cell is empty.
{
if (x == 3)
newrow[i] = TRUE;
else
newrow[i] = FALSE;
}
// printf("%d, %d, %d, %d\n", my_rank, i, x, newrow[i]);
}
for(i=0; i < LIFE_GRID; i++) myrow[i] = newrow[i];
}
/*
* print_grid() is passed the address of an array of characters. It moves through this
* array printing each character to the display. It also prints cell numbers across the
* top, and along the left side of the output.
*/
void print_grid (byte grid[LIFE_GRID][LIFE_GRID])
{
int y, x;
byte cell;
#if CURSES
#define PRINT printw
#else
#define PRINT printf
#endif
// Print column numbers left to right.
PRINT (" ");
for (x = 0; x < LIFE_GRID; x++)
PRINT ("%i ", x);
PRINT ("\n");
// Print a row number and the contens of that row.
for (y = 0; y < LIFE_GRID; y++)
{
PRINT ("%i ", y);
if (y > 0) Recv (INT, &grid[y][0],LIFE_GRID, y);
for (x = 0; x < LIFE_GRID; x++)
{
if (grid[y][x] == TRUE)
PRINT ("* ");
else
PRINT (" ");
}
PRINT ("\n");
}
#if CURSES
refresh();
#endif
}