; Sneak Attack by David Plotkin MODULE BYTE ChrBase=756,Max,Bkgrnd=710, Fate=53770,Level=[1],CursIn=752, Stick=632,Ps,Loud=[0],Indx=[0], DownL=[0],DownR=[0],Loud1=[0], Snd1=$D208,Snd2=$D20F,Freq=[169], Wsync=$D40A,Colbk=$D018, Nmien=$D40E,Hard=[15], Consol=53279 CARD Scrn=88,RamSet,HiMem=$2E5, Score=[0],Comp=[300],Sdlst=560, Vdslst=512 CARD ARRAY Linept(24) BYTE ARRAY Charset,Chopperstatus(30), Chopperx(30),Choppery(30), Expx(60),Expy(60),ExpStatus(60), TrStatus(30),Trx(30),Try(30), MisStatus(30),Misx(30),Misy(30), Ll(20),Rr(20),Dlist, ShapeTable(0)= [254 16 124 71 127 12 62 0 127 8 62 226 254 24 126 0 96 96 48 48 24 60 231 255 24 24 24 24 24 60 231 255 6 6 12 12 24 60 231 255 128 85 17 66 24 170 91 131 60 126 255 255 195 66 36 24 60 36 24 255 60 24 36 102 0 0 0 0 0 0 0 0 60 36 24 255 60 24 36 102 60 36 219 255 60 24 36 102 60 60 24 60 60 24 24 28 60 60 24 60 60 60 102 195] PROC Download() ;Step back HiMem and move the ;character set into RAM CARD Index BYTE Val RamSet=(HiMem-$400)&$FC00 ChrBase=RamSet RSH 8 HiMem=RamSet FOR Index=0 TO 1023 DO Val=Peek(57344+Index) Poke(RamSet+Index,Val) OD Charset=RamSet RETURN PROC Dlint() ;the display list interrupt routine [$48 $8A $48 $98 $48] Wsync=1 Colbk=50 [$68 $A8 $68 $AA $68 $40] PROC ScoreLine() ;set up the dli Dlist=Sdlst Vdslst=Dlint Dlist(27)=130 Nmien=$C0 RETURN PROC Update() ;print score and level Position(1,23) Print("Score: ") Position(8,23) PrintC(Score) Position(18,23) Print("Level: ") Position(25,23) PrintB(Level) RETURN PROC Title() BYTE colpf0=53270,colpf1=53271, colpf2=53273,colpf3=53273, rtclock=20,vcount=54283 Graphics(18) Position(3,4) PrintD(6,"SNEAK ATTACK") Position(8,5) PrintD(6,"BY") Position(3,7) PrintD(6,"david plotkin") Position(3,9) PrintD(6,"PRESS start") WHILE Consol<>6 DO colpf3=Fate Wsync=0 colpf0=128-vcount+rtclock RSH 2 colpf1=vcount+rtclock RSH 2 OD RETURN PROC Gr0Init() ;Set up the address of each screen ;line and initialize CARD xx Graphics(0) CursIn=1 Print(" ") FOR xx=0 TO 23 DO Linept(xx)=Scrn+(40*xx) OD FOR xx=0 TO 29 DO Chopperstatus(xx)=0 Chopperx(xx)=0 Choppery(xx)=0 Misx(xx)=0 Misy(xx)=0 MisStatus(xx)=0 TrStatus(xx)=0 OD FOR xx=0 TO 59 DO ExpStatus(xx)=0 OD FOR xx=0 TO 19 DO Ll(xx)=0 Rr(xx)=0 OD Bkgrnd=0 Update() RETURN PROC Plot0(BYTE x,y,ch) ;Plot a char at location x,y BYTE ARRAY line line=Linept(y) line(x)=ch RETURN BYTE FUNC Locate0(BYTE x,y) ;Returns the value of the char at x,y BYTE ARRAY line line=Linept(y) RETURN(line(x)) PROC Noise() ;the explosion noises IF Loud=0 AND Loud1=0 AND Freq=169 THEN RETURN FI IF Loud THEN Loud==-2 Sound(0,90,8,Loud) FI IF Loud1 THEN Loud1==-2 Sound(1,150,8,Loud1) FI IF Freq<168 THEN Freq==+8 Sound(2,Freq,10,4) ELSE Freq=169 Sound(2,0,0,0) FI RETURN PROC HitChute(BYTE wh) ;see which chute was hit by missile wh BYTE lp FOR lp=0 TO 29 DO IF Misx(wh)=Trx(lp) AND (Misy(wh)=Try(lp) OR Misy(wh)=Try(lp)+1) THEN TrStatus(lp)=2 Plot0(Trx(lp),Try(lp),0) Plot0(Trx(lp),Try(lp)+1,10) Plot0(Trx(lp),Try(lp)+2,0) EXIT FI OD IF Try(lp) LSH 3 < Freq THEN Freq=Try(lp) LSH 3 FI RETURN PROC HitMan(BYTE wh) ;see which man was hit by missile wh BYTE lp FOR lp=0 TO 29 DO IF Misx(wh)=Trx(lp) AND (Misy(wh)=Try(lp)+1 OR Misy(wh)=Try(lp)+2) THEN TrStatus(lp)=3 Plot0(Trx(lp),Try(lp)+1,6) Plot0(Trx(lp),Try(lp),0) Plot0(Trx(lp),Try(lp)+2,0) FI OD Loud1=12 RETURN PROC ExplodeChopper(BYTE lp) ;explosions in place of Chopper lp BYTE lq FOR lq=0 TO 59 STEP 2 DO ;find empty IF ExpStatus(lq)=0 THEN ExpStatus(lq)=1 ExpStatus(lq+1)=1 Expx(lq)=Chopperx(lp) Expx(lq+1)=Chopperx(lp)+1 Expy(lq)=Choppery(lp) Expy(lq+1)=Choppery(lp) Chopperstatus(lp)=0 Plot0(Expx(lq),Expy(lq),6) Plot0(Expx(lq+1),Expy(lq+1),6) EXIT FI OD RETURN PROC HitChopper(BYTE wh) ;which chopper was hit by missile wh BYTE lp FOR lp=0 TO 29 DO IF Misy(wh)=Choppery(lp) AND (Misx(wh)=Chopperx(lp) OR Misx(wh)=Chopperx(lp)+1) THEN ExplodeChopper(lp) EXIT FI OD Loud=12 RETURN PROC MissileHit(BYTE wh) ;see if missile wh hit anything BYTE dum dum=Locate0(Misx(wh),Misy(wh)) IF dum=0 THEN Plot0(Misx(wh),Misy(wh),84) RETURN FI MisStatus(wh)=0 IF dum=1 OR dum=2 THEN HitChopper(wh) Score==+1 ELSEIF (dum=7 AND Indx<6 OR dum=8 AND Indx>3) THEN HitChute(wh) Score==+2 ELSEIF (dum=8 AND Indx<4 OR dum=9 AND Indx>1) THEN HitMan(wh) Score==+1 FI RETURN PROC Modify() ;Modify the RAM character set CARD xx FOR xx=0 TO 103 DO Charset(xx+8)=ShapeTable(xx) OD RETURN PROC LaunchTrooper(BYTE wh) ;drop a paratrooper from chopper wh BYTE lp IF Fate>240-(Level LSH 1) THEN FOR lp=0 TO 29 DO ;find MT trooper IF TrStatus(lp)=0 THEN ;got one TrStatus(lp)=1 Trx(lp)=Chopperx(wh) IF Trx(lp)=0 THEN Trx(lp)=1 FI Try(lp)=Choppery(wh)+1 Plot0(Trx(lp),Try(lp),7) Plot0(Trx(lp),Try(lp)+1,8) Plot0(Trx(lp),Try(lp)+2,9) EXIT FI OD FI RETURN PROC EraseChopper(BYTE wh) ;erase chopper number wh Plot0(Chopperx(wh),Choppery(wh),0) Plot0(Chopperx(wh)+1,Choppery(wh),0) Chopperstatus(wh)=0 Chopperx(wh)=0 Choppery(wh)=0 RETURN PROC DrawChopper(BYTE wh) ;draw chopper number wh Plot0(Chopperx(wh),Choppery(wh),1) Plot0(Chopperx(wh)+1,Choppery(wh),2) RETURN PROC ClearScreen() ;clear the screen BYTE lp FOR lp=0 TO 29 DO IF Chopperstatus(lp) THEN EraseChopper(lp) FI IF TrStatus(lp) THEN TrStatus(lp)=0 Plot0(Trx(lp),Try(lp),0) Plot0(Trx(lp),Try(lp)+1,0) Plot0(Trx(lp),Try(lp)+2,0) FI IF MisStatus(lp)=1 THEN MisStatus(lp)=0 Plot0(Misx(lp),Misy(lp),0) FI OD FOR lp=0 TO 59 STEP 2 DO IF ExpStatus(lp)=1 THEN ExpStatus(lp)=0 ExpStatus(lp+1)=0 Plot0(Expx(lp),Expy(lp),0) Plot0(Expx(lp+1),Expy(lp+1),0) FI OD RETURN PROC MoveChopper() ;move the choppers BYTE lp,ps=[0] FOR lp=0 TO 29 DO IF Chopperstatus(lp)=1 THEN ;right IF Chopperx(lp)=38 THEN EraseChopper(lp) ELSE Plot0(Chopperx(lp), Choppery(lp),0) Chopperx(lp)==+1 DrawChopper(lp) LaunchTrooper(lp) FI FI IF Chopperstatus(lp)=2 THEN ;left IF Chopperx(lp)=0 THEN EraseChopper(lp) ELSE Plot0(Chopperx(lp)+1, Choppery(lp),0) Chopperx(lp)==-1 DrawChopper(lp) LaunchTrooper(lp) FI FI OD IF ps=0 THEN Charset(8)=56 Charset(16)=28 ps=1 ELSE ps=0 Charset(8)=254 Charset(16)=127 FI RETURN PROC LaunchChopper() ;Decide whether to send off a new ;chopper, which side, how high up BYTE lp IF Fate>230-(Level LSH 1) THEN FOR lp=0 TO 29 DO ;find MT chopper IF Chopperstatus(lp)=0 THEN Choppery(lp)=Rand(Hard) IF Fate>128 THEN Chopperx(lp)=38 ;right side Chopperstatus(lp)=2 ELSE Chopperx(lp)=0 ;left side Chopperstatus(lp)=1 FI DrawChopper(lp) EXIT FI OD FI RETURN PROC DrawBase() ;draw the base BYTE lp FOR lp=19 TO 21 DO Plot0(lp,22,128) OD Plot0(20,21,4) RETURN PROC AimGun() ;read the joystick and move the base IF Stick=11 THEN Ps=3 ELSEIF Stick=7 THEN Ps=5 ELSE Ps=4 FI Plot0(20,21,Ps) RETURN PROC Shoot() ;send off a bullet BYTE trig=644,lp,flg=[0] IF trig=1 OR flg=0 THEN flg=1 RETURN FI FOR lp=0 TO 29 DO ;find empty shot IF MisStatus(lp)=0 THEN ;got one MisStatus(lp)=1 Misy(lp)=20 IF Ps=3 THEN Misx(lp)=19 ELSEIF Ps=5 THEN Misx(lp)=21 ELSE Misx(lp)=20 FI MissileHit(lp) EXIT FI OD flg=0 RETURN PROC MoveShots() ;move the fired bullets BYTE lp FOR lp=0 TO 29 DO ;for each shot IF MisStatus(lp)=1 THEN Plot0(Misx(lp),Misy(lp),0) IF Stick=11 THEN Misx(lp)==-1 ELSEIF Stick=7 THEN Misx(lp)==+1 ELSE Misy(lp)==-1 FI IF (Misx(lp)<>39 AND Misy(lp)<>255 AND Misx(lp)<>0) THEN MissileHit(lp) ELSE MisStatus(lp)=0 FI FI OD RETURN PROC MoveExplosions() ;move the explosions BYTE lp FOR lp=0 TO 59 STEP 2 DO IF ExpStatus(lp)=1 THEN Plot0(Expx(lp),Expy(lp),0) Plot0(Expx(lp+1),Expy(lp+1),0) Expy(lp)==+1 Expy(lp+1)==+1 Expx(lp)==-1 Expx(lp+1)==+1 IF Expy(lp)<>22 AND Expx(lp)<>0 AND Expx(lp+1)<>39 THEN Plot0(Expx(lp),Expy(lp),6) Plot0(Expx(lp+1),Expy(lp+1),6) ELSE ExpStatus(lp)=0 ExpStatus(lp+1)=0 FI FI OD RETURN PROC BaseExplode() ;explode the base BYTE ARRAY endx(0)=[16 24 17 23 20], endy(0)=[22 22 19 19 17] BYTE lp,time=20 color=38 FOR lp=0 TO 4 DO Plot(20,22) DrawTo(endx(lp),endy(lp)) OD FOR lp=0 TO 16 DO Sound(0,Fate,8,16-lp) Sound(1,Fate,8,16-lp) time=0 DO UNTIL time=15 OD OD SndRst() color=32 FOR lp=0 TO 4 DO Plot(20,22) DrawTo(endx(lp),endy(lp)) OD RETURN PROC EndRight() ;move the troopers from the right ;to the base BYTE lp,lq,nn,time=20 FOR lp=0 TO 19 DO IF Rr(lp)=1 THEN lq=21+lp WHILE lq>20 DO IF nn=12 THEN nn=13 ELSE nn=12 FI Plot0(lq,22,nn) time=0 DO UNTIL time=10 OD Plot0(lq,22,0) lq==-1 OD Plot0(21,22,11) FI OD FOR lp=0 TO 3 DO Plot0(21,22-lp,11) time=0 DO UNTIL time=10 OD OD BaseExplode() RETURN PROC EndLeft() ;Move the troopers from the left to ;the base BYTE lp,lq,lc,nn,time=20 FOR lp=0 TO 19 DO lq=19-lp IF Ll(lq)=1 THEN FOR lc=lq TO 19 DO IF nn=12 THEN nn=13 ELSE nn=12 FI Plot0(lc,22,nn) time=0 DO UNTIL time=10 OD Plot0(lc,22,0) OD Plot0(19,22,11) FI OD FOR lp=0 TO 3 DO Plot0(19,22-lp,11) time=0 DO UNTIL time=10 OD OD BaseExplode() RETURN PROC EndPrint() ;print the end of game message and ;test for new game BYTE trig=644,lp Position(10,7) Print("Game Over...Final Score:") Position(15,8) PrintC(Score) Position(15,9) Print("FINAL LEVEL :") PrintB(Level) Position(10,20) Print("Press FIRE to play again") DO UNTIL trig=0 OD DownL=0 DownR=0 Put(125) FOR lp=0 TO 19 DO Ll(lp)=0 Rr(lp)=0 OD Score=0 Level=1 DrawBase() Update() Hard=15 RETURN PROC GameOverTwo() ;game over when four troopers down BYTE lp SndRst() ClearScreen() Loud=0 Loud1=0 Freq=169 FOR lp=0 TO 19 DO IF Ll(lp)=1 THEN Plot0(lp,22,11) FI IF Rr(lp)=1 THEN Plot0(lp+21,22,11) FI OD IF DownL=4 THEN EndLeft() ELSE EndRight() FI EndPrint() RETURN PROC GameOverOne() ;game over when trooper lands on base BYTE lp SndRst() ClearScreen() Loud=0 Loud1=0 Freq=169 FOR lp=0 TO 19 DO IF Ll(lp)=1 THEN Plot0(lp,22,11) FI IF Rr(lp)=1 THEN Plot0(lp+21,22,11) FI OD BaseExplode() EndPrint() RETURN PROC TrooperDown(BYTE wh) ;redraw trooper wh at bottom of screen BYTE cc TrStatus(wh)=0 cc=Trx(wh) Plot0(Trx(wh),Try(wh),0) ;erase chute Plot0(Trx(wh),Try(wh)+1,11) ;replace IF Trx(wh)<20 AND Ll(cc)=0 THEN Ll(cc)=1 DownL==+1 ELSEIF Trx(wh)>20 AND Rr(cc-21)=0 THEN Rr(cc-21)=1 DownR==+1 ELSEIF Trx(wh)=20 THEN GameOverOne() FI IF DownL=4 OR DownR=4 THEN GameOverTwo() FI RETURN PROC TrooperFall() ;make trooper fall when chute hit BYTE lp,qq,cc FOR lp=0 TO 29 DO IF TrStatus(lp)=2 THEN Plot0(Trx(lp),Try(lp)+1,0) Try(lp)==+1 IF Try(lp)=21 THEN cc=Trx(lp) IF Trx(lp)<20 AND Ll(cc)=1 THEN DownL==-1 Ll(cc)=0 ELSEIF Trx(lp)>20 AND Rr(cc-21)=1 THEN Rr(cc-21)=0 DownR==-1 FI FI IF (Try(lp)<22 AND Trx(lp)<>20) OR (Try(lp)<20 AND Trx(lp)=20) THEN Plot0(Trx(lp),Try(lp)+1,10) ELSE TrStatus(lp)=0 FI FI OD RETURN PROC MoveTroopers() ;move paratroopers down screen BYTE lp,qq BYTE ARRAY Trooper(0)= [60 126 255 255 195 66 36 24 60 36 24 255 60 24 36 102 0 0 0 0 0 0 0 0] FOR lp=0 TO Indx DO Charset(56+lp)=0 OD MoveBlock(Charset+56+Indx+1, Trooper,16) Indx==+1 IF Indx<8 THEN RETURN FI Indx=0 FOR lp=0 TO 29 DO IF TrStatus(lp)=1 THEN Plot0(Trx(lp),Try(lp),0) Try(lp)==+1 IF Try(lp)=21 THEN TrooperDown(lp) FI FI IF TrStatus(lp)=3 THEN TrStatus(lp)=0 Plot0(Trx(lp),Try(lp)+1,0) FI OD MoveBlock(Charset+56,Trooper,24) FOR lp=0 TO 29 DO IF TrStatus(lp)=1 THEN Plot0(Trx(lp),Try(lp),7) Plot0(Trx(lp),Try(lp)+1,8) Plot0(Trx(lp),Try(lp)+2,9) FI OD RETURN PROC NewLevel() ;go to higher level BYTE lp,time=20 Level==+1 IF Level>100 THEN Level=100 FI SndRst() Loud=0 Loud1=0 Freq=169 Comp==+300 FOR lp=10 TO 150 STEP 10 DO Sound(0,lp,10,4) Sound(1,lp+10,10,4) time=0 DO UNTIL time=2 OD OD Position(25,23) PrintB(Level) IF Level>8 THEN Hard=19 FI SndRst() RETURN PROC Main() BYTE time=20,lp,ch=764 Title() Gr0Init() Snd1=0 Snd2=3 Download() Modify() DrawBase() ScoreLine() DO LaunchChopper() MoveChopper() MoveExplosions() Noise() TrooperFall() MoveTroopers() Position(8,23) PrintC(Score) IF Score>Comp THEN NewLevel() FI time=0 FOR lp=2 TO 6 STEP 2 DO AimGun() Shoot() MoveShots() DO UNTIL time=lp OD OD OD RETURN