Treasure Hunt

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

Treasure Hunt is a real-time dungeon exploration game in which the player navigates a network of interconnected caves searching for gold, avoiding rock walls and pursuing demons. The cave map is encoded compactly in string B$ at lines 70–76, where each room’s three exits are stored as ASCII characters offset by 37, allowing up to 21 rooms including a special Treasure Room (room 21). Movement uses the classic Sinclair 5/6/7/8 key layout, and the player can fire arrows in a chosen direction by pressing F followed by a direction key. The program uses PEEK of the display file base address (obtained at line 55 via PEEK 16396/16397) to detect collisions with cave walls and other obstacles without maintaining a separate map array. A score/economy system lets the player bank treasure between runs, buy extra arrows at 4 points each, and survive death with a 15-point penalty if their cumulative score is high enough.


Program Analysis

Program Structure

The program is divided into several functional regions:

  1. Lines 1–95: Initialisation — arrays, string constants, score variables, display-file address, map data, and random seed.
  2. Lines 150–360: Cave rendering and main game loop — draw walls, place demons, move hero, handle arrow firing, and detect collisions.
  3. Lines 605–970: Room-switch logic — tunnel display, exit lookup from B$, and re-entry into the drawing routine.
  4. Lines 1000–1125: Arrow-firing subroutine.
  5. Lines 1200–1255: Demon movement subroutine.
  6. Lines 1295–1660: Start sequence, entrance hall, treasure banking, and arrow purchasing.
  7. Lines 2000–2040: Death handler with conditional continue.
  8. Lines 2045–2115: Treasure Room setup (room 21).
  9. Lines 2999–3035: Trap/guardian movement subroutine used only in the Treasure Room.

Cave Map Encoding

The 21-room graph is stored in string B$ (lines 70–76) as a flat sequence of ASCII characters. Each room occupies three consecutive characters representing its three exits. Exit numbers are recovered by subtracting 37 from the character code, so the digit 9 (ASCII 57) maps to room 20, A (65) to room 28, etc. The decoding occurs at lines 920–945:

  • R1 — left/top exit (displayed at top of screen)
  • R2 — right/bottom exit (displayed at bottom)
  • R3 — third exit used as a replacement when the player came from R1 or R2

Lines 960–965 swap out the “back” exit so the on-screen numbers always show two new destinations, preventing the player from trivially retracing steps.

Display-File Collision Detection

Line 55 calculates Q, the base address of the display file, using the system variables at addresses 16396–16397. During gameplay, PEEK (Q+33*N+M) reads the character code at the hero’s target cell; any value above 62 (i.e., not a space or normal ASCII) triggers death (line 325), and code 23 (the * treasure marker) awards 10 points (line 330). Code 8 is treated as a wall/obstacle that simply blocks movement (line 335). This technique avoids maintaining a separate collision map entirely.

Random Cave Generation

Each cave room is procedurally drawn at lines 165–210. RAND (PR*10+NOW) seeds the generator with a combination of the room number and a session seed (NOW, set once at line 68), so the same room always looks identical within a session but differs between sessions. Block graphics characters (codes 128–130 and the \:. graphic) and random positioning create stalagmite/stalactite shapes.

Demon AI

Up to three demons are tracked in the 2D array D(3,2). Each demon moves one step per call to the subroutine at line 1200 using SGN(N-Y) and SGN(M-X) — a simple but effective Manhattan-direction chase. If a demon reaches the hero’s cell (M,N), execution jumps to the death routine at 2000. The demon count DEM can spontaneously increase from 0 to 1 during movement (line 340, probability 3%), and the arrow-firing routine decrements DEM and shuffles the array to remove a hit demon (lines 1100–1110).

Arrow Firing

The subroutine at lines 1000–1125 waits for a direction key after F is pressed. The arrow travels one cell at a time, printing + then erasing it, until it hits a non-zero display cell or goes off-screen. On hitting a demon’s cell it prints an inverse + (%+), awards 5 points to S, and removes the demon. In the Treasure Room the final arrow position is also stored in FX/FY for use by the guardian subroutine.

Treasure Room (Room 21)

Room 21 is a special diamond-shaped chamber drawn by the loop at lines 2055–2080 using string slicing of C$. A guardian creature is set up with variables J, K, MY, MX and updated each frame via GOSUB 3000. The guardian bounces between directions when it would walk into a non-zero cell (lines 3002–3008), creating simple wall-reflection behaviour. The treasure itself is represented by clusters of *** at randomised positions.

Economy and Death System

