DECLARE SUB SetMenuNames () DECLARE FUNCTION MinDistToPoints% (px1%, py1%, ps1%, px2%, py2%, ps2%, px3%, py3%, ps3%, Car%, dir%, accel%) DECLARE SUB DoAI () DECLARE SUB DrawCars () DECLARE SUB BuildTrack (t%) DECLARE SUB DoRace () DECLARE SUB DoCheckpoints (Car%) DECLARE SUB GetTracks () DECLARE SUB ClearKBBuffer () DECLARE SUB DoPhysics (Car%) DECLARE SUB ChangeDirection (Car%, newDirection%) DECLARE SUB ResetKBState () DECLARE SUB UpdateKBState () DECLARE SUB CalcDecay (Pl%) DECLARE SUB SingleMenu () DECLARE SUB PrintMenuStuff () DECLARE SUB DoInputs (Players AS INTEGER) DECLARE SUB GetCarVals (Cartype%, Pl%) DECLARE SUB Centre (Row!, Text$) DECLARE SUB GetCars () DECLARE SUB ScanStartingEdge (x1%, y1%, x2%, y2%) DECLARE SUB ScanEndingEdge (x1%, y1%, x2%, y2%) DECLARE SUB DrawTriangle (x1%, y1%, x2%, y2%, x3%, y3%, C%) ' Working edge arrays DIM SHARED workingEdgeStart%(480), workingEdgeEnd%(480) TYPE TrackSegment angle AS INTEGER length AS INTEGER widthDelta AS INTEGER END TYPE TYPE Checkpoint x AS INTEGER y AS INTEGER triggerX AS INTEGER triggerY AS INTEGER size AS INTEGER END TYPE DIM SHARED MaxCheckpoints AS INTEGER MaxCheckpoints = 50 DIM SHARED Checkpoints(MaxCheckpoints - 1) AS Checkpoint DIM SHARED NumCheckpoints AS INTEGER DIM SHARED carSprite(10 * 4 * 144) AS INTEGER DIM SHARED MaxCars MaxCars = 10 DIM SHARED NumCars NumCars = 5 DIM SHARED Players AS INTEGER DIM SHARED Status AS INTEGER DIM SHARED SelectedTrack AS INTEGER DIM SHARED Time AS SINGLE DIM SHARED carBackground(MaxCars * 144) AS INTEGER TYPE CarData Car AS INTEGER x AS INTEGER y AS INTEGER direction AS INTEGER oldX AS INTEGER oldY AS INTEGER oldDirection AS INTEGER vx AS INTEGER vy AS INTEGER speed AS INTEGER maxSpeed AS INTEGER accel AS INTEGER decay AS INTEGER skid AS INTEGER skidDirection AS INTEGER skidColour AS INTEGER drawSkid AS INTEGER isAccelerating AS INTEGER currentCheckpoint AS INTEGER lap AS INTEGER surface AS INTEGER movementFrame AS INTEGER END TYPE DIM SHARED Cars(MaxCars - 1) AS CarData DIM SHARED HasKBEvents AS INTEGER DIM SHARED IsKeyPressed(127) AS INTEGER DIM SHARED SoundCycle% DIM SHARED MaxTracks AS INTEGER MaxTracks = 5 DIM SHARED TrackName(MaxTracks - 1) AS STRING DIM SHARED Track(MaxTracks - 1, 20) AS TrackSegment DIM SHARED NumSegments(MaxTracks - 1) AS INTEGER DIM SHARED TrackN$ DIM SHARED CarN$ SCREEN 12 CLS GetCars GetTracks RANDOMIZE TIMER SelectedTrack = 0 Cars(Car%).Car = 0 SingleMenu END ' Car sprites (RLE) DATA 2,13,1,0,3,15,1,0,3,-32737,1,0,3,-32737,1,15,3,-32752,1,-32737,3,0,1,-32737,3,0 DATA 1,-32743,2,9,1,6,1,0,2,-32752,1,-32737,1,15,2,-32737,1,-32752,1,15,2,-32737,1,-32752 DATA 1,0,3,-32737,1,0,3,-32737,94,0,2,13,12,0,1,7,3,-7944,1,-32713,2,28916,1,28872 DATA 1,-32717,2,28912,1,28876,1,-32717,2,28912,1,28876,1,-32713,2,28916,1,28872,1,7 DATA 3,-7944,106,0,2,13,1,0,3,-32737,1,0,3,-32737,1,15,2,-32737,1,-32752,1,15,2,-32737 DATA 1,-32752,1,0,2,-32752,1,-32737,1,-32743,2,9,1,6,1,-32737,3,0,1,-32737,3,0,1,15 DATA 3,-32752,1,0,3,-32737,1,0,3,-32737,1,0,3,15,94,0,2,13,12,0,1,14,3,-3983,1,-16354 DATA 2,-3870,1,12513,1,-16356,2,-3872,1,12515,1,-16356,2,-3872,1,12515,1,-16354,2,-3870 DATA 1,12513,1,14,3,-3983,106,0,2,13,1,0,1,-32752,2,-32737,2,0,2,-32737,1,15,1,0,1,-32752 DATA 2,-32737,2,0,2,-32737,2,0,1,-32737,1,-32752,1,0,1,15,1,-32737,1,-32752,1,0,1,15 DATA 1,-32737,1,-32752,1,0,1,15,1,-32737,1,6,1,0,1,-32743,1,-32746,2,0,1,-32743,1,-32746 DATA 2,0,1,-32743,1,-32746,2,0,1,-32737,1,-32746,94,0,2,13,12,0,1,-32753,1,4096,1,28912 DATA 1,-3841,1,-16383,1,0,1,12542,1,-4081,1,-16367,1,0,1,12430,1,-3841,1,-16367,1,0 DATA 1,12430,1,-3841,1,-16383,1,0,1,12542,1,-4081,1,-32753,1,4096,1,28912,1,-3841 DATA 106,0,2,13,2,0,1,-32737,1,-32746,2,0,1,-32743,1,-32746,2,0,1,-32743,1,-32746 DATA 1,6,1,0,1,-32743,1,-32746,1,-32752,1,0,1,15,1,-32737,1,-32752,1,0,1,15,1,-32737 DATA 1,-32752,1,0,1,15,2,-32737,2,0,2,-32737,2,0,1,-32737,1,15,1,0,1,-32752,1,-32737 DATA 2,0,2,-32737,1,0,1,-32752,2,-32737,94,0,2,13,12,0,1,31,1,128,1,-3872,1,-3841 DATA 1,56,1,0,1,-3897,1,255,1,-32712,1,0,1,4295,1,-3841,1,-32712,1,0,1,4295,1,-3841 DATA 1,56,1,0,1,-3897,1,255,1,31,1,128,1,-3872,1,-3841,106,0,2,13,3,15,1,0,3,-32737 DATA 1,0,3,-32737,1,0,1,-32737,2,-32752,1,0,1,-32737,3,0,1,-32737,2,15,1,0,1,-32737 DATA 2,15,1,0,1,-32737,2,15,1,0,1,-32737,3,0,1,-32737,2,-32752,1,0,3,-32737,4,0,1,-32737 DATA 94,0,2,13,12,0,1,-8065,2,-8096,1,128,1,-3969,2,28750,1,128,1,-3969,2,28750,1,128 DATA 1,-3969,2,28750,1,128,1,-3969,2,28750,1,128,1,-8065,2,-8096,1,128,106,0,2,13 DATA 3,0,4,-32737,1,0,1,-32737,2,-32752,1,0,1,-32737,3,0,1,-32737,2,15,1,0,1,-32737 DATA 2,15,1,0,1,-32737,2,15,1,0,1,-32737,3,0,1,-32737,2,-32752,1,0,3,-32737,1,0,3,-32737 DATA 1,0,3,15,95,0,2,13,12,0,1,-8065,2,24688,1,4096,1,-7937,2,8423,1,4096,1,-7937 DATA 2,8423,1,4096,1,-7937,2,8423,1,4096,1,-7937,2,8423,1,4096,1,-8065,2,24688,1,4096 DATA 106,0,2,13,2,0,2,15,2,0,2,-32737,2,0,2,-32737,1,15,1,0,1,-32752,2,-32737,2,0 DATA 2,-32737,2,0,1,-32737,1,-32752,1,0,1,15,1,-32737,1,-32752,1,0,1,15,1,-32737,1,-32752 DATA 1,0,1,15,2,-32737,2,0,1,-32737,1,15,1,0,1,-32752,1,-32737,2,0,2,-32737,94,0,2,13 DATA 12,0,1,63,1,0,1,-8000,1,-7937,1,-32669,1,0,1,28828,1,-3841,1,-32669,1,0,1,28828 DATA 1,-3841,1,-32669,1,0,1,28828,1,-3841,1,-32669,1,0,1,28828,1,-3841,1,63,1,0,1,-8000 DATA 1,-7937,106,0,2,13,2,0,2,-32737,1,15,1,0,1,-32752,2,-32737,2,0,1,-32737,1,-32752 DATA 1,0,1,15,1,-32737,1,-32752,1,0,1,15,1,-32737,1,-32752,1,0,1,15,2,-32737,2,0,2,-32737 DATA 2,0,1,-32737,1,15,1,0,1,-32752,1,-32737,2,0,2,-32737,2,0,2,-32737,2,0,2,15,94,0 DATA 2,13,12,0,1,-16369,1,0,1,12400,1,-3969,1,24604,1,0,1,-28445,1,-3841,1,24604,1,0 DATA 1,-28445,1,-3841,1,24604,1,0,1,-28445,1,-3841,1,24604,1,0,1,-28445,1,-3841,1,-16369 DATA 1,0,1,12400,1,-3969,106,0,2,13,1,0,3,15,1,0,2,-32737,1,-32752,1,0,2,-32737,1,-32746 DATA 1,0,2,-32737,1,-32746,1,15,3,-32752,1,-32737,3,0,1,-32737,3,0,1,-32752,3,15,1,-32752 DATA 3,15,1,-32737,3,0,1,15,3,-32752,1,0,3,-32737,94,0,2,13,12,0,1,62,3,-7999,1,103 DATA 2,-3944,1,4248,1,103,2,-3944,1,-12136,1,103,2,-3944,1,-12136,1,103,2,-3944,1,4248 DATA 1,62,3,-7999,106,0,2,13,1,0,3,-32737,1,15,3,-32752,1,-32737,3,0,1,-32752,3,15 DATA 1,-32752,3,15,1,-32737,3,0,1,-32737,3,0,1,15,3,-32752,1,0,2,-32737,1,-32746,1,0 DATA 2,-32737,1,-32746,1,0,2,-32737,1,-32752,1,0,3,15,94,0,2,13,12,0,1,-16377,3,12408 DATA 1,24590,2,-28431,1,-28543,1,24590,2,-28431,1,-28495,1,24590,2,-28431,1,-28495 DATA 1,24590,2,-28431,1,-28543,1,-16377,3,12408,106,0,2,13,1,15,8,-32737,3,-32752 DATA 1,-32737,3,0,1,-32737,3,0,1,-32737,3,15,1,-32737,3,15,3,-32737,1,-32752,3,9,1,-32746 DATA 3,-32743,1,-32746,3,-32743,1,-32746,3,-32737,95,0,2,13,12,0,1,-7953,2,28904,1,28792 DATA 1,-3841,2,12542,1,12294,1,-3953,2,12430,1,12406,1,-3953,2,12430,1,12406,1,-3841 DATA 2,12542,1,12294,1,-7953,2,28904,1,28792,106,0,2,13,3,-32737,1,0,3,-32743,1,-32746 DATA 3,-32743,1,-32746,3,9,1,-32746,3,-32737,1,-32752,1,-32737,3,15,1,-32737,3,15 DATA 1,-32737,3,0,1,-32737,3,0,1,-32737,3,-32752,4,-32737,1,15,3,-32737,94,0,2,13 DATA 12,0,1,28799,2,28897,1,-7967,1,-3841,2,-3897,1,198,1,4351,2,4295,1,-7994,1,4351 DATA 2,4295,1,-7994,1,-3841,2,-3897,1,198,1,28799,2,28897,1,-7967,106,0,2,13,2,0,2,15 DATA 1,0,1,-32752,2,-32737,2,0,2,-32737,2,0,2,-32737,1,15,1,0,2,-32752,1,-32737,3,0 DATA 1,-32737,3,0,1,-32752,2,0,1,15,2,0,1,-32752,1,-32737,2,0,2,-32737,2,0,2,-32737 DATA 2,0,2,15,94,0,2,13,12,0,1,14,1,8192,2,-8079,1,7,1,0,1,-3872,1,-3848,1,7,1,0,1,-3872 DATA 1,-3848,1,7,1,0,1,-3872,1,-3848,1,7,1,0,1,-3872,1,-3848,1,14,1,8192,2,-8079,106,0 DATA 2,13,2,0,2,15,2,0,2,-32737,2,0,2,-32737,2,0,1,-32752,1,-32737,1,-32752,2,0,1,15 DATA 1,-32737,3,0,1,-32737,3,0,1,15,1,0,2,-32752,2,0,2,-32737,2,0,2,-32737,1,0,1,-32752 DATA 2,-32737,2,0,2,15,94,0,2,13,12,0,1,7,1,64,2,-8072,1,14,1,0,1,28912,1,-3855,1,14 DATA 1,0,1,28912,1,-3855,1,14,1,0,1,28912,1,-3855,1,14,1,0,1,28912,1,-3855,1,7,1,64 DATA 2,-8072,106,0,2,13,1,0,1,-32752,1,-32737,1,-32752,1,15,1,0,1,-16321,1,0,1,9,1,0 DATA 1,-16321,1,0,1,9,1,0,1,-16321,1,0,1,15,1,0,1,-32743,1,0,1,15,1,0,1,-32752,1,0 DATA 1,9,1,0,1,-32752,1,6,2,0,1,-16336,3,15,1,-16321,3,0,1,-16321,3,0,1,-32737,1,-32752 DATA 2,0,1,15,95,0,2,13,10,0,1,-8136,2,0,1,4096,1,-3969,1,4160,1,-8169,1,16,1,-3855 DATA 1,8,1,8211,1,16,1,-3856,1,12,1,8211,1,16,1,-3856,1,12,1,-8169,1,16,1,-3855,1,8 DATA 1,0,1,4096,1,-3969,1,4160,2,0,1,-8136,103,0,2,13,2,0,1,15,3,0,1,-32737,1,-32752 DATA 2,0,1,-16321,1,0,2,15,1,-16321,3,0,1,-16336,1,15,1,9,1,0,1,-32752,1,6,1,15,1,0 DATA 1,-32752,1,0,1,15,1,0,1,-32743,1,0,1,9,1,0,1,-16321,1,0,1,9,1,0,1,-16321,1,0 DATA 1,15,1,0,1,-16321,2,0,1,-32752,1,-32737,1,-32752,94,0,2,13,10,0,1,-16271,2,0 DATA 1,128,1,-7937,1,8320,1,-32642,1,-32768,1,-3848,1,1,1,-32692,1,-32768,1,-3856 DATA 1,3,1,-32692,1,-32768,1,-3856,1,3,1,-32642,1,-32768,1,-3848,1,1,1,0,1,128,1,-7937 DATA 1,8320,2,0,1,-16271,103,0,2,13,3,-32737,1,-32743,3,-32737,1,-32743,3,-32737,1,-32743 DATA 1,-32737,3,-32752,1,-32737,3,0,1,-32737,3,15,1,-32737,3,15,1,-32737,3,15,1,-32737 DATA 3,0,1,-32737,3,-32752,8,-32737,94,0,2,13,12,0,1,-3841,3,-3872,1,-3841,3,28878 DATA 1,-3841,2,28878,1,206,1,-3841,2,28878,1,206,1,-3841,3,28878,1,-3841,3,-3872,106,0 DATA 2,13,9,-32737,3,-32752,1,-32737,3,0,1,-32737,3,15,1,-32737,3,15,1,-32737,3,15 DATA 1,-32737,3,0,1,-32737,3,-32752,3,-32737,1,-32743,3,-32737,1,-32743,3,-32737,1,-32743 DATA 94,0,2,13,12,0,1,-3841,3,28912,1,-3841,3,12519,1,-3841,2,12519,1,12295,1,-3841 DATA 2,12519,1,12295,1,-3841,3,12519,1,-3841,3,28912,106,0,2,13,1,15,2,-32737,1,-32752 DATA 1,-32737,2,-32752,1,0,1,-32737,3,0,1,-32737,3,0,1,-32743,2,9,1,6,1,-32737,2,15 DATA 1,0,1,-32737,2,15,1,0,1,-32737,2,6,1,0,1,-32737,2,6,1,0,1,-32737,2,-32746,1,0 DATA 3,-32737,1,0,4,-32737,94,0,2,13,12,0,1,-7937,2,12512,1,4224,1,-3841,2,4295,1,128 DATA 1,-3842,2,4350,1,129,1,-3842,2,4350,1,129,1,-3841,2,4295,1,128,1,-7937,2,12512 DATA 1,4224,106,0,2,13,7,-32737,1,0,1,-32737,2,-32746,1,0,1,-32737,2,6,1,0,1,-32737 DATA 2,6,1,0,1,-32737,2,15,1,0,1,-32737,2,15,1,0,1,-32743,2,9,1,6,1,-32737,3,0,1,-32737 DATA 3,0,1,-32737,2,-32752,1,0,1,15,2,-32737,1,-32752,94,0,2,13,12,0,1,-3969,2,28864 DATA 1,4224,1,-3841,2,12430,1,4096,1,-3849,2,-3961,1,4104,1,-3849,2,-3961,1,4104,1,-3841 DATA 2,12430,1,4096,1,-3969,2,28864,1,4224,106,0 DATA "Small Oval" DATA 9 DATA 0, 5, 0,-90, 18, 0, 0, 3, 0,-90, 18, 0, 0, 10, 0,-90, 18, 0, 0, 3, 0,-90, 18, 0, 0, 5, 0 DATA "Narrowing Square" DATA 12 DATA 0, 9, 0,-70, 18, 0, 0, 7,-15,-55, 12, 0,-50, 8, 0,-5, 5, 0, 0, 6, 10, 0, 26, 0,-90, 11, 0, 0, 18, 0,-90, 11, 5, 0, 19, 0 DATA "Tri-Oval" DATA 7 DATA 0, 9, 0,-125, 26, 0, 0, 13, 0,-95, 10, 0, 0, 32, 0,-140, 14, 0, 0, 18, 0 DATA "Chicane Falls" DATA 13 DATA 0, 20, 0,-90, 10, 0, 0, 17, 0,-90, 10, 0, 0, 11, 0,-90, 12, 0, 0, 6, 0, 180, 22, 0, 0, 8, 0,-180, 23, 0, 0, 18, 0,-90, 10, 0, 0, 12, 0 DATA "Winder" DATA 12 DATA 0, 8,-15,-95, 21, 0,-110, 8, 0, 55, 17, 0, 150, 12, 0, 0, 20, 0,-180, 10, 0, 0, 38, 15,-90, 13, 0, 0, 20, 0,-95, 11, 10,-5, 18,-10 SUB BuildTrack (t%) SCREEN 12 CLS DegToRad! = (3.141593 / 180) NumCheckpoints = 0 trackX! = 316 trackY! = 95 curAngle! = 90 curWidth! = 36 DIM x1%, y1%, x2%, y2% LINE (0, 0)-(640, 480), 2, BF cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) trackX! = 316 trackY! = 95 curAngle! = 90 curWidth! = 35 FOR i% = 0 TO NumSegments(t%) - 1 kd1% = 0 kd2% = 0 FOR j% = 0 TO Track(t%, i%).length - 1 cosine = COS(curAngle! * DegToRad!) sine = SIN(curAngle! * DegToRad!) prevX1% = x1%: prevX2% = x2% prevY1% = y1%: prevY2% = y2% prevKX1% = kX1%: prevKX2% = kX2% prevKY1% = kY1%: prevKY2% = kY2% x1% = trackX! + (curWidth! * cosine) y1% = trackY! - (curWidth! * sine) kX1% = trackX! + ((curWidth! + 4) * cosine) kY1% = trackY! - ((curWidth! + 4) * sine) x2% = trackX! - (curWidth! * cosine) y2% = trackY! + (curWidth! * sine) kX2% = trackX! - ((curWidth! + 4) * cosine) kY2% = trackY! + ((curWidth! + 4) * sine) IF prevX1% <> 0 THEN DrawTriangle (prevX1%), (prevY1%), (x1%), (y1%), (prevX2%), (prevY2%), 0 DrawTriangle (prevX2%), (prevY2%), (x1%), (y1%), (x2%), (y2%), 0 IF Track(t%, i%).angle <> 0 AND j% > 0 THEN SELECT CASE j% MOD 4 CASE 0: kc% = 15 CASE 1: kc% = 9 CASE 2: kc% = 15 CASE 3: kc% = 12 END SELECT DrawTriangle (prevX1%), (prevY1%), (prevKX1%), (prevKY1%), (kX1%), (kY1%), kc% DrawTriangle (prevX1%), (prevY1%), (kX1%), (kY1%), (x1%), (y1%), kc% DrawTriangle (prevX2%), (prevY2%), (prevKX2%), (prevKY2%), (kX2%), (kY2%), kc% DrawTriangle (prevX2%), (prevY2%), (kX2%), (kY2%), (x2%), (y2%), kc% END IF END IF ' Checkpoint building logic IF cp% = 1 AND NumCheckpoints < MaxCheckpoints - 1 THEN Checkpoints(NumCheckpoints).x = trackX! Checkpoints(NumCheckpoints).y = trackY! Checkpoints(NumCheckpoints).triggerX = trackX! + (curWidth! * sine) Checkpoints(NumCheckpoints).triggerY = trackY! + (curWidth! * cosine) Checkpoints(NumCheckpoints).size = curWidth! + 5 NumCheckpoints = NumCheckpoints + 1 'LINE (trackX! - 1, trackY! - 1)-(trackX! + 1, trackY! + 1), 12, BF END IF cp% = (cp% + 1) MOD 4 trackX! = trackX! + (10 * sine) trackY! = trackY! + (10 * cosine) curAngle! = curAngle! + (Track(t%, i%).angle / Track(t%, i%).length) curWidth! = curWidth! + (Track(t%, i%).widthDelta / Track(t%, i%).length) NEXT j% NEXT i% ' Add the last checkpoint to make a full loop Checkpoints(NumCheckpoints).x = Checkpoints(0).x Checkpoints(NumCheckpoints).y = Checkpoints(0).y Checkpoints(NumCheckpoints).triggerX = Checkpoints(0).triggerX Checkpoints(NumCheckpoints).triggerY = Checkpoints(0).triggerY Checkpoints(NumCheckpoints).size = Checkpoints(0).size NumCheckpoints = NumCheckpoints + 1 ' Close the track loop DrawTriangle (x1%), (y1%), (316), (95 - 35), (x2%), (y2%), 0 DrawTriangle (x2%), (y2%), (316), (95 - 35), (316), (95 + 35), 0 LINE (318, 60)-(318, 130), 15, , &HF0F0 LINE (319, 60)-(319, 130), 15, , &HF0F0 LINE (317, 60)-(317, 130), 15, , &HF0F0 LINE (320, 60)-(320, 130), 15, , &HF0F LINE (321, 60)-(321, 130), 15, , &HF0F LINE (322, 60)-(322, 130), 15, , &HF0F LINE (323, 60)-(323, 130), 15 LINE (316, 60)-(316, 130), 15 END SUB SUB CalcDecay (Pl%) IF Cars(Pl%).speed > 75 THEN Cars(Pl%).skid = -1 Cars(Pl%).decay = (Cars(Pl%).speed \ 20) * (Cars(Pl%).speed \ 20) IF Cars(Pl%).direction = Cars(Pl%).skidDirection THEN Cars(Car%).decay = 0 Cars(Car%).skid = 0 END IF END IF END SUB SUB Centre (Row, Text$) LOCATE Row, 40 - (LEN(Text$) \ 2) PRINT Text$ END SUB SUB ChangeDirection (Car%, newDirection%) IF Cars(Car%).skid = -1 AND newDirection% <> Cars(Car%).direction THEN Cars(Car%).speed = (Cars(Car%).speed * 2) \ 3 Factor% = ABS(Cars(Car%).direction - newDirection%) IF Factor% <> 1 AND Factor% <> 3 THEN EXIT SUB Cars(Car%).skidDirection = Cars(Car%).direction Cars(Car%).direction = newDirection% CalcDecay Car% ' Reset direction keys to prevent multiple direction changes IsKeyPressed(72) = 0 IsKeyPressed(75) = 0 IsKeyPressed(77) = 0 IsKeyPressed(80) = 0 END SUB SUB ClearKBBuffer DEF SEG = &H40 POKE &H1C, PEEK(&H1A) DEF SEG END SUB SUB DoAI FOR i% = 1 TO NumCars - 1 cx1% = Checkpoints((Cars(i%).currentCheckpoint)).x cy1% = Checkpoints((Cars(i%).currentCheckpoint)).y cs1% = Checkpoints((Cars(i%).currentCheckpoint)).size - 10 cx2% = Checkpoints((Cars(i%).currentCheckpoint + 1) MOD NumCheckpoints).x cy2% = Checkpoints((Cars(i%).currentCheckpoint + 1) MOD NumCheckpoints).y cs2% = Checkpoints((Cars(i%).currentCheckpoint + 1) MOD NumCheckpoints).size - 10 cx3% = Checkpoints((Cars(i%).currentCheckpoint + 2) MOD NumCheckpoints).x cy3% = Checkpoints((Cars(i%).currentCheckpoint + 2) MOD NumCheckpoints).y cs3% = Checkpoints((Cars(i%).currentCheckpoint + 2) MOD NumCheckpoints).size - 10 IF Cars(i%).movementFrame > 0 THEN Cars(i%).movementFrame = Cars(i%).movementFrame - 1 dir% = Cars(i%).direction deltaA% = MinDistToPoints(cx1%, cy1%, cs1%, cx2%, cy2%, cs2%, cx3%, cy3%, cs3%, i%, dir%, 1) deltaN% = MinDistToPoints(cx1%, cy1%, cs1%, cx2%, cy2%, cs2%, cx3%, cy3%, cs3%, i%, dir%, 0) IF deltaN% < deltaA% THEN Cars(i%).isAccelerating = 0 ELSE Cars(i%).isAccelerating = 1 ELSE ' Turn options: -1, 0, 1 dir% = Cars(i%).direction pdir% = (dir% + 4 - 1) MOD 4 ndir% = (dir% + 1) MOD 4 deltaP% = 5 + MinDistToPoints(cx1%, cy1%, cs1%, cx2%, cy2%, cs2%, cx3%, cy3%, cs3%, i%, pdir%, Cars(i%).isAccelerating) delta% = MinDistToPoints(cx1%, cy1%, cs1%, cx2%, cy2%, cs2%, cx3%, cy3%, cs3%, i%, dir%, Cars(i%).isAccelerating) deltaN% = 5 + MinDistToPoints(cx1%, cy1%, cs1%, cx2%, cy2%, cs2%, cx3%, cy3%, cs3%, i%, ndir%, Cars(i%).isAccelerating) ' Change direction if it will result in a smaller Manhattan distance IF deltaP% < delta% AND deltaP% < deltaN% THEN ChangeDirection i%, pdir% Cars(i%).movementFrame = 15 ELSEIF deltaN% < delta% AND deltaN% < deltaP% THEN ChangeDirection i%, ndir% Cars(i%).movementFrame = 15 ELSE Cars(i%).movementFrame = 2 END IF END IF NEXT i% END SUB SUB DoCheckpoints (Car%) DIM cp AS Checkpoint cp = Checkpoints(Cars(Car%).currentCheckpoint) IF Cars(Car%).x + 18 > cp.triggerX - cp.size AND Cars(Car%).x - 6 < cp.triggerX + cp.size AND Cars(Car%).y + 18 > cp.triggerY - cp.size AND Cars(Car%).y - 6 < cp.triggerY + cp.size THEN Cars(Car%).currentCheckpoint = Cars(Car%).currentCheckpoint + 1 IF Cars(Car%).currentCheckpoint >= NumCheckpoints THEN Cars(Car%).currentCheckpoint = 0 Cars(Car%).lap = Cars(Car%).lap + 1 END IF END IF END SUB SUB DoPhysics (Car%) Cars(Car%).skidColour = 8 oldVX% = Cars(Car%).vx oldVY% = Cars(Car%).vy surface% = Cars(Car%).surface maxSpeed% = Cars(Car%).maxSpeed * 10 SkidBase% = 1500 SkidRand% = 300 AccelSkidSpeed% = maxSpeed% \ 3 DecayFactor% = 25 IF surface% = 2 OR surface% = 6 THEN Cars(Car%).skidColour = 6 IF Cars(Car%).speed > 500 THEN Cars(Car%).isAccelerating = 0 SkidBase% = 100 SkidRand% = 30 DecayFactor% = 5 END IF IF surface% = 8 THEN DecayFactor% = 30 END IF ' Directions = Up, Right, Down, Left IF Cars(Car%).decay > Cars(Car%).speed THEN Cars(Car%).decay = Cars(Car%).speed carSpeed% = (Cars(Car%).speed - Cars(Car%).decay) \ 50 IF Cars(Car%).direction = 0 THEN Cars(Car%).vy = Cars(Car%).vy - carSpeed% IF Cars(Car%).direction = 1 THEN Cars(Car%).vx = Cars(Car%).vx + carSpeed% IF Cars(Car%).direction = 2 THEN Cars(Car%).vy = Cars(Car%).vy + carSpeed% IF Cars(Car%).direction = 3 THEN Cars(Car%).vx = Cars(Car%).vx - carSpeed% IF Cars(Car%).isAccelerating THEN Cars(Car%).speed = Cars(Car%).speed + Cars(Car%).accel IF Cars(Car%).speed < AccelSkidSpeed% THEN IF SoundCycle% <= 0 AND Car% = 0 THEN SOUND (SkidBase% \ 2) + (RND * (SkidRand% \ 3)), .5 SoundCycle% = 8 ELSE SoundCycle% = SoundCycle% - 1 END IF Cars(Car%).drawSkid = 1 IF Cars(Car%).direction = 2 OR Cars(Car%).direction = 0 THEN Cars(Car%).vx = Cars(Car%).vx + INT((RND - .365) * 2) ELSE Cars(Car%).vy = Cars(Car%).vy + INT((RND - .365) * 2) END IF END IF ELSE DecayFactor% = DecayFactor% * 2 IF Cars(Car%).speed > 0 THEN Cars(Car%).speed = Cars(Car%).speed - (1 + (Cars(Car%).speed \ 50)) END IF IF Cars(Car%).skid = -1 THEN Cars(Car%).drawSkid = 1 IF SoundCycle% <= 0 AND Car% = 0 THEN SOUND SkidBase% + (RND * SkidRand%), .5 SoundCycle% = 8 ELSE SoundCycle% = SoundCycle% - 1 END IF IF Cars(Car%).skidDirection = 3 THEN Cars(Car%).vx = Cars(Car%).vx - (Cars(Car%).decay \ 50) IF Cars(Car%).skidDirection = 1 THEN Cars(Car%).vx = Cars(Car%).vx + (Cars(Car%).decay \ 50) IF Cars(Car%).skidDirection = 0 THEN Cars(Car%).vy = Cars(Car%).vy - (Cars(Car%).decay \ 50) IF Cars(Car%).skidDirection = 2 THEN Cars(Car%).vy = Cars(Car%).vy + (Cars(Car%).decay \ 50) Cars(Car%).decay = Cars(Car%).decay - (DecayFactor% + Cars(Car%).accel) IF Cars(Car%).decay < 2 THEN Cars(Car%).decay = 0 Cars(Car%).skid = 0 Cars(Car%).skidDirection = -1 END IF END IF IF Cars(Car%).speed < 0 THEN Cars(Car%).speed = 0 IF Cars(Car%).speed > maxSpeed% THEN Cars(Car%).speed = maxSpeed% FOR j% = Car% TO NumCars - 1 IF j% <> Car% AND Cars(Car%).vx > Cars(j%).vx - 60 AND Cars(Car%).vx < Cars(j%).vx + 60 AND Cars(Car%).vy > Cars(j%).vy - 60 AND Cars(Car%).vy < Cars(j%).vy + 60 THEN IF Cars(Car%).direction = 0 THEN Cars(Car%).vy = Cars(Car%).vy + 65 IF Cars(Car%).direction = 1 THEN Cars(Car%).vx = Cars(Car%).vx - 65 IF Cars(Car%).direction = 2 THEN Cars(Car%).vy = Cars(Car%).vy - 65 IF Cars(Car%).direction = 3 THEN Cars(Car%).vx = Cars(Car%).vx + 65 Cars(Car%).speed = Cars(Car%).speed \ 2 SOUND 50, .5 END IF NEXT j% IF Cars(Car%).vx > 6250 THEN IF Cars(Car%).direction = 1 THEN Cars(Car%).speed = 0 Cars(Car%).vx = 6250 END IF IF Cars(Car%).vy > 4650 THEN IF Cars(Car%).direction = 2 THEN Cars(Car%).speed = 0 Cars(Car%).vy = 4650 END IF IF Cars(Car%).vx < 50 THEN IF Cars(Car%).direction = 3 THEN Cars(Car%).speed = 0 Cars(Car%).vx = 50 END IF IF Cars(Car%).vy < 150 THEN IF Cars(Car%).direction = 0 THEN Cars(Car%).speed = 0 Cars(Car%).vy = 150 END IF Cars(Car%).x = Cars(Car%).vx \ 10 Cars(Car%).y = Cars(Car%).vy \ 10 END SUB SUB DoRace LOCATE 1, 1 PRINT STRING$(80, " ") snd = -1 FOR i% = 1 TO NumCars - 1 Cars(i%).Car = RND * 9 NEXT i% carY% = 60 carX% = 304 FOR i% = 0 TO NumCars - 1 GetCarVals Cars(i%).Car, i% Cars(i%).x = 304 Cars(i%).y = carY% Cars(i%).oldX = 0 Cars(i%).oldY = 0 Cars(i%).vx = carX% * 10 Cars(i%).vy = carY% * 10 Cars(i%).currentCheckpoint = 0 Cars(i%).lap = 1 Cars(i%).direction = 1 Cars(i%).speed = 0 Cars(i%).skidDirection = -1 carY% = carY% + 15 IF carY% > 120 THEN carY% = 60: carX% = carX% - 24 NEXT i% LOCATE 1, 1 COLOR 15 PRINT "MPH:" LOCATE 1, 20 PRINT "Lap:" LOCATE 1, 40 PRINT "Time:" ResetKBState TimeCheck = TIMER DO UpdateKBState DrawCars Time = TIMER - TimeCheck LOCATE 1, 5 COLOR 14 PRINT Cars(0).speed \ 10; " " LOCATE 1, 24 PRINT Cars(0).lap LOCATE 1, 46 PRINT USING "###.##"; Time Cars(0).isAccelerating = IsKeyPressed(30) IF IsKeyPressed(72) THEN ChangeDirection 0, 0 IF IsKeyPressed(77) THEN ChangeDirection 0, 1 IF IsKeyPressed(80) THEN ChangeDirection 0, 2 IF IsKeyPressed(75) THEN ChangeDirection 0, 3 IF IsKeyPressed(16) THEN EXIT DO DoAI FOR i% = 0 TO NumCars - 1 DoPhysics i% DoCheckpoints i% IF Cars(i%).lap > 5 AND Cars(i%).currentCheckpoint >= 1 THEN LINE (210, 160)-(450, 260), 8, BF LINE (200, 150)-(440, 250), 0, BF LINE (200, 150)-(440, 250), 15, B LINE (201, 151)-(439, 249), 7, B LINE (202, 152)-(438, 248), 7, B IF i% = 0 THEN COLOR 15 Centre 12, " === Congratulations! ===" Centre 13, " " COLOR 14 Centre 14, " You won the race. " ELSE COLOR 15 Centre 13, " AI " + LTRIM$(STR$(i%)) + " won the race. " END IF SLEEP 1 EXIT DO END IF NEXT i% LOOP WHILE INKEY$ = "": WEND END SUB SUB DrawCars WAIT &H3DA, 8 FOR i% = 0 TO NumCars - 1 IF Cars(i%).oldX <> 0 THEN PUT (Cars(i%).oldX, Cars(i%).oldY), carSprite((Cars(i%).Car * 144 * 4) + (Cars(i%).oldDirection * 144)) END IF ' Grab the surface while there is no car on it Cars(i%).surface% = POINT(Cars(i%).x + 6, Cars(i%).y + 6) IF Cars(i%).drawSkid THEN IF Cars(i%).direction = 1 OR Cars(i%).direction = 3 THEN PSET (Cars(i%).oldX + 6, Cars(i%).oldY + 3), Cars(i%).skidColour PSET (Cars(i%).oldX + 6, Cars(i%).oldY + 9), Cars(i%).skidColour END IF IF Cars(i%).direction = 0 OR Cars(i%).direction = 2 THEN PSET (Cars(i%).oldX + 3, Cars(i%).oldY + 6), Cars(i%).skidColour PSET (Cars(i%).oldX + 9, Cars(i%).oldY + 6), Cars(i%).skidColour END IF Cars(i%).drawSkid = 0 END IF PUT (Cars(i%).x, Cars(i%).y), carSprite((Cars(i%).Car * 144 * 4) + (Cars(i%).direction * 144)) Cars(i%).oldX = Cars(i%).x Cars(i%).oldY = Cars(i%).y Cars(i%).oldDirection = Cars(i%).direction NEXT i% END SUB SUB DrawTriangle (x1%, y1%, x2%, y2%, x3%, y3%, C%) ' Ensure vertices are in the correct order IF y2% < y1% THEN SWAP y2%, y1%: SWAP x2%, x1% IF y3% < y1% THEN SWAP y3%, y1%: SWAP x3%, x1% IF y3% < y2% THEN SWAP y3%, y2%: SWAP x3%, x2% ' Scan convert top triangle ScanStartingEdge x1%, y1%, x2%, y2% ScanEndingEdge x1%, y1%, x3%, y3% height% = y2% - y1% FOR i% = 0 TO height% ey% = i% + y1% LINE (workingEdgeStart%(i%), ey%)-(workingEdgeEnd%(i%), ey%), C% NEXT i% IF y3% > y2% THEN ScanStartingEdge x2%, y2%, x3%, y3% height2% = y3% - y1% FOR i% = height% TO height2% ey% = i% + y1% LINE (workingEdgeStart%(i% - height%), ey%)-(workingEdgeEnd%(i%), ey%), C% NEXT i% END IF END SUB SUB GetCars i% = 0 l% = 0 v% = 0 DO READ l% READ v% FOR j% = 1 TO l% carSprite(i%) = v% i% = i% + 1 NEXT j% LOOP UNTIL i% >= 144 * 10 * 4 END SUB SUB GetCarVals (Cartype%, Car%) IF Cartype% = 0 THEN Cars(Car%).maxSpeed = 160 Cars(Car%).accel = 15 END IF IF Cartype% = 1 THEN Cars(Car%).maxSpeed = 200 Cars(Car%).accel = 11 END IF IF Cartype% = 2 THEN Cars(Car%).maxSpeed = 180 Cars(Car%).accel = 12 END IF IF Cartype% = 3 THEN Cars(Car%).maxSpeed = 215 Cars(Car%).accel = 10 END IF IF Cartype% = 4 THEN Cars(Car%).maxSpeed = 140 Cars(Car%).accel = 20 END IF IF Cartype% = 5 THEN Cars(Car%).maxSpeed = 170 Cars(Car%).accel = 14 END IF IF Cartype% = 6 THEN Cars(Car%).maxSpeed = 175 Cars(Car%).accel = 13 END IF IF Cartype% = 7 THEN Cars(Car%).maxSpeed = 150 Cars(Car%).accel = 17 END IF IF Cartype% = 8 THEN Cars(Car%).maxSpeed = 190 Cars(Car%).accel = 12 END IF IF Cartype% = 9 THEN Cars(Car%).maxSpeed = 245 Cars(Car%).accel = 8 END IF END SUB SUB GetTracks FOR i% = 0 TO MaxTracks - 1 READ TrackName(i%) READ NumSegments(i%) FOR j% = 0 TO NumSegments(i%) - 1 READ Track(i%, j%).angle, Track(i%, j%).length, Track(i%, j%).widthDelta NEXT j% NEXT i% END SUB FUNCTION MinDistToPoints% (px1%, py1%, ps1%, px2%, py2%, ps2%, px3%, py3%, ps3%, Car%, dir%, accel%) vx% = Cars(Car%).vx vy% = Cars(Car%).vy minDist1% = 32000 minDist2% = 32000 minDist3% = 32000 maxSpeed% = Cars(Car%).maxSpeed * 10 DecayFactor% = 25 IF NOT accel% THEN DecayFactor% = DecayFactor% * 2 decay% = Cars(Car%).decay speed% = Cars(Car%).speed skid% = Cars(Car%).skid skidDir% = Cars(Car%).skidDirection addedPenalty% = 0 IF skid% = -1 AND dir% <> Cars(Car%).direction THEN speed% = (speed% * 2) \ 3 IF speed% > 600 THEN addedPenalty% = addedPenalty% + 50 END IF IF Cars(Car%).speed > 75 AND dir% <> Cars(Car%).direction THEN skid% = -1 decay% = (speed% \ 20) * (speed% \ 20) IF dir% = skidDir% THEN decay% = 0 skid% = 0 ELSE skidDir% = Cars(Car%).direction END IF END IF FOR p% = 8 TO 0 STEP -1 IF decay% > speed% THEN decay% = speed% carSpeed% = (speed% - decay%) \ 25 IF dir% = 0 THEN vy% = vy% - carSpeed% IF dir% = 1 THEN vx% = vx% + carSpeed% IF dir% = 2 THEN vy% = vy% + carSpeed% IF dir% = 3 THEN vx% = vx% - carSpeed% IF accel% THEN speed% = speed% + (Cars(Car%).accel * 2) ELSE IF speed% > 0 THEN speed% = speed% - (1 + (speed% \ 25)) END IF IF skid% = -1 THEN IF skidDir% = 3 THEN vx% = vx% - (decay% \ 25) IF skidDir% = 1 THEN vx% = vx% + (decay% \ 25) IF skidDir% = 0 THEN vy% = vy% - (decay% \ 25) IF skidDir% = 2 THEN vy% = vy% + (decay% \ 25) decay% = decay% - ((DecayFactor% + Cars(Car%).accel) * 2) IF decay% < 2 THEN decay% = 0 skid% = 0 END IF END IF IF speed% < 0 THEN speed% = 0 IF speed% > maxSpeed% THEN speed% = maxSpeed% cx% = vx% \ 10 cy% = vy% \ 10 IF ABS(cx% - px1%) + ABS(cy% - py1%) - ps1% < minDist1% THEN minDist1% = ABS(cx% - px1%) + ABS(cy% - py1%) - ps1% IF ABS(cx% - px2%) + ABS(cy% - py2%) - ps2% < minDist2% THEN minDist2% = ABS(cx% - px2%) + ABS(cy% - py2%) - ps2% IF ABS(cx% - px3%) + ABS(cy% - py3%) - ps3% < minDist3% THEN minDist3% = ABS(cx% - px3%) + ABS(cy% - py3%) - ps3% IF minDist1% < 0 THEN minDist1% = 0 IF minDist2% < 0 THEN minDist2% = 0 IF minDist3% < 0 THEN minDist3% = 0 IF p% = 0 THEN IF POINT(cx% + 6, cy% + 6) = 2 THEN addedPenalty% = addedPenalty% + 250 END IF NEXT p% MinDistToPoints% = minDist1% + minDist2% + minDist3% + addedPenalty% END FUNCTION SUB PrintMenuStuff CLS COLOR 9 Centre 3, "VELOCITY" COLOR 1 Centre 4, "==========" COLOR 3 Centre 6, "Car" Centre 12, "Track" Centre 15, "AI Drivers" COLOR 8 Centre 7, "< >" Centre 13, "< >" Centre 16, "< >" END SUB SUB ResetKBState FOR i% = 0 TO 127 IsKeyPressed(i%) = 0 NEXT i% END SUB SUB ScanEndingEdge (x1%, y1%, x2%, y2%) DIM ex%, ey%, i%, w% DIM deltaX%, height% DIM advanceAmt%, errorTerm%, errorTermAdv% DIM xMajorAdvAmt% ex% = x1% deltaX% = x2% - x1% w% = ABS(deltaX%) IF deltaX% > 0 THEN advanceAmt% = 1 ELSE advanceAmt% = -1 height% = y2% - y1% IF height% <= 0 THEN workingEdgeEnd%(i%) = ex% EXIT SUB END IF ' Case 1: vertical IF w% = 0 THEN FOR i% = 0 TO height% workingEdgeEnd%(i%) = ex% NEXT i% ' Case 2: y-major ELSEIF height% > w% THEN IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeEnd%(i%) = ex% errorTerm% = errorTerm% + w% IF errorTerm% > 0 THEN ex% = ex% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% ' Case 3: x-major ELSE xMajorAdvAmt% = (w% \ height%) * advanceAmt% errorTermAdv% = w% MOD height% IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeEnd%(i%) = ex% ex% = ex% + xMajorAdvAmt% errorTerm% = errorTerm% + errorTermAdv% IF errorTerm% > 0 THEN ex% = ex% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% END IF END SUB SUB ScanStartingEdge (x1%, y1%, x2%, y2%) DIM ex%, ey%, i%, w% DIM deltaX%, height% DIM advanceAmt%, errorTerm%, errorTermAdv% DIM xMajorAdvAmt% ex% = x1% deltaX% = x2% - x1% w% = ABS(deltaX%) IF deltaX% > 0 THEN advanceAmt% = 1 ELSE advanceAmt% = -1 height% = y2% - y1% IF height% <= 0 THEN workingEdgeStart%(i%) = ex% EXIT SUB END IF ' Case 1: vertical IF w% = 0 THEN FOR i% = 0 TO height% workingEdgeStart%(i%) = ex% NEXT i% ' Case 2: y-major ELSEIF height% > w% THEN IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeStart%(i%) = ex% errorTerm% = errorTerm% + w% IF errorTerm% > 0 THEN ex% = ex% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% ' Case 3: x-major ELSE xMajorAdvAmt% = (w% \ height%) * advanceAmt% errorTermAdv% = w% MOD height% IF deltaX% >= 0 THEN errorTerm% = 0 ELSE errorTerm% = 1 - height% FOR i% = 0 TO height% workingEdgeStart%(i%) = ex% ex% = ex% + xMajorAdvAmt% errorTerm% = errorTerm% + errorTermAdv% IF errorTerm% > 0 THEN ex% = ex% + advanceAmt% errorTerm% = errorTerm% - height% END IF NEXT i% END IF END SUB SUB SetMenuNames IF Cars(0).Car = 0 THEN CarN$ = "Veloce" IF Cars(0).Car = 1 THEN CarN$ = "Testa" IF Cars(0).Car = 2 THEN CarN$ = "Wolf" IF Cars(0).Car = 3 THEN CarN$ = "GTR-1" IF Cars(0).Car = 4 THEN CarN$ = "Stinger" IF Cars(0).Car = 5 THEN CarN$ = "Rebel" IF Cars(0).Car = 6 THEN CarN$ = "Ace" IF Cars(0).Car = 7 THEN CarN$ = "Snake" IF Cars(0).Car = 8 THEN CarN$ = "Hurricane" IF Cars(0).Car = 9 THEN CarN$ = "Formula" TrackN$ = TrackName(SelectedTrack) END SUB SUB SingleMenu SCREEN 12 Item% = 0 PrintMenuStuff DO WAIT &H3DA, 8 SetMenuNames GetCarVals Cars(0).Car, 0 IF Item% = 0 THEN COLOR 15 ELSE COLOR 7 Pad$ = SPACE$((22 - LEN(CarN$)) \ 2) Centre 7, Pad$ + CarN$ + Pad$ COLOR 8 carSpeed% = (Cars(0).maxSpeed - 120) \ 12 Centre 9, " Speed: [ " + STRING$(carSpeed%, 254) + STRING$(10 - carSpeed%, 250) + " ]" carAccel% = ((Cars(0).accel - 6) * 10) \ 14 Centre 10, " Handling: [ " + STRING$(carAccel%, 254) + STRING$(10 - carAccel%, 250) + " ]" PUT (221, 127), carSprite((Cars(0).Car * 144 * 4)), PSET IF Item% = 1 THEN COLOR 15 ELSE COLOR 7 Pad$ = SPACE$((22 - LEN(TrackN$)) \ 2) Centre 13, Pad$ + TrackN$ + Pad$ IF Item% = 2 THEN COLOR 15 ELSE COLOR 7 Centre 16, " " + LTRIM$(STR$(NumCars - 1)) + " " IF Item% = 3 THEN COLOR 15 ELSE COLOR 7 Centre 19, "[ RACE ]" IF Item% = 4 THEN COLOR 15 ELSE COLOR 7 Centre 20, "[ Quit ]" a$ = "" WHILE a$ = "": a$ = INKEY$: WEND IF a$ = CHR$(0) + "H" THEN Item% = (Item% + 5 - 1) MOD 5 IF a$ = CHR$(0) + "P" THEN Item% = (Item% + 1) MOD 5 IF a$ = CHR$(0) + "K" THEN IF Item% = 0 THEN Cars(0).Car = (Cars(0).Car + 9) MOD 10 IF Item% = 1 THEN SelectedTrack = (SelectedTrack + (MaxTracks - 1)) MOD MaxTracks IF Item% = 2 AND NumCars > 2 THEN NumCars = NumCars - 1 END IF IF a$ = CHR$(0) + "M" THEN IF Item% = 0 THEN Cars(0).Car = (Cars(0).Car + 1) MOD 10 IF Item% = 1 THEN SelectedTrack = (SelectedTrack + 1) MOD MaxTracks IF Item% = 2 AND NumCars < MaxCars THEN NumCars = NumCars + 1 END IF IF a$ = CHR$(13) THEN IF Item% = 3 THEN BuildTrack SelectedTrack: DoRace: Item% = 0: PrintMenuStuff IF Item% = 4 THEN EXIT DO END IF IF UCASE$(a$) = "Q" THEN EXIT DO LOOP END SUB SUB UpdateKBState keyValue% = INP(&H60) HasKeyEvents = (keyValue% <> 0) isReleaseEvent = (keyValue% AND 128) <> 0 scanCode% = (keyValue% AND 127) IsKeyPressed(scanCode%) = NOT isReleaseEvent ClearKBBuffer END SUB