Lab 1: C Warm-up Assignment
Due: Wednesday, Jan 25 before 1 am (late Tuesday night)

This, and all, lab assignments should be done with a partner. See the Wed lab page for information about how you can set up a git repository for your joint lab 1 project.

Lab 1 Partners
  Katherine Bertaut and Ames Bielenberg   Nick Felt and Chloe Stevens
  Steven Hwang and Jordan Singleton   Phil Koonce and Sam White
  Luis Ramirez and Kyle Erf   Niels Verosky and Elliot Weiser

Contents:

Problem Introduction
Implementation Details
Requirements
Useful C and Unix Functions
What to Hand in

Introduction

This lab is designed to give you some practice with writing and debugging C programs. In particular, you will use the following in your solution to this lab:
  1. writing a program in several modules (.c files and .h files with shared definitions)
  2. C-style pass by reference
  3. using the different parts of memory (globals, locals, and heap)
  4. C scoping (using static and extern)
  5. using a makefile
  6. parsing command line arguments
  7. C file I/O
  8. using gdb and valgrind to debug your program

Sequential Game of Life

For this lab, you will implement a program that plays Conway's Game of Life. Conway's Game of Life is an example of discrete event simulation, where a world of entities live, die, or are born based based on their surrounding neighbors. Each time step simulates another round of living or dying.

Your world is represented by a 2-D array of values (0 or 1). If a grid cell's value is 1, it represents a live object, if it is 0 a dead object. At each discrete time step, every cell in the 2-D grid gets a new value based on the current value of its eight neighbors:

  1. A live cell with zero or one live neighbors dies from loneliness.
  2. A live cell with four or more live neighbors dies due to overpopulation.
  3. A dead cell with exactly three live neighbors becomes alive.

Your 2-D world should be a TORUS; every cell in the grid has exactly eight neighbors. In the torus world, cells on the edge of the grid have neighbors that wrap around to the opposite edge. For example, the grid locations marked with an 'x' are the eight neighbors of the grid cell whose value is shown as 1.

x  1  x  0  0  0  0
x  x  x  0  0  0  0
0  0  0  0  0  0  0
0  0  0  0  0  0  0
0  0  0  0  0  0  0
0  0  0  0  0  0  0
x  x  x  0  0  0  0
Conway's Game of Life description from Wikipedia, shows some example patterns you can use to test the correctness of your solution (like Blinker, Toad or Beacon).

Your program will take a number of command line options for initializing the game playing variables (dimensions of the grid, number of iterations, how to initialize the grid), and other options to print out the grid as the computation proceeds or write result to an output file.

In addition, you will add timing code to your program to time the GOL computation (not including the initialization or output phases).

Getting Started

Start by creating a git repository for you and your partner's lab1 solution.

If you'd like, you could use the C code from Wednesday's lab as the starting point for your lab1 solution (you should rename files, wipe out most of their contents, and change the Makefile of course):

cp ~newhall/public/cs87/lab1/* .

Implementation Details

Your solution should use support multiple command line arguments that specify how to initialize the game variables, including the the size of the board, the number of time steps, and the initial configuration of the board (use getopt to parse command line arguments.) Your program should work for any size game board, thus the board should be dynamically allocated using malloc based on its M and N dimension values read in from a file or given as command line arguments.

Command line options

The following are the set of command lines your program must support:
    ./gol {-n n -m m -n k [-s] | -f infile} [-x] [-o outfile] 
       -n  n:      number of rows in the game board
       -m  m:      number of columns in the game board
       -k  k:      number of iterations
       -s:         initialize to oscillator board (default is random)
       -f infile:  read in all board config info from a file
       -x:         don't print board out after every iteration
       -o outfile: print result board to output file
       -h:         print out this help message
You may additionally add other command line options to initialize the game board to other pre-set patterns ([-s | -b | ... ]).

The command line options specify how to initialize the game and how to run the simulation.

There are two ways to initialize the game:

  1. The -f command line option means that the GOL problem size and initial state are read in from a file:
    ./gol -f startfile1           # initialize to values read in from a file
    
  2. or the -n -m -k [-s] command line options are used to specifying the dimensions, number of iterations, and the starting point world initial configuration:
    ./gol -n 20 -m 30 -k 100 -s   # initialize 20x30 board to an oscillator pattern
    ./gol -n 20 -m 30 -k 100      # initialize 20x30 board to a random pattern
                                  # setting about 25% of randomly selected 
                                  # cells to 1 works well, but you can decide
    
These two modes are independent---you cannot have a command line with both the -f and -m options.

The -x and -o outfile options are optional and work with either initialization mode. The -x option is useful for running timing tests of different sized problems of the sequential version of GOL (we may use this later in the semester). Here are some example command lines:

# initialize 20x30 board to an oscillator pattern, output final
# board to a file named "outfile" in the same format as the infile format
./gol -n 20 -m 30 -k 100 -s  -o outfile

# initialize program from data read in from "infile" and output the final
# board to a file named "outfile" in the same format as the infile format
./gol -f infile -o outfile

# init from a file and do not print any output to stdout for this run
./gol -f infile -x  
Your program should handle badly formed command lines (e.g. print out an error message and exit instead of using incompatible or incomplete command line options).

File Format

The input (and ouput) file format consists of several lines of an ascii file. The first three lines give the dimensions and number of iterations, the fourth line has a number of coordinate pairs followed by the lines with i j coordinate values specifying grid cells that should be set to 1 (all others should be 0):
num rows
num cols
num iterations
num of following coordinate pairs (set each (i, j) value to 1
i j
i j 
...
For example, this is an interesting pattern that will start in lower left and walk up to upper right of grid:
30
30
100
5
29 1
28 2
27 0
27 1
27 2
A good way to check if your output file is correct is to try to use it as an input file to a subsequent run.

Computing Values at Each time step

One problem you will need to solve is how to update each grid cell value at each time step. Because each grid cell's value is based on its neighbor's current value, you cannot update each cell's new value in place (otherwise its neighbors will read the new value and not the current value in computing their new value).

Requirements

Useful C and Unix Utilities


Example output

Here is an example of what you might see from different runs. The first shows just the start and end board configuration from a run that is initialized to a very simple oscillator pattern, and the second is the same configuration, but run with -x (notice the time difference between the two):
# a run with output:
$ gol -n 11 -m 11 -k 21 -s

start board:

- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - @ @ @ - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 

end board:

- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - @ - - - - - 
- - - - - @ - - - - - 
- - - - - @ - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 
- - - - - - - - - - - 

total time for 21 iterations of 11x11 is 5.493663 secs

# a run with no output (-x) measures just the gol 
computation (not the printfs):
$  gol -n 11 -m 11 -k 21 -s -x
total time for 21 iterations of 11x11 is 1.001186 secs

What to Hand in

Submit a single tar file with the following contents using
cs87handin (see Unix Tools for more information on script, dos2unix, make, and tar):

  1. A README file with:
    1. Your name and your partner's name
    2. If you have not fully implemented some functionality, then list the parts that work (and how to test them if it is not obvious) so that you can be sure to receive credit for the parts you do have working.

  2. All the source files needed to compile, run and test your code (Makefile, .c files, .h files, and optional test scripts). Please do not submit object (.o) or executable files (I can build these using your Makefile).