Treasure Chase is a cat-and-mouse game in which the player moves a treasure token around a grid while a pursuing “hound” automatically closes in. The 22×32 playing field is populated procedurally: each cell has a 5% chance of becoming a wall (value 2, displayed as inverse asterisk) and a 10% chance of becoming a coin (value 1, displayed as inverse period), stored in a two-dimensional array H(22,32). The player scores 10 points for landing on a wall cell and 1 point for a coin cell, with both clearing on collection; a running high score is preserved across rounds in C1. Movement uses the classic ZX81 key layout (5/8 for left/right, 6/7 for up/down), and pressing 0 teleports the treasure to a random position, while the hound steps one cell closer each tick using simple Chebyshev-style tracking logic.
Program Analysis
Program Structure
The program is divided into four logical phases:
- Initialisation (lines 1–13): Resets player position, places the hound randomly, zeroes the score, and enters FAST mode.
- Map generation (lines 20–61): Fills the 22×32 grid with walls and coins using probabilistic RND checks, storing terrain in array
Hand printing inverse characters. - Game loop (lines 65–160): Renders player and hound, updates scores, advances the hound one step toward the player, reads keys to move the treasure, clamps positions, and checks for capture.
- End / restart (lines 200–240): Prints a capture message, prompts to play again, and either stops or jumps back to line 5 (preserving high score in
C1).
Display and Character Encoding
All interactive characters are rendered as ZX81 inverse video. The player token is %0 (inverse 0), the hound is %A (inverse A), walls are %* (inverse asterisk), and coins are %. (inverse period). The status line at row 0 spells out %Y%O%U%R and %H%I%G%H% %S%C%O%R%E in inverse characters to give a header-bar effect. Erasing a character is done by printing "% " (inverse space).
Terrain Array and 1-Based Indexing
The terrain array H(22,32) uses 1-based indices in ZX81 BASIC, so screen positions (I,J) — which run 0–21 and 0–31 — are stored as H(I+1,J+1). Cell values encode terrain type:
| Value | Meaning | Score | Display |
|---|---|---|---|
| 0 | Empty | 0 | inverse space |
| 1 | Coin | +1 | inverse period |
| 2 | Wall | +10 | inverse asterisk |
After the player’s treasure lands on a cell, its value is read, the score updated, and the cell zeroed — preventing double-counting on subsequent passes.
Hound (Pursuer) AI
Lines 81–87 implement simple axis-aligned stepping: the hound’s target coordinates (X1,Y1) are incremented or decremented independently on each axis toward the treasure (A,B). This is equivalent to Chebyshev movement — the hound can close diagonally one step per frame and will inevitably catch the treasure on an open field.
Player Input and Movement
Key mapping follows the standard ZX81 numeric-key convention:
5— move left (B=B-1)8— move right (B=B+1)6— move down (A=A+1)7— move up (A=A-1)0— teleport to random position
Position is clamped at lines 132–135 to keep the treasure within the visible grid. There is no boundary check on the hound’s coordinates X and Y, though in practice the hound is clamped indirectly because it always moves toward a clamped target.
High Score Persistence
The variable C1 is initialised only once at line 1 and is not reset when the player restarts at line 5. This means the high score accumulates across games within a single session. Line 72 updates C1 only when the current score C exceeds it, providing correct high-score semantics.
Notable Bugs and Anomalies
- INKEY$ read multiple times per loop: Lines 89–120 each call
INKEY$independently. On the ZX81,INKEY$is re-evaluated on every reference, so a key held down can trigger multiple branches simultaneously (e.g., both the erase at line 89 and a movement at a later line). - Row 0 terrain exclusion: Line 31 skips wall/coin placement when
I=0orJ=0, but the condition only catches the first row and first column. This leaves row 0 clear for the score display but means column 0 is also always empty. - PAUSE 9000: Line 80 pauses for approximately 9000 display frames before processing input. On the unexpanded ZX81 this is very long; this is the primary pacing mechanism but also means input is only sampled after the pause expires, making the game sluggish.
- Lines 220–240 (CLEAR / SAVE / RUN) are unreachable during normal gameplay and appear to be a loader/saver block executed manually or at load time.
- Hound erased by INKEY$ check: Line 89 erases the hound’s current cell (
AT A,B) if any key is pressed, before movement keys are checked — this means the hound is temporarily invisible for one frame whenever a key is held.
FAST/SLOW Mode Usage
FAST is entered at line 13 before the map-drawing loop to suppress the display interrupt and speed up the 704-cell fill operation. SLOW is restored at line 61 before the game loop begins, re-enabling the display so the player can see the action.
Content
Source Code
1 LET C1=0
2 REM TREASURE CHASE
5 LET X=0
6 LET Y=16
7 LET Y1=Y
8 LET X1=X
9 LET A=INT (RND*22)
10 LET B=INT (RND*32)
12 LET C=0
13 FAST
20 DIM H(22,32)
26 FOR I=0 TO 21
28 FOR J=0 TO 31
30 PRINT AT I,J;"% "
31 IF I=0 OR J=0 THEN GOTO 50
32 IF NOT RND<.05 THEN GOTO 40
34 LET H(I+1,J+1)=2
36 PRINT AT I,J;"%*"
40 IF NOT RND<.1 THEN GOTO 50
42 LET H(I+1,J+1)=1
44 PRINT AT I,J;"%."
50 NEXT J
60 NEXT I
61 SLOW
65 PRINT AT X,Y;"%0"
66 PRINT AT A,B;"%A"
67 IF H(A+1,B+1)=2 THEN LET C=C+10
68 IF H(A+1,B+1)=2 THEN LET H(A+1,B+1)=0
69 IF H(A+1,B+1)=1 THEN LET C=C+1
70 IF H(A+1,B+1)=1 THEN LET H(A+1,B+1)=0
72 IF C>C1 THEN LET C1=C
73 PRINT AT 0,0;"%Y%O%U%R";C;AT 0,9;"%H%I%G%H% %S%C%O%R%E";AT 0,21;C1
80 PAUSE 9000
81 IF A>X THEN LET X1=X+1
82 IF A<X THEN LET X1=X-1
83 IF B>Y THEN LET Y1=Y+1
84 IF B<Y THEN LET Y1=Y-1
85 PRINT AT X,Y;"% "
86 LET X=X1
87 LET Y=Y1
88 IF X=A AND Y=B THEN GOTO 200
89 IF NOT INKEY$="" THEN PRINT AT A,B;"% "
95 IF INKEY$="0" THEN LET A=INT (RND*22)
98 IF INKEY$="5" THEN LET B=B-1
100 IF INKEY$="8" THEN LET B=B+1
110 IF INKEY$="6" THEN LET A=A+1
120 IF INKEY$="7" THEN LET A=A-1
132 IF A>21 THEN LET A=21
133 IF A<1 THEN LET A=1
134 IF B>31 THEN LET B=31
135 IF B<0 THEN LET B=0
140 IF X=A AND Y=B THEN GOTO 200
160 GOTO 65
200 PRINT AT 10,10;"**GOT YOU**"
202 PRINT AT A,B;"X"
205 PRINT AT 20,2;"PLAY AGAIN ,INPUT Y OR N"
207 INPUT G$
208 IF G$="N" THEN STOP
210 GOTO 5
220 CLEAR
230 SAVE "1029%1"
240 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
