Mad Dog Tank Blaster

Developer(s): Thomas B. Woods
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Game

Mad Dog Tank Blaster is a two-character action game in which the player manoeuvres a soldier (“O”) around a grid while an enemy tank (“X”) moves and fires bullets in random directions. The player wins by placing up to five mines (key “P”) in the tank’s path; the tank wins by running the player down, shooting them, or surviving 30 turns. The grid is stored in a 19×29 array S() where value 1 marks a mine and value 2 marks the player’s position, allowing collision detection without screen-scanning. Movement subroutines are dispatched via computed GOSUB (e.g., GOSUB 1000+INT(RND*4)*100) to choose one of four cardinal directions each turn, and bullet travel is handled in separate FOR loops that step by 5 columns/rows.


Program Structure

The program divides cleanly into several functional blocks:

  1. Lines 1–32: Variable initialisation and title-screen display with block-graphic tank art.
  2. Lines 35–54: Brief animated “explosion” flash on the title screen (asterisks printed and erased).
  3. Lines 70–97: Instructions screen, shown only on the first game (TANK=0 and YOU=0).
  4. Lines 97–165: Grid drawing (in FAST mode) and player/tank placement.
  5. Lines 170–610: Main game loop: read input, dispatch a random tank movement subroutine, increment turn counter, check for timeout.
  6. Lines 1000–1360: Four tank-movement/firing subroutines at 1000, 1100, 1200, 1300 (right, left, down, up).
  7. Lines 2002–2845: Player movement subroutines (left 2500, down 2600, up 2700, right 2800) plus mine-placement at 3000.
  8. Lines 7000–7990: Near-miss explosion when bullet reaches player column/row without hitting a mine.
  9. Lines 8400–8580: Mine-hit explosion, clearing the S() array around the blast.
  10. Lines 9000–9997: Win/lose outcome messages, score display, replay loop, and SAVE statement.

Key Data Structures

A two-dimensional array S(19,29) mirrors the playfield. Cells hold:

ValueMeaning
0Empty
1Mine placed by player
2Player’s current position

Tank position is tracked by variables X (column) and Y (row); player position by L (column) and P (row). This avoids any need for SCREEN$ lookups.

Computed GOSUB Dispatch

The tank AI uses the idiom GOSUB 1000+INT(RND*4)*100 (lines 200 and 1021/1125/1227/1325) to jump to one of subroutines 1000, 1100, 1200, or 1300 with a single expression. After moving, the same expression is used again to fire a bullet — this means each tank move is followed by a shot in a freshly randomised direction, independent of the movement direction.

Tank Movement Subroutines

Each of the four movement subroutines (1000 = right, 1100 = left, 1200 = down, 1300 = up) follows the same pattern:

  1. A guard checks whether the tank is already near the relevant wall; if so it redirects to the opposite subroutine (e.g., line 1000 redirects to 1100 if X>21).
  2. A FOR loop moves the tank 2–8 cells in steps of 2 (always on even coordinates, matching the grid layout).
  3. The previous cell is erased before drawing %X at the new position.
  4. If S(Y,X)>0 the tank has hit a mine or the player: branch to line 690 (squash) or 8500 (mine explosion).
  5. A bullet loop (starting at 1030/1130/1230/1330) then fires in a random direction.

Player Movement and Input Handling

Line 190 (referenced but not listed — the GOTO at line 610 actually targets 190, which reads L$=INKEY$) feeds into a dispatcher at line 2002. The cursor key codes 33–36 are checked via CODE K$ and dispatched with GOTO 2000+VAL K$*100 — another computed-jump idiom. Each movement subroutine animates the player one step using a short FOR loop, updates S(), and checks for collision with a mine (S(P,L)=1) or with the tank (S(Y,X)=2).

Note: line 190 is referenced throughout but not present in the listing. The main loop at line 610 says GOTO 190; this implies line 190 contains the LET L$=INKEY$ / GOSUB 2002 sequence that was omitted from the listing, and lines 7760/7990 also branch there. This is a significant anomaly in the listing as provided.

Mine Mechanics

Pressing “P” (line 3000) places a mine at S(P-2,L) — two rows above the player — and prints character \@@ (a block graphic) there. Up to 5 mines are allowed (M<6). The mine is detected both by the tank movement loops (value 1 in S()) triggering line 8500/8400, and by the player accidentally stepping onto their own mine (line 650, which sets Q=1).

