This is a cave exploration treasure hunt game in which the player navigates a network of 20 interconnected rooms, collecting treasures and fighting demons while avoiding hazards. The cave map is encoded compactly in the string variable B$ (lines 200–230) as pairs of ASCII characters whose CODE values, offset by 57, yield room connection numbers — a space-efficient adjacency table. Room graphics are procedurally generated using random block-graphic characters (chars 128–143) and UDGs, and the screen border is filled with solid-block strings built in C$ and D$. The game supports both joystick (via the STICK function) and keyboard input, selectable at startup, with six difficulty levels controlling the demon encounter probability (DD) and the death-penalty threshold (DDL). A special treasure room (PR=21) features a bouncing UDG sprite and a trap-movement subroutine at line 2160 that rotates the sprite’s direction vector when it hits a wall attribute.
Treasure Hunt was written by Paul Sherwood for T/S1000 16K, published in TS User Mag. #4. Modified by S.J. (BUTCH) Weinberg for T/S2068 Aug. 1984.
Program Analysis
Program Structure
The program is divided into clearly labeled sections via REM statements. Execution begins at line 10 but immediately jumps to the setup routine at line 1460 (line 250: GO TO 1460). The main game loop runs between lines 510 and 710, with subroutines for firing (line 940), demon movement (line 1320), the treasure room (line 1850), the trap/bouncing sprite (line 2160), and input handling (lines 2460–2670).
- Lines 10–250: Initialization — dimensions, string building, map data
- Lines 260–430: Cave plot and room rendering
- Lines 440–510: Demon placement
- Lines 510–710: Main hero movement loop
- Lines 740–930: Room transition logic
- Lines 940–1310: Arrow firing subroutine
- Lines 1320–1440: Demon movement subroutine
- Lines 1450–1580: Start/intro screens
- Lines 1590–1730: Entrance hall / score banking
- Lines 1740–1820: Death handling
- Lines 1830–2140: Treasure room
- Lines 2150–2270: Trap/bouncing sprite subroutine
- Lines 2280–2300: End-game scoring
- Lines 2310–2450: Difficulty and control selection
- Lines 2460–2670: Joystick and keyboard movement/fire input subroutines
Room Map Encoding
The 20-room cave network’s adjacency data is stored in the string B$ (lines 200–230) as a sequence of ASCII characters. Each room uses three characters: the two neighboring rooms accessible from north/south exits plus a third connection. The room number is extracted by CODE(R$)-57, mapping printable ASCII starting at 9 (ASCII 57) to room number 0, : to 1, and so on. This is a compact, branchless way to embed a lookup table in a BASIC string.
Procedural Cave Rendering
Each room is rendered procedurally at lines 280–390. RANDOMIZE (PR*10+NOW) seeds the random number generator with a combination of room number and a session constant, so the same room always looks the same within a session but differs between sessions. Block graphics characters 128–143 are placed randomly using CHR$(128+RND*2) and CHR$ 142, and UDGs are used for the treasure (\f) and demon (\g) sprites. The border walls are drawn using the pre-built solid-block strings C$ and D$ assembled in lines 70–120.
STICK Function Usage
The program uses the TS2068 STICK (rendered as |) function throughout for joystick input. Movement reads |(1,1) for port 1, direction bits: 1=up, 2=down, 4=left, 8=right. Firing direction is captured at lines 2520–2590 by waiting in a loop until a non-neutral joystick state is detected, then decomposing the direction into MX/MY components and a sprite-type flag ST (1, 2, 4, or 8).
Difficulty System
Six difficulty levels set two parameters: DD, the base probability per game-loop iteration that a demon will move toward the hero (line 690: IF RND<DD+TR/200), and DDL, which controls the death-penalty threshold. At DDL=1, the player can continue after death only if their score exceeds 50; at DDL=2, the threshold rises to 50+PS (previous session score), increasing pressure over multiple lives.
| DL | DD | DDL |
|---|---|---|
| 1 | 0.03 | 1 |
| 2 | 0.08 | 1 |
| 3 | 0.10 | 1 |
| 4 | 0.05 | 2 |
| 5 | 0.10 | 2 |
| 6 | 0.30 | 2 |
Treasure Room Bouncing Sprite
Room 21 is a special treasure room rendered at lines 1850–2140. A UDG sprite (\.', char 141) bounces around the room by maintaining direction variables MX and MY. The subroutine at line 2160 implements wall collision by checking the attribute of the next cell; if it equals 56 (a wall color), the direction vector is rotated 90 degrees using a swap between MX and MY with sign inversion, giving a billiard-ball reflection behavior.
Arrow Firing
When the player fires (subroutine at line 940), an arrow sprite (\a, \b, \c, or \d UDGs for four directions) is animated cell by cell along (Y1, X1) until it hits a wall attribute (58) or the screen boundary. If it lands on a demon’s stored coordinates in D(I,1)/D(I,2), the demon is removed by swapping it with the last demon in the array and decrementing DEM, scoring 5 points. This is a standard array-compaction idiom.
ATTR-Based Collision
Rather than tracking sprite positions in variables, the game uses the ATTR function to read cell color attributes for collision detection. Attribute value 58 indicates a wall, 57 triggers death, and 62 with specific conditions triggers treasure collection (line 640). This allows the cave’s random graphical elements to implicitly define the collision map without a separate data structure.
Notable Bugs and Anomalies
- Line 30 dimensions
T(20)and line 40 immediately re-dimensions it — the duplicateDIM T(20)at line 40 is redundant and would normally erase the array just initialized in the loop at lines 140–160, though both statements appear before the initialization loop, so the net effect here is harmless. - Line 50 assigns
Z$in lowercase, but line 1590 referencesZ$while line 1530 referencesz$— in Sinclair BASIC, variable names are case-sensitive for string variables entered from the keyboard, but since the program is loaded, both resolve to the same token; however,Z$(uppercase) at line 1590 will work correctly only if the BASIC interpreter treats them identically, which it does on the TS2068. - Line 2665 contains a logical error: the condition
IF F$<>"5" OR F$<>"6" OR F$<>"7" OR F$<>"8"is always true (a value cannot simultaneously equal all four strings), so theGO TO 2600is never bypassed and line 2670’sRETURNis unreachable. - Line 640 uses an unparenthesized compound condition mixing
ANDandOR, which in Sinclair BASIC evaluates left-to-right without precedence, potentially causing unintended logic whenPR=21. - Line 1480 polls
INKEY$=""to wait for a keypress but does not check for a specific key (“C” as instructed on screen), accepting any keypress.
Content
Source Code
10 REM Treasure hunt Writen by Paul Sherwood for T/S1000 16K from TS User Mag.1#4 Mod by S.J. (BUTCH) Weinberg for T/S2068 Aug.1984 Final mod. & complete game assembly 2/25/85
20 BORDER 0: PAPER 7: INK 0: CLS : PRINT AT 10,9; PAPER 2; INK 6; FLASH 1;"STOP THE TAPE"; FLASH 0: PAUSE 300: POKE 23617,0: POKE 23658,8
30 PAPER 7: CLS : DIM D(3,2): DIM T(20)
40 DIM T(20)
50 LET Z$="You are in the entrance hall"
60 LET LR=0
70 LET C$="\::\::\::\::\::\::\::\::\::\::\::\::"
80 LET D$="\::\::\::\::\::\::\::\::\::\::\::\::"
90 LET C$=C$+"\::\::\::\::\::"
100 LET D$=D$+"\::\::\::\::\::"
110 LET C$=C$+"\::\::\::\::\::\::\::\::\::\::\::\::\::\::"
120 LET D$=D$+"\::\::\::\::\::\::\::\::\::\::\::\::\::\::"
130 LET ARR=5
140 FOR I=1 TO 20
150 LET T(I)=1
160 NEXT I
170 LET PS=0: LET S=0: LET TR=0
180 RANDOMIZE
190 LET NOW=INT (RND*5000)
200 LET B$="9;>9:?9=@9<A:AB;BC"
210 LET B$=B$+"<CD=>D>?E?@F@AG"
220 LET B$=B$+"BHJCHIDIMEFKFGL"
230 LET B$=B$+"EKMHJNIMNGJL9KL"
240 LET R1=0: LET R2=0: LET R3=0
250 GO TO 1460
260 BORDER 6: OVER 0: CLS
270 REM cave plot
280 BORDER 6: RANDOMIZE (PR*10+NOW)
290 FOR I=0 TO 20
300 LET IY=RND*16+2
310 LET IX=RND*27+2
320 PRINT AT IY,IX;"\:'";
330 IF RND>.5 THEN PRINT AT IY-1,IX-1;CHR$ (128+RND*2);
340 PRINT AT IY,IX+1;"\:.";
350 PRINT AT IY+1,IX;CHR$ (128+RND*2);
360 IF RND>.6 THEN PRINT AT IY+1,IX+1;CHR$ 142;
370 PRINT AT I,0;"\::";AT I,31;"\::";
380 NEXT I
390 PRINT AT 0,1;C$;AT 20,1;C$;
400 PRINT AT 0,17;R1;AT 20,17;R2;
410 LET N=11: LET M=1
420 IF T(PR)=1 THEN PRINT AT IY,IX+1;"\f";
430 LET T(PR)=0
440 REM demon plot
450 LET DEM=INT (RND*4)
460 FOR I=1 TO DEM
470 LET D(I,1)=INT (RND*19+1)
480 LET D(I,2)=INT (RND*30+1)
490 PRINT AT D(I,1),D(I,2);"\g";: BEEP .02,-10
500 NEXT I
510 REM hero run
520 PRINT AT N,M;"\e": BEEP .02,10
530 IF CONT=1 AND |(2,1)=0 THEN GO TO 590
540 IF CONT=2 AND INKEY$<>"F" THEN GO TO 590
550 IF ARR=0 THEN GO TO 590
560 LET ARR=ARR-1
570 GO SUB 940
580 PRINT AT 21,0;"ARROWS ";ARR;
590 LET N1=N: LET M1=M
600 IF CONT=1 THEN GO SUB 2460
610 IF CONT=2 THEN GO SUB 2490
620 IF ATTR (N,M)=58 THEN GO TO 1740
630 IF ATTR (N,M)=57 THEN GO TO 1740
640 IF ATTR (N,M)=62 AND PR=21 OR ATTR (N,M)=62 AND TR<50 THEN LET TR=TR+10: BEEP .02,30
650 IF ATTR (N,M)=60 THEN GO TO 740
660 IF ABS (10-N)=10 THEN GO TO 1740
670 IF PR=21 THEN GO TO 720
680 IF DEM=0 AND RND<.03 THEN LET DEM=1
690 IF RND<DD+TR/200 THEN GO SUB 1320
700 PRINT AT N1,M1;" ";
710 GO TO 510
720 GO SUB 2160
730 GO TO 700
740 REM room switch
750 BORDER 0: CLS
760 LET LR=PR
770 IF PR<>21 THEN GO TO 800
780 LET PR=INT (RND*19+1)
790 GO TO 830
800 IF N=0 THEN LET PR=R1
810 IF N=20 THEN LET PR=R2
820 IF PR=0 THEN BORDER 4: CLS : GO TO 1590
830 PRINT '''TAB 2;"You are in the tunnel"''TAB 2;"between ";LR;" and ";PR'''TAB 2;"You have ";ARR;" arrows"'''TAB 2;"Your score is ";TR+S: FOR I=1 TO 500: NEXT I
840 IF PR=21 THEN GO TO 1850
850 LET R$=B$(PR*3-2)
860 LET R1=CODE (R$)-57
870 LET R$=B$(PR*3-1)
880 LET R2=CODE (R$)-57
890 LET R$=B$(PR*3)
900 LET R3=CODE (R$)-57
910 IF R1=LR THEN LET R1=R3
920 IF R2=LR THEN LET R2=R3
930 GO TO 260
940 REM fire
950 IF PR=21 THEN GO SUB 2160
960 IF RND<.5 THEN GO SUB 1320
970 IF CONT=1 AND |(2,1)=1 THEN PRINT AT 21,20;"F": FOR E=1 TO 60: NEXT E: PRINT AT 21,20;" ": IF PR=21 THEN GO TO 1010: GO TO 940
980 IF CONT=1 THEN GO TO 1010
990 IF CONT=2 THEN LET F$=INKEY$
1000 IF CONT=2 AND F$="F" OR F$="" THEN PRINT AT 21,20;"F": FOR E=1 TO 60: NEXT E: PRINT AT 21,20;" ": IF PR=21 THEN GO TO 1010: GO TO 940
1010 LET Y1=N
1020 LET X1=M
1030 IF CONT=1 THEN GO SUB 2520
1040 IF CONT=2 THEN GO SUB 2600
1050 LET X1=X1+MX
1060 LET Y1=Y1+MY
1070 IF ABS (15-X1)=15 OR ABS (10-Y1)=10 THEN GO TO 1310
1080 IF ATTR (Y1,X1)=58 THEN GO TO 1150
1090 IF ST=1 THEN PRINT AT Y1,X1;"\a";: BEEP .02,20: FOR E=1 TO 10: NEXT E
1100 IF ST=2 THEN PRINT AT Y1,X1;"\c";: BEEP .02,20: FOR E=1 TO 10: NEXT E
1110 IF ST=4 THEN PRINT AT Y1,X1;"\d";: BEEP .02,20: FOR E=1 TO 10: NEXT E
1120 IF ST=8 THEN PRINT AT Y1,X1;"\b";: BEEP .02,20: FOR E=1 TO 10: NEXT E
1130 PRINT AT Y1,X1;" ";
1140 GO TO 1050
1150 LET DHIT=DEM
1160 FOR I=1 TO DHIT
1170 LET Y=D(I,1)
1180 LET X=D(I,2)
1190 IF X<>X1 OR Y<>Y1 THEN GO TO 1270
1200 IF ST=1 THEN PRINT AT Y1,X1;"\a";: BEEP .05,-20
1210 IF ST=2 THEN PRINT AT Y1,X1;"\c";: BEEP .05,-20
1220 IF ST=4 THEN PRINT AT Y1,X1;"\d";: BEEP .05,-20
1230 IF ST=8 THEN PRINT AT Y1,X1;"\b";: BEEP .05,-20
1240 LET S=S+5
1250 LET D(I,1)=D(DEM,1): LET D(I,2)=D(DEM,2)
1260 LET DEM=DEM-1
1270 NEXT I
1280 IF PR=21 THEN LET FX=X1
1290 IF PR=21 THEN LET FY=Y1
1300 PRINT AT Y1,X1;" ";
1310 RETURN
1320 REM demon run
1330 FOR I=1 TO DEM
1340 LET X=D(I,2)
1350 LET Y=D(I,1)
1360 PRINT AT Y,X;" ";
1370 LET Y=Y+SGN (N-Y)
1380 LET X=X+SGN (M-X)
1390 PRINT AT Y,X;"\g";: BEEP .02,-10: FOR E=1 TO 50: NEXT E
1400 IF X=M AND Y=N THEN GO TO 1740
1410 LET D(I,1)=Y
1420 LET D(I,2)=X
1430 NEXT I
1440 RETURN
1450 REM start
1460 BORDER 5: CLS : PRINT ''" This is treasure hunt!"''"You are in a network of caves."''"You are looking for gold."''"If you are careful you may reach"'"the treasure room, but beware:"''"there are monsters which will"'"eat you: "''"To touch anything red or"'"blue means instant death.": FOR E=1 TO 5: BEEP .05,3: BEEP .05,6: BEEP .05,9: NEXT E
1470 PRINT ''TAB 6; PAPER 6; INK 1; FLASH 1;"TOUCH C TO CONTINUE"; FLASH 0
1480 IF INKEY$="" THEN GO TO 1480
1490 BORDER 5: CLS : PRINT ''"To score you must pick up"''"the treasures (\f)=10 points"''"or kill the monsters(\g)=5 points"''"You can only colect 5 "''"treasures before going back"''"to room 0 the ENTRANCE HALL."''" GOOD LUCK!": FOR E=1 TO 5: BEEP .05,3: BEEP .05,6: BEEP .05,9: NEXT E
1500 PRINT ''TAB 6; PAPER 6; INK 1; FLASH 1;"TOUCH C TO CONTINUE"; FLASH 0
1510 IF INKEY$="" THEN GO TO 1510
1520 GO SUB 2310
1530 PRINT ''''z$
1540 PRINT ''"Choose cave 1,2,3 or 4?"
1550 INPUT PR: PRINT ''''"You have chosen ";PR: PAUSE 160
1560 IF PR<1 OR PR>4 THEN GO TO 1550
1570 LET LR=0
1580 GO TO 840
1590 PRINT ''Z$
1600 PRINT ''"Your treasure is safe here."''"your score is ";S+TR
1610 PRINT ''TAB 0;"You have ";ARR;" arrows."''"Are you going back in?": FOR E=1 TO 50: NEXT E
1620 INPUT Q$
1630 IF Q$="NO" OR Q$="N" THEN PRINT ''"You scored ";S+TR: GO TO 2290
1640 LET S=S+TR
1650 LET TR=0
1660 PRINT ''"How many arrows do you want?"''"They are 4 points each."
1670 INPUT F
1680 IF F*4>S THEN GO TO 1720
1690 LET S=S-F*4
1700 LET ARR=ARR+F
1710 GO TO 1540
1720 CLS
1730 PRINT ''"You cant afford them": GO TO 1660
1740 REM death of a hero
1750 BORDER 2: CLS : PRINT AT 5,1;"Unfortunatly you have perished."''" You scored: ";S+TR: FOR E=1 TO 300: NEXT E
1760 IF DDL=1 AND S+TR<50 THEN GO TO 2280
1770 IF DDL=2 AND S+TR<50+PS THEN GO TO 2280
1780 LET S=S-15
1790 LET PS=S+TR
1800 PRINT ''''" You played well"''" I shall deduct 15 points"''" for damage to the body"'''" You may continue.": PAUSE 500
1810 BORDER 4: CLS
1820 GO TO 1590
1830 REM treasure room
1840 PRINT AT 0,0;
1850 CLS
1860 FOR I=-10 TO 10
1870 LET AI=ABS I
1880 PRINT TAB 0; INK 1;D$( TO AI);
1890 PRINT TAB (30-AI); INK 1;D$( TO AI)
1900 NEXT I
1980 PRINT AT 0,10; INK 1;D$( TO 10)
1990 PRINT AT 20,10; INK 1;D$( TO 10)
2000 PRINT AT 10,0;"\::";TAB 29;"\::"
2010 LET DEM=1
2020 LET QW=INT (RND*4)
2030 FOR I=1 TO QW+1
2040 PRINT AT 12+I,12+(RND*2);"\f\f\f";
2050 NEXT I
2060 LET N=10
2070 LET MY=-1
2080 LET MX=0
2090 LET K=18
2100 LET J=7
2110 LET M=2
2120 LET FX=J
2130 LET FY=K
2140 GO TO 510
2150 REM trap
2160 IF ATTR (J+MX,K+MY)=56 THEN GO TO 2220
2170 LET AD=MY
2180 IF AD=0 THEN LET MY=MX
2190 IF AD=0 THEN LET MX=0
2200 IF AD<>0 THEN LET MY=0
2210 IF AD<>0 THEN LET MX=0-AD
2220 LET J=J+MX
2230 LET K=K+MY
2240 PRINT AT K,J;"\.'";
2245 IF ATTR (FY,FX)<>56 THEN GO TO 2120
2250 IF RND>.5 THEN PRINT AT FY,FX;"\.'"
2260 IF RND<.25 THEN GO SUB 1320
2270 RETURN
2280 PRINT ''"Sorry you have perished but"''"your final score is ";S+TR+(ARR*4): GO TO 2300
2290 PRINT ''"Sorry you don't want to"''"try for a larger score."''"Your final score is ";S+TR+(ARR*4)
2300 BEEP .20,17: BEEP .20,17: BEEP .20,17: BEEP .15,5: BEEP .20,14: BEEP .20,10: BORDER 7: STOP
2310 CLS : PRINT " \.'\.'\.'\.' TREASURE HUNT \.'\.'\.'\.'\.'"''" Chooze your dificulty level"''"from 1 to 6 (small # are easier)"''" Dificulty: ";
2320 INPUT DL: PRINT DL
2330 IF DL=1 THEN LET DD=.03: LET DDL=1
2340 IF DL=2 THEN LET DD=.08: LET DDL=1
2350 IF DL=3 THEN LET DD=.1: LET DDL=1
2360 IF DL=4 THEN LET DD=.05: LET DDL=2
2370 IF DL=5 THEN LET DD=.1: LET DDL=2
2380 IF DL=6 THEN LET DD=.3: LET DDL=2
2390 IF DL<1 OR DL>6 THEN GO TO 2320
2400 PRINT ''TAB 10;"Now chooze "''" 1. Joystick"''" 2. Keyboard arrows"''" touch # then ENTER"
2410 INPUT CONT
2420 IF CONT=1 THEN PRINT '"You will be using the Joystisk.": PAUSE 200: CLS : GO TO 2450
2430 IF CONT=2 THEN PRINT '"You will be using the arrows.": PAUSE 200: CLS : GO TO 2450
2440 IF CONT<1 OR CONT>2 THEN GO TO 2410
2450 RETURN
2460 LET M=M+(1 AND |(1,1)=8)-(1 AND |(1,1)=4)
2470 LET N=N+(1 AND |(1,1)=2)-(1 AND |(1,1)=1)
2480 RETURN
2490 LET M=M+(1 AND INKEY$="8")-(1 AND INKEY$="5")
2500 LET N=N+(1 AND INKEY$="6")-(1 AND INKEY$="7")
2510 RETURN
2520 IF |(1,1)=0 OR |(1,1)=9 OR |(1,1)=10 OR |(1,1)=6 OR |(1,1)=5 THEN GO TO 2520
2530 LET MY=0+(1 AND |(1,1)=2)-(1 AND |(1,1)=1)
2540 IF |(1,1)=2 THEN LET ST=2
2550 IF |(1,1)=1 THEN LET ST=1
2560 LET MX=0+(1 AND |(1,1)=8)-(1 AND |(1,1)=4)
2570 IF |(1,1)=8 THEN LET ST=8
2580 IF |(1,1)=4 THEN LET ST=4
2590 RETURN
2600 LET F$=INKEY$
2610 LET MY=0+(1 AND F$="6")-(1 AND F$="7")
2620 IF F$="7" THEN LET ST=1: RETURN
2630 IF F$="6" THEN LET ST=2: RETURN
2640 LET MX=0+(1 AND F$="8")-(1 AND F$="5")
2650 IF F$="5" THEN LET ST=4: RETURN
2660 IF F$="8" THEN LET ST=8: RETURN
2665 IF F$<>"5" OR F$<>"6" OR F$<>"7" OR F$<>"8" THEN GO TO 2600
2670 RETURN
9997 STOP
9998 SAVE "TREAS HUNT" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

