forth/life.fs

38 lines
1.5 KiB
Forth
Executable File

VARIABLE STATEBLK
VARIABLE LIFEBLK
VARIABLE STATEP
\ : -ROT ROT ROT ;
: WRAPY DUP 0< IF DROP 15 THEN DUP 15 > IF DROP 0 THEN ;
: WRAPX DUP 0< IF DROP 63 THEN DUP 63 > IF DROP 0 THEN ;
: WRAP WRAPY SWAP WRAPX SWAP ;
: DECEASED? WRAP 64 * + LIFEBLK @ BLOCK + C@ BL = ;
: LIVING? DECEASED? 0= ;
: (-1,-1) 2DUP 1- SWAP 1- SWAP LIVING? 1 AND ;
: (0,-1) >R 2DUP 1- LIVING? 1 AND R> + ;
: (1,-1) >R 2DUP 1- SWAP 1+ SWAP LIVING? 1 AND R> + ;
: (-1,0) >R 2DUP SWAP 1- SWAP LIVING? 1 AND R> + ;
: (1,0) >R 2DUP SWAP 1+ SWAP LIVING? 1 AND R> + ;
: (-1,1) >R 2DUP 1+ SWAP 1- SWAP LIVING? 1 AND R> + ;
: (0,1) >R 2DUP 1+ LIVING? 1 AND R> + ;
: (1,1) >R 1+ SWAP 1+ SWAP LIVING? 1 AND R> + ;
: NEIGHBORS (-1,-1) (0,-1) (1,-1) (-1,0) (1,0) (-1,1) (0,1) (1,1) ;
: BORN? NEIGHBORS 3 = ;
: SURVIVES? 2DUP LIVING? -ROT NEIGHBORS 2 = AND ;
: LIVES? 2DUP BORN? -ROT SURVIVES? OR ;
: NEWSTATE STATEBLK @ BLOCK UPDATE STATEP ! ;
: STATE! STATEP @ C! 1 STATEP +! ;
: ALIVE [CHAR] * STATE! ;
: DEAD BL STATE! ;
: ITERATE-CELL 2DUP SWAP LIVES? IF ALIVE ELSE DEAD THEN ;
: ITERATE-ROW 0 BEGIN DUP 64 < WHILE ITERATE-CELL 1+ REPEAT DROP ;
: ITERATE-BLOCK 0 BEGIN DUP 16 < WHILE ITERATE-ROW 1+ REPEAT DROP ;
: GENERATION LIFEBLK @ STATEBLK @ LIFEBLK ! STATEBLK ! ;
: ITERATE NEWSTATE ITERATE-BLOCK GENERATION ;
: DONE? KEY [CHAR] Q = ;
: PROMPT CR ." PRESS Q TO EXIT; OTHER KEY TO CONTINUE" ;
: VIEW PAGE LIFEBLK @ LIST PROMPT ;
: LIFE BEGIN VIEW ITERATE DONE? UNTIL ;