PROGRAM LIFE (INPUT,OUTPUT); (* FLORIAN MATTHES 10.9.1986 *) (* THE GAME OF LIF OF J.H. CONWAY *) (* AUF EINEM RECHTECKIGEN FELD ENTWICKELN SICH ZELLGRUP- *) (* PEN VON GENERATION ZU GENERATION NACH FOLGENDEN REGELN:*) (* 1. EINE ZELLE KANN NUR BELEGT ODER UNBELEGT SEIN. *) (* 2. UEBERLEBEN: EINE BELEGTE ZELLE UEBERLEBT ZUR *) (* NAECHSTEN GENERATION, WENN ZWEI ODER DREI DER AN- *) (* GRENZENDEN NACHBARZELLEN EBENFALLS BELEGT SIND. *) (* 3. TOD: EINE BELEGTE ZELLE WIRD WIEDER FREI, WENN MEHR *) (* ALS DREI ODER WENIGER ALS ZWEI ANGRENZENDE ZELLEN *) (* BELEGT SIND. *) (* 4. GEBURT: EINE UNBELEGTE ZELLE IST IN DER FOLGENDEN *) (* GENERATION BELEGT, FALLS GENAU DREI DER BENACHBARTEN*) (* ZELLEN BELEGT SIND. *) CONST CLEARWINDOW = #147; BOARDWIDTH = 30; BOARDHEIGHT = 20; EMPTY = " "; X = 5; (* POSITION HINWEISE *) Y = 21; (* = BOARDHEIGHT + 1 *) TYPE TCELL = 0..1; TROW = ARRAY [0..BOARDWIDTH] OF TCELL; VAR BOARD : ARRAY [0..BOARDHEIGHT] OF TROW; QUIT : BOOLEAN; PROCEDURE SHOWCELL(I,J:INTEGER; CELL: TCELL); (* ZEICHNE ZELLE IN ZEILE I, SPALTE J MIT INHALT CELL AN. *) BEGIN DISPLAY(1,J,I," ",CELL); END; (* SHOWCELL *) PROCEDURE CLEARBOARD; VAR I,J:INTEGER; BEGIN FOR I:= 0 TO BOARDHEIGHT DO FOR J:=0 TO BOARDWIDTH DO BOARD[I,J]:=0; END; (* CLEARBOARD *) PROCEDURE EDITBOARD(VAR STOP: BOOLEAN); (* ERLAUBE BENUTZEREINGABEN VON DER TASTATUR ODER MIT DEM *) (* JOYSTICK. AENDERE BOARD (GLOBAL). STOP=TRUE, FALLS *) (* BENUTZER PROGRAMMENDE WAEHLT *) VAR X,Y,J: INTEGER; LEAVE: BOOLEAN; CH : CHAR; BEGIN X:= BOARDWIDTH DIV 2; Y:= BOARDHEIGHT DIV 2; (* MITTE *) LEAVE:= FALSE; REPEAT DISPLAY(1,X,Y,"X",BOARD[Y,X]); (* INVERS ODER NORMAL *) REPEAT J:= JOY(2); GETKEY(CH); UNTIL ORD(CH)+J<>0; SHOWCELL(Y,X, BOARD[Y,X]); (* ZELLE ANZEIGEN *) IF (J>=128) OR (CH=' ') THEN (* PUNKT INVERTIEREN *) BOARD[Y,X]:= 1 - BOARD[Y,X]; IF (J IN [8,1,2]) OR (CH = #145) THEN (* NACH OBEN *) IF Y=0 THEN Y:= BOARDHEIGHT ELSE Y:= Y-1; IF (J IN [2,3,4]) OR (CH = #29 ) THEN (* NACH RECHTS *) X:= (X+1) MOD (BOARDWIDTH+1); IF (J IN [4,5,6]) OR (CH = #17 ) THEN (* NACH UNTEN *) Y:= (Y+1) MOD (BOARDHEIGHT+1); IF (J IN [6,7,8]) OR (CH = #157) THEN (* NACH LINKS *) IF X=0 THEN X:= BOARDWIDTH ELSE X:= X-1; CASE CH OF #3:(* RUN/STOP-TASTE *) BEGIN LEAVE:=TRUE; QUIT:= TRUE END; #13:(* RETURN-TASTE *) BEGIN LEAVE:=TRUE; QUIT:= FALSE END; ELSE (* LEER, ALSO KEIN 'NO LABEL IN CASE ERROR' *) END; (* CASE *) UNTIL LEAVE; END; (* EDITBOARD *) PROCEDURE CALCULATEBOARD; (* BERECHNE GESAMTES FELD NEU, ZEIGE NUR DIE FELDER AN, *) (* DIE IHREN INHALT SEIT DER LETZTEN GENERATION VERAENDERT*) (* HABEN. DAS BRETT IST ZYKLISCH ORGANISIERT: ZELLEN IN *) (* DER ERSTEN REIHE SIND NACHBARN DER ZELLEN IN DER UNTER-*) (* STEN REIHE, ZELLEN IN DER ERSTEN SPALTE SIND NACHBARN *) (* DER ZELLEN IN DER LETZTEN SPALTE. *) VAR NEXTOLDROW, OLDROW, R0: TROW; I : INTEGER; PROCEDURE CALCULATEROW (VAR PR, R, NR: TROW; I: INTEGER); (* BELEGE ZEILE I NACH DEN LIFE-REGELN NEU. *) (* PR (PREVIOUS ROW) UND NR (NEXT ROW) ENTHALTEN DIE *) (* ALTE OBERE UND UNTERE ZEILE. R ENTHAELT DIE AKTUELLE *) (* ZEILE. DIE BERECNUNG ERFOLGT NACH FOLGENDEM PRINZIP: *) (* BERECHNE SUMME DREIER UEBEREINANDERLIEGENDER FELDER. *) (* DIE SUMME DREIER SOLCHER NEBENEINANDERLIEGENDER *) (* SPALTEN LIEFERT DIE SUMME ALLER NACHBARFELDER DES *) (* FELDES R[J]. BEIM DURCHLAUFEN DER ZEILE WIRD JEWEILS *) (* NUR EINE SUMME (SUMR) NEU BERECHNET, WAEHREND DIE *) (* BEIDEN ANDEREN SUMMEN NUR 'NACH LINKS' GESCHOBEN *) (* WERDEN. *) VAR SUM0,SUML,SUM,SUMR,TOTAL: INTEGER; J : INTEGER; BEGIN SUML:= PR[BOARDWIDTH] + R[BOARDWIDTH] + NR[BOARDWIDTH]; SUM := PR[0] + R[0] + NR[0]; SUM0:= SUM; FOR J:= 0 TO BOARDWIDTH DO BEGIN IF J=BOARDWIDTH THEN SUMR:= SUM0 ELSE SUMR:= PR[J+1] + R[J+1] + NR[J+1]; TOTAL:= SUML + SUM + SUMR; (* INCL. ZELLE R[J] ! *) IF R[J]=0 THEN BEGIN IF TOTAL=3 THEN (* NEUEN PUNKT SETZEN *) BEGIN SHOWCELL(I,J,1); R[J]:=1 END; END ELSE IF (TOTAL<3) OR (TOTAL>4) THEN (* LOESCHEN *) BEGIN SHOWCELL(I,J,0); R[J]:=0 END; SUML:=SUM; SUM:=SUMR; END; END; (* CALCULATE ROW *) BEGIN R0 := BOARD[0]; OLDROW:= BOARD[BOARDHEIGHT]; FOR I:= 0 TO BOARDHEIGHT-1 DO BEGIN NEXTOLDROW:= BOARD[I]; CALCULATEROW(OLDROW,BOARD[I],BOARD[I+1],I); OLDROW:= NEXTOLDROW; END; CALCULATEROW(OLDROW,BOARD[BOARDHEIGHT],R0,BOARDHEIGHT); END; (* CALCULATE BOARD *) BEGIN WRITE(CLEARWINDOW); IF RWINDOW(2)=80 THEN (* 80 ZEICHENMODUS AKTIV *) BEGIN WINDOW(20,0,60,24); FAST END; CLEARBOARD; REPEAT DISPLAY(1,X,Y ,"BEWEGUNG MIT CURSOR/JOYSTICK",1); DISPLAY(1,X,Y+1,"SPACE : PUNKT SETZEN-LOESCHEN",1); DISPLAY(1,X,Y+2,"RETURN: ENDE, STOP: -->BASIC",1); EDITBOARD(QUIT); DISPLAY(1,X,Y ,EMPTY); (* LOESCHE TEXTE *) DISPLAY(1,X,Y+1,EMPTY); (* FUER EDITIEREN *) IF NOT QUIT THEN REPEAT CALCULATEBOARD UNTIL KEYPRESSED OR (JOY(2)<>0); UNTIL QUIT; WRITE(#19,#19,CLEARWINDOW); END.