Program GameOfLife;{INPUT,OUTPUT} { Program to play the game of Life as developed by H.L. Conway at the University of Cambridge and introduced in the "Mathematical Games" section of the October 1970 "Scientific American" magazine. SUMMARY: Life is played on a grid of squares. A given square is either occupied or empty. The program user specifies which squares are occupied initially. The game of Life program produces new generations of the matrix by applying life's laws for birth, survival, and death to the present generation. These laws are: BIRTH: An unoccupied square becomes occupied if in the preceding generation exactly three of the eight neighboring squares were occupied (squares that touch horizontally, vertically or diagonally are said to be neighboring squares). SURVIVAL: An occupied square remains occupied if in the preceding generation two or three neighboring squares were occupied. DEATH: An occupied square becomes unoccupied if in the preceding generation fewer than two or more than three neighboring squares were occupied. MODIFICATION RECORD: FEB 18, 1981 - Modified for Paascal/Z by Raymond E. Penley. - Any external routines may be obtained from the Pascal/Z Users' Group. FEB 21, 1981 - Added escape from data entry portion. } CONST {The following cursor controls work with a terminal such as the Lear Siegler ADM3A, SOROC 120, Televideo.} lf=10; (* cursor down = ctrl/J *) uparrow=11; (* cursor up = ctrl/K *) bkspce=8; (* cursor back = ctrl/H *) ff=12; (* cursor fwd = ctrl/L *) space=32; (* ASCII space *) sub=26; (* ASCII clear screen code *) esc = 27; (* ASCII escape code *) maxboardsize = 22; widthmaxboard=77; TYPE state = (dead, stable, growing); neighbor = set of 0..8; boards = packed array [1..widthmaxboard,1..maxboardsize] of char; VAR survivepopulation:neighbor; boardstate :state; newboard, oldboard :boards; j :1..maxboardsize; i :1..widthmaxboard; firsttime :boolean; numberofneighbors:0..8; alivecount, boardsize, changecount, generation, maxgeneration, boardwidth :integer; left,right, up,down, horizoffset, vertoffset :-1..+1; {$M-}{ integer mult & divd error checking OFF } {$F-}{ floating point error checking OFF } {$R-}{ range checking OFF } {$S-}{ stack checking OFF } PROCEDURE GOTOXY(X,Y:INTEGER); BEGIN IF X<0 THEN X := 0; IF X>79 THEN X := 79; IF Y<0 THEN Y := 0; IF Y>23 THEN Y := 23; WRITE( CHR(27),'=',CHR(Y+32),CHR(X+32)); END; PROCEDURE KEYIN(VAR C:CHAR); EXTERNAL; procedure clearscreen; begin write(chr(sub)); end; procedure getanimals(VAR hit: boolean); var ch, escape, up, right, rght, left, down :char; begin escape := chr(esc); up := chr(uparrow); right := chr(space); rght := chr(ff); down := chr(lf); left := chr(bkspce); hit := false; repeat KEYIN(ch); (* read(keyboard,ch); *) if ( ch=escape ) then begin ch := 'D'; hit := true; end else if ( ch=down ) then begin if ( (j+1)>boardsize ) then j := boardsize else j := j+1; gotoxy(i,j); end else if ( ch=up ) then begin if ( (j-1)<1 ) then j := 1 else j := j-1; gotoxy(i,j); end else if (ch=right) or (ch=rght) then begin if ( (i+1)>boardwidth ) then begin i := 1; if ( (j+1)>boardsize ) then j := boardsize else j := j+1; end else i := i+1; gotoxy(i,j); end else if ( ch=left ) then begin if ( (i-1)<1 ) then begin i := boardwidth; if ( (j-1)<1 ) then j := 1 else j := j-1; end else i := i-1; gotoxy(i,j); end else if ( ch='*' ) then begin write(ch); oldboard[i,j] := '*'; alivecount := alivecount+1; if ( (i+1)>widthmaxboard ) then begin i := 1; if ( (j+1)>maxboardsize ) then j := maxboardsize else j := j+1; gotoxy(i,j); end else i := i+1; end; until (ch='d') or (ch='D'); end; (* get animals *) Procedure PrintHeader; begin writeln('Generation #',generation:3, ' Population =',alivecount:3); end;{ of PrintHeader } procedure initialize; { Here is the input section. It initializes all necessary parameters and creates the initial board} label 1; const s1 = 'Please enter the '; var hit : boolean; begin 1:{ here if hit } generation := 0; If firsttime then clearscreen else gotoxy(0,0); writeln(s1, 'maximum number of generations'); write (' you would like for this game: ->'); readln(maxgeneration); write (s1, 'board width for this game: ->'); readln(boardwidth); write (s1, 'board heighth for this game: ->'); readln(boardsize); if ( boardsize>maxboardsize ) then boardsize := maxboardsize; if ( boardwidth>widthmaxboard ) then boardwidth := widthmaxboard; clearscreen; writeln; for j := 1 to boardsize do begin write(' '); for i := 1 to boardwidth do begin oldboard[i,j] := ' '; write('-'); end; if ( j1 ) then left := -1 else left := 0; if ( i1 ) then up := -1 else up := 0; if ( j0) or (vertoffset<>0)) then numberofneighbors := numberofneighbors+1; end; {The last test prevents counting a cell as a neighbor of itself. Now see which cells should be alive in the next generation.} newboard[i,j] := ' '; if ((oldboard[i,j]=' ') and (numberofneighbors = 3)) or ((oldboard[i,j] = '*') and (numberofneighbors in survivepopulation)) then begin newboard[i,j] := '*'; alivecount := alivecount +1 end; end {j loop}; end{i loop}; {of the processing of each individual cell} end; {of processboard} {$C+}{ Control-C checking ON } procedure printgeneration; { We have now completed a new generation. Print it out and copy it back into the oldboard to get ready for the next cycle} begin generation := generation +1; clearscreen; PrintHeader; for j := 1 to boardsize do begin for i := 1 to boardwidth do begin write (newboard[i,j]); {see if anything has changed during this generation} if ( newboard[i,j]<>oldboard[i,j] ) then begin changecount := changecount+1; oldboard[i,j] := newboard[i,j] end end; if ( j= maxgeneration); printresults; end; end.{Game of Life} .