This is a space docking arcade game in which the player manoeuvres a ship (displayed as inverse “< >” characters) upward toward a randomly positioned fuel satellite, earning points for each successful docking. The program opens with a RAND USR 16514 call in FAST mode, executing a machine-code routine before the game logic runs. Scoring uses a running total stored in G, initialised to a random offset of up to 349 points, with 210 added per successful dock. A blinking “SAVED” animation subroutine at line 702 is implemented with a software delay loop rather than PAUSE, and star-field decoration is scattered via four random PRINT AT statements in the GOSUB 650 subroutine. An in-game instruction screen is accessible via GOTO 9000, which is referenced in the status bar but requires the user to navigate there manually since the line is never called programmatically during normal play.
Program Analysis
Program Structure
The program is divided into several functional blocks:
- Initialisation (lines 1–7): Machine-code call, variable setup, random score seed, and initial star-field draw.
- Game setup (lines 10–90): Constants established, cockpit border printed, satellite positioned randomly.
- Main game loop (lines 100–230): Draws satellite and ship, reads keyboard, enforces bounds, tests win/loss conditions.
- Dock success (lines 300–361): Moves satellite up five rows, updates score, triggers “SAVED” animation, restarts loop.
- Fuel exhausted / game over (lines 500–645): Displays result screen with ships saved and total points, then restarts.
- Star-field subroutine (lines 650–701): Prints four random inverse-pixel stars and resets the POKE 16418 scroll counter.
- “SAVED” flash subroutine (lines 702–730): Blinks the word three times using a software delay inner loop.
- Instructions (lines 9000–9010): Printed but never called from within the game; accessed only via the status bar hint.
- Save/auto-run block (lines 9100–9120): Clears memory and SAVEs the program with an auto-run flag in the filename.
Machine Code Usage
Line 3 executes RAND USR 16514 in FAST mode (line 2). Address 16514 lies inside the ZX81/TS1000 system variables / ROM area and is used here as a common trick to invoke a ROM routine or patch memory before the BASIC game begins. The exact effect depends on whatever routine resides there, but the FAST/SLOW sandwich (lines 2 and 4) is the standard idiom for a quick machine-code call with minimal screen flicker.
Key Variables
| Variable | Role |
|---|---|
A | Constant 1 (PI/PI), used as the increment unit throughout |
B | Constant 0 (PI-PI), used as the zero-boundary sentinel |
S | Ship row (starts at 18, decrements toward 0) |
T | Ship column (starts at 15, keyboard-controlled) |
X | Satellite column (random each round) |
Y | Satellite row (starts at 15, moves up 5 on each dock) |
V | Fuel/timer countdown (starts at 600, decremented by 1 each iteration) |
R | Ships saved counter (incremented at line 350) |
G | Running score (random seed 0–349 plus 210 per dock) |
P | Reused: delay loop counter in game-over screen AND flash counter in subroutine 702 |
BASIC Idioms
- PI arithmetic for constants:
LET A=PI/PI(=1) andLET B=PI-PI(=0) avoids storing integer literals and is a classic ZX81 memory-saving trick. These are then used everywhere instead of literal 0 and 1. - POKE 16418,0 (line 654): Resets the system variable DF_SZ or a related scroll register to prevent the lower display area from auto-scrolling during PRINT AT operations — a standard ZX81 display-control idiom.
- Inverse-video characters: The ship is rendered as
% %<%O%>%(inverse space, inverse <, inverse O, inverse >, inverse space), and the satellite as% %<\..%>%(with a block-graphic body). The score bar and borders use solid inverse-space blocks. - Erasing sprites: The previous ship position is overwritten at line 120 with a blank inverse-space string, using
S+A(one row below) — a simple erase-by-overwrite scheme with no attribute complications.
Game Loop Logic
Each iteration of the main loop (lines 110–230) draws the ship, decrements the fuel counter V, reads one key from INKEY$ for Z (left), M (right), and A (up), clamps T between 0 and 25, then checks three conditions in order: fuel empty → game over (line 190); ship reached row 0 without docking → next round with score (line 200); ship column matches satellite column at the correct row → dock success (line 210). If the ship has risen to the satellite row but missed horizontally, it resets to the starting position (line 220).
“SAVED” Flash Animation (lines 702–730)
The subroutine at line 702 implements a three-cycle blink by alternately printing %S%A%V%E%D (inverse) and blanks. Each display state is held for a short software delay: lines 724–730 form a tight loop counting T from 0 to 3. Because P is the outer counter and T the inner, and both variables are shared with the main game, callers must not rely on their values afterward — which the code handles correctly by reinitialising T at line 65 and V at line 40 on each game-loop restart.
Bugs and Anomalies
- Variable
Preuse:Pis used both as the game-over delay loop counter (lines 550–575) and as the blink counter inside subroutine 702. Since subroutine 702 is only called from the dock-success path (line 357) and never from the game-over path, there is no actual conflict, but the shared name is potentially confusing. - Instructions line never called: Line 655 prints a status bar message referencing
GOTO 9000for instructions, but no code path in the game ever jumps there. The player must manually typeGOTO 9000or the game reachesSTOPonly if they somehow navigate there outside normal play. - Ship erase row offset: The erase print at line 120 uses
AT S+A,T+A(one row below and one column right of the ship), which does not exactly overwrite the ship’s position atAT S,T. This means a ghost trail of the previous position atS,Tis not always cleanly erased, potentially leaving artefacts — though the frequent full-screen redraws at lines 80–81 and 351–352 mitigate this. - Random score seed:
Gis initialised to a random value 0–349 at line 6, before being overwritten at line 5 to 0 — but line 6 immediately follows line 5 and re-randomises it. The initialLET G=0at line 5 is therefore redundant.
Content
Source Code
1 REM Y% .'. :%KNOT $TAB @@RND: TAB '.RNDTAN
2 FAST
3 RAND USR 16514
4 SLOW
5 LET G=0
6 LET G=INT (RND*350)
7 GOSUB 650
10 LET A=PI/PI
20 LET B=PI-PI
21 PRINT AT 20,15;"':.:% :.:'"
22 PRINT AT 21,14;".:% % % % % :."
30 LET R=B
40 LET V=600
50 LET S=18
60 LET T=15
65 LET Y=15
80 PRINT AT 0,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
81 PRINT AT 1,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
82 GOSUB 650
90 LET X=INT (RND*25)
100 PRINT AT Y,X;"% %<%O%>% "
110 PRINT AT S,T;"% %<..%>% "
112 PRINT AT 19,15;"% % ''% % "
120 PRINT AT S+A,T+A;"% % % % % "
130 LET V=V-A
140 IF INKEY$="Z" THEN LET T=T-A
150 IF INKEY$="M" THEN LET T=T+A
160 IF INKEY$="A" THEN LET S=S-A
170 IF T<B THEN LET T=B
180 IF T>25 THEN LET T=25
190 IF V=B THEN GOTO 500
200 IF S=B THEN GOTO 350
210 IF T=X AND S=Y-A THEN GOTO 300
220 IF S=Y-A AND T<>X THEN GOTO 50
230 GOTO 110
300 LET Y=Y-5
310 GOTO 80
350 LET R=R+A
351 PRINT AT 0,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
352 PRINT AT 1,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
355 LET G=G+110+100
356 PRINT AT 20,1;"%P%O%I%N%T%S% ";G
357 GOSUB 702
361 GOTO 50
500 CLS
510 PRINT AT 10,11;"%G%A%M%E% %O%V%E%R"
520 PRINT AT 12,5;"**YOU SAVED ";R;" SHIPS**"
530 PRINT AT 14,8;"TOTAL POINTS ";G
550 FOR P=1 TO 100
575 NEXT P
642 CLS
645 GOTO 1
650 PRINT AT RND*15,RND*31;"%."
651 PRINT AT RND*15,RND*31;"%."
652 PRINT AT RND*15,RND*31;"%."
653 PRINT AT RND*15,RND*31;"%."
654 POKE 16418,0
655 PRINT AT 22,0;"% SPACE DOCKING---INST.GOTO 9000% "
656 PRINT AT 23,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
701 RETURN
702 PRINT AT 3,13;"%S%A%V%E%D"
704 LET P=0
706 GOSUB 724
708 PRINT AT 3,13;"%S%A%V%E%D"
710 GOSUB 724
712 PRINT AT 3,13;"% % % % % "
714 GOSUB 724
716 LET P=P+1
718 IF P=3 THEN RETURN
720 GOTO 708
724 LET T=0
726 LET T=T+1
728 IF T=3 THEN RETURN
730 GOTO 726
9000 PRINT AT 2,0;"PRESS(A)TO MAKE YOUR SHIP GO UP"
9002 PRINT AT 4,0;"PRESS(Z)TO GO LEFT"
9004 PRINT AT 6,0;"PRESS(M)TO GO RIGHT"
9006 PRINT AT 8,0;"YOU MUST BE DIRECTLY UNDER THE"
9008 PRINT AT 9,0;"FUEL SATELLITE TO CONTINUE."
9010 STOP
9100 CLEAR
9110 SAVE "1025%8"
9120 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
