This ZX81/TS1000 program implements a two-dimensional chase game in which the player moves a plotted point around the screen while an enemy point autonomously pursues them. The player is controlled via keys 5, 6, 7, and 8 (the ZX81’s directional keys), and the game ends when the enemy catches the player or 499 iterations elapse. The enemy’s movement logic at lines 210–220 uses fractional arithmetic with division by 2 to make it slower on one axis, creating asymmetric pursuit behaviour. A border is drawn using two FOR/NEXT loops before gameplay begins, and the final score is the loop counter N at the moment of capture or timeout.
Program Analysis
Program Structure
The program is divided into four clear phases:
- Initialisation (lines 20–50): Random starting positions for the player (
A,B) and enemy (C,D) are chosen within the playfield bounds. - Border drawing (lines 60–130): Two
FOR/NEXTloops plot the top, bottom, left, and right edges of the 64×43 pixel display area. - Game loop (lines 150–250): Up to 499 iterations handle input, player movement, enemy AI, collision detection, and rendering.
- End screen (lines 260–280): Prints “GAME OVER” and the player’s score (the value of loop variable
Nat exit).
Display Mode Switching
FAST at line 5 suppresses the display during initialisation and border drawing for speed. SLOW at line 145 re-enables the display just before the game loop, so the player can see the action. This is a standard ZX81 technique to accelerate setup routines.
Player Movement
Lines 180–190 use a compact boolean arithmetic idiom common in ZX81 BASIC. Key comparisons evaluate to 1 (true) or 0 (false), which are then multiplied by boundary conditions to prevent the player from leaving the playfield:
A=A+(K$="8")*(A<62)-(K$="5")*(A>1)— moves right on “8”, left on “5”B=B+(K$="7")*(B<41)-(K$="6")*(B>1)— moves up on “7”, down on “6”
These correspond to the standard ZX81 directional keys: 5 (left), 6 (down), 7 (up), 8 (right).
Enemy AI
The enemy pursuer at lines 210–220 uses sign-function-style arithmetic to home in on the player:
C=C+(C<A)-(C>A)/2— moves toward the player’s X position, but retreating is halved (division by 2 yields 0.5 which truncates to 0 in integer context, effectively preventing backward movement)D=D+(D<B)/2-(D>B)— moves toward the player’s Y position with the same asymmetry on the other axis
The division by 2 is a deliberate asymmetry: on the X axis the enemy advances at full speed but never retreats; on the Y axis the enemy retreats at full speed but only advances at half rate (which on a ZX81 with integer display truncation effectively means it does not advance on Y). This creates a pursuit that closes faster along one axis, making the chase less trivially predictable.
Rendering
The program uses UNPLOT A,B to erase the player’s previous position before replotting at the new one (line 170/200), giving smooth single-pixel movement. The enemy at C,D is only ever plotted (line 230), never unplotted — its trail remains on screen, gradually filling the play area and restricting the player’s safe space.
Collision Detection
Line 240 checks IF A=C AND B=D for exact pixel coincidence. Because the enemy leaves a persistent trail, the player can also be trapped without a direct coordinate match, but the only condition that triggers the end screen is exact overlap.
Scoring
The score displayed at line 270 is simply the FOR/NEXT loop counter N, which ranges from 1 to 499. A higher score means the player survived longer. If the loop completes without collision, N will be 499 (the last value before the loop exits normally), and “GAME OVER” is printed after NEXT N falls through to line 260.
Notable Anomalies
- Line 140 prints the title
"CHASE"with embedded literal quote characters, achieved by doubling the quotes inside the string — a standard ZX81 string literal technique. - Lines 290–310 (
CLEAR,SAVE,RUN) are unreachable during normal execution because line 280 is aSTOP. They exist as a tape-saving convenience: the user can manuallyGOTO 290to save and auto-restart the program.
Variable Summary
| Variable | Role |
|---|---|
A, B | Player X, Y coordinates |
C, D | Enemy X, Y coordinates |
K$ | Current keypress from INKEY$ |
N | Game loop counter / score |
Content
Source Code
5 FAST
10 REM "CHASE"
20 LET A=INT (RND*62)+1
30 LET B=INT (RND*41)+1
40 LET C=INT (RND*62)+1
50 LET D=INT (RND*41)+1
60 FOR N=0 TO 63
70 PLOT N,0
80 PLOT N,42
90 NEXT N
100 FOR N=42 TO 0 STEP -1
110 PLOT 0,N
120 PLOT 63,N
130 NEXT N
140 PRINT AT 0,12;"""CHASE"""
145 SLOW
150 FOR N=1 TO 499
160 LET K$=INKEY$
170 UNPLOT A,B
180 LET A=A+(K$="8")*(A<62)-(K$="5")*(A>1)
190 LET B=B+(K$="7")*(B<41)-(K$="6")*(B>1)
200 PLOT A,B
210 LET C=C+(C<A)-(C>A)/2
220 LET D=D+(D<B)/2-(D>B)
230 PLOT C,D
240 IF A=C AND B=D THEN GOTO 260
250 NEXT N
260 PRINT AT 0,11;"GAME OVER"
270 PRINT TAB 6;"YOUR SCORE IS, ";N
280 STOP
290 CLEAR
300 SAVE "1031%7"
310 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
