REM From: Sam Strickland REM Newsgroups: comp.ai.alife REM Subject: Re: Life program REM Date: Fri, 24 Nov 1995 19:03:16 REM A QuickBasic LIFE Algorithm REM This algorithm is optimized to take advantage of the fact that if you are my REM neighbor, then I am also your neighbor; if you leave, we both lose one neighbor, REM and if a new person moves in next to me, my neighbor count increases by one. CLS DEFINT A-Z REM Much more efficient to use integers DIM status(25, 80), update(25, 80) FOR row = 1 TO 25 FOR column = 1 TO 80 update(row, column) = 0 NEXT NEXT REM Initialize the big unending glider generator. (See Poundstone's book, REM The Recursive Universe.) REM REM Two arrays will contain neighbor counts, plus 16 if the pertinent cell is alive. REM One array is updated each generation, based upon the information contained REM in the other one. The new array is copied into the old at the end of the update, REM in preparation for the next generation. Note that the neighbor count of each REM neighbor of a cell which changes state is incremented or decremented at the REM time the cell is drawn or blanked. Thus no counting of neighbors is necessary REM for each generation, nor is it necessary to redraw the entire array. REM REM This algorithm is based upon an article (LIFE - In the Fast Lane) in Call-A.P.P.L.E REM (volume 7, number 9), in 1984, by Sam Strickland and Sam Vass. That particular REM implementation cycled through this pattern on an Apple II at a 30 Hz generation rate REM (33 ms per generation, including display color-coded by generation). I would be REM happy to send you a copy of the article if you need it and cannot locate it. REM REM Sam M. Strickland REM update(6, 45) = 15 update(7, 42) = 15 update(7, 43) = 15 update(7, 44) = 15 update(7, 45) = 15 update(8, 33) = 15 update(8, 41) = 15 update(8, 42) = 15 update(8, 43) = 15 update(8, 44) = 15 update(8, 54) = 15 update(8, 55) = 15 update(9, 32) = 15 update(9, 34) = 15 update(9, 41) = 15 update(9, 44) = 15 update(9, 54) = 15 update(9, 55) = 15 update(10, 20) = 15 update(10, 21) = 15 update(10, 31) = 15 update(10, 35) = 15 update(10, 36) = 15 update(10, 41) = 15 update(10, 42) = 15 update(10, 43) = 15 update(10, 44) = 15 update(10, 50) = 15 update(11, 20) = 15 update(11, 21) = 15 update(11, 31) = 15 update(11, 35) = 15 update(11, 36) = 15 update(11, 42) = 15 update(11, 43) = 15 update(11, 44) = 15 update(11, 45) = 15 update(11, 50) = 15 update(12, 31) = 15 update(12, 35) = 15 update(12, 36) = 15 update(12, 45) = 15 update(13, 32) = 15 update(13, 34) = 15 update(14, 33) = 15 update(15, 42) = 15 update(15, 44) = 15 update(16, 43) = 15 update(16, 44) = 15 update(17, 43) = 15 FOR row = 6 TO 17 FOR column = 20 TO 55 status(row, column) = update(row, column) NEXT NEXT FOR row = 6 TO 17 FOR column = 20 TO 55 IF status(row, column) = 15 THEN update(row, column) = update(row, column) + 1 update(row - 1, column - 1) = update(row - 1, column - 1) + 1 update(row - 1, column) = update(row - 1, column) + 1 update(row - 1, column + 1) = update(row - 1, column + 1) + 1 update(row, column - 1) = update(row, column - 1) + 1 update(row, column + 1) = update(row, column + 1) + 1 update(row + 1, column - 1) = update(row + 1, column - 1) + 1 update(row + 1, column) = update(row + 1, column) + 1 update(row + 1, column + 1) = update(row + 1, column + 1) + 1 LOCATE row, column PRINT CHR$(2) END IF NEXT NEXT clrn = 0 REM Now for the generation loop: WHILE INKEY$ = "" clrn = clrn + 1 REM Color coded by generation IF clrn = 16 THEN clrn = 1 FOR row = 6 TO 23 FOR column = 21 TO 54 status(row, column) = update(row, column) REM Copy updated neighbor counts NEXT NEXT FOR row = 6 TO 23 FOR column = 21 TO 54 IF status(row, column) < 16 THEN IF status(row, column) = 3 THEN update(row, column) = update(row, column) + 16 update(row - 1, column - 1) = update(row - 1, column - 1) + 1 update(row - 1, column) = update(row - 1, column) + 1 update(row - 1, column + 1) = update(row - 1, column + 1) + 1 update(row, column - 1) = update(row, column - 1) + 1 update(row, column + 1) = update(row, column + 1) + 1 update(row + 1, column - 1) = update(row + 1, column - 1) + 1 update(row + 1, column) = update(row + 1, column) + 1 update(row + 1, column + 1) = update(row + 1, column + 1) + 1 LOCATE row, column COLOR clrn PRINT CHR$(2) REM Add it to the display. END IF ELSE IF status(row, column) < 18 OR status(row, column) > 19 THEN update(row, column) = update(row, column) - 16 update(row - 1, column - 1) = update(row - 1, column - 1) - 1 update(row - 1, column) = update(row - 1, column) - 1 update(row - 1, column + 1) = update(row - 1, column + 1) - 1 update(row, column - 1) = update(row, column - 1) - 1 update(row, column + 1) = update(row, column + 1) - 1 update(row + 1, column - 1) = update(row + 1, column - 1) - 1 update(row + 1, column) = update(row + 1, column) - 1 update(row + 1, column + 1) = update(row + 1, column + 1) - 1 LOCATE row, column PRINT " " REM Kill it. END IF END IF NEXT NEXT WEND END REM The Apple II version was much more efficient, since no arithmetic was used (memory REM increments and decrements, instead) and the screen buffer was modified directly, instead REM of using a PRINT statement. This is pretty fast on a 486, but you can probably appreciate REM how much faster it would be with assembly code.