--with utility; use utility; with text_io; use text_io; --with integer_io; use integer_io; procedure Life1 is --Pre: The user must supply an initial configuration of living cells. --Post: The program prints a sequence of maps showing the changes in the -- configuration of living cells according to the rules for the game -- of Life. --Uses: functions UserSaysYes, NeighborCount and procedures WriteMap, -- Initialize --{version 1} -- uses Utility; {a unit containing utility procedures, Turbo Pascal specific}--const {maxrow and maxcol are determined by the screen size} maxrow : constant := 20; --{maximum number of rows allowed} maxcol : constant := 60; --{maximum number of columns allowed} type rowrange is range 0..(maxrow+1); type colrange is range 0..(maxcol+1); -- {These ranges are increased in size to allow room for a hedge border -- around the grid. The reason for this will be explained in Section 1.4.2.} type state is (dead, alive); --{status of a cell} type grid is array(rowrange, colrange) of state; --{rectangular array} --var map: grid; --{description of the current generation} newmap: grid; --{description of the next generation} row: rowrange; col: colrange; function NeighborCount(map: in out grid; row: rowrange; col: colrange) return integer is --Pre: The pair (row, col) is a valid cell in a Life configuration. --Post: The function returns the number of living neighbors of the given cell. --var nbrrow: integer; --{row of a neighbor of the cell (row,col)} nbrcol: integer; --{column of a neighbor of the cell (row,col)} count: integer; -- {counter of living neighbors} begin -- {function NeighborCount} count := 0; -- {Use nested loops to count neighbors.} for nbrrow in (row - 1) .. (row + 1) loop for nbrcol in (col - 1) .. (col + 1) loop if (map(nbrrow,nbrcol) = alive) then count := count + 1; end if; end loop; -- col end loop; -- row if map(row,col) = alive then --Do not count the cell itself as a neighbor. count := count - 1; end if; return count; end; -- {function NeighborCount} procedure Initialize(map: in out grid; newmap: in out grid) is --Pre: None. --Post: All cells in the rectangular arrays map and newmap have been set -- to empty, also their hedges have been set to empty. The rectangular -- array map is set to the initial configuration of living cells. --var row: integer; --coordinates of a cell} col: integer; --Use integer rather than a subrange to catch user errors.} begin --{procedure Initialize} put_line("This program is a simulation of the game of Life."); put_line("The grid has a size of " & integer'image(maxrow) & " rows"); put_line("The grid has a size of " & integer'image(maxcol) & " columns"); for row in 0 .. (maxrow+1) loop for col in 0 .. (maxcol+1) loop map(row,col) := dead; --{Set all cells including the hegdes} newmap(row,col) := dead; --{to be empty.} end loop; -- col end loop; -- row put_line("On each line give a pair of coordinates for a living cell."); put_line("Terminate the list with the special pair 0 0"); get(row); get(col); while (row /= 0) or (col /= 0) loop --Check termination condition.} --begin {Check input for legality.} if (row>=1) and (row<=maxrow) and (col>=1) and (col<=maxcol) then map(row,col) := alive; else put_line("Values are not within range."); end if; get(row); get(col); end loop; -- {loop processing pair row, col} end; -- {procedure Initialize} procedure WriteMap(map: in out grid) is --Pre: The rectangular array map contains the current Life configuration. --Post: The current Life configuration is written for the user. --const full : constant character := '*'; empty: constant character := ' '; --var row: rowrange; col: colrange; begin --{procedure WriteMap} put_line("The map is below:"); for row in 0 .. (maxrow+1) loop for col in 0 .. (maxcol+1) loop if map(row,col) = alive then put(full); else put(empty); end if; end loop; -- processing column put_line(" "); end loop; -- processing row} end; -- {procedure WriteMap} function UserSaysYes return Boolean is --Pre: None. --Post: Returns true if the user responds with any response beginning with -- 'y' or 'Y', false if the user responds with any response beginning -- with 'n' or 'N'. --Uses: None. --} --var response: character; Valid: Boolean; begin --{function UserSaysYes} loop put(" (y,n)? "); Get(response); skip_line; valid := response = 'n' or response = 'N' or response = 'y' or response = 'Y'; if not valid then put_line("Please respond by typing one of the letters y or n"); end if; exit when valid; end loop; return response = 'y' or response = 'Y'; end; -- {function UserSaysYes} begin --{main program Life1} Initialize(map, newmap); --Obtain the initial configuration for map.} WriteMap(map); --Write out the initial configuration as a check.} put_line("This is the initial configration you have chosen,"); put_line("Press any key to continue. "); get( C ); loop --Begin the main loop on generations.} for row in 1 .. maxrow loop --Loop through the entire array.} for col in 1 .. maxcol loop case NeighborCount(map, row, col) is when 0|1 => newmap(row, col) := dead; --dies of loneliness} when 2 => newmap(row, col) := map(row, col); --stays the same} when 3 => newmap(row, col) := alive; --becomes alive} when 4..8=> newmap(row, col) := dead; --dies of overcrowding} end case; end loop; --col end loop; -- row map := newmap; WriteMap(map); put("Do you want to continue viewing the new generations"); --Determine if the user wishes to continue.} exit when not UserSaysYes; end loop; end; --main program Life1}