This program simulates a space navigation game in which the player steers a craft through a field of randomly drifting obstacles (represented by cursor-control characters) toward a white hole destination. The REM statement at line 1 contains decorative block-graphic characters, and line 10 calls machine code at address 16514 via USR to perform fast initialisation before switching to SLOW mode. Player input on keys “0” and “1” adjusts the horizontal position variable X using a compact Boolean arithmetic idiom in line 70. Collision detection at line 120 uses PEEK on the display file address (derived from system variables at 16398–16399) to check whether the character under the craft is a cursor-control code 8, triggering an animated explosion sequence of block-graphic characters at lines 140–150.
Program Analysis
Program Structure
The program is a single-file game loop with five logical phases:
- Initialisation (lines 2–20): clears state, calls machine code, sets SLOW mode.
- Game setup (lines 30–45): derives screen coordinates from
PIand starts the main loop of 100 iterations. - Main game loop (lines 50–126): scrolls a decorated border line, moves the player, scatters random obstacle characters, and checks for collision.
- Collision / explosion (lines 130–190): animates a block-graphic explosion, updates the load score, and resumes the outer loop.
- End-of-run scoring (lines 500–540): records the best score, displays results, pauses, and restarts.
Machine Code Usage
Line 10 executes RAND USR 16514. Address 16514 is in the ZX81/TS1000 ROM; RAND USR is the standard way to call machine code from BASIC. The FAST / SLOW bracketing (lines 5 and 15) ensures the MC routine runs without display interference and then returns to the normal display-enabled mode.
Coordinate Initialisation via PI
Rather than using plain integer literals, the starting coordinates are derived from the built-in constant PI. X = 2*PI ≈ 6.28 and Y = PI + X ≈ 9.42. Because PRINT AT truncates to integer, these resolve to column 6 and row 9 — a compact way to encode starting positions that also saves a few bytes compared with storing integer literals directly.
Player Input Idiom
Line 70 uses the classic Boolean arithmetic trick:
LET X=X+(INKEY$="0" AND X<30)-(INKEY$="1" AND X>PI)
Each Boolean sub-expression evaluates to 1 (true) or 0 (false), so the single LET both moves right and moves left with built-in boundary clamping, avoiding any IF statements.
Obstacle Generation
Lines 100 prints four pairs of AT / CHR$ 8 sequences in random screen positions. CHR$ 8 is the DELETE/backspace control code, which on the ZX81 display appears as a cursor-left character but visually leaves a distinctive mark used here as a hazard sprite. Line 90 uses IF RND>.7 THEN GOTO 50 to skip obstacle placement 70 % of the time, keeping the field sparse.
PEEK-Based Collision Detection
Line 120 reads the display file address from system variables:
IF PEEK (PEEK 16398+256*PEEK 16399)=8 THEN GOTO 130
System variables at 16398 (low byte) and 16399 (high byte) hold the current PRINT AT cursor address within the display file. Peeking that address checks the character code directly in video RAM. A value of 8 (the obstacle character) triggers the collision branch. Line 110 positions the cursor at the player location before the PEEK so the correct cell is sampled.
Block-Graphic Explosion Animation
Lines 130–160 loop 10 times, alternating two 3×3 block-graphic patterns around the player position to create a flicker effect. The characters used are ZX81 block graphics forming a dense filled square and then an inverse/hollow square, simulating an explosion burst.
Scoring and Persistence
Variable U counts down by 1 each iteration (line 80) and gains 100 on a collision hit (line 166), making hits beneficial to score. The high score is preserved in A across restarts because the program GOTO 5 (line 540) rather than RUN, so A retains its value. Line 2 (LET A=0) is only reached on a true RUN or first load.
Notable Techniques Summary
RAND USRmachine-code call withFAST/SLOWbracketing.- Boolean arithmetic for clamped single-line player movement.
- Display-file PEEK for pixel-level (character-cell) collision detection.
- PI-derived coordinate initialisation to save tokenised bytes.
- High-score persistence via
GOTOrestart rather thanRUN.
Potential Anomalies
The FOR I loop spans lines 45–190, but the NEXT I at line 125 is inside the body and the collision branch at line 130 jumps back to NEXT I at line 190, which continues the outer loop correctly. However, if the 100-iteration loop completes without reaching GOTO 500 via line 126 in every iteration, control falls through to line 126 only after line 125 exhausts the loop — this is consistent with the intended flow. The variable U is reset to 1 only at line 20, so across GOTO 5 restarts it retains whatever value it had; this may be intentional to carry a running load total, but could also cause unexpected initial conditions.
Content
Source Code
1 REM Y%.\.'\. :%KNOT $TAB \@@RND\: TAB \'.RNDTAN
2 LET A=0
5 FAST
10 RAND USR 16514
15 SLOW
20 LET U=1
30 LET X=2*PI
40 LET Y=PI+X
45 FOR I=1 TO 100
50 PRINT AT Y,X;"."
60 SCROLL
65 PRINT "%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%."
70 LET X=X+(INKEY$="0" AND X<30)-(INKEY$="1" AND X>PI)
80 LET U=U-1
90 IF RND>.7 THEN GOTO 50
100 PRINT AT RND*15+5,RND*30;CHR$ 8;AT RND*15+5,RND*30;CHR$ 8;AT RND*15+5,RND*30;CHR$ 8;AT RND*15+5,RND*30;CHR$ 8
110 PRINT AT Y,X;
120 IF PEEK (PEEK 16398+256*PEEK 16399)=8 THEN GOTO 130
125 NEXT I
126 GOTO 500
130 FOR N=1 TO 10
140 PRINT AT Y-1,X-1;"\:'\''\':";AT Y,X-1;"\: .\ :";AT Y+1,X-1;"\:.\..\.:"
150 PRINT AT Y-1,X-1;"\ .\..\. ";AT Y,X-1;"\ :%.\: ";AT Y+1,X-1;"\ '\''\' "
160 NEXT N
166 LET U=U+100
170 PRINT AT 6,3;" PRESENT LOAD = ";U;" TONS ";AT 4,2;" ";100-I;" MILLION MILES LEFT TO GO "
180 PAUSE 200
190 NEXT I
500 IF U>A THEN LET A=U
510 PRINT AT 11,4;" FINAL = ";U;" BEST = ";A;" "
520 PAUSE 400
530 CLS
540 GOTO 5
998 SAVE "WHITE-HOL%E"
999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