Explosion Routine

A shared explosion display at lines 8500–8560 prints a 3×3 asterisk pattern, then clears it, then zeroes a cross-shaped region of S() around the blast coordinates. Variable Z is used as a temporary save of Y when the explosion is triggered from a vertical bullet (lines 8400–8420 swap Y/B/X before falling through to 8500). Line 8565 restores Y from Z afterwards. If Z=0 (set at line 9000 when the tank hits the player’s mine directly), control falls to the win sequence at 9020.

Scoring and Replay

YOU counts player wins; TANK counts tank wins. These persist across replays because line 85 checks them to skip the instructions. The replay loop is GOTO 3 (line 9700), which re-initialises most variables but preserves TANK and YOU. The game ends with a player overall-win message if YOU > TANK+8 (line 9450).

Notable Bugs and Anomalies

  • Array bounds: S() is dimensioned (19,29) (1-indexed, so rows 1–19, columns 1–29). The tank moves on odd or even coordinates between 1 and 29; accesses like S(Y+F,B) in the explosion loop could reach row 0 or 20, which are out of bounds.
  • Line 2004 dispatch: Uses GOTO 2000+VAL K$*100. The cursor keys on the ZX81 have codes 8 (left), 10 (down), 11 (up), 12 (right). The guard CODE K$>=33 AND CODE K$<=36 suggests this is targeted at Sinclair cursor codes in that range (←↑→↓ on some character sets), which would yield destinations 3300–3600 — not the movement subroutines at 2500–2800. This appears to be a code/logic mismatch that would prevent player movement from working correctly.
  • Line 2835: LET L=L-1 after a loop that increments L to L+2 leaves L at L+1 (odd), breaking the even-column alignment used elsewhere.
  • Turn counter: T is incremented at line 605 unconditionally each pass through the main loop, representing “minutes” in the narrative text, though it increments once per tank action rather than per real-time unit.

Content

Appears On

One individual’s cassette containing a number of programs.

Related Products

Play vs computer controlled tank. Move your man, plant mines and avoid the tank. Tank shoots or can run you...

Related Articles

Related Content

Image Gallery

Source Code

   1 LET TANK=0
   2 LET YOU=0
   4 LET Q=5
   5 LET M=0
   6 LET T=0
   7 DIM S(19,29)
   8 LET Z=1
  10 LET P=18
  12 LET L=26
  13 LET S(P,L)=2
  15 PRINT AT 6,10;"MAD DOG"
  17 PRINT AT 8,5;"TANK BLASTER"
  20 PRINT AT 11,2;":.:.:.:.:................."
  22 PRINT AT 12,2;"% % % % % "
  25 PRINT AT 13,0;"'.% % % % % % % % % .'"
  27 PRINT AT 14,1;"'.:.:.:.:.:.:.:..'"
  30 PRINT AT 18,2;"BY TOM WOODS"
  32 PAUSE 100
  35 PRINT AT 10,14;"**"
  37 PRINT AT 11,14;"* **"
  40 PRINT AT 12,14;"  *"
  50 PRINT AT 11,14;"    "
  53 PRINT AT 10,14;"   "
  54 PRINT AT 12,14;"   "
  70 CLS 
  85 IF TANK>0 OR YOU>0 THEN GOTO 97
  89 PRINT AT 3,0;"THE ENEMY TANK COMMANDER HAS    GONE MAD. HE IS SHOOTING WILDLY IN ALL DIRECTIONS. YOU MUST     DESTROY HIM BEFORE YOU RUN OUT  OF TIME, GET SHOT, OR RUN DOWN. USE THE ARROWS TO MANEUVER YOUR MAN. YOU CAN PLACE EACH OF YOUR 5 MINES BY PUSHING ""P""."
  90 PRINT AT 12,0;"HOLD THE KEY UNTIL YOU MOVE.    DON/T STEP ON YOUR OWN MINES.   GOOD LUCK AND WORK QUICKLY. YOU DON/T HAVE MUCH TIME.           HIT %E%N%T%E%R TO BEGIN."
  91 PRINT ,,"""%X""IS THE TANK","""%O""IS YOU"
  92 INPUT A$
  95 CLS 
  97 FAST 
 100 FOR Y=1 TO 29 STEP 2
 110 FOR X=1 TO 19 STEP 2
 120 PRINT AT X,Y;"% "
 130 NEXT X
 140 NEXT Y
 145 SLOW 
 150 LET X=4
 160 LET Y=4
 163 PRINT AT Y,X;"%X"
 165 PRINT AT P,L;"%O"
 170 LET K$="X"
 200 GOSUB 1000+INT (RND*4)*100
 605 LET T=T+1
 608 IF T=30 THEN GOTO 9200
 610 GOTO 190
 650 LET Q=1
 660 GOTO 9100
 690 IF S(Y,X)=1 THEN GOTO 9000
 700 FOR X=1 TO 3
 710 PRINT AT P,L;" "
 715 PRINT AT P,L;"%X"
 720 NEXT X
 750 PRINT AT P,2;"%Y%O%U% %G%O%T% %S%Q%U%A%S%H%E%D"
 760 LET Q=2
 999 GOTO 9127
 1000 IF X>21 THEN GOTO 1100
 1002 FOR X=X TO X+INT ((RND*3)+1)*2 STEP 2
 1003 IF S(Y,X-2)=0 THEN PRINT AT Y,X-2;"  %X"
 1010 IF S(Y,X)>0 THEN GOTO 690
 1015 NEXT X
 1017 LET X=X-2
 1021 GOSUB 1030+INT (RND*4)*100
 1030 FOR B=X+2 TO 28 STEP 5
 1032 PRINT AT Y,B;"*"
 1033 PRINT AT Y,B;" "
 1034 IF S(Y,B)=1 THEN GOTO 8500
 1037 IF Y=P THEN GOSUB 1060
 1039 IF B>=L-2 THEN GOTO 7000
 1050 NEXT B
 1055 RETURN 
 1060 IF ABS (L-B)<=1 THEN GOTO 9090
 1065 RETURN 
 1100 IF X<9 THEN GOTO 1000
 1102 FOR X=X TO X-INT ((RND*3)+1)*2 STEP -2
 1104 IF S(Y,X+2)=0 THEN PRINT AT Y,X;"%X  "
 1110 IF S(Y,X)>0 THEN GOTO 690
 1115 NEXT X
 1120 LET X=X+2
 1125 GOSUB 1030+INT (RND*4)*100
 1130 FOR B=X-2 TO 2 STEP -5
 1132 PRINT AT Y,B;"*"
 1135 PRINT AT Y,B;" "
 1140 IF S(Y,B)=1 THEN GOTO 8500
 1142 IF Y=P THEN GOSUB 1060
 1143 IF B<=L+2 THEN GOTO 7000
 1150 NEXT B
 1155 RETURN 
 1200 IF Y>11 THEN GOTO 1300
 1201 FOR Y=Y TO Y+INT ((RND*3)+1)*2 STEP 2
 1203 IF S(Y-2,X)=0 THEN PRINT AT Y-2,X;" "
 1205 PRINT AT Y,X;"%X"
 1210 IF S(Y,X)>0 THEN GOTO 690
 1220 NEXT Y
 1225 LET Y=Y-2
 1227 GOSUB 1030+INT (RND*4)*100
 1230 FOR B=Y+2 TO 18 STEP 5
 1235 PRINT AT B,X;"*"
 1240 PRINT AT B,X;" "
 1242 IF S(B,X)=1 THEN GOTO 8400
 1243 IF X=L THEN GOSUB 1265
 1244 IF B>=P-2 THEN GOTO 7950
 1255 NEXT B
 1260 RETURN 
 1265 IF ABS (P-B)<=1 THEN GOTO 9090
 1270 RETURN 
 1300 IF Y<9 THEN GOTO 1200
 1302 FOR Y=Y TO Y-INT ((RND*3)+1)*2 STEP -2
 1305 IF S(Y+2,X)=0 THEN PRINT AT Y+2,X;" "
 1307 PRINT AT Y,X;"%X"
 1310 IF S(Y,X)>0 THEN GOTO 690
 1320 NEXT Y
 1322 LET Y=Y+2
 1325 GOSUB 1030+INT (RND*4)*100
 1330 FOR B=Y-2 TO 2 STEP -5
 1335 PRINT AT B,X;"*"
 1340 PRINT AT B,X;" "
 1341 IF S(B,X)=1 THEN GOTO 8400
 1342 IF X=L THEN GOSUB 1265
 1343 IF B<=P+2 THEN GOTO 7950
 1355 NEXT B
 1360 RETURN 
 2002 IF L$="P" THEN GOTO 3000
 2003 IF L$<>"" THEN LET K$=L$
 2004 IF CODE K$>=33 AND CODE K$<=36 THEN GOTO 2000+VAL K$*100
 2005 RETURN 
 2500 IF L<4 THEN RETURN 
 2502 LET S(P,L)=0
 2505 FOR L=L TO L-2 STEP -1
 2510 PRINT AT P,L-1;" %O "
 2520 NEXT L
 2530 LET L=L+1
 2535 IF S(P,L)=0 THEN LET S(P,L)=2
 2540 GOTO 2840
 2600 IF P>16 THEN RETURN 
 2602 LET S(P,L)=0
 2605 FOR P=P TO P+2
 2610 PRINT AT P-1,L;" "
 2620 PRINT AT P,L;"%O"
 2630 NEXT P
 2640 LET P=P-1
 2645 IF S(P,L)=0 THEN LET S(P,L)=2
 2650 GOTO 2840
 2700 IF P<4 THEN RETURN 
 2702 LET S(P,L)=0
 2705 FOR P=P TO P-2 STEP -1
 2710 PRINT AT P+1,L;" "
 2720 PRINT AT P,L;"%O"
 2730 NEXT P
 2740 LET P=P+1
 2745 IF S(P,L)=0 THEN LET S(P,L)=2
 2750 GOTO 2840
 2800 IF L>26 THEN RETURN 
 2802 LET S(P,L)=0
 2805 FOR L=L TO L+2
 2810 PRINT AT P,L-1;" %O "
 2830 NEXT L
 2835 LET L=L-1
 2836 IF S(P,L)=0 THEN LET S(P,L)=2
 2840 IF S(Y,X)=2 THEN GOTO 700
 2842 IF S(P,L)=2 THEN RETURN 
 2845 IF S(P,L)=1 THEN GOTO 650
 3000 LET M=M+1
 3010 IF M<6 AND P>3 THEN LET S(P-2,L)=1
 3030 IF M<6 AND P>3 THEN PRINT AT P-2,L;"@@"
 3050 LET K$="X"
 3055 IF S(Y,X)=1 THEN GOTO 9000
 3070 RETURN 
 7000 IF S(Y,B-1)=1 OR S(Y,B)=1 OR S(Y,B+1)=1 THEN GOTO 8500
 7700 PRINT AT Y-1,B-1;"** "
 7710 PRINT AT Y,B-1;" * "
 7720 PRINT AT Y+1,B-1;" **"
 7730 PRINT AT Y-1,B-1;"%   "
 7740 PRINT AT Y,B-1;"   "
 7750 PRINT AT Y+1,B-1;"   "
 7755 LET L$=INKEY$
 7760 GOTO 2000
 7950 IF S(B-1,X)=1 OR S(B,X)=1 OR S(B+1,X)=1 THEN GOTO 8400
 7960 PRINT AT B-1,X-1;"** "
 7965 PRINT AT B,X-1;" * "
 7970 PRINT AT B+1,X-1;" **"
 7975 PRINT AT B-1,X-1;"%   "
 7980 PRINT AT B,X-1;"   "
 7985 PRINT AT B+1,X-1;"   "
 7987 LET L$=INKEY$
 7990 GOTO 2000
 8400 LET Z=Y
 8410 LET Y=B
 8420 LET B=X
 8500 PRINT AT Y-1,B-1;"** "
 8510 PRINT AT Y,B-1;" * "
 8520 PRINT AT Y+1,B-1;" **"
 8530 PRINT AT Y-1,B-1;"%   "
 8540 PRINT AT Y,B-1;"   "
 8550 PRINT AT Y+1,B-1;"   "
 8551 FOR F=-1 TO 1
 8552 LET S(Y+F,B)=0
 8554 LET S(Y,B+F)=0
 8560 NEXT F
 8562 LET C=Y
 8565 IF B=X THEN LET Y=Z
 8567 LET L$=INKEY$
 8570 IF Z<>0 THEN RETURN 
 8580 GOTO 9020
 9000 LET Z=0
 9010 GOTO 8420
 9020 PRINT AT C,2;"%Y%O%U% %G%O%T% %H%I%M% %W%I%T%H% %Y%O%U%R% %M%I%N%E"
 9022 LET YOU=YOU+1
 9023 LET Z$="MINE "
 9024 IF M<>1 THEN LET Z$(5)="S"
 9025 PAUSE 100
 9027 CLS 
 9028 IF T<10 THEN PRINT "IN JUST ";T;" MINUTES YOU BLASTED   THAT WILD TANK" 
 9030 IF T>=10 THEN PRINT "IT TOOK SOME TIME BUT YOU       FINALLY GOT THE TANK"
 9031 IF M<=3 THEN PRINT "AND YOU ONLY USED ";M;" ";Z$;" TO DO IT"
 9032 IF M=4 OR M=5 THEN PRINT " IT TOOK ";M;"MINES---YOU NEED MORE PRACTICE"
 9034 IF T>=20 THEN PRINT "YOU ONLY HAD ";30-T;" MINUTES LEFT"
 9045 PRINT AT 7,0;"BECAUSE OF YOUR DARING AND SKILLYOU SHALL BE AWARDED THE MEDAL  OF HONOR."   
 9046 IF TANK>YOU+1 THEN PRINT "ONLY ";TANK-YOU;" GAMES TO CATCH UP"
 9050 GOTO 9400
 9090 LET Q=0
 9100 PRINT AT P-1,L-1;" **"
 9105 PRINT AT P,L-1;"* **"
 9110 PRINT AT P+1,L-1;"** *"
 9120 IF Q=0 THEN PRINT AT P,L-1;"%Y%O%U%/%R%E% %S%H%O%T"
 9125 IF Q=1 THEN PRINT AT P,2;"%Y%O%U% %R%A%N% %O%V%E%R% %Y%O%U%R% %O%W%N% %M%I%N%E"
 9127 PAUSE 100
 9200 CLS 
 9201 LET TANK=TANK+1
 9202 IF M=0 THEN PRINT "YOU DIDN/T GET A SINGLE MINE    PLANTED."
 9203 IF Q=2 AND T<=10 THEN PRINT "YOU GOT RUN OVER AFTER JUST ";T;"   MINUTES."
 9204 IF Q=0 AND T<=10 THEN PRINT "YOU GOT GUNNED DOWN IN ONLY ";T;"   MINUTES."
 9206 IF M>1 AND Q=1 THEN LET A$="BUT "
 9210 IF M>1 THEN PRINT AT 5,0;"THE ENEMY TANK AVOIDED ALL OF   YOUR MINES."
 9212 IF Q=1 THEN PRINT A$;"BY RUNNING OVER YOUR OWN    MINE YOU MADE IT AWFUL EASY FOR THE TANK."
 9213 LET A$=""
 9214 IF Q=2 THEN PRINT "YOU MUST LEARN TO STAY OUT OF   THE WAY OF THAT TANK."
 9215 IF Q=0 AND T<20 THEN PRINT "YOU LOSE"
 9220 IF Q<>5 AND T>20 THEN PRINT "AT LEAST YOU MANAGED TO HOLD    OUT FOR ";T;" MINUTES"
 9225 IF Q=5 THEN PRINT "FOR USING UP ALL YOUR TIME A    COURT MARTIAL IS BEING FILED"
 9227 IF M=0 THEN PRINT "TRY USING A FEW MINES NEXT TIME.";
 9230 IF M=0 AND T=30 THEN PRINT "AND DON/T FORGET ABOUT THE CLOCKAT THIS RATE YOU WON/T GET      ANYWHERE."
 9240 IF TANK-YOU=4 THEN PRINT " THE TANK IS MAKING YOU LOOK BAD"
 9400 PRINT AT 14,4;"SCORE: YOU-";YOU
 9410 PRINT TAB 10;"TANK-";TANK
 9450 IF YOU>TANK+8 THEN GOTO 9800
 9500 PRINT AT 20,0;"PLAY AGAIN? HIT %E%N%T%E%R"
 9600 INPUT Z$
 9650 CLS 
 9700 GOTO 3
 9800 PRINT AT 20,0;"% %T%H%E% %T%A%N%K% %G%I%V%E%S% %U%P%-%-%Y%O%U% %W%I%N% "
 9997 STOP 
 9998 SAVE "TAN%K"
 9999 RUN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top