Authors
Publication
Publication Details
Volume: 4 Issue: 4
Date
Jul 1986
Pages
4-7
See all articles from CATS v4 n4
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 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.
- DEF FN is used to quickly move numerical values out of the character array where they are stored.
- 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.
- 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.
- Mode OVER 1 is used to erase PLOTted lines by re-PLOTting them.
10 REM Duel\n20 REM by Mark Fisher, c1986 Math by Murray Barasch\n21 REM https://archive.org/details/cats-newsletter/CATS%20v4%20n4%20Jul%201986/page/4/mode/1up?view=theater\n25 REM probably based on Race Track\n26 REM http://chesswanks.com/txt/RaceTrack.html\n30 ON ERR GO TO 9500\n40 DEF FN v(a,b,c)=CODE a$(a,b,c): REM Value\n50 DEF FN d(c)=FN v(a,b,c,)-FNv(a,b,c+2)\n60 GO TO 8000\n100 REM Get Coordinates\n110 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)\n120 LET dx=x-ox: LET dy=y-oy\n130 RETURN\n300 REM stick reading\n310 LET px=0: LET py=0: REM pointer x,y\n320 POKE 16384, STICK(1,r)\n330 LET px=px+s*((POINT (4,175) AND px<2 AND px+x<=254)-(POINT(5,175) AND px>-2 AND x-px>=1))\n340 LET py=py+s*((POINT (7,175) AND py<2 AND py+y<=173)-(POINT (6,175) AND ру>-2 AND у-ру>=2))\n350 PLOT x,y: DRAW 8*px/s,8*py/s\n360 LET ex=STICK(2,r)\n370 PLOT x,y: DRAW 8*px/s,8*py/s\n380 IF ex=0 THEN GO TO 320\n390 RETURN\n1000 REM Main Loop\n1010 FOR a=1 TO 2: IF q$="2" THEN LET r=a\n1020 INK a*2+3\n1030 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\n1040 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\n1050 GO SUB 2000: REM get missile firing orders\n1060 GO SUB 2500: REM move & update missiles\n1070 INK a*2+2\n1080 GO SUB 4000: REM get ship move\n1090 GO SUB 4500: REM move ship\n1100 REM IF INKEY$="s" THEN RANDOMIZE USR 64628: REM copy screen\n1110 LET o=a: NEXT a\n1120 GO TO 1000\n2000 REM Get Missile Coords\n2010 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\n2020 PRINT #1;AT 0,0;">>>>>>>>PLAYER #";a;" MISSILE<<<<<<<Dist.=";FN v(a,1,4);"x";FN v(a,1,5),"Missiles = ";FN v(a,1,2);" "\n2030 LET s=1: GO SUB 300: REM s=step size\n2040 PRINT #1;AT 0,0;,,\n2050 IF NOT FN v(a,1,2) OR (px=0 AND py=0) THEN RETURN: REM no missiles fired\n2060 LET a$(a,1,2)=CHR$ (FN v(a,1,2)-1)\n2070 IF a$(a,2,1)=CHR$ 255 THEN GO TO 2100: REM fire #2\n2080 IF a$(a,3,1)<>CHR$ 255 THEN LET b=3: LET tx=0: LET ty=0: PLOT x,y: GO SUB abort: REM if two other, abort #3\n2090 LET a$(a,3)=a$(a,2)\n2100 LET a$(a,2)=CHR$ 8+ CHR$ (px+3)+CHR$(py+3)+a$(1,4 TO ): REM fuel, x&y aim, and past movement\n2110 RETURN\n2500 REM update missile movement\n2510 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\n2520 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\n2530 IF NOT FN v(a,b,1) THEN LET a$(a,b,2 ТО 3)=CHR$ 0+CHR$ 0: REM if no fuel, no accel\n2540 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..\n2550 GO SUB nearmiss\n2560 PLOT x,y: DRAW tx,ty\n2570 IF t<=1 THEN GO SUB check: GO SUB abort: GO TO 2620\n2580 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\n2590 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\n2600 LET a$(a,b,8 TO )=a$(a,b,6 TO ): REM move track data\n2610 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\n2620 NEXT b\n2630 LET b=1: RETURN\n2800 REM abort missile\n2810 FOR c=14 TO 8 STEP -2: REM erase aborted missile\n2820 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)\n2830 NEXT c\n2840 LET a$(a,b,1)=" COPY "\n2850 PLOT x,y: DRAW tx,ty\n2860 RETURN\n3000 REM nearmiss\n3010 LET mcos=(tx)/(SQR ((tx)*(tx)+(ty)*(ty)))\n3020 LET msin=(ty)/(SQR ((ty)*(ty)+(tx)*(tx)))\n3030 LET scos=(sx-sox)/(SQR((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy)))\n3040 LET ssin=(sy-soy)/(SQR((soy-sy)*(soy-sy)+(sox-sx)*(sox-sx)))\n3050 LET mv=SQR (tx*tx+ty*ty)\n3060 LET sv=SQR ((sox-sx)*(sox-sx)+(soy-sy)*(soy-sy))\n3070 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)))\n3080 IF t<1 THEN LET tx=tx*t: LET ty=ty*t\n3090 RETURN\n3200 REM check miss\n3210 LET mx=tx+x: LET my=ty+y\n3220 LET sx=sox+t*sv*scos\n3230 LET sy=soy+t*sv*ssin\n3240 LET dx=sx-mx: REM Dist missile to opposing ship\n3250 LET dy=sy-my: REM Dist missile to opposing ship\n3260 IF ABS dx<8 AND ABS dy<8 THEN DRAW dx,dy: CIRCLE sx,sy,3: GO SUB boom\n3270 RETURN\n3500 REM boom\n3510 LET a$(o,1,3)=CHR$ (FN v(o,1,3)+2+(ABS dx<4)+(ABS dy<4))\n3520 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\n3530 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\n3540 FOR i=2 TO 10 STEP 3: CIRCLE mx,my,i: NEXT i\n3550 PRINT OVER 0;AT 1,7;" Ship ";o;" destroyed ": IF a$(o,1,3)<>" COPY " THEN LET k(a)=k(a)+1\n3560 LET а$(о,1,3) = " COPY "\n3570 IF a$(o,2,1)=" COPY " AND a$(o,3,1)=" COPY " THEN GO TO end: REM if no active missiles, stop.\n3580 RETURN\n4000 REM Ship Move\n4010 GO SUB 100: REM find parent ship\n4020 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)\n4030 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\n4040 LET s=2: GO SUB 300: LET px=px/2: LET py=py/2: REM coarser step than missile\n4050 RETURN\n4500 REM update ship movement\n4510 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\n4520 IF a$(a,1,3)=" COPY " THEN LET a$(a,1,8 TO )=a$(a,1,6 TO): GO TO 4620\n4530 LET mx=px*5+dx+FN v(a,1,6): LET my=py*5+dy+FN (a,1,7): REM Get new points\n4540 LET a$(a,b,1)=CHR$ (CODE a$(a,b,1)-5*(ABS px) AND CODE a$(a,b,1))\n4550 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\n4560 IF FN v(a,b,3)>0 THEN LET a$(a,b,3)=CHR$ (CODE a$(a,b,3)-1): REM reduce damage\n4570 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\n4580 LET dx=ABS (FN v(a,1,6)-FN v(o,1,6)): REM Dist to opposing ship\n4590 LET dy=ABS (FN v(a,1,7)-FN v(o,1,7)): REM Dist to opposing ship\n4600 LET a$(a,1,4 TO )=CHR$ dx+CHR$ dy+CHR$ mx+CHR$ my+a$(a,1,6 TO )\n4610 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\n4620 RETURN\n8000 REM setup\n8010 OVER 1: BORDER 0: PAPER 0: INK 7: CLS\n8020 GO SUB 8500\n8030 DIM a$(2,3,15): DIM k(2)\n8040 DIM d(2): LET x=0: LET y=0: LET b=1: REM x,y=screen coord,b=ship or missile select flag\n8050 LET dx=0: LET dy=0: LET o=2: REM x&y movement from last pos; o=other player\n8060 RESTORE 8100: FOR a=1 TO 2: FOR c=1 TO 15\n8070 READ x\n8080 LET a$(a,1,c)=CHR$ x\n8090 NEXT c: NEXT a\n8100 DATA 250,10,0,255,255,3,87,3,87,3,87,3,87,3,87: REM ship 1\n8110 DATA 250,10,0,255,255,252,87,252,87,252,87,252,87,252,87: REM ship 2\n8120 FOR b=2 TO 3\n8130 LET a$(1,b)=CHR$ 255+a$(1,1,2 TO ): LET a$(2,b)=CHR$ 255+a$(2,1,2 TO )\n8140 NEXT b\n8150 LET abort=2800\n8160 LET nearmiss=3000\n8170 LET check=3200\n8180 LET boom=3500\n8190 LET end=9560\n8200 PRINT #1;AT 0,0;"(I)nstructions, (1)-(2) Sticks";,,,: PAUSE 0: LET q$=INKEY$: LET r=1: CLS\n8210 IF NOT (q$="1" OR q$="2") THEN GO TO 8600\n8220 CIRCLE 252,87,1: CIRCLE 3,87,1: PLOT 3,3: DRAW 249,0: DRAW 0,169: DRAW -249,0: DRAW 0,-169\n8230 PRINT AT 1,3:d(1);TAB 28;d(2): LET b=1: FOR i=1 TO 2\n8240 FOR a=1 TO 2\n8250 GO SUB 100: READ px: READ py\n8260 DATA 1,0,-1,0,1,0,-1,0,1,-1,-1,1,1,-1,-1,1\n8270 GO SUB 4500\n8280 NEXT a: NEXT i\n8290 GO TO 1000\n8500 REM titles\n8510 PRINT AT 2,10;"************ * Duel * ************"\n8520 PRINT AT 5,15;"by";" Mark Fisher"," 1985"''" You are fighting a space duel. Each ship has 10 missiles and equal fuel."\n8530 PRINT " Missiles have proximity fuses- they will explode if they pass within 8 units."\n8540 PRINT " If damaged, you cannot change course, but you can still fire missiles."\n8550 PRINT " If you go out of bounds, you will be destroyed."\n8560 RETURN\n8600 REM Instructions\n8610 CLS: PRINT " Joysticks"''"Joysticks control direction of thrust of ships and missiles."\n8620 PRINT '"Actual direction is the functionof total acceleration applied tothe vehicle."\n8630 PRINT '"The missiles are aimed through 16 points:"\n8640 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\n8650 RESTORE 8640: FOR i=1 to 16: PAUSE 5: PLOT 40,60: READ x: READ y: DRAW 10*x,10*y: NEXT i\n8660 PRINT AT 18,0;"And ships are aimed through 8 points:"\n8670 DATA 1,0,1,-1,0,-1,-1,-1,-1,0,-1,1,0,1,1,1\n8680 RESTORE 8670: FOR i=1 TO 8: PAUSE 10: PLOT 210,60: READ x: REaD y: DRAW 10*x,10*y: NEXT i\n8690 PRINT "Press FIRE to enter desired vec-tor.";\n8700 PAUSE 100: PRINT #1;AT 0,0;"Try it now, using STICK 1: Press FIRE for more:"\n8710 CIRCLE 130,60,3: LET r=1: LET s=1: LET x=130: LET y=60: GO SUB 300\n8720 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."\n8730 PRINT '"2) A ship may only maintain 2 missiles: If a third is fired the oldest missile will be aborted."\n8740 PRINT '"3) Initial missile direction is determined by the ship's motion, added to the missile aim vector."\n8750 PRINT '"4) Missiles will be aborted when they no longer approach target."\n8760 PRINT #1;"(P) to play, (ENTER) to continue": PAUSE 0: LET q$=INKEY$: IF q$="p" THEN GO TO 8040\n8770 CLS: PRINT "Ships"''"Ship speed is built up by suc- cessive forward accelerations. If you accelerate five times forward, "\n8780 DATA 150,10,0,255,255,30,87,30,87,30,87,30,87,30,87: REM ship 1\n8790 RESTORE 8780: FOR c=1 TO 15: READ x: LET a$(1,1,c)=CHR$ x: NEXT c\n8800 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\n8810 INPUT "Press ENTER";q$: PRINT ''"- it will take five moves to return to a stop."\n8820 LET px=-1: FOR x=i TO 5: GO SUB 100: GO SUB 4500: NEXT i\n8830 GO TO 8040\n9000 REM Renumber and Save\n9010 INPUT "Start ";start\n9020 INPUT "End ";end\n9030 IF end>=9000 THEN LET end=9000\n9040 INPUT "Start renumber using ";n\n9050 LET x=PEEK 23635+256*PEEK 23636\n9060 IF PEEK x*256+PEEK (x+1)<start THEN GO TO 9110\n9070 IF PEEK x*256+PEEK (x+1)>=end THEN STOP\n9080 POKE x,INT (n/256)\n9090 POKE x+1,n-PEEK x*256\n9100 LET n=n+10\n9110 LET x=x+4+PEEK (x+2)+PEEK (x+3)\n9120 GO TO 9060\n9500 REM error handling\n9510 ON ERR RESET\n9520 IF PEEK 23739=21 OR PEEK 23739=9 THEN GO TO 9560: REM replay?\n9530 IF PEEK 23739=6 THEN LET t=1\n9540 ON ERR GO TO 9500\n9550 GO TO PEEK 23736+256*PEEK 23737+1\n9560 REM replay\n9570 PRINT AT 3,8;"Score is ";k(1);" to ";k(2);TAB 8;"Play again? (y/n)"\n9580 IF INKEY$="y" THEN GO TO 8040\n9590 IF INKEY$="n" THEN STOP\n9600 GO TO 9580