--- title: "Duel" type: "article" slug: "duel" url: "http://localhost/article/duel/" markdown_url: "http://localhost/article/duel.md" published_at: "2022-09-14T02:42:34+00:00" modified_at: "2026-06-21T23:20:35+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "A single or two player space game, inspired by Race Track, as described in a Martin Gardner column. Uses a number of the specialized abilities of the TS 2068, and a few tricks that speed up some of the BASIC. Character arrays are used to store the coordinate sequences that keep track of the ships…" category: - name: "CATS Newsletter" slug: "cats-newsletter" taxonomy: "category" url: "http://localhost/category/periodicals/cats-newsletter/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "Full Text" slug: "fulltext" taxonomy: "post_tag" url: "http://localhost/tag/fulltext/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" - name: "Type-in program" slug: "type-in-program" taxonomy: "post_tag" url: "http://localhost/tag/type-in-program/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Mark Fisher" slug: "mark-fisher" taxonomy: "indiv" url: "http://localhost/indiv/mark-fisher/" publication_r: id: 35941 title: "CATS Newsletter" type: "periodical" url: "http://localhost/periodical/cats-newsletter/" authors: "Mark Fisher" authors_r: - name: "Mark Fisher" slug: "mark-fisher" taxonomy: "indiv" url: "http://localhost/indiv/mark-fisher/" volume: "4" issue: "4" issues_articles: - id: 40100 title: "CATS v4 n4" type: "issue" url: "http://localhost/issue/cats-newsletter-v4-n4/" pages: "4-7" pubdate: "Jul 1986" download: "http://localhost/wp-content/uploads/2023/02/duel.tap" archive_link: false article_media: - id: 54507 title: "Space War" type: "computer_media" url: "http://localhost/computer_media/space-war/" --- # Duel A single or two player space game, inspired by [Race Track, as described in a Martin Gardner column](https://web.archive.org/web/20190724161306/http://chesswanks.com/txt/RaceTrack.html). Uses a number of the specialized abilities of the TS 2068, and a few tricks that speed up some of the BASIC. 1. Character arrays are used to store the coordinate sequences that keep track of the ships and missiles. This allows a single string slicing operation to shift the values to their new positions for each move, rather than a FOR-NEXT series of transfers. 2. DEF FN is used to quickly move numerical values out of the character array where they are stored. 3. ON ERR is used for two purposes: To allow the plotting of vectors that go off the screen without disrupting program flow, and later, to allow the 2068 to recover if a division by zero is encountered in calculating closest approaches. 4. STICK is decoded in an unusual way. As the bit values returned by STICK describe the position of the joystick, the value returned by STICK is poked into address 16384 (which just happens to be the first byte in the display tile), thus setting or resetting the first eight pixels of the dfile. POINT is used to pick up the individual pixel values. 5. Mode OVER 1 is used to erase PLOTted lines by re-PLOTting them. ``` 10 REM Duel 20 REM by Mark Fisher, c1986 Math by Murray Barasch 21 REM https://archive.org/details/cats-newsletter/CATS%20v4%20n4%20Jul%201986/page/4/mode/1up?view=theater 25 REM probably based on Race Track 26 REM http://chesswanks.com/txt/RaceTrack.html 30 ON ERR GO TO 9500 40 DEF FN v(a,b,c)=CODE a$(a,b,c): REM Value 50 DEF FN d(c)=FN v(a,b,c,)-FNv(a,b,c+2) 60 GO TO 8000 100 REM Get Coordinates 110 LET x=FN v(a,b,6): LET y=FN v(a,b,7): LET ox=FN v(a,b,8): LET oy=FN v(a,b,9) 120 LET dx=x-ox: LET dy=y-oy 130 RETURN 300 REM stick reading 310 LET px=0: LET py=0: REM pointer x,y 320 POKE 16384, STICK(1,r) 330 LET px=px+s*((POINT (4,175) AND px<2 AND px+x<=254)-(POINT(5,175) AND px>-2 AND x-px>=1)) 340 LET py=py+s*((POINT (7,175) AND py<2 AND py+y<=173)-(POINT (6,175) AND ру>-2 AND у-ру>=2)) 350 PLOT x,y: DRAW 8*px/s,8*py/s 360 LET ex=STICK(2,r) 370 PLOT x,y: DRAW 8*px/s,8*py/s 380 IF ex=0 THEN GO TO 320 390 RETURN 1000 REM Main Loop 1010 FOR a=1 TO 2: IF q$="2" THEN LET r=a 1020 INK a*2+3 1030 IF a$(a,1,3)=" COPY " THEN GO SUB 2500: LET px=0: LET py=0: GO TO 1090: REM ship gone but missiles active 1040 IF a$(o,1,3)=" COPY " AND a$(o,2,1)=" COPY " AND a$(o,3,1)=" COPY " THEN GO TO end: REM other ship gone and no missiles 1050 GO SUB 2000: REM get missile firing orders 1060 GO SUB 2500: REM move & update missiles 1070 INK a*2+2 1080 GO SUB 4000: REM get ship move 1090 GO SUB 4500: REM move ship 1100 REM IF INKEY$="s" THEN RANDOMIZE USR 64628: REM copy screen 1110 LET o=a: NEXT a 1120 GO TO 1000 2000 REM Get Missile Coords 2010 LET b=1: GO SUB 100: IF a$(a,1,2)=CHR$ 0 or a$(a,1,3)=" COPY " OR a$(o,1,3)=" COPY " THEN RETURN: REM find parent ship 2020 PRINT #1;AT 0,0;">>>>>>>>PLAYER #";a;" MISSILE<<<<<<CHR$ 255 THEN LET b=3: LET tx=0: LET ty=0: PLOT x,y: GO SUB abort: REM if two other, abort #3 2090 LET a$(a,3)=a$(a,2) 2100 LET a$(a,2)=CHR$ 8+ CHR$ (px+3)+CHR$(py+3)+a$(1,4 TO ): REM fuel, x&y aim, and past movement 2110 RETURN 2500 REM update missile movement 2510 LET a=0: LET b=1: GO SUB 100: LET a=(NOT a-1)+1: LET sx=x: LET sy=y: LET sox=ox: LET soy=oy 2520 FOR b=2 TO 3: GO SUB 100: IF a$(a,b,1)=" COPY " THEN GO TO 2620: REM if missile is inactive, skip update 2530 IF NOT FN v(a,b,1) THEN LET a$(a,b,2 ТО 3)=CHR$ 0+CHR$ 0: REM if no fuel, no accel 2540 LET tx=(FN v(a,b,2)-3)*5+dx: LET ty=(FN v(a,b,3)-3)*5+dy: LЕТ mx=tx+x: LET my=ty+y: REM Get new points.. 2550 GO SUB nearmiss 2560 PLOT x,y: DRAW tx,ty 2570 IF t<=1 THEN GO SUB check: GO SUB abort: GO TO 2620 2580 IF mx>253 OR mx<2 OR my>173 OR my<2 THEN GO SUB abort: GO TO 2620: REM and check that it is not off screen 2590 IF a$(a,b,12 TO 15)<>a$(a,1,12 TO 15) THEN PLOT FN v(a,b,14), FN v(a,b,15): DRAW FN d(12),FN d(13): REM If track is different from ship, erase track 2600 LET a$(a,b,8 TO )=a$(a,b,6 TO ): REM move track data 2610 LET a$(a,b,4 TO 7)=CHR$ ABS dx+CHR$ ABS dy+CHR$ mx+CHR$ my: IF a$(a,b,1)>CHR$ 0 THEN LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-1): REM update fuel and nex points 2620 NEXT b 2630 LET b=1: RETURN 2800 REM abort missile 2810 FOR c=14 TO 8 STEP -2: REM erase aborted missile 2820 IF a$(a,b,c-2 TO c-1)<>a$(a,1,c-2 TO c-1) THEN PLOT FN v(a,b,c),FN v(a,b,c+1): DRAW FN d(c-2),FN d(c-1) 2830 NEXT c 2840 LET a$(a,b,1)=" COPY " 2850 PLOT x,y: DRAW tx,ty 2860 RETURN 3000 REM nearmiss 3010 LET mcos=(tx)/(SQR ((tx)*(tx)+(ty)*(ty))) 3020 LET msin=(ty)/(SQR ((ty)*(ty)+(tx)*(tx))) 3030 LET scos=(sx-sox)/(SQR((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy))) 3040 LET ssin=(sy-soy)/(SQR((soy-sy)*(soy-sy)+(sox-sx)*(sox-sx))) 3050 LET mv=SQR (tx*tx+ty*ty) 3060 LET sv=SQR ((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy)) 3070 LET t=-((x-sox)*((mv*mcos)-(sv*scos))+(y-soy)*((mv*msin)-(sv*ssin)))/((mv*mv+sv*sv)-(2*mv*sv*(mcos*scos+msin*ssin))) 3080 IF t<1 THEN LET tx=tx*t: LET ty=ty*t 3090 RETURN 3200 REM check miss 3210 LET mx=tx+x: LET my=ty+y 3220 LET sx=sox+t*sv*scos 3230 LET sy=soy+t*sv*ssin 3240 LET dx=sx-mx: REM Dist missile to opposing ship 3250 LET dy=sy-my: REM Dist missile to opposing ship 3260 IF ABS dx<8 AND ABS dy<8 THEN DRAW dx,dy: CIRCLE sx,sy,3: GO SUB boom 3270 RETURN 3500 REM boom 3510 LET a$(o,1,3)=CHR$ (FN v(o,1,3)+2+(ABS dx<4)+(ABS dy<4)) 3520 CIRCLE mx,my,3: PRINT #1;AT 0,0;"<><>>=<>*/ SHIP #";o;" HIT ,/-^?'#$Damange =";FN v(o,1,3),"Dist. ";INT dx;" x ";INT dy;" ": PAUSE 200 3530 LET d(o)=d(o)+FN v(o,1,3):PRINT OVER 0;AT 1,2;d(1);TAB 28;d(2): IF FN v(o,1,3)<4 THEN RETURN 3540 FOR i=2 TO 10 STEP 3: CIRCLE mx,my,i: NEXT i 3550 PRINT OVER 0;AT 1,7;" Ship ";o;" destroyed ": IF a$(o,1,3)<>" COPY " THEN LET k(a)=k(a)+1 3560 LET а$(о,1,3) = " COPY " 3570 IF a$(o,2,1)=" COPY " AND a$(o,3,1)=" COPY " THEN GO TO end: REM if no active missiles, stop. 3580 RETURN 4000 REM Ship Move 4010 GO SUB 100: REM find parent ship 4020 PRINT #1;АТ 0,0;"^^^^^^^PLAYER #";a;" SHIP MOVE^^^^^^": FLASH FN v(a,1,3)>1;"Damage =";FN v(a,1,3); FLASH FN v(a,1,1)<20;" Fuel=";FN v(a,1,1);TAB 21;"Mssl =";FN v(a,1,2) 4030 IF a#(a,1,1)=CHR$ 0 OR a$(a,1,3)>CHR$ 1 THEN PAUSE 80: LET px=0: LET py=0: RETURN: REM if damage or no fuel, no accel 4040 LET s=2: GO SUB 300: LET px=px/2: LET py=py/2: REM coarser step than missile 4050 RETURN 4500 REM update ship movement 4510 PLOT FN v(a,1,14),FN (a,1,15): DRAW FN d(12),FN d(13): CIRCLE FN v(a,1,6),FN v(a,1,7),2: REM erase track 4520 IF a$(a,1,3)=" COPY " THEN LET a$(a,1,8 TO )=a$(a,1,6 TO): GO TO 4620 4530 LET mx=px*5+dx+FN v(a,1,6): LET my=py*5+dy+FN (a,1,7): REM Get new points 4540 LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-5*(ABS px) AND CODE a$(a,b,1)) 4550 LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-5*(ABS py) AND CODE a$(a,b,1)): REM reduce fuel if burned 4560 IF FN v(a,b,3)>0 THEN LET a$(a,b,3)=CHR$ (CODE a$(a,b,3)-1): REM reduce damage 4570 IF mx>253 OR mx<3 OR my>173 or my<3 THEN LET a$(a,1,3)=CHR$ 4: LET o=a: GO TO boom: REM and check that it is not off screen 4580 LET dx=ABS (FN v(a,1,6)-FN v(o,1,6)): REM Dist to opposing ship 4590 LET dy=ABS (FN v(a,1,7)-FN v(o,1,7)): REM Dist to opposing ship 4600 LET a$(a,1,4 TO )=CHR$ dx+CHR$ dy+CHR$ mx+CHR$ my+a$(a,1,6 TO ) 4610 PLOT FN v(a,1,8),FN v(a,1,9): DRAW FN d(6),FN d(7): CIRCLE FN v(a,1,6),FN v(a,1,7),2 4620 RETURN 8000 REM setup 8010 OVER 1: BORDER 0: PAPER 0: INK 7: CLS 8020 GO SUB 8500 8030 DIM a$(2,3,15): DIM k(2) 8040 DIM d(2): LET x=0: LET y=0: LET b=1: REM x,y=screen coord,b=ship or missile select flag 8050 LET dx=0: LET dy=0: LET o=2: REM x&y movement from last pos; o=other player 8060 RESTORE 8100: FOR a=1 TO 2: FOR c=1 TO 15 8070 READ x 8080 LET a$(a,1,c)=CHR$ x 8090 NEXT c: NEXT a 8100 DATA 250,10,0,255,255,3,87,3,87,3,87,3,87,3,87: REM ship 1 8110 DATA 250,10,0,255,255,252,87,252,87,252,87,252,87,252,87: REM ship 2 8120 FOR b=2 TO 3 8130 LET a$(1,b)=CHR$ 255+a$(1,1,2 TO ): LET a$(2,b)=CHR$ 255+a$(2,1,2 TO ) 8140 NEXT b 8150 LET abort=2800 8160 LET nearmiss=3000 8170 LET check=3200 8180 LET boom=3500 8190 LET end=9560 8200 PRINT #1;AT 0,0;"(I)nstructions, (1)-(2) Sticks";,,,: PAUSE 0: LET q$=INKEY$: LET r=1: CLS 8210 IF NOT (q$="1" OR q$="2") THEN GO TO 8600 8220 CIRCLE 252,87,1: CIRCLE 3,87,1: PLOT 3,3: DRAW 249,0: DRAW 0,169: DRAW -249,0: DRAW 0,-169 8230 PRINT AT 1,3:d(1);TAB 28;d(2): LET b=1: FOR i=1 TO 2 8240 FOR a=1 TO 2 8250 GO SUB 100: READ px: READ py 8260 DATA 1,0,-1,0,1,0,-1,0,1,-1,-1,1,1,-1,-1,1 8270 GO SUB 4500 8280 NEXT a: NEXT i 8290 GO TO 1000 8500 REM titles 8510 PRINT AT 2,10;"************ * Duel * ************" 8520 PRINT AT 5,15;"by";" Mark Fisher"," 1985"''" You are fighting a space duel. Each ship has 10 missiles and equal fuel." 8530 PRINT " Missiles have proximity fuses- they will explode if they pass within 8 units." 8540 PRINT " If damaged, you cannot change course, but you can still fire missiles." 8550 PRINT " If you go out of bounds, you will be destroyed." 8560 RETURN 8600 REM Instructions 8610 CLS: PRINT " Joysticks"''"Joysticks control direction of thrust of ships and missiles." 8620 PRINT '"Actual direction is the functionof total acceleration applied tothe vehicle." 8630 PRINT '"The missiles are aimed through 16 points:" 8640 DATA 2,0,2,-1,2,-2,1,-2,0,-2,-1,-2,-2,-2,-2,-1,-2,0,-1,1,-2,2,-1,2,0,2,1,2,2,2,2,1 8650 RESTORE 8640: FOR i=1 to 16: PAUSE 5: PLOT 40,60: READ x: READ y: DRAW 10*x,10*y: NEXT i 8660 PRINT AT 18,0;"And ships are aimed through 8 points:" 8670 DATA 1,0,1,-1,0,-1,-1,-1,-1,0,-1,1,0,1,1,1 8680 RESTORE 8670: FOR i=1 TO 8: PAUSE 10: PLOT 210,60: READ x: REaD y: DRAW 10*x,10*y: NEXT i 8690 PRINT "Press FIRE to enter desired vec-tor."; 8700 PAUSE 100: PRINT #1;AT 0,0;"Try it now, using STICK 1: Press FIRE for more:" 8710 CIRCLE 130,60,3: LET r=1: LET s=1: LET x=130: LET y=60: GO SUB 300 8720 CLS: PRINT '"Aiming missiles:"''"1) If aim vector is not plotted, a missile will not be fired. To skip missile firing, press FIRE without moving stick." 8730 PRINT '"2) A ship may only maintain 2 missiles: If a third is fired the oldest missile will be aborted." 8740 PRINT '"3) Initial missile direction is determined by the ship's motion, added to the missile aim vector." 8750 PRINT '"4) Missiles will be aborted when they no longer approach target." 8760 PRINT #1;"(P) to play, (ENTER) to continue": PAUSE 0: LET q$=INKEY$: IF q$="p" THEN GO TO 8040 8770 CLS: PRINT "Ships"''"Ship speed is built up by suc- cessive forward accelerations. If you accelerate five times forward, " 8780 DATA 150,10,0,255,255,30,87,30,87,30,87,30,87,30,87: REM ship 1 8790 RESTORE 8780: FOR c=1 TO 15: READ x: LET a$(1,1,c)=CHR$ x: NEXT c 8800 LET a=1: LET o=2: LET b=1: FOR i=1 to 5: GO SUB 100: LET px=1: LET py=0: GO SUB 4500: NEXT i 8810 INPUT "Press ENTER";q$: PRINT ''"- it will take five moves to return to a stop." 8820 LET px=-1: FOR x=i TO 5: GO SUB 100: GO SUB 4500: NEXT i 8830 GO TO 8040 9000 REM Renumber and Save 9010 INPUT "Start ";start 9020 INPUT "End ";end 9030 IF end>=9000 THEN LET end=9000 9040 INPUT "Start renumber using ";n 9050 LET x=PEEK 23635+256*PEEK 23636 9060 IF PEEK x*256+PEEK (x+1)=end THEN STOP 9080 POKE x,INT (n/256) 9090 POKE x+1,n-PEEK x*256 9100 LET n=n+10 9110 LET x=x+4+PEEK (x+2)+PEEK (x+3) 9120 GO TO 9060 9500 REM error handling 9510 ON ERR RESET 9520 IF PEEK 23739=21 OR PEEK 23739=9 THEN GO TO 9560: REM replay? 9530 IF PEEK 23739=6 THEN LET t=1 9540 ON ERR GO TO 9500 9550 GO TO PEEK 23736+256*PEEK 23737+1 9560 REM replay 9570 PRINT AT 3,8;"Score is ";k(1);" to ";k(2);TAB 8;"Play again? (y/n)" 9580 IF INKEY$="y" THEN GO TO 8040 9590 IF INKEY$="n" THEN STOP 9600 GO TO 9580 ``` ## Source Code: Space War ``` 10 REM ********* Space War *********************************** 20 ON ERR GO TO 9500 30 DEF FN v(a,b,c)=CODE a$(a,b,c): REM Value 40 DEF FN d(c)=FN v(a,b,c)-FN v(a,b,c+2) 50 GO TO 8000 100 REM *************** Get Coordinates *********************** 110 LET x=FN v(a,b,6): LET y=FN v(a,b,7): LET ox=FN v(a,b,8): LET oy=FN v(a,b,9) 120 LET dx=x-ox: LET dy=y-oy 130 RETURN 300 REM ****j** stick reading ********************************* 310 LET px=0: LET py=0: REM Pointer x,y 320 POKE 16384, STICK (1,1) 330 LET px=px+s*((POINT (4,175) AND px<2 AND px+x<=254)-(POINT (5,175) AND px>-2 AND x-px>=1)) 340 LET py=py+s*((POINT (7,175) AND py<2 AND py+y<=173)-(POINT (6,175) AND py>-2 AND y-py>=2)) 350 PLOT x,y: DRAW 8*px/s,8*py/s 360 REM IF px=0 AND py=0 THEN PAUSE 30 370 LET ex= STICK (2,1) 380 PLOT x,y: DRAW 8*px/s,8*py/s 390 IF ex=0 THEN GO TO 320 400 RETURN 1000 REM ***************** Main Loop *************************** 1010 FOR a=1 TO 2 1020 INK a*2+3 1030 IF a$(a,1, TO 5)=" " THEN GO SUB 2500: LET px=0: LET py=0: GO SUB 4500: GO TO 1100 1040 GO SUB 2000: REM get missile firing orders 1050 GO SUB 2500: REM move & update missiles 1060 INK a*2+2 1070 GO SUB 4000: REM get ship move 1080 GO SUB 4500: REM Move ship 1090 IF INKEY$="s" THEN RANDOMIZE USR 64628 1100 IF a$(o,1, TO 5)=" " AND a$(o,2,1)=" COPY " AND a$(o,3,1)=" COPY " THEN STOP 1110 LET o=a: NEXT a 1120 GO TO 1000 2000 REM ************* Get Missile coords ********************* 2010 LET b=1: GO SUB 100: IF a$(a,1,2)=CHR$ 0 OR a$(a,1, TO 5)=" " OR a$(o,1, TO 5)=" " THEN RETURN : REM find parent ship 2020 PRINT #1;AT 0,0;">>>>>>>>PLAYER #";a;" MISSILE<<<<<<CHR$ 255 THEN LET b=3: LET tx=0: LET ty=0: PLOT x,y: GO SUB abort: REM if two other, abort #3 2090 LET a$(a,3)=a$(a,2) 2100 LET a$(a,2)=CHR$ 8+CHR$ (px+3)+CHR$ (py+3)+a$(a,1,4 TO ): REM Fuel,x&y aim, and past movement 2110 RETURN 2500 REM ***************update missile movement***************** 2505 LET a=o: LET b=1: GO SUB 100: LET a=(NOT a-1)+1: LET sx=x: LET sy=y: LET sox=ox: LET soy=oy 2510 FOR b=2 TO 3: GO SUB 100: IF a$(a,b,1)=" COPY " THEN GO TO 2620: REM If missile is inactive, skip update 2520 IF NOT FN v(a,b,1) THEN LET a$(a,b,2 TO 3)=CHR$ 0+CHR$ 0: REM if no fuel, no accel 2530 LET tx=(FN v(a,b,2)-3)*5+dx: LET ty=(FN v(a,b,3)-3)*5+dy: LET mx=tx+x: LET my=ty+y: REM Get new points.. 2540 GO SUB nearmiss 2550 PLOT x,y: DRAW tx,ty 2565 IF t<=1 THEN GO SUB check: GO SUB abort: GO TO 2620 2570 IF mx>253 OR mx<2 OR my>173 OR my<2 THEN GO SUB abort: GO TO 2620: REM and check that it is not off screen 2580 IF a$(a,b,12 TO 15)<>a$(a,1,12 TO 15) THEN PLOT FN v(a,b,14),FN v(a,b,15): DRAW FN d(12),FN d(13): REM If track is different from ship, erase track 2590 LET a$(a,b,8 TO )=a$(a,b,6 TO ): REM move track data 2600 LET a$(a,b,4 TO 7)=CHR$ ABS dx+CHR$ ABS dy+CHR$ mx+CHR$ my: IF a$(a,b,1)>CHR$ 0 THEN LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-1): REM Update fuel& nex points 2620 NEXT b 2630 LET b=1: RETURN 2800 REM ******* abort missile ********************************* 2810 FOR c=14 TO 8 STEP -2: REM Erase aborted missile 2820 IF a$(a,b,c-2 TO c-1)<>a$(a,1,c-2 TO c-1) THEN PLOT FN v(a,b,c),FN v(a,b,c+1): DRAW FN d(c-2),FN d(c-1) 2830 NEXT c 2840 LET a$(a,b,1)=" COPY " 2850 PLOT x,y: DRAW tx,ty 2860 RETURN 3000 REM ******* nearmiss ************************************** 3010 LET mcos=(tx)/(SQR ((tx)*(tx)+(ty)*(ty))) 3020 LET msin=(ty)/(SQR ((ty)*(ty)+(tx)*(tx))) 3030 LET scos=(sx-sox)/(SQR ((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy))) 3040 LET ssin=(soy-sy)/(SQR ((soy-sy)*(soy-sy)+(sox-sx)*(sox-sx))) 3050 LET mv=SQR (tx*tx+ty*ty) 3060 LET sv=SQR ((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy)) 3100 LET t=-((x-sox)*((mv*mcos)-(sv*scos))+(y-soy)*((mv*msin)-(sv*ssin)))/((mv*mv+sv*sv)-(2*mv*sv*(mcos*scos+msin*ssin))) 3110 IF t<1 THEN LET tx=tx*t: LET ty=ty*t 3120 RETURN 3200 REM ********** check miss ********************************* 3220 LET mx=tx+x: LET my=ty+y 3230 LET sx=sox+t*sv*scos 3240 LET sy=soy+t*sv*ssin 3250 LET dx=mx-sx: REM Dist missile to opposing ship 3260 LET dy=my-sy: REM Dist missile to opposing ship 3270 IF ABS dx<12 AND ABS dy<12 THEN GO SUB boom 3280 RETURN 3500 REM ***** boom ******************************************** 3520 LET a$(o,1,3)=CHR$ (FN v(o,1,3)+2+(ABS dx<8)+(ABS dy<8)) 3530 CIRCLE mx,my,3: PRINT #1;AT 0,0;"*<><>>=<>*/ SHIP #";o;" HIT ,/-^?`#$Damage =";FN v(o,1,3),"Dist. ";INT dx;" x ";INT dy;" ": PAUSE 200 3540 IF FN v(o,1,3)<4 THEN RETURN 3550 FOR i=2 TO 10 STEP 3: CIRCLE mx,my,i: NEXT i 3560 PRINT OVER 0;AT 1,7;" Ship ";o;" destroyed " 3570 IF a$(o,2,1)=" COPY " AND a$(o,3,1)=" COPY " THEN STOP : REM if no active missiles, stop. 3580 LET a$(o,1, TO 5)=" " 3590 RETURN 4000 REM ****** Ship Move ************************************** 4010 GO SUB 100: REM find parent ship 4020 PRINT #1;AT 0,0;"^^^^^^^PLAYER #";a;" SHIP MOVE^^^^^^"; FLASH FN v(a,1,3)>1;"Damage =";FN v(a,1,3), FLASH FN v(a,1,1)<20;"Fuel =";FN v(a,1,1);" " 4030 IF a$(a,1,1)=CHR$ 0 OR a$(a,1,3)>CHR$ 1 THEN PAUSE 80: LET px=0: LET py=0: RETURN : REM if damage or no fuel, no accel 4040 LET s=2: GO SUB 300: LET px=px/2: LET py=py/2: REM coarser step than missile 4050 RETURN 4500 REM *********update ship movement ************************* 4510 PLOT FN v(a,1,14),FN v(a,1,15): DRAW FN d(12),FN d(13): CIRCLE FN v(a,1,6),FN v(a,1,7),2: REM erase track 4515 IF a$(a,1, TO 5)=" " THEN LET a$(a,1,8 TO )=a$(a,1,6 TO ): GO TO 4610 4520 LET mx=px*5+dx+FN v(a,1,6): LET my=py*5+dy+FN v(a,1,7): REM Get new points.. 4530 LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-(ABS px) AND CODE a$(a,b,1)) 4540 LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-(ABS py) AND CODE a$(a,b,1)): REM reduce fuel if burned 4550 IF FN v(a,b,3)>0 THEN LET a$(a,b,3)=CHR$ (CODE a$(a,b,3)-1): REM reduce damage 4560 IF mx>253 OR mx<2 OR my>173 OR my<2 THEN LET a$(a,1,3)=CHR$ 10: LET o=a: GO TO boom: REM and check that it is not off screen 4570 LET dx=ABS (FN v(a,1,6)-FN v(o,1,6)): REM Dist to opposing ship 4580 LET dy=ABS (FN v(a,1,7)-FN v(o,1,7)): REM Dist to opposing ship 4590 LET a$(a,1,4 TO )=CHR$ dx+CHR$ dy+CHR$ mx+CHR$ my+a$(a,1,6 TO ) 4600 PLOT FN v(a,1,8),FN v(a,1,9): DRAW FN d(6),FN d(7): CIRCLE FN v(a,1,6),FN v(a,1,7),2 4610 RETURN 6000 { GO TO 9500: LET x1=0: LET y1=20 6010 LET i=2*PI/360 6020 PLOT 125,80: DRAW x1,y1 6030 PRINT x1,y1 6040 LET t=ATN (y1/x1) 6050 PRINT t,t/i 6060 INPUT x,y 6070 IF SGN x1=SGN x AND SGN y1=SGN y THEN LET t=t+PI 6080 PRINT t/i 6090 DRAW x,y 6100 PRINT "- ";ATN (y/x)/i,(t-ATN (y/x))/i 6110 PAUSE 0: CLS 7000 GO TO 6000 7999 STOP 8000 REM ******************** Setup **************************** 8010 OVER 1: BORDER 0: PAPER 0: INK 7: CLS 8015 GO SUB 8500 8020 DIM a$(2,3,15) 8030 LET x=0: LET y=0: LET b=1: REM x,y=screen coord,b=ship or missile select flag 8040 LET dx=0: LET dy=0: LET o=2: REM x&y movement from last pos; o=other player 8050 FOR a=1 TO 2: FOR c=1 TO 15 8060 READ x 8070 LET a$(a,1,c)=CHR$ x 8080 NEXT c: NEXT a 8090 DATA 150,10,0,255,255,3,87,3,87,3,87,3,87,3,87: REM ship #1 8100 DATA 150,10,0,255,255,252,87,252,87,252,87,252,87,252,87: REM ship #2 8110 FOR b=2 TO 3 8120 LET a$(1,b)=CHR$ 255+a$(1,1,2 TO ): LET a$(2,b)=CHR$ 255+a$(2,1,2 TO ) 8130 NEXT b 8140 LET abort=2800 8150 LET nearmiss=3000 8155 LET check=3200 8160 LET boom=3500 8170 CIRCLE 252,87,1: CIRCLE 3,87,1: PLOT 3,3: DRAW 249,0: DRAW 0,169: DRAW -249,0: DRAW 0,-169 8180 LET b=1: FOR i=1 TO 2 8190 FOR a=1 TO 2 8200 GO SUB 100: READ px: READ py 8210 DATA 1,0,-1,0,1,0,-1,0,1,-1,-1,1,1,-1,-1,1 8220 GO SUB 4500 8230 NEXT a: NEXT i 8231 PRINT #1;AT 0,0;"Press any key to play": PAUSE 0: GO SUB 8500 8240 GO TO 1000 8500 REM ******* titles **************************************** 8510 PRINT AT 2,10;"************ * spacewar * ************" 8520 PRINT AT 5,15;"by"," Mark Fisher"," \* 1985"''" You are fighting a space duel. Each ship has 10 missiles and equal fuel." 8530 PRINT " Missiles have proximity fuses- they will explode if they pass within 15 units." 8540 PRINT " If damaged, you cannot change course, but you can still fire missiles." 8550 PRINT " If you go out of bounds, you will be destroyed." 8560 RETURN 9000 REM ********** Renumber and Save ************************** 9010 INPUT "Start ";start 9020 INPUT "End ";end 9030 IF end>=9000 THEN LET end=9000 9040 INPUT "Start renumber using ";n 9050 LET x=PEEK 23635+256*PEEK 23636 9060 IF PEEK x*256+PEEK (x+1)=end THEN STOP 9080 POKE x,INT (n/256) 9090 POKE x+1,n-PEEK x*256 9100 LET n=n+10 9110 LET x=x+4+PEEK (x+2)+PEEK (x+3) 9120 GO TO 9060 9500 REM *********** error handling **************************** 9510 ON ERR RESET 9520 IF PEEK 23739=21 OR PEEK 23739=9 THEN GO TO 9560: REM replay? 9530 IF PEEK 23739=6 THEN LET t=PI/2 9540 ON ERR GO TO 9500 9550 GO TO PEEK 23736+256*PEEK 23737+1 9560 REM ***** replay ****************************************** 9570 PRINT AT 3,8;"Play again? (y/n)" 9580 IF INKEY$="y" THEN RUN 9590 IF INKEY$="n" THEN STOP 9600 GO TO 9580 9610 REM ***** start up **************************************** 9800 CLEAR 64255: LET p=64261: POKE 26704,INT (p/256): POKE 26703,p-(INT (p/256)*256): LOAD ""CODE 9810 RUN 9900 CLEAR : SAVE "spacewar" LINE 9800: SAVE "prcode"CODE 64256,1111 9910 PRINT "rewind and verify:"'': VERIFY "spacewar": VERIFY "prcode"CODE 9999 INK 7: LIST 2500 ```