REM Gnat swarm simulation v1.1 REM by Scott Teresi, www.teresi.us REM Created: July 25, 1996 REM Version history: REM 1.1 7/16/97 Added ability for gnats to land. REM CUSTOMIZABLE SETTINGS PARTICLES = 6: REM NUMBER OF BUGS IN THE SWARM SPDCHNG = 0: REM SET TO 0 FOR SPEED-LEVEL FORCE, 1 FOR ACCELERATION-LEVEL FAR = 80: REM DISTANCE BUGS CAN "SEE" (CIRCLE OF INTERACTION) SIGHT = 0: REM SET TO 0 NORMALLY; SET TO 1 TO SHOW BUGS' CIRCLES OF INTERACTION EXCITE = .8: REM EXCITEMENT OF BUGS (SHOULD BE < 1) MAGNIF = 25: REM HIGHER NUMBER HAS THE RESULT OF MAGNIFYING THE SWARM SMELL = 8: REM HIGHER NUMBER MEANS MORE REPELLING FORCE (CAN BE < 1) INDEP = 7: REM HIGHER NUMBER MEANS MORE RANDOMNESS IN PATHS WHEN SPDCHNG = 0 MAXACC = 5: REM MAXIMUM ALLOWABLE ACCELERATION MAXSPD = 10: REM MAXIMUM ALLOWABLE SPEED AT ANY MOMENT LANDING = .3: REM PROBABILITY OF LANDING WHEN HITTING THE SCREEN EDGE GETUP = .05: REM PROBABILITY OF GETTING UP AGAIN AFTER LANDING REM Normal oper.: SPDCHNG=0, MAGNIF=20, SMELL=9, INDEP=7, MAXACC=4, MAXSPD=7. REM More wiggly: SPDCHNG=0, MAGNIF=25, SMELL=8, INDEP=7, MAXACC=5, MAXSPD=7. REM With SPDCHNG=0, try an independence of .1 for a demonstration of atoms. REM For better results with SPDCHNG=1, set MAXSPD=1 and SMELL=1. REM For jello, set SPDCHNG=1 and MAXSPD=1 with a high SMELL. DIM POSX(PARTICLES), POSY(PARTICLES), SPDX(PARTICLES), SPDY(PARTICLES) DIM ACCX(PARTICLES), ACCY(PARTICLES), CLR(PARTICLES), LANDED(PARTICLES) RIGHTEDGE = 638 BOTTOMEDGE = 478 SCREEN 12 REM INITIALIZE BUGS RANDOMIZE TIMER AREA = RIGHTEDGE / 3: REM SIZE OF PIXEL SQUARE WHERE BUGS' INITIAL POSITIONS ARE CHOSEN FOR I = 1 TO PARTICLES POSX(I) = RND(1) * AREA + (RIGHTEDGE - AREA) / 2 POSY(I) = RND(1) * AREA + (BOTTOMEDGE - AREA) / 2 SPDX(I) = RND(1) * 5 - 2.5 SPDY(I) = RND(1) * 5 - 2.5 ACCX(I) = 0 ACCY(I) = 0 LANDED(I) = 0 CLR(I) = 15 NEXT I CLR(1) = 13: REM ONE PURPLE BUG REM **** MAIN LOOP **** REM CALCULATE FORCES MAINLOOP: FOR I = 1 TO PARTICLES REM ADD RANDOM MOMENTUM CHANGES ACCX(I) = ACCX(I) + RND(1) * INDEP - INDEP / 2 ACCY(I) = ACCY(I) + RND(1) * INDEP - INDEP / 2 REM ADD ATTRACTIVE FORCES FOR FORCE = 1 TO PARTICLES IF FORCE = I THEN GOTO NEXTFORCE DIST = SQR((POSX(I) - POSX(FORCE)) ^ 2 + (POSY(I) - POSY(FORCE)) ^ 2) IF DIST > FAR THEN GOTO NEXTFORCE: REM THIS BUG NOT SEEN IF DIST < .0001 THEN DIST = .0001: REM PREVENT EXTREMELY ERRATIC BEHAVIOR UNITX = (POSX(FORCE) - POSX(I)) / DIST: REM UNIT VECTOR POINTS TOWARD FORCE UNITY = (POSY(FORCE) - POSY(I)) / DIST IF SPDCHNG = 0 THEN SPDX(I) = SPDX(I) * EXCITE + (DIST / MAGNIF) ^ 2 * UNITX: REM ATTRACT SPDX(I) = SPDX(I) + 1 / ((DIST / SMELL) ^ 2) * UNITX * -1: REM REPEL IF CLOSE SPDY(I) = SPDY(I) * EXCITE + (DIST / MAGNIF) ^ 2 * UNITY SPDY(I) = SPDY(I) + 1 / ((DIST / SMELL) ^ 2) * UNITY * -1 ELSE ACCX(I) = ACCX(I) * EXCITE + (DIST / MAGNIF) ^ 2 * UNITX: REM ATTRACT ACCX(I) = ACCX(I) + 1 / ((DIST / SMELL) ^ 2) * UNITX * -1: REM REPEL IF CLOSE ACCY(I) = ACCY(I) * EXCITE + (DIST / MAGNIF) ^ 2 * UNITY ACCY(I) = ACCY(I) + 1 / ((DIST / SMELL) ^ 2) * UNITY * -1 END IF NEXTFORCE: NEXT FORCE IF ABS(ACCX(I)) > MAXACC THEN ACCX(I) = SGN(ACCX(I)) * MAXACC IF ABS(ACCY(I)) > MAXACC THEN ACCY(I) = SGN(ACCY(I)) * MAXACC IF ABS(SPDX(I)) > MAXSPD THEN SPDX(I) = SGN(SPDX(I)) * MAXSPD IF ABS(SPDY(I)) > MAXSPD THEN SPDY(I) = SGN(SPDY(I)) * MAXSPD SPDX(I) = SPDX(I) + ACCX(I) SPDY(I) = SPDY(I) + ACCY(I) NEXT I REM PLOT THE BUGS ON SCREEN REM ERASE OLD POSITIONS FOR I = 1 TO PARTICLES OLDPOSX = POSX(I) OLDPOSY = POSY(I) CIRCLE (OLDPOSX, OLDPOSY), .8, 0 PSET (OLDPOSX, OLDPOSY), 0 IF SIGHT THEN CIRCLE (OLDPOSX, OLDPOSY), FAR, 0: REM SHOW CIRCLE OF INTERACTION NEXT I FOR I = 1 TO PARTICLES REM CHECK IF BUG HAS LANDED LANDED = 0 IF POSX(I) < 1 THEN POSX(I) = 1: ACCX(I) = 4: LANDED = 1 IF POSX(I) > RIGHTEDGE THEN POSX(I) = RIGHTEDGE: ACCX(I) = -4: LANDED = 1 IF POSY(I) < 1 THEN POSY(I) = 1: ACCY(I) = 4: LANDED = 1 IF POSY(I) > BOTTOMEDGE THEN POSY(I) = BOTTOMEDGE: ACCY(I) = -4: LANDED = 1 IF LANDED AND RND(1) < LANDING THEN LANDED(I) = 1 IF LANDED(I) THEN IF RND(1) < GETUP THEN LANDED(I) = 0: REM DECIDE TO TAKE OFF END IF IF LANDED(I) = 0 THEN POSX(I) = POSX(I) + SPDX(I) POSY(I) = POSY(I) + SPDY(I) END IF REM PLOT NEW POSITIONS CIRCLE (POSX(I), POSY(I)), .8, CLR(I) PSET (POSX(I), POSY(I)), CLR(I) IF SIGHT THEN CIRCLE (POSX(I), POSY(I)), FAR, CLR(I) NEXT I GOTO MAINLOOP