Asteroid Field

This file is part of and Timex Sinclair Public Domain Library Tape 1007. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Arcade, Game

This program implements a scrolling radar game for the ZX81/TS1000, in which the player moves a cursor row across a screen of randomly placed asteroids and scores points for hitting them. The display uses inverse-video characters (encoded as % prefixes in the source) to draw borders, a score line, and the playfield. Memory is addressed directly via PEEK of system variables at addresses 16396–16397 to find the base of the display file, allowing the POKE-based gameplay logic to work at the correct screen locations regardless of memory layout. Targets are placed randomly using RND across 263 cells of the display, with value 151 (an inverse space or block character) marking hits; the player row is scanned and wiped using POKE values 146 and 128, and input is read via INKEY$ for left/right movement. The game runs 10 passes (T loop) of 8 random placements (Z inner loop), accumulating a score, then prompts to play again.


Program Analysis

Program Structure

The program is divided into five logical phases:

  1. Initialisation (lines 1–33): Switches to FAST mode, fills the screen with inverse spaces using a 384-iteration PRINT loop, then draws two border rows at screen rows 8 and 10 using PRINT AT.
  2. Setup (lines 40–50): Clears the score variable S with NOT PI (= 0) and calculates R, the address of the player’s row in the display file.
  3. Outer game loop (lines 60–229): Runs 10 passes (T = 1 to 10). Each pass places 8 random targets, then scans 31 cells of the player row, scoring and wiping hits while accepting left/right movement.
  4. Game over (lines 230–233): Prints “GAME OVER” and a “PRESS ENTER TO PLAY AGAIN” prompt, waits for INPUT A$.
  5. Restart (lines 234–235): Clears screen and jumps back to line 1.

Display File Addressing

Line 30 reads the display file base address from the ZX81 system variables at locations 16396 (low byte) and 16397 (high byte), storing it in P. This is the standard technique for locating the display file at runtime, since it can move depending on available RAM and program size. All subsequent PEEK/POKE operations are relative to P, making the game portable across different memory configurations.

The player row address R is initialised to P + 133 (line 50), which corresponds to row 9 of the 32-column ZX81 display (4 rows × 33 bytes per row including the NEWLINE byte = 132, so row index 133 lands at the start of row 9, the middle of the bordered playfield).

Key BASIC Idioms

  • SGN PI is used throughout as a way to produce the constant 1 (since SGN of any positive number is 1), which serves as the loop start value. This is a common ZX81 idiom to avoid storing numeric literals inline.
  • NOT PI evaluates to 0 and is used to initialise S to zero (line 40).
  • VAL "number" is used for all numeric constants in GOTO, GOSUB, and loop bounds — a well-known memory-saving technique since the ZX81 stores floating-point numbers inline with keywords, whereas VAL of a string stores the number as ASCII text, which is shorter for small integers.

Gameplay Mechanics

On each of the 10 passes, 8 target characters (value 151, an inverse block) are POKEd into random display-file addresses within the range P+1 to P+263. The code at line 90 checks that the chosen address does not already contain a NEWLINE byte (value 118) before placing a target, preventing corruption of row terminators.

The inner scan loop (lines 120–200) iterates over the 31 addressable bytes of the player’s current row. For each byte, it checks for a hit (value 151), increments S if found, then POKEs values 146 and 128 in sequence — effectively erasing the cell by writing an intermediate and then a blank character. Between each cell scan, the program reads INKEY$ for ‘A’ (move right, adding 33) or ‘L’ (move left, subtracting 33), with boundary checks at lines 170 and 190 to prevent the cursor row from going out of the display file area.

Notable Techniques

  • The FAST / SLOW mode switch (lines 1 and 101) is used strategically: the initialisation fill runs in FAST mode for speed, then SLOW mode is restored before the interactive loop so the display updates are visible.
  • Inverse-video characters (the %-prefixed characters in the source) are used for borders, score display, and game-over messages, giving a blocked appearance without any UDG or machine-code graphics routines.
  • The score line at line 205 is printed with inline inverse-video label text alongside the numeric variables S and T, using the ZX81’s ability to mix string literals and numeric output in a single PRINT statement.

Variables Summary

VariablePurpose
PBase address of the display file
RAddress of the player’s current row in the display file
SScore (count of targets hit)
TOuter loop counter (pass number, 1–10)
ZGeneral-purpose loop counter
XRandom target address within display file
A$Dummy variable for ENTER keypress at game-over prompt

Potential Anomalies

  • Lines 240–260 (CLEAR, SAVE, RUN) are never reached during normal execution, since the game loops back to line 1 via line 235. These lines are present for the purpose of saving the program to tape and are not part of the runtime flow.
  • The movement keys ‘A’ (right) and ‘L’ (left) are unconventional; on the physical keyboard ‘A’ and ‘L’ are on opposite ends of the keyboard’s home row. Moving right with ‘A’ and left with ‘L’ may feel reversed to some players.
  • The inner Z loop at lines 120–200 has both a NEXT at line 200 and uses Z as its variable, while the outer target-placement loop (lines 70–110) also uses Z. Since the outer Z loop completes at line 110 before the inner one begins at line 120, there is no actual conflict, but reuse of the same loop variable could cause confusion when reading the code.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10294-10335.

Related Products

Related Articles

Related Content

Image Gallery

Asteroid Field

Source Code

   1 FAST 
   5 FOR Z=SGN PI TO VAL "384"
  10 PRINT "% ";
  20 NEXT Z
  30 LET P=PEEK VAL "16396"+VAL "256"*PEEK VAL "16397"
  31 PRINT AT 8,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
  33 PRINT AT 10,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
  40 LET S=NOT PI
  50 LET R=VAL "133"+P
  60 FOR T=SGN PI TO VAL "10"
  70 FOR Z=SGN PI TO VAL "8"
  80 LET X=RND*VAL "263"+SGN PI+P
  90 IF PEEK X=VAL "118" THEN GOTO VAL "80"
 100 POKE X,VAL "151"
 101 SLOW 
 110 NEXT Z
 120 FOR Z=SGN PI TO VAL "31"
 130 IF PEEK (R+Z)=VAL "151" THEN LET S=S+SGN PI
 140 POKE R+Z,VAL "146"
 150 POKE R+Z,VAL "128"
 160 IF INKEY$="A" THEN LET R=R+VAL "33"
 170 IF R>=VAL "264"+P THEN LET R=R-VAL "33"
 180 IF INKEY$="L" THEN LET R=R-VAL "33"
 190 IF R<=P THEN LET R=R+VAL "33"
 200 NEXT Z
 205 PRINT AT 9,0;"% %S%C%O%R%E% ";S;"% % % % % % %P%A%S%S%E%S% %M%A%D%E% ";T;"% % % % % % "
 229 NEXT T
 230 PRINT AT 5,10;"%G%A%M%E% %O%V%E%R"
 231 PRINT AT 12,0;"% % % % %P%R%E%S%S% %E%N%T%E%R% %T%O% %P%L%A%Y% %A%G%A%I%N% % % "
 232 PRINT AT 13,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
 233 INPUT A$
 234 CLS 
 235 GOTO 1
 240 CLEAR 
 250 SAVE "1032%8"
 260 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