DECLARE SUB printhelp () DECLARE SUB printstartupgrid () DECLARE SUB randomisegrid () DECLARE SUB processCLAs () REM *********************************************************************** REM * QBasic ANT HIGHWAY for DOS v1.1 23/05/2002 (c)Robin Upton * REM *********************************************************************** REM * This program is hereby placed in the public domain. You may adapt & * REM * improve it as you see fit, provided it is not used for commercial * REM * benefit without my agreement and provided that acknowledgement of * REM * the source is given. * REM * Contact me: ant@robinupton.com * REM *********************************************************************** REM * Ant Highway Investigators may be interested in the following: * REM * ------------------------------------------------------------ * REM * * REM * Scientific American, September 1989, 124-127. * REM * Journal of Statistical Physics, 67, (1992), 289-302. * REM * Mathematical Intelligencer, 15 vol. 2, (1993), 54-55. * REM * Mathematical Intelligencer, 16 vol. 1, (1994), 37-42. * REM * Mathematical Intelligencer, 17 vol. 3, (1995), 48-56. * REM * * REM *********************************************************************** DECLARE FUNCTION Getcolour% (cx AS INTEGER, cy AS INTEGER) DECLARE FUNCTION Getgridcell% (gx AS INTEGER, gy AS INTEGER) DECLARE SUB Incrementgridcell (gx AS INTEGER, gy AS INTEGER) DECLARE SUB centrescreen () DECLARE SUB checkforpattern () DECLARE SUB clearscreen () DECLARE SUB initialise () DECLARE SUB moveant () DECLARE SUB moveonant () DECLARE SUB outputtodisk () DECLARE SUB printant () DECLARE SUB printcell (px AS INTEGER, py AS INTEGER) DECLARE SUB printclock () DECLARE SUB printcounter () DECLARE SUB printcredits () DECLARE SUB printgrid () DECLARE SUB printstartupgrid () DECLARE SUB randomisegrid () REM ************************************************************************ REM ************************** SETUP DEFAULTS HERE ************************* REM ************************************************************************ DIM SHARED initstartupstring AS STRING DIM SHARED graphicsmode AS STRING DIM SHARED printabove AS LONG DIM SHARED screensavermode AS INTEGER DIM SHARED fastmode AS INTEGER DIM SHARED patternaborton AS INTEGER DIM SHARED saveabove AS LONG DIM SHARED datestyle AS STRING DIM SHARED cputype AS STRING DIM SHARED outfile AS STRING DIM SHARED colormode AS STRING DIM SHARED beepon AS INTEGER REM ************************************************************************ REM ******************************* ADJUST HERE **************************** REM ************************************************************************ CONST xgridsize = 360 'Should be a multiple of 3! CONST ygridsize = 360 'Should be a multiple of 3! 'Note that this is limited to 180 in some QBASIC compiilers, 'following the restriction of having no variable more than 64K. '(Hence the idea of having an array in 9 pieces :) REM ************************************************************************ REM ************************************************************************ REM ************************************************************************ DIM SHARED startupstring AS STRING, gfxmode AS STRING DIM SHARED xorigin, yorigin, x AS INTEGER, y AS INTEGER DIM SHARED gridabort, patternabort, userabort AS INTEGER DIM SHARED printon, direction, mono, cgrad, mycolour(15), nocolours AS INTEGER DIM SHARED lastx(2), lasty(2), lastdirection(2) AS INTEGER DIM SHARED xscreensize, yscreensize, xpixels, ypixels, screenres AS INTEGER DIM SHARED xdim, ydim, startxdim, startydim AS INTEGER DIM SHARED counter AS LONG, wasstable, stablebefore AS INTEGER DIM SHARED thirdofxgridsize, thirdofygridsize AS INTEGER DIM SHARED twothirdsofxgridsize, twothirdsofygridsize AS INTEGER DIM SHARED printfreq AS INTEGER ' ****************************** DEFINE THE STARTUP VARIABLES ******** initstartupstring = "" '<=Amend here to load in a particular grid. graphicsmode = "VGA" 'Choice of {MONO, CGA, EGA, VGA, NULL} printabove = 0 'Minimum length of grids that get displayed. screensavermode = 1 'Stops on a keypress fastmode = 1 'Whether it runs by itself. Keys: C, T, M, Q. patternaborton = 1 'Whether it restarts if it goes into a loop. saveabove = 99999 'Minimum length of grids that get saved. datestyle = "UK" 'Choice of {UK,US} cputype = "other" 'Choice of {8086,8088,186,286,386,486,other} outfile = "antgrids.txt" 'Where the grids are saved. colormode = "TOGGLE" ' beepon = 0 'Whether it beeps on new screen ' ********************* PROGRAM PROPER BEYOND THIS POINT **** processCLAs initialise WHILE (1 = 1) REM *********** RESTART HERE ************* wasstable = 0 stablebefore = 0 gridabort = 0 patternabort = 0 userabort = 0 direction = 0 counter = 0 printon = 1 - SGN(printabove) x = xgridsize / 2 y = screenres * (INT(ygridsize / (2 * screenres))) xdim = startxdim ydim = startydim IF (gfxmode$ = "MONO" OR colormode = "MONO") THEN mono = 1 ELSE IF colormode = "COLOR" THEN mono = 0 ELSE mono = INT(RND * 2) END IF END IF REM ********************************************* REM * None of these is > 64k... Kludge or what? * REM ********************************************* REDIM SHARED grid0(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid1(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid2(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid3(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid4(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid5(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid6(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid7(thirdofxgridsize, thirdofygridsize) REDIM SHARED grid8(thirdofxgridsize, thirdofygridsize) randomisegrid IF (gfxmode$ <> "NULL") THEN centrescreen clearscreen printclock printstartupgrid END IF WHILE (userabort + gridabort + patternabort = 0) REM ************ LOOP HERE ************* IF screensavermode = 1 THEN IF INKEY$ <> "" THEN SYSTEM REM *********** direction = (direction + 5 - 2 * (Getgridcell(x, y) MOD 2)) MOD 4 counter = counter + 1 IF (gfxmode$ <> "NULL") THEN IF (printon = 1) THEN IF (x - xorigin < 1 OR x - xorigin > xdim OR y - yorigin < screenres OR y - yorigin > ydim) THEN IF (gfxmode$ = "EGA" OR gfxmode$ = "VGA") THEN IF (x - xorigin <= 1 OR x - xorigin >= xdim) THEN xdim = 10 + INT(1.3 * xdim) ELSE ydim = 10 + INT(1.3 * ydim) END IF END IF centrescreen SELECT CASE colormode CASE "COLOR" mono = 0 CASE "MONO" mono = 1 CASE "TOGGLE" mono = 1 - mono END SELECT printgrid END IF printant printcounter IF ((counter AND printfreq) = printfreq) THEN printclock ELSE IF (counter AND printfreq) = printfreq THEN printcounter IF counter > printabove THEN printon = 1 centrescreen END IF END IF END IF END IF IF fastmode = 0 THEN DO printclock junk$ = INKEY$ SELECT CASE junk$ CASE "C", "c" IF mono = 1 THEN mono = 0 printgrid END IF CASE "M", "m" IF mono = 0 THEN mono = 1 printgrid END IF CASE "T", "t" mono = 1 - mono printgrid CASE "Q", "q" userabort = 1 CASE "R", "r" fastmode = 1 CASE CHR$(27) SYSTEM END SELECT LOOP UNTIL (junk$ <> "" AND junk$ <> "T" AND junk$ <> "t" AND junk$ <> "c" AND junk$ <> "C" AND junk$ <> "M" AND junk$ <> "m") END IF moveant WEND IF beepon = 1 THEN BEEP outputtodisk WEND SUB centrescreen xorigin = INT(x - xdim / 2) yorigin = INT(2 * INT((y - ydim / 2) / 2)) END SUB SUB checkforpattern IF lastdirection(1) = direction THEN IF lastdirection(2) = direction THEN REM * The directions all match so it may be stable. IF (lastx(1) * 2 = lastx(2) + x AND lasty(1) * 2 = lasty(2) + y) THEN REM * Stable pattern has emerged - check it's travelling at the right speed. xvector = (x - lastx(1)) / 2 yvector = (y - lasty(1)) / 2 LOCATE 3, 3 IF (xvector = -1 OR xvector = 1) AND (yvector = -1 OR yvector = 1) THEN patternabort = 1 i1 = 2 REM * Look across & back to the first empty cell WHILE (Getgridcell(x - xvector * i1, y - 2 * yvector) > 0) i1 = i1 + 1 WEND i2 = 2 REM * Look up & back to the first empty cell WHILE (Getgridcell(x - 2 * xvector, y - yvector * i2) > 0) i2 = i2 + 1 WEND IF (i1 + i2 <> 16) THEN patternabort = 0 REM * Look for a crash on back & across edge j = 0 WHILE (patternabort = 1 AND x + xvector * (j - i1) > 0 AND x + xvector * (j - i1) < 3 * thirdofxgridsize AND y + yvector * (j - 2) > 0 AND y + yvector * (j - 2) < 3 * thirdofygridsize) j = j + 1 IF (Getgridcell(x + xvector * (j - i1), y + yvector * (j - 2)) > 0) THEN patternabort = 0 WEND REM * Look for a crash on up & back edge j = 0 WHILE (patternabort = 1 AND x + xvector * (j - 2) > 0 AND x + xvector * (j - 2) < xgridsize AND y + yvector * (j - i2) > 0 AND y + yvector * (j - i2) < ygridsize) j = j + 1 IF (Getgridcell(x + xvector * (j - 2), y + yvector * (j - i2)) > 0) THEN patternabort = 0 WEND stablebefore = stablebefore + 1 IF stablebefore = 6 THEN wasstable = wasstable + 1 stablebefore = 0 END IF END IF END IF lastx(2) = lastx(1) lasty(2) = lasty(1) lastx(1) = x lasty(1) = y END IF END IF lastdirection(2) = lastdirection(1) lastdirection(1) = direction END SUB SUB clearscreen 'Clears the top part of the screen LOCATE 1, 1 COLOR 0 PRINT STRING$(xscreensize * yscreensize + 7, "Û"); END SUB FUNCTION Getcolour% (cx AS INTEGER, cy AS INTEGER) Getcolour% = mycolour(FIX((cgrad - 1 + Getgridcell(cx, cy)) / cgrad) MOD nocolours) ' COLOR END FUNCTION FUNCTION Getgridcell% (gx AS INTEGER, gy AS INTEGER) REM ********************************************** REM * [6][5][8] * REM * The grids are as follows: [3][4][5] * REM * [0][1][2] * REM ********************************************** REM * Messy code but quite fast... :( * REM ********************************************** IF (gx < 0 OR gx >= xgridsize OR gy < 0 OR gy >= ygridsize) THEN Getgridcell = 0 ELSE IF gx < thirdofxgridsize THEN 'grids 0,3,6 IF gy < thirdofygridsize THEN Getgridcell = grid0(gx, gy) '0 ELSE IF gy < 2 * thirdofygridsize THEN Getgridcell = grid3(gx, gy - thirdofygridsize) '3 ELSE Getgridcell = grid6(gx, gy - twothirdsofygridsize) '6 END IF END IF ELSE IF gx < 2 * thirdofxgridsize THEN 'grids 1,4,7 IF gy < thirdofygridsize THEN Getgridcell = grid1(gx - thirdofxgridsize, gy) '1 ELSE IF gy < 2 * thirdofygridsize THEN Getgridcell = grid4(gx - thirdofxgridsize, gy - thirdofygridsize) '4 ELSE Getgridcell = grid7(gx - thirdofxgridsize, gy - twothirdsofygridsize) '7 END IF END IF ELSE 'grids 2,5,8 IF gy < thirdofygridsize THEN Getgridcell = grid2(gx - twothirdsofxgridsize, gy) '2 ELSE IF gy < 2 * thirdofygridsize THEN Getgridcell = grid5(gx - twothirdsofxgridsize, gy - thirdofygridsize) '5 ELSE Getgridcell = grid8(gx - twothirdsofxgridsize, gy - twothirdsofygridsize) '8 END IF END IF END IF END IF END IF END FUNCTION SUB Incrementgridcell (gx AS INTEGER, gy AS INTEGER) REM ********************************************** REM * [6][5][8] * REM * The grids are as follows: [3][4][5] * REM * [0][1][2] * REM ********************************************** REM * Messy code but quite fast... :( * REM ********************************************** IF NOT (gx < 0 OR gx >= xgridsize OR gy < 0 OR gy >= ygridsize) THEN IF gx < thirdofxgridsize THEN 'grids 0,3,6 IF gy < thirdofygridsize THEN grid0(gx, gy) = grid0(gx, gy) + 1 '0 ELSE IF gy < 2 * thirdofygridsize THEN grid3(gx, gy - thirdofygridsize) = grid3(gx, gy - thirdofygridsize) + 1 '3 ELSE grid6(gx, gy - twothirdsofygridsize) = grid6(gx, gy - twothirdsofygridsize) + 1 '6 END IF END IF ELSE IF gx < 2 * thirdofxgridsize THEN 'grids 1,4,7 IF gy < thirdofygridsize THEN grid1(gx - thirdofxgridsize, gy) = grid1(gx - thirdofxgridsize, gy) + 1 '1 ELSE IF gy < twothirdsofygridsize THEN grid4(gx - thirdofxgridsize, gy - thirdofygridsize) = grid4(gx - thirdofxgridsize, gy - thirdofygridsize) + 1 '4 ELSE grid7(gx - thirdofxgridsize, gy - twothirdsofygridsize) = grid7(gx - thirdofxgridsize, gy - twothirdsofygridsize) + 1 '7 END IF END IF ELSE 'grids 2,5,8 IF gy < thirdofygridsize THEN grid2(gx - twothirdsofxgridsize, gy) = grid2(gx - twothirdsofxgridsize, gy) + 1 '2 ELSE IF gy < twothirdsofygridsize THEN grid5(gx - twothirdsofxgridsize, gy - thirdofygridsize) = grid5(gx - twothirdsofxgridsize, gy - thirdofygridsize) + 1 '5 ELSE grid8(gx - twothirdsofxgridsize, gy - twothirdsofygridsize) = grid8(gx - twothirdsofxgridsize, gy - twothirdsofygridsize) + 1 '8 END IF END IF END IF END IF END IF END SUB SUB initialise CLS SELECT CASE cputype 'How often the clock will need updating... CASE "8086", "8088", "186" printfreq = 31 CASE "286" printfreq = 127 CASE "386" printfreq = 511 CASE "486" printfreq = 2047 CASE ELSE printfreq = 8191 END SELECT gfxmode = RTRIM$(UCASE$(graphicsmode)) SELECT CASE gfxmode CASE "MONO", "CGA" SCREEN 0 screenres = 2 xscreensize = 80 yscreensize = 22 startxdim = xscreensize startydim = 2 * yscreensize cgrad = 5 nocolours = 15 'actually =>16 colours :) CASE "EGA" SCREEN 8 xpixels = 640 ypixels = 165 screenres = 1 xscreensize = 80 yscreensize = 22 startxdim = 12 startydim = 12 cgrad = 5 nocolours = 15 'actually =>16 colours :) CASE "VGA" SCREEN 12 xpixels = 640 ypixels = 376 screenres = 1 startxdim = 120 startydim = 120 xscreensize = 80 yscreensize = 25 cgrad = 5 nocolours = 15 'actually =>16 colours :) CASE ELSE gfxmode = "NULL" screenres = 1 END SELECT thirdofxgridsize = INT(xgridsize / 3) thirdofygridsize = INT(ygridsize / 3) twothirdsofxgridsize = 2 * INT(xgridsize / 3) twothirdsofygridsize = 2 * INT(ygridsize / 3) IF gfxmode$ <> "NULL" THEN printcredits printclock END IF RANDOMIZE TIMER REM ** CGA display can't cope with unrestricted use of all the colours REM ** Goes wrong if colours 10 & 12 are next to each other - REM ** hope this doesn't happen so often... mycolour(0) = 0 mycolour(1) = 2 mycolour(2) = 10 mycolour(3) = 3 mycolour(4) = 1 mycolour(5) = 7 mycolour(6) = 5 mycolour(7) = 14 mycolour(8) = 14 mycolour(9) = 6 mycolour(10) = 6 mycolour(11) = 4 mycolour(12) = 4 mycolour(13) = 15 mycolour(14) = 15 END SUB SUB moveant CALL Incrementgridcell(x, y) IF patternaborton = 1 THEN IF ((counter AND 7) = 0) THEN 'counter/8 is an integer temp = counter / 13 IF temp = INT(temp) THEN checkforpattern END IF END IF IF (printon = 1) THEN CALL printcell(x, y + y MOD screenres) IF (direction MOD 2 = 0) THEN y = y + 1 - direction IF (direction MOD 2 = 1) THEN x = x + 2 - direction IF (y < 0 OR y >= 3 * thirdofygridsize OR x < 0 OR x >= 3 * thirdofxgridsize) THEN gridabort = 1 END SUB SUB outputtodisk IF (counter > saveabove OR wasstable > 0) THEN OPEN "A", #1, outfile PRINT #1, "v1.1 " + CHR$(71 - 6 * userabort - 26 * patternabort); PRINT #1, CHR$(45 + 35 * printon) + CHR$(45 + wasstable + 3 * SGN(wasstable)) + "- "; PRINT #1, MID$(STR$(3 * thirdofxgridsize), 2); PRINT #1, "x" + MID$(STR$(3 * thirdofygridsize), 2) + " "; PRINT #1, TIME$ + "@" + MID$(DATE$, 4, 2) + "/" + LEFT$(DATE$, 2) + " "; PRINT #1, startupstring + " x=" + MID$(STR$(x), 2) + ", y=" + MID$(STR$(y), 2); PRINT #1, CHR$(9) + "#=" + MID$(STR$(counter), 2) CLOSE #1 END IF REM ************************************************************************ REM * abcd [gridsize]