--- title: "Space Docking" id: 57586 type: "computer_media" slug: "space-docking-2" url: "http://localhost/computer_media/space-docking-2/" markdown_url: "http://localhost/computer_media/space-docking-2.md" published_at: "2024-10-05T22:36:37+00:00" modified_at: "2026-04-03T07:58:19+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/space-docking.png" excerpt: "Guide your inverse-video spaceship through a star field to dock with a randomly placed fuel satellite — before your fuel counter hits zero." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56722 title: "Synchro-Sette December 1982" type: "computer_media" url: "http://localhost/computer_media/synchro-sette-december-1983/" media_type: "Program" mediadate: "December 1982" images: - url: "http://localhost/wp-content/uploads/2024/10/space-docking.png" media_type_tags: "Game" --- # Space Docking This is a space docking arcade game in which the player manoeuvres a ship (displayed using inverse-video characters) upward toward a randomly positioned fuel satellite, using Z/M keys to move left and right and A to ascend. The program opens with a RAND USR 16514 call to execute a machine-code routine before entering the main game loop. Scoring increments by 210 points per successful docking, and the game tracks how many ships the player has saved across rounds. A subroutine at line 650 draws star-field dots using PRINT AT with RND coordinates and resets a system variable via POKE 16418. Line 702 provides a brief flashing “SAVED” animation implemented with nested delay loops rather than PAUSE. *** ## Program Analysis ### Program Structure The program is organised into a main game loop with several supporting subroutines and an instructions page branched to by a non-existent `GOTO 9000` hint on screen. The overall flow is: 1. Lines 1–4: Machine-code initialisation (`RAND USR 16514`) with `FAST`/`SLOW` framing. 2. Lines 5–82: Variable setup, initial screen draw, star-field and HUD setup via `GOSUB 650`. 3. Lines 90–230: Core game loop — place satellite, move ship, handle keys, detect collision. 4. Lines 300–310: Successful docking — advance satellite row, redraw. 5. Lines 350–361: Ship lost — increment round counter, award points, flash “SAVED” message, continue. 6. Lines 500–645: Game-over screen, pause loop, restart. 7. Lines 650–701: Star-field / HUD draw subroutine. 8. Lines 702–730: “SAVED” flash animation subroutine with software delay. 9. Lines 9000–9020: In-game instructions page (reached only by the player typing `GOTO 9000`). 10. Lines 9998–9999: `SAVE` / `RUN` loader stub. ### Machine Code Usage Line 3 executes `RAND USR 16514`. Address 16514 (0x4082) sits in the ZX81 system variable / display file area. This is a common technique to invoke a short machine-code patch that has been pre-loaded elsewhere in RAM — here presumably to patch display behaviour or set up the character set, since the game makes heavy use of inverse-video text. ### Key Variables | Variable | Role | | --- | --- | | `A` | Constant 1 (PI/PI), used everywhere in place of the literal 1 to save memory | | `B` | Constant 0 (PI-PI), used as a zero sentinel throughout | | `V` | Fuel / move counter (counts down from 600) | | `S` | Ship row position | | `T` | Ship column position | | `X` | Satellite column (random) | | `Y` | Satellite row (starts at 15, advances up by 5 on each dock) | | `R` | Ships saved counter | | `G` | Score (total points) | | `P` | Loop counter used in both the game-over pause and the flash animation | ### Notable BASIC Idioms - **PI arithmetic for constants:**`LET A=PI/PI` (=1) and `LET B=PI-PI` (=0) are classic ZX81 memory-saving idioms. Using these named variables avoids storing floating-point literals in every subsequent expression. - **Boundary clamping:** Lines 170–180 clamp `T` between `B` (0) and 25, preventing the ship from leaving the screen horizontally. - **Collision detection:** Line 210 checks `T=X AND S=Y-A` (ship column matches satellite column and ship row is one above the satellite row) for a successful dock. Line 220 handles the “wrong column, same row” case by resetting the ship downward. - **POKE 16418,0:** In the star-field subroutine (line 654) this zeroes the ZX81 system variable `FRAMES` (low byte), commonly done to reset the frame counter or suppress cursor flicker side-effects. ### Graphics and Display All sprites are rendered using `PRINT AT` with inverse-video characters encoded as `%X` escapes. The player’s ship at line 110 shows as `% %<\..%>%` — a stylised craft. The satellite at line 100 is `% %<%O%>%`. The docking bay frame (lines 21–22) uses block-graphic characters (▘, ▖, ▌, ▟, etc.) to draw a bay outline at the bottom of the play area. Stars are scattered randomly by printing inverse full-stop characters (`%.`) at random positions in the subroutine at lines 650–654. ### Animation and Timing The “SAVED” flash at lines 702–720 alternates between printing `%S%A%V%E%D` and blank spaces three times, with a short software delay loop (lines 724–730, counting to 3) between each frame. This is a purely software-timed approach with no `PAUSE` statement. The game-over pause (lines 550–575) similarly uses a `FOR` loop counting to 100 as a delay before restarting. ### Scoring On a successful docking (line 355), the score `G` is incremented by 210 (110+100). The initial value of `G` at line 6 is set to a random number in the range 0–349 (`INT(RND*350)`), effectively randomising the starting score — this appears intentional as a quirky design choice rather than a bug, though it makes score comparison between games inconsistent. ### Bugs and Anomalies - Line 6 sets `G=INT(RND*350)` immediately before the game loop, giving a random initial score. This is likely unintentional and means the displayed final score is not purely merit-based. - The `IF INKEY$="A" THEN LET S=S-A` at line 160 only moves the ship upward; there is no downward key defined. The ship can only ascend or hold position, which makes boundary clamping on `S` (visible at line 200 checking `S=B`) the only lower-bound check. - Line 190 checks `V=B` (fuel=0) but `V` is decremented by 1 each iteration (line 130). Since `V` starts at 600 and decrements by the constant `A` (which is exactly 1.0), this will reach exactly 0 and the check will fire correctly. - The instructions at lines 9000–9020 are only accessible if the player manually types `GOTO 9000`; the status bar at line 655 advertises “INST.GOTO 9000” for this purpose. `STOP` at line 9020 halts the program after displaying instructions rather than returning to the game. ## 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 T25 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 PRINT AT 11,0;"WHEN CONTACT IS MADE, HOLD KEY (A)MOMENTARILY" 9020 STOP 9998 SAVE "SPACE DOCKIN%G" 9999 RUN ```