The player carries two score accumulators: TR (treasure collected in the current run, lost on death unless the score threshold is met) and S (banked score). Returning to the entrance safely banks TR into S (line 1540). On death, if S+TR < 50+PS the game stops outright; otherwise 15 points are deducted and play resumes from the entrance (lines 2020–2040). The variable PS records the previous best combined score to raise the continuation threshold progressively.

Notable Techniques and Anomalies

  • Boolean arithmetic for movement: Lines 310–315 use (1 AND INKEY$="8") etc. to compute directional deltas without IF statements — a common Sinclair BASIC idiom.
  • String-encoded map: Packing the entire cave graph into a single string literal is an efficient alternative to a numeric array.
  • Line 3000 potential bug: PEEK (Q+33*(K+MY)+K+MX) should likely be Q+33*(K+MY)+(J+MX) — the guardian’s X-coordinate J is missing; K is used twice, so the wall-bounce check reads the wrong screen cell. The guardian still moves but direction reversal is unreliable.
  • Line 822 dead-end: If both R1 and R2 happen to equal LR (the last room), PR could be set to 0, causing the branch at line 822 to jump to line 1505 (the safe-house message) instead of a valid room.
  • C$ construction: The decorative border string is built in three concatenated assignments (lines 11, 13, 15) to stay within the line-length limit, then sliced with C$( TO AI) in the Treasure Room loop for the diamond-border effect.

Key Variable Summary

VariableRole
PRCurrent room number (1–20, or 21 = Treasure Room)
LRLast room visited (used to exclude back-exit)
N, MHero row and column
DEMNumber of active demons (0–3)
D(I,1/2)Demon row/column coordinates
TRUnbanked treasure score for current run
SBanked score
ARRArrows remaining
QDisplay file base address
B$Packed cave exit map
T(I)Treasure-present flag for each room
J, KTreasure Room guardian column/row
FX, FYLast arrow impact position (Treasure Room)

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10122 – 10175.

Related Products

Related Articles

Related Content

Image Gallery

Treasure Hunt

Source Code

   1 REM %T%R%E%A%S%U%R%E% %H%U%N%T
   5 DIM D(3,2)
   7 DIM T(20)
   8 LET Z$="YOU ARE IN THE ENTRANCE HALL"
  10 LET LR=0
  11 LET C$="% % % % % % % % % % % % "
  13 LET C$=C$+"\##\##\##\##"
  15 LET C$=C$+"% % % % % % % % % % % % % % "
  20 LET ARR=5
  25 FOR I=1 TO 20
  30 LET T(I)=1
  35 NEXT I
  37 LET PS=0
  40 LET S=0
  55 LET Q=PEEK 16396+256*PEEK 16397+1
  60 LET TR=0
  65 RAND 
  68 LET NOW=INT (RND*5000)
  70 LET B$="9BE9AF9DG9CHAHIBIJ"
  72 LET B$=B$+"CJKDEKEFLFGMGHN"
  74 LET B$=B$+"IOQJOPKPTLMRMNS"
  76 LET B$=B$+"LRTOQUPTUNQS9RS"
  80 LET R1=0
  82 LET R2=0
  84 LET R3=0
  95 GOTO 1300
 150 CLS 
 160 REM %C%A%V%E% %P%L%O%T
 162 RAND (PR*10+NOW)
 165 FOR I=0 TO 20
 170 LET IY=RND*16+2
 175 LET IX=RND*27+2
 180 PRINT AT IY,IX;"% ";
 185 IF RND>.5 THEN PRINT AT IY-1,IX-1;CHR$ (128-RND*2);
 190 PRINT AT IY,IX+1;"\:.";
 195 PRINT AT IY+1,IX;CHR$ (128+RND*2);
 200 IF RND>.6 THEN PRINT AT IY+1,IX+1;CHR$ 130;
 205 PRINT AT I,0;"% ";AT I,31;"% ";
 210 NEXT I
 212 PRINT AT 0,1;C$;AT 20,1;C$;
 214 PRINT AT 0,17;R1;AT 20,17;R2
 215 LET N=11
 220 LET M=1
 222 IF T(PR)=1 THEN PRINT AT IY,IX+1;"*";
 224 LET T(PR)=0
 225 REM %D%E%M%O%N% %P%L%O%T
 230 LET DEM=INT (RND*4)
 235 FOR I=1 TO DEM
 240 LET D(I,1)=INT (RND*19+1)
 245 LET D(I,2)=INT (RND*30+1)
 250 PRINT AT D(I,1),D(I,2);"%M";
 255 NEXT I
 265 REM %H%E%R%O% %R%U%N
 275 PRINT AT N,M;"X";
 280 IF INKEY$<>"F" THEN GOTO 300
 285 IF ARR=0 THEN GOTO 300
 290 LET ARR=ARR-1
 295 GOSUB 1000
 298 PRINT AT 21,0;"ARROWS:";ARR;
 300 LET N1=N
 305 LET M1=M
 310 LET M=M+(1 AND INKEY$="8")-(1 AND INKEY$="5")
 315 LET N=N+(1 AND INKEY$="6")-(1 AND INKEY$="7")
 320 LET Q1=PEEK (Q+33*N+M)
 325 IF Q1>62 THEN GOTO 2000
 330 IF Q1=23 AND TR<50 THEN LET TR=TR+10
 335 IF Q1=8 THEN GOTO 300
 338 IF ABS (10-N)=10 THEN GOTO 2000
 339 IF PR=21 THEN GOTO 355
 340 IF DEM=0 AND RND<.03 THEN LET DEM=1
 342 IF RND<.3+TR/200 THEN GOSUB 1200
 345 PRINT AT N1,M1;" ";
 350 GOTO 265
 355 GOSUB 3000
 360 GOTO 345
 605 CLS 
 800 REM %R%O%O%M% %S%W%I%T%C%H
 810 LET LR=PR
 812 IF PR<>21 THEN GOTO 815
 813 LET PR=INT (RND*19+1)
 814 GOTO 825
 815 IF N=0 THEN LET PR=R1
 820 IF N=20 THEN LET PR=R2
 822 IF PR=0 THEN GOTO 1505
 825 PRINT AT 3,2;"YOU ARE IN THE TUNNEL"
 830 PRINT AT 5,2;"BETWEEN ";LR;" AND ";PR
 835 PRINT AT 8,2;"YOU HAVE ";ARR;" ARROWS";
 840 PRINT AT 11,2;"YOUR SCORE IS ";TR+S
 915 IF PR=21 THEN GOTO 2050
 920 LET R$=B$(PR*3-2)
 925 LET R1=CODE (R$)-37
 930 LET R$=B$(PR*3-1)
 935 LET R2=CODE (R$)-37
 940 LET R$=B$(PR*3)
 945 LET R3=CODE (R$)-37
 960 IF R1=LR THEN LET R1=R3
 965 IF R2=LR THEN LET R2=R3
 970 GOTO 150
