This program implements a side-scrolling wave-dodging game where the player controls a cursor (“>”) that must avoid or intercept incoming wave patterns. The wave data is stored in the string A$, which encodes block-graphic wave segments using ZX81/TS1000 escape sequences, and scrolls across the screen one character at a time. Scoring is handled via a GOSUB to line 10, which checks whether the player’s vertical position matches the wave position and awards points based on remaining energy (10−E). The game loops through waves in reverse (FOR E=9 TO 20 STEP -C, where C=1 makes this count upward from 9) and resets between waves via GOTO 80. The SAVE command at line 1000 uses inverse video in the filename as an auto-run flag.
Program Analysis
Program Structure
The program is organized into an initialization phase, a main game loop, a scoring subroutine, and a save/restart block. Variables are initialized at lines 1–5, and the wave graphic string is defined at line 6. The main game loop begins at line 60 and iterates through wave levels via a FOR E loop (lines 70–210). A subroutine at lines 10–50 handles collision detection and scoring. Lines 220–230 display the final score and restart the game.
| Lines | Role |
|---|---|
| 1–6 | Variable initialization |
| 10–50 | Scoring/collision subroutine |
| 60–215 | Main game loop (waves and scrolling) |
| 220–230 | Score display and game restart |
| 999–1010 | STOP, SAVE with auto-run, and restart |
Wave Data and Block Graphics
The string A$ at line 6 contains a repeating block-graphic wave pattern using ZX81/TS1000 block character escapes (\.:, \:., \ :, \.., etc.). During gameplay, a 10-character window (A$(A TO A+9)) is printed at row F (row 7), creating the illusion of a scrolling wave. Each iteration of the inner FOR A loop advances this window by one character, producing smooth horizontal scrolling.
Player Movement and Controls
The player’s vertical position is stored in X, initialized to 3. Line 150 uses a compact arithmetic idiom to update X without an IF chain:
LET X=X+(INKEY$="" AND X<5)-(INKEY$="Z" AND X>C)
This evaluates the boolean expressions (which return 1 or 0 in Sinclair BASIC) to move the cursor down when no key is pressed and X<5, or up when “Z” is pressed and X>1. The “M” key triggers the scoring subroutine via GOSUB 10 at line 170.
Scoring Subroutine (Lines 10–50)
The subroutine is structured unconventionally: lines 10–50 are physically before the initialization block but are only called via GOSUB 10 from line 170. The logic checks if the player (X) is at the wave row (Y) at line 20, returning early if not. If aligned, points equal to 10-E are awarded (provided that position hasn’t already been scored), the slot in B$ is cleared, and the subroutine returns.
Wave Level Loop and Anomalies
The outer loop FOR E=9 TO 20 STEP -C at line 70, with C=1, actually steps from 9 to 20 in increments of +1 (since STEP -1 would require C=-1). This means the loop runs through values 9, 10, 11 … 20, giving 12 wave levels. The inner loop FOR B=C TO 20 at line 90 initializes B$(E) with CHR$(E+14) but B itself is not used inside the loop body — the actual scroll variable is A in the nested FOR A loop at lines 130–180.
Notable Techniques and Idioms
- Boolean arithmetic for branchless movement update (line 150).
- Substring slicing of a long graphic string for scrolling (line 140,
A$(A TO A+9)). - Dual
ATclauses in a singlePRINTstatement (lines 80, 140) to update multiple screen regions efficiently. - Score HUD printed with inverse-video characters at line 80 using
%-prefixed letters. - The
DIM B$(18)at line 100 inside the outer loop resets the board array each wave level. GOTO 215bypasses theNEXT Eat line 210 when a collision is detected, jumping directly to the inter-wave goto at 215, which loops back to the score display header viaGOTO 80.
Bugs and Anomalies
- Line 20 references
YbeforeYis assigned (it is set at line 120 inside the inner loop). On first entry to the subroutine before the inner loop runs,Ywould be 0 (default), which may cause spurious scoring. - The inner
FOR Bloop (lines 90–not explicitly NEXT’d before 100) and theDIMat line 100 inside the outer loop will resetB$on every outer iteration, which is the intended wave-reset behavior but makesFOR Bredundant as its loop variable is unused. - Line 190 uses
GOTO 220(score display) only when a collision occurs; otherwiseNEXT Eat line 210 advances the wave, and line 215’sGOTO 80re-enters the wave setup — this skips the score display between non-collision waves.
Content
Source Code
1 LET C=1
2 LET D=0
3 LET F=6
4 LET X=3
5 LET C$=" "
6 LET A$="\.:\:.\ :\..\ .\..\ :\. \.:\..\.:\:.\ :\..\ .\..\ :\. \.:"
10 PRINT AT X,C;" "
20 IF X<>Y THEN RETURN
30 LET S=S+(10-E)*(B$(E)<>C$)
40 LET B$(E)=C$
50 RETURN
60 LET S=D
70 FOR E=9 TO 20 STEP -C
80 PRINT AT D,D;"% %S%C%O%R%E% % % % ";AT D,F+C;S;AT F+C,D;"% % %W%A%V%E% ";CHR$ (166-E);"% % "
90 FOR B=C TO 20
100 DIM B$(18)
110 LET B$(E)=CHR$ (E+14)
120 LET Y=INT (RND*5)+C
130 FOR A=C TO C+E
140 PRINT AT Y,C;B$(A TO A+8);AT X,D;C$;AT F,D;A$(A TO A+9)
150 LET X=X+(INKEY$="" AND X<5)-(INKEY$="Z" AND X>C)
160 PRINT AT X,D;">"
170 IF INKEY$="M" THEN GOSUB 10
180 NEXT A
190 IF X=Y AND B$(E)<>C$ THEN GOTO 220
210 NEXT E
215 GOTO 80
220 PRINT AT D,F;S
225 PAUSE 500
230 GOTO 60
999 STOP
\n1000 SAVE "1026%0"
\n1010 GOTO 60
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
