--- title: "Treasure Hunt" id: 57259 type: "computer_media" slug: "treasure-hunt-3" url: "http://localhost/computer_media/treasure-hunt-3/" markdown_url: "http://localhost/computer_media/treasure-hunt-3.md" published_at: "2024-10-04T07:43:14+00:00" modified_at: "2026-04-03T07:58:40+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/147_TH.png" excerpt: "Navigate a randomly-drawn cave network, dodge pursuing demons, fire arrows, and race to the Treasure Room before the walls — or the monsters — claim you." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56734 title: "Timex Sinclair Public Domain Library Tape 1003" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1003/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/147_TH.png" media_type_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 | Variable | Role | | --- | --- | | `PR` | Current room number (1–20, or 21 = Treasure Room) | | `LR` | Last room visited (used to exclude back-exit) | | `N`, `M` | Hero row and column | | `DEM` | Number of active demons (0–3) | | `D(I,1/2)` | Demon row/column coordinates | | `TR` | Unbanked treasure score for current run | | `S` | Banked score | | `ARR` | Arrows remaining | | `Q` | Display file base address | | `B$` | Packed cave exit map | | `T(I)` | Treasure-present flag for each room | | `J`, `K` | Treasure Room guardian column/row | | `FX`, `FY` | Last arrow impact position (Treasure Room) | ## 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 1000 REM %F%I%R%E 1003 IF PR=21 THEN GOSUB 3000 1005 IF RND<.5 THEN GOSUB 1200 1010 LET F$=INKEY$ 1015 IF F$="" OR F$="F" THEN GOTO 1000 1020 LET Y1=N 1025 LET X1=M 1030 LET MY=0+(1 AND F$="6")-(1 AND F$="7") 1035 LET MX=0+(1 AND F$="8")-(1 AND F$="5") 1040 LET X1=X1+MX 1045 LET Y1=Y1+MY 1050 IF ABS (15-X1)=15 OR ABS (10-Y1)=10 THEN GOTO 1125 1053 IF PEEK (Q+33*Y1+X1)<>0 THEN GOTO 1070 1055 PRINT AT Y1,X1;"+"; 1060 PRINT AT Y1,X1;" "; 1065 GOTO 1040 1070 LET DHIT=DEM 1075 FOR I=1 TO DHIT 1080 LET Y=D(I,1) 1085 LET X=D(I,2) 1090 IF X<>X1 OR Y<>Y1 THEN GOTO 1115 1095 PRINT AT Y1,X1;"%+"; 1096 LET S=S+5 1100 LET D(I,1)=D(DEM,1) 1105 LET D(I,2)=D(DEM,2) 1110 LET DEM=DEM-1 1115 NEXT I 1117 IF PR=21 THEN LET FX=X1 1118 IF PR=21 THEN LET FY=Y1 1120 PRINT AT Y1,X1;" "; 1125 RETURN 1200 REM %D%E%M%O%N% %R%U%N 1201 FOR I=1 TO DEM 1205 LET X=D(I,2) 1210 LET Y=D(I,1) 1215 PRINT AT Y,X;" "; 1220 LET Y=Y+SGN (N-Y) 1225 LET X=X+SGN (M-X) 1235 PRINT AT Y,X;"%M"; 1238 IF X=M AND Y=N THEN GOTO 2000 1240 LET D(I,1)=Y 1245 LET D(I,2)=X 1250 NEXT I 1255 RETURN 1295 REM %S%T%A%R%T 1300 PRINT " THIS IS TREASURE-HUNT",,, 1305 PRINT " YOU ARE IN A NETWORK OF CAVES.",, 1310 PRINT "YOU ARE LOOKING FOR GOLD.",,, 1315 PRINT "IF YOU ARE CAREFUL YOU MAY REACH",, 1320 PRINT "THE TREASURE ROOM, BUT BEWARE:",,, 1325 PRINT "THERE ARE MONSTERS WHICH WILL",,, 1330 PRINT "EAT YOU: EVEN TO TOUCH THE ROCKS",, 1335 PRINT "MEANS INSTANT DEATH.",,,,, 1340 PRINT Z$,,, 1342 PRINT "CHOOSE CAVE 1,2,3,OR 4?",, 1345 INPUT PR 1350 IF PR<1 OR PR>4 THEN GOTO 1345 1360 LET LR=0 1500 GOTO 915 1505 PRINT Z$,,, 1510 PRINT "YOUR TREASURE IS SAFE HERE,",,, 1515 PRINT "YOUR SCORE IS ";S+TR,,,, 1518 PRINT TAB 0;"YOU HAVE ";ARR;" ARROWS.",,,, 1520 PRINT TAB 0;"ARE YOU GOING BACK IN?",,,,, 1525 INPUT F$ 1530 IF F$="NO" THEN PRINT "YOU SCORED ";S+TR 1535 IF F$="NO" THEN STOP 1540 LET S=S+TR 1545 LET TR=0 1550 PRINT "HOW MANY ARROWS DO YOU WANT?",,, 1560 PRINT "THEY ARE 4 POINTS EACH",,, 1570 INPUT F 1580 IF F*4>S THEN GOTO 1650 1590 LET S=S-F*4 1600 LET ARR=ARR+F 1610 GOTO 1342 1650 CLS 1655 PRINT " YOU CANT AFFORD THEM",,, 1660 GOTO 1550 2000 REM %D%E%A%T%H% %O%F% %A% %H%E%R%O 2005 CLS 2010 PRINT AT 5,1;"UNFORTUNATELY YOU HAVE PERISHED" 2015 PRINT AT 8,1;"YOU SCORED: ";S+TR 2018 PRINT 2019 PRINT 2020 IF S+TR<50+PS THEN STOP 2025 LET S=S-15 2028 LET PS=S+TR 2029 PRINT "YOU PLAYED WELL:",,, 2030 PRINT "I SHALL DEDUCT 15" 2031 PRINT 2032 PRINT "FOR DAMAGE TO THE BODY"; 2033 PRINT 2034 PRINT 2035 PRINT "YOU MAY CONTINUE"; 2036 FOR I=1 TO 50 2037 NEXT I 2038 CLS 2040 GOTO 1505 2045 REM %T%R%E%A%S%U%R%E% %R%O%O%M 2050 PRINT AT 0,0; 2052 CLS 2055 FOR I=-10 TO 10 2058 LET AI=ABS I 2060 PRINT TAB 0;C$( TO AI); 2065 PRINT TAB (30-AI);C$( TO AI) 2070 NEXT I 2075 PRINT AT 0,10;C$( TO 10) 2080 PRINT AT 20,10;C$( TO 10) 2085 PRINT AT 10,0;"% ";TAB 29;"@@" 2086 LET DEM=1 2087 LET QW=INT (RND*4) 2090 FOR I=1 TO QW+1 2095 PRINT AT 12+I,12+(RND*2);"***"; 2100 NEXT I 2105 LET N=10 2106 LET MY=-1 2107 LET MX=0 2108 LET K=18 2109 LET J=7 2110 LET M=2 2111 LET FX=J 2112 LET FY=K 2115 GOTO 265 2999 REM "%T%R%A%P" 3000 IF PEEK (Q+33*(K+MY)+K+MX)=P THEN GOTO 3015 3002 LET AD=MY 3005 IF AD=0 THEN LET MY=MX 3006 IF AD=0 THEN LET MX=0 3007 IF AD<>0 THEN LET MY=0 3008 IF AD<>0 THEN LET MX=0-AD 3015 LET J=J+MX 3020 LET K=K+MY 3025 PRINT AT K,J;"'."; 3030 IF RND>.5 THEN PRINT AT FY,FX;"'." 3032 IF RND<.25 THEN GOSUB 1200 3035 RETURN 4000 SAVE "1014%7" 5000 RUN ```