Duel

Authors

Mark Fisher

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.

  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<<<<<<<Dist.=";FN v(a,1,4);"x";FN v(a,1,5),"Missiles = ";FN v(a,1,2);" "
2030 LET s=1: GO SUB 300: REM s=step size
2040 PRINT #1;AT 0,0;,,
2050 IF NOT FN v(a,1,2) OR (px=0 AND py=0) THEN RETURN: REM no missiles fired
2060 LET a$(a,1,2)=CHR$ (FN v(a,1,2)-1)
2070 IF a$(a,2,1)=CHR$ 255 THEN GO TO 2100: REM fire #2
2080 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
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)<start THEN GO TO 9110
9070 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

Products

 

Downloadable Media

Scroll to Top