This is a shooting-gallery game in which the player fires at a moving target sliding across the screen. The program uses FAST mode to fill the screen with inverse-space characters as a border effect, then switches to SLOW mode for gameplay. A target moves left to right across row 3 in steps of two columns, with a random delay (controlled by a FOR/NEXT busy-wait loop seeded by RND) governing its speed. The player presses “V” to shoot, and the program checks whether the target is at column 14 for a hit; scores for shots fired and hits are maintained in variables Q and D respectively. After 20 shots the game ends with a flashing score display achieved by alternating PRINT statements in a tight loop.
Program Analysis
Program Structure
The program divides into five logical phases:
- Initialisation (lines 3–8): Variables
D(hits),Q(shots) andA(loop counter) are zeroed; FAST mode is entered. - Screen fill (lines 10–20): A
FOR-less loop prints rows of inverse-space characters 21 times to build a border/background, then falls through to line 25. - Target animation (lines 25–80): The target slides from column 0 to column 29 in steps of 2, with a random speed delay regenerated each pass.
- Shot handling (lines 90–140): A keypress at “V” triggers shot logic, checks for a hit at column 14, updates scores, and re-enters the animation loop.
- Game over (lines 500–560): After 20 shots, a flashing score is displayed, and the program saves itself and re-runs.
Screen Fill Technique
Rather than using a conventional FOR/NEXT loop, the background is drawn with an unstructured loop: lines 10–20 print a full row of inverse spaces, increment A, and branch back or forward depending on whether A has reached 21. Running in FAST mode makes this fill effectively instantaneous from the user’s perspective. The result is a screen packed with inverse-space characters serving as a dark backdrop.
Target Movement and Speed
The target is a pair of inverse-space characters printed at row 3 using PRINT AT 3,C;"% % \.' (an inverse space, space, inverse space, and a block graphic ▞). Column C steps from 0 to 29 in increments of 2 inside the outer FOR C loop. Between each column step a busy-wait FOR E=1 TO F … NEXT E provides the delay, where F=INT(RND*10)/2 produces a random integer 0–4, giving variable target speed that is re-randomised each full pass.
Shooting Mechanic and Hit Detection
Within the delay loop at line 52 the program polls INKEY$ for “V”. On a keypress, execution jumps to line 90, which draws a “bullet” column at column 16 (rows 18 and 19) and simultaneously redraws the player sprite at row 4/18 column 16. The hit test at line 96 is simply IF C=14 THEN GOTO 106; because the target steps by 2 and the bullet is fixed at column 16, a hit is registered when the target occupies column 14 — meaning the graphic overlap occurs one step before the bullet column. This is a deliberate approximation rather than a true collision check.
Hit Animation
Lines 106–108 draw an explosion using block graphics centred on column 15:
- Line 106 uses
\'(▘) and\ '(▝) combined with\.(▖) and\ .(▗) to paint a four-quadrant burst pattern. - Line 108 overwrites with
\:'(▛) and\:.(▙) variants to animate a second frame. - Both lines also reprint surrounding inverse-space characters to restore the background after the animation.
Score Display and Game Over
Shots (Q) and hits (D) are displayed with inline concatenation: PRINT AT 18,2;Q;"% SHOTS" and AT 18,23;D;"% HITS" (the % being an inverse space used as a separator). When Q>20, the game-over routine at line 500 enters a tight loop alternating between printing blank spaces and the hit count at position (18,23), creating a simple flashing effect without any explicit timing mechanism other than the loop itself.
Save and Auto-Run
Line 550 saves the program under a filename that includes inverse characters ("1026%6" where %6 is an inverse digit), which on the ZX81/TS1000 encodes an auto-run flag so the program starts automatically when loaded. Line 560 immediately re-runs the program after saving, so a fresh game begins without user intervention.
Variables Summary
| Variable | Purpose |
|---|---|
A | Screen-fill loop counter (0–21, then discarded) |
C | Current target column (FOR loop, 0–29 step 2) |
D | Hit counter |
E | Speed delay loop index |
F | Random delay value (0–4) |
Q | Shot counter |
Y | Short busy-wait loop at game over (lines 522–524) |
Notable Bugs and Anomalies
- After a hit (line 106–140), the outer
FOR Cloop is re-entered at line 40 withCreset to 0, but theFORstatement re-initialisesCcleanly, so this is not a bug — it simply restarts the target from the left. - On a miss (no hit at
C=14), line 102 jumps back into the middle of theFOR Eloop at line 55, bypassing theFORstatement. On the ZX81 this reuses the existingEloop descriptor rather than reinitialising it, which could cause the delay to run from whereverEwas rather than from 1. This is a subtle timing irregularity. - Line 36 prints a gun/player sprite at rows 19–20 column 16 every time a new random speed is chosen, not just once — this is harmless but redundant.
- The
CLEARat line 540 is never reached because the game-over loop at lines 510–530 never exits.
Content
Source Code
3 LET D=0
4 LET Q=0
6 LET A=0
8 FAST
10 PRINT "% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
12 LET A=A+1
14 IF A=21 THEN GOTO 25
20 GOTO 10
25 SLOW
27 PRINT AT 4,0;"% "
30 LET F=INT (RND*10)/2
36 PRINT AT 20,16;"%*";AT 19,16;"%*"
40 FOR C=0 TO 29 STEP 2
50 PRINT AT 3,C;"% % \.'"
52 IF INKEY$="V" THEN GOTO 90
55 FOR E=1 TO F
57 NEXT E
60 NEXT C
70 PRINT AT 3,30;"% "
80 GOTO 30
90 PRINT AT 18,16;" ";AT 18,16;"% ";AT 4,16;" ";AT 4,16;"% "
92 LET Q=Q+1
94 PRINT AT 18,2;Q;"% SHOTS"
96 IF C=14 THEN GOTO 106
100 IF Q>20 THEN GOTO 500
102 GOTO 55
106 PRINT AT 3,15;"% % % ";AT 2,15;"\' % \ '";AT 4,15;"\. % \ .";AT 4,15;"% % % ";AT 2,15;"% % % "
108 PRINT AT 2,15;"\:'% \':";AT 4,15;"\:.% \.:";AT 4,15;"% % % ";AT 2,15;"% % % "
120 LET D=D+1
130 PRINT AT 18,23;D;"% HITS"
135 IF Q>20 THEN GOTO 500
140 GOTO 40
500 PRINT AT 10,3;"GAME% OVER"
510 PRINT AT 18,23;"% % "
520 PRINT AT 18,23;D
522 FOR Y=1 TO 4
524 NEXT Y
530 GOTO 510
540 CLEAR
550 SAVE "1026%6"
560 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
