White Hole

This file is part of and Synchro-Sette February 1983. Download the collection to get this file.
Date: February 1983
Type: Program
Platform(s): TS 1000

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:

  1. Initialisation (lines 2–20): clears state, calls machine code, sets SLOW mode.
  2. Game setup (lines 30–45): derives screen coordinates from PI and starts the main loop of 100 iterations.
  3. Main game loop (lines 50–126): scrolls a decorated border line, moves the player, scatters random obstacle characters, and checks for collision.
  4. Collision / explosion (lines 130–190): animates a block-graphic explosion, updates the load score, and resumes the outer loop.
  5. 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 USR machine-code call with FAST/SLOW bracketing.
  • 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 GOTO restart rather than RUN.

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

Appears On

Cassette to accompany the February 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

White Hole

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.

People

No people associated with this content.

Scroll to Top