\n1000 REM %F%I%R%E
\n1003 IF PR=21 THEN GOSUB 3000
\n1005 IF RND<.5 THEN GOSUB 1200
\n1010 LET F$=INKEY$
\n1015 IF F$="" OR F$="F" THEN GOTO 1000
\n1020 LET Y1=N
\n1025 LET X1=M
\n1030 LET MY=0+(1 AND F$="6")-(1 AND F$="7")
\n1035 LET MX=0+(1 AND F$="8")-(1 AND F$="5")
\n1040 LET X1=X1+MX
\n1045 LET Y1=Y1+MY
\n1050 IF ABS (15-X1)=15 OR ABS (10-Y1)=10 THEN GOTO 1125
\n1053 IF PEEK (Q+33*Y1+X1)<>0 THEN GOTO 1070
\n1055 PRINT AT Y1,X1;"+";
\n1060 PRINT AT Y1,X1;" ";
\n1065 GOTO 1040
\n1070 LET DHIT=DEM
\n1075 FOR I=1 TO DHIT
\n1080 LET Y=D(I,1)
\n1085 LET X=D(I,2)
\n1090 IF X<>X1 OR Y<>Y1 THEN GOTO 1115
\n1095 PRINT AT Y1,X1;"%+";
\n1096 LET S=S+5
\n1100 LET D(I,1)=D(DEM,1)
\n1105 LET D(I,2)=D(DEM,2)
\n1110 LET DEM=DEM-1
\n1115 NEXT I
\n1117 IF PR=21 THEN LET FX=X1
\n1118 IF PR=21 THEN LET FY=Y1
\n1120 PRINT AT Y1,X1;" ";
\n1125 RETURN 
\n1200 REM %D%E%M%O%N% %R%U%N
\n1201 FOR I=1 TO DEM
\n1205 LET X=D(I,2)
\n1210 LET Y=D(I,1)
\n1215 PRINT AT Y,X;" ";
\n1220 LET Y=Y+SGN (N-Y)
\n1225 LET X=X+SGN (M-X)
\n1235 PRINT AT Y,X;"%M";
\n1238 IF X=M AND Y=N THEN GOTO 2000
\n1240 LET D(I,1)=Y
\n1245 LET D(I,2)=X
\n1250 NEXT I
\n1255 RETURN 
\n1295 REM %S%T%A%R%T
\n1300 PRINT "   THIS IS TREASURE-HUNT",,,
\n1305 PRINT "  YOU ARE IN A NETWORK OF CAVES.",,
\n1310 PRINT "YOU ARE LOOKING FOR GOLD.",,,
\n1315 PRINT "IF YOU ARE CAREFUL YOU MAY REACH",,
\n1320 PRINT "THE TREASURE ROOM, BUT BEWARE:",,,
\n1325 PRINT "THERE ARE MONSTERS WHICH WILL",,,
\n1330 PRINT "EAT YOU: EVEN TO TOUCH THE ROCKS",,
\n1335 PRINT "MEANS INSTANT DEATH.",,,,,
\n1340 PRINT Z$,,,
\n1342 PRINT "CHOOSE CAVE 1,2,3,OR 4?",,
\n1345 INPUT PR
\n1350 IF PR<1 OR PR>4 THEN GOTO 1345
\n1360 LET LR=0
\n1500 GOTO 915
\n1505 PRINT Z$,,,
\n1510 PRINT "YOUR TREASURE IS SAFE HERE,",,,
\n1515 PRINT "YOUR SCORE IS ";S+TR,,,,
\n1518 PRINT TAB 0;"YOU HAVE ";ARR;" ARROWS.",,,,
\n1520 PRINT TAB 0;"ARE YOU GOING BACK IN?",,,,,
\n1525 INPUT F$
\n1530 IF F$="NO" THEN PRINT "YOU SCORED ";S+TR
\n1535 IF F$="NO" THEN STOP 
\n1540 LET S=S+TR
\n1545 LET TR=0
\n1550 PRINT "HOW MANY ARROWS DO YOU WANT?",,,
\n1560 PRINT "THEY ARE 4 POINTS EACH",,,
\n1570 INPUT F
\n1580 IF F*4>S THEN GOTO 1650
\n1590 LET S=S-F*4
\n1600 LET ARR=ARR+F
\n1610 GOTO 1342
\n1650 CLS 
\n1655 PRINT "  YOU CANT AFFORD THEM",,,
\n1660 GOTO 1550
\n2000 REM %D%E%A%T%H% %O%F% %A% %H%E%R%O
\n2005 CLS 
\n2010 PRINT AT 5,1;"UNFORTUNATELY YOU HAVE PERISHED"
\n2015 PRINT AT 8,1;"YOU SCORED: ";S+TR
\n2018 PRINT 
\n2019 PRINT 
\n2020 IF S+TR<50+PS THEN STOP 
\n2025 LET S=S-15
\n2028 LET PS=S+TR
\n2029 PRINT "YOU PLAYED WELL:",,,
\n2030 PRINT "I SHALL DEDUCT 15"
\n2031 PRINT 
\n2032 PRINT "FOR DAMAGE TO THE BODY";
\n2033 PRINT 
\n2034 PRINT 
\n2035 PRINT "YOU MAY CONTINUE";
\n2036 FOR I=1 TO 50
\n2037 NEXT I
\n2038 CLS 
\n2040 GOTO 1505
\n2045 REM %T%R%E%A%S%U%R%E% %R%O%O%M
\n2050 PRINT AT 0,0;
\n2052 CLS 
\n2055 FOR I=-10 TO 10
\n2058 LET AI=ABS I
\n2060 PRINT TAB 0;C$( TO AI);
\n2065 PRINT TAB (30-AI);C$( TO AI)
\n2070 NEXT I
\n2075 PRINT AT 0,10;C$( TO 10)
\n2080 PRINT AT 20,10;C$( TO 10)
\n2085 PRINT AT 10,0;"% ";TAB 29;"\@@"
\n2086 LET DEM=1
\n2087 LET QW=INT (RND*4)
\n2090 FOR I=1 TO QW+1
\n2095 PRINT AT 12+I,12+(RND*2);"***";
\n2100 NEXT I
\n2105 LET N=10
\n2106 LET MY=-1
\n2107 LET MX=0
\n2108 LET K=18
\n2109 LET J=7
\n2110 LET M=2
\n2111 LET FX=J
\n2112 LET FY=K
\n2115 GOTO 265
\n2999 REM "%T%R%A%P"
\n3000 IF PEEK (Q+33*(K+MY)+K+MX)=P THEN GOTO 3015
\n3002 LET AD=MY
\n3005 IF AD=0 THEN LET MY=MX
\n3006 IF AD=0 THEN LET MX=0
\n3007 IF AD<>0 THEN LET MY=0
\n3008 IF AD<>0 THEN LET MX=0-AD
\n3015 LET J=J+MX
\n3020 LET K=K+MY
\n3025 PRINT AT K,J;"\'.";
\n3030 IF RND>.5 THEN PRINT AT FY,FX;"\'."
\n3032 IF RND<.25 THEN GOSUB 1200
\n3035 RETURN 
\n4000 SAVE "1014%7"
\n5000 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