(* ============================================================================== * File: GameOfLife.p * Purpose: Basic implementation of Conway's "Game of Life" * Author: Jordan Kidney ( kidney@cpsc.ucalgary.ca ) * Created on: March 25, 2006 ============================================================================== *) program GameofLife (input,output); (*----------------------- CONSTANST -------------------------------------------*) const DEAD_CELL = 0; const ALIVE_CELL = 1; const MAX_ROW = (10 + 2); (* A 1 is added to both col and row values to create *) const MAX_COL = (20 + 2); (* an empty buffer area to make checking for neighbours along the edges and corners*) type EnvType = array[1..MAX_ROW , 1..MAX_COL] of integer; (*------------------------ initEnviroment --------------------------------------- * Purpose: Initialize the enviroment to all Dead cells * Param: env - the enviroment to initalize * ---------------------------------------------------------------------------- *) procedure initEnvironment(var env : EnvType ); begin var i,j : integer; for i:=1 to MAX_ROW do for j:=1 to MAX_COL do begin env[i][j] := DEAD_CELL; end; end; { initEnvironment } (*----------------------- drawEnvironment --------------------------------------- * Purpose: Draws the given environment to the creen and waits for the user to * hit the enter key. * Param: env - the enviroment to initalize * curr_step - current step in the simulation * max_step - maximum number of steps in the simulation * ---------------------------------------------------------------------------- *) procedure drawEnvironment(var env : EnvType ; curr_step : integer ; max_step : integer ); begin var i,j : integer; var ch : char; writeln("Step : ", curr_step, " of ", max_step); (* draw a line for the top *) for i:=1 to MAX_COL do begin write("="); end; writeln(""); (* print out the environment *) for i:=2 to (MAX_ROW-1) do begin write("|"); for j:=2 to (MAX_COL-1) do begin if( env[i][j] = ALIVE_CELL ) then write("*") else write(" "); end; writeln("|"); end; (* draw a line for the bottom *) for i:=1 to MAX_COL do begin write("="); end; writeln(""); (* Pause for input from the user *) write(""); readln(ch); end; { drawEnvironment } (*----------------------- countNeighbours --------------------------------------- * Purpose: counts the number of neighbours around the given cell * Param: env - the environemnt * row - row location of cell to check * col - col location of cell to check * returns: the number of neighbours * ---------------------------------------------------------------------------- *) function countNeighbours (var env : EnvType ; row : integer ; col : integer ) : integer; begin var row_offset : array[0..8] of integer; var col_offset : array[0..8] of integer; var neb_count : integer; var i : integer; neb_count := 0; (* hard code the values for the offsets used to check the neighbours *) row_offset[0]:= 0; col_offset[0]:=-1; row_offset[1]:=-1; col_offset[1]:=-1; row_offset[2]:=-1; col_offset[2]:= 0; row_offset[3]:=-1; col_offset[3]:= 1; row_offset[4]:= 0; col_offset[4]:= 1; row_offset[5]:= 1; col_offset[5]:= 1; row_offset[6]:= 1; col_offset[6]:= 0; row_offset[7]:= 1; col_offset[7]:=-1; (* now count the neighbours *) for i:=0 to 7 do begin if ( env[row + row_offset[i]][ col + col_offset[i]] = ALIVE_CELL ) then neb_count := neb_count + 1; end; countNeighbours := neb_count; end; { countNeighbours } (*------------------------ copyEnviroment --------------------------------------- * Purpose: copy environment information from src to dest * Param: dest - destination environment to pu tinfo into * src - source environment to get information from * ---------------------------------------------------------------------------- *) procedure copyEnvironment(var dest : EnvType ; var src : EnvType ); begin var i,j : integer; for i:=1 to MAX_ROW do for j:=1 to MAX_COL do begin dest[i][j] := src[i][j]; end; end; { initEnvironment } (*----------------------- step --------------------------------------------------- * Purpose: Make one step in the simulation * Param: env - the environment to step forwards * ------------------------------------------------------------------------------ *) procedure step (var env : EnvType); begin var env_tmp : EnvType; var neb_count : integer; var i : integer; var j : integer; initEnvironment(env_tmp); (* go through the enviroment appling the rules *) for i:=2 to (MAX_ROW-1) do for j:=2 to (MAX_COL-1) do begin neb_count := countNeighbours (env,i,j); if(env[i][j] = ALIVE_CELL) then begin if( neb_count < 2 ) then env_tmp[i][j] := DEAD_CELL else if ( neb_count > 3 ) then env_tmp[i][j] := DEAD_CELL else env_tmp[i][j] := env[i][j]; end else if( (env[i][j] = DEAD_CELL) and (neb_count = 3) ) then env_tmp[i][j] := ALIVE_CELL; end; (* copy results back into the original array *) copyEnvironment(env,env_tmp); end; { step } (*----------------------- readInt ------------------------------------------------- * Purpose: reads in an int from the user and makes sure it is with range * Param: Message - the message to display out to the user * low - the lowest value in the range * high - the highest value in the range * Return: the integer entered by the user * ------------------------------------------------------------------------------ *) function readInt(Message : string; low: integer; high: integer ): integer; begin var val : integer; var EndLoop : boolean; (* Used as a flag to end loops for error checking *) EndLoop := false; repeat write(Message,' (between ',low,' and ',high,'): '); readln(val); if ( (val < low) or (val > high) ) then writeln('Error: The number is not within the proper range') else EndLoop := true until EndLoop = true; readInt := val; end; { readInt } (*----------------------- randomInit ------------------------------------------------ * Purpose: randomly distributes alive cells in the world * Param: env - the environment to put alive cells in * num_alive - the number of cells to place in the environment * ------------------------------------------------------------------------------ *) procedure randomInit(var env : EnvType; num_alive : integer ); begin var i : integer; var row : integer; var col : integer; for i:=0 to num_alive do begin row := 2 + random(MAX_ROW-3); col := 2 + random(MAX_COL-3); env[row][col] := ALIVE_CELL; end; end; (* ========================== MAIN ============================================== *) begin var environment : EnvType; var num_alive : Integer; var num_steps : Integer; var i : integer; initEnvironment(environment); (* read in information from the user *) num_alive := readInt('Number of alive cells', 1, 150); num_steps := readInt('Number of steps', 1, 1000); randomInit(environment, num_alive); for i:=0 to num_steps do begin drawEnvironment(environment,i, num_steps); step(environment); end; writeln("Done."); end. (* ============================================================================== *)