This is a text-based cave-exploration adventure game for one player, who assembles a two-member party from five named companions before navigating through nine numbered caves to escape with treasure. Each cave presents a randomly determined encounter — including a ghost, sand troll, wild wolf, poisoned gas, mysterious bottles, chests of gems, treasure maps, or sacks of unknown contents — with outcomes driven by a 1–16 random number generator in subroutine 8000. The game tracks three party statistics (cash, strength, and magic power) and computes a final score as 10×CASH + 20×S + 30×P upon reaching cave 10. Cave interiors are rendered with a simple box diagram using ZX81-style block graphics, and the current exit direction is marked with an inverse-video asterisk inside the box.
Program Analysis
Program Structure
The program is divided into clearly separated functional blocks by line-number ranges:
- Lines 5–350: Initialisation, SLOW mode, and sanity-clamp guards on all state variables.
- Lines 1100–3240: Status display — party members, statistics, score, and a block-graphic cave map with directional marker.
- Lines 5100–5240: Main game loop — direction input, dispatch via computed GOSUB, delay loop, and return to line 300.
- Lines 5513–5900: Individual encounter subroutines, each returning with
RETURN. - Lines 7000–7999: Win sequence with congratulations, final score, and a decorative inverse-character border.
- Lines 8000–8020: Core random-number subroutine; returns a value 1–16 in
D. - Lines 8210–8557: Party-selection screen and five hire subroutines (one per companion).
- Lines 9500–9930: Variable initialisation, array setup, game entry, and SAVE with auto-run flag.
Computed GOSUB Dispatch
The encounter system at line 5230 uses a calculated target:
IF D>2 AND D<15 THEN GOSUB 5480+20*D
With D ranging from 3 to 14, this maps to subroutines at 5540, 5560, 5580, 5600, 5620, 5640, … , 5740. Lines below 3 trigger a chest encounter (line 5221 dispatches to 5513), and values above 14 trigger the sack encounter (line 5225 dispatches to 5780). This is a common ZX81/TS1000 BASIC technique for replacing ON…GOSUB with arithmetic.
Similarly, party hiring uses GOSUB 8500+10*G(W) at line 8390, dispatching to one of five subroutines (8510–8550) based on the player’s menu choice stored in array G(2).
State Variables
| Variable | Meaning |
|---|---|
CAVE | Current cave number (1–9); reaching 10 triggers the win state |
CASH | Treasure carried, in dollars |
S | Combined party strength |
P | Combined party magic power |
D | Current random roll (1–16), reused across encounters |
D$ | Current exit direction chosen (N/S/E/W) |
A$, B$ | Names of the two hired companions (may acquire prefixes like “WOUNDED ” or “BATTERED “) |
G(2) | Two-element integer array holding party hire choices |
K | Player’s sack choice (input but never used in outcome logic) |
Cave Map Rendering
Lines 3120–3240 draw a simple rectangular room using ZX81 block-graphic characters. The four walls are drawn with \:.., \'', \ :, and \.. escape sequences. Depending on D$, an inverse-video asterisk (%*) is printed on the north, south, east, or west wall segment to indicate the chosen exit direction. The cave number itself is rendered using CHR$(CAVE+156), exploiting the ZX81 character set where codes 157–165 map to the inverse digits 1–9.
Delay Loops
Several subroutines use busy-wait FOR…NEXT loops for pacing. Line 5236–5237 use 150 iterations as a universal “STAND BY” pause, while lines 5546–5547 and 5562–5564 use 125 iterations for dramatic effect before a random outcome is revealed. Line 5603 uses PAUSE 15*D, making the wait duration proportional to the random roll — a subtle tension-building device.
Bugs and Anomalies
- Lines 5565–5572 numbering gap: Line 5566 follows 5565 with a conditional — but line 5565 itself is only a
RETURN, so control never reaches 5566–5572 naturally. The treasure-map subroutine at 5560 effectively ends at 5565 before the outcome logic runs. This appears to be a cut-and-paste error where the outcome code was displaced from the subroutine it belongs to. - Variable
Kis unused: The player inputs their sack choice intoKat line 5786, butKis never referenced again; the outcome depends solely on the subsequent random roll. The input serves only as an in-universe dramatic beat. - Line 5568 unreachable: The condition
IF D<11at 5568 contradicts the immediately precedingIF D<11at 5567 (which already printed the “faded” message); both refer to the sameDfrom subroutine 8000. This double-branch is logically redundant but harmless. - CASH can go negative: The sand-troll encounter (lines 5586) subtracts
10*DfromCASHwithout a floor guard; CASH can become deeply negative, though the sanity clamp at line 320 only resets it to 0 at the top of the display loop. - Line 8200 vs 8210: Initialisation calls
GOSUB 8200at line 9890, but the party-selection subroutine starts at line 8210. Line 8200 does not exist, so execution falls through to 8210. This is a valid ZX81 BASIC behaviour (jump to next higher line) and functions correctly.
Scoring Formula
The score is computed identically at lines 3100 and 7090 as 10*CASH + 20*S + 30*P, weighting magic power most heavily and raw cash least. This incentivises hiring companions with high magic (e.g. Merlin with P=10) over pure fighters, since each magic point is worth three times a dollar of treasure in the final tally.
Content
Source Code
5 SLOW
10 RAND
100 GOSUB 9500
300 CLS
310 IF CAVE<1 THEN LET CAVE=1
320 IF CASH<1 THEN LET CASH=0
330 IF S<1 THEN LET S=0
340 IF P<1 THEN LET P=0
350 IF CAVE>9 THEN GOTO 7000
1100 PRINT "%Y%O%U% %A%R%E% %I%N% %C%A%V%E% %N%U%M%B%E%R%:";CHR$ (156+CAVE)
1120 IF CASH>0 THEN PRINT "YOUR PARTY IS CARRYING","$";CASH;" WORTH OF TREASURE"
1140 PRINT " ";A$;" AND ";B$
1145 PRINT TAB (8);"ARE WITH YOU"
1150 PRINT "YOUR TOTAL STRENGTH IS ";S
1160 PRINT "YOUR COMBINED %M%A%G%I%C% %P%O%W%E%R IS ";P
3100 PRINT ,"POINTS: ";10*CASH+20*S+30*P
3120 PRINT TAB (8);"......: :......"
3130 IF D$="S" THEN PRINT TAB (8);": %* :"
3150 PRINT TAB (8);": ";CHR$ (CAVE+156);" :"
3170 IF D$="E" THEN PRINT TAB (8);"'' %* ''''"
3190 IF D$="W" THEN PRINT TAB (8);"'' %* ''''"
3200 IF D$<>"W" AND D$<>"E" THEN PRINT TAB (8);"'' ''''"
3210 PRINT TAB (8);".. ...."
3220 PRINT TAB (8);": :"
3230 IF D$="N" THEN PRINT TAB (8);": %* :"
3240 PRINT TAB (8);"'''''': :''''''"
5100 PRINT " WHICH EXIT (N,S,E,W)?"
5120 INPUT D$
5125 IF D$="U" THEN STOP
5210 CLS
5220 GOSUB 8000
5221 IF D<3 THEN GOSUB 5513
5225 IF D>14 THEN GOSUB 5780
5230 IF D>2 AND D<15 THEN GOSUB 5480+20*D
5232 PRINT ,,,"%-%-%-%S%T%A%N%D% %B%Y%-%-%-"
5235 LET X=0
5236 FOR X=1 TO 150
5237 NEXT X
5240 GOTO 300
5513 PRINT "AHEAD OF YOU IS A CHEST"
5514 GOSUB 8000
5515 PRINT "IT CONTAINS ";D/2;" KG OF GEMS"
5516 PRINT "YOUR AVAILABLE STRENGTH IS ";S
5517 PRINT "(THE MOST YOU CAN TAKE IS ";INT (S/4);")"
5520 PRINT "HOW MUCH WILL YOU TAKE ?"
5521 INPUT DD
5522 IF DD>D/2 OR DD>INT (S/4) THEN GOTO 5521
5523 LET S=S-DD
5524 LET CASH=CASH+2.5*DD
5539 RETURN
5540 PRINT "YOU ARE FACE TO FACE WITH THE"
5542 PRINT " GHOST OF %L%O%N%G %J%O%H%N %S%I%L%V%E%R..."
5544 PRINT "WILL HE HARM YOU ?"
5545 LET X=0
5546 FOR X=1 TO 125
5547 NEXT X
5548 GOSUB 8000
5549 IF D>8 THEN PRINT "YES...HE STRIKES..."
5550 IF D>8 THEN PRINT "AND ";A$;" IS INJURED"
5551 IF D>8 THEN LET S=S-2
5552 IF D>16 THEN LET P=P-1
5553 IF D<9 THEN PRINT "NO, HE HAS TURNED AWAY","YOU MAY PROCEED"
5554 IF D>12 THEN LET CAVE=CAVE-1
5555 IF D<9 THEN LET CAVE=CAVE+1
5556 RETURN
5560 PRINT "%A%H%A%,%A% %T%R%E%A%S%U%R%E% %M%A%P%.%.%.%C%A%N% %Y%O%U","%R%E%A%D% %I%T%-%-%-%W%E% %S%H%A%L%L% %S%E%E"
5561 GOSUB 8000
5562 LET X=0
5563 FOR X=1 TO 125
5564 NEXT X
5565 RETURN
5566 IF D<11 THEN PRINT "%N%O%,% %I%T% %H%A%S% %F%A%D%E%D%.%.%."
5567 IF D<11 THEN LET S=S-INT (D/3)
5568 IF D<11 THEN PRINT "YES $$$$$$$$$ AND IT TELLS","YOU WHERE TO FIND $";10*D/2,"WORTH OF GOLD DUBLOONS"
5569 IF D>10 THEN LET CASH=CASH+10*D/2
5570 IF D>10 THEN LET CAVE=CAVE+1
5572 RETURN
5580 PRINT "%G%A%D%Z%O%O%K%S%.%.%.%A% %S%A%N%D% %T%R%O%L%L","HAS IT SPOTTED YOU ?"
5582 GOSUB 8000
5583 GOSUB 5562
5584 IF D<7 THEN PRINT "LUCKY...HE HAS TURNED AWAY"
5585 IF D>6 THEN PRINT "HORRORS, HE ATTACKS ";A$
5586 IF D>6 THEN LET CASH=CASH-10*D
5587 IF CASH>0 AND D>6 THEN PRINT "STEALING $";10*D;" WORTH OF EMERALDS"
5589 IF D<7 THEN LET CAVE=CAVE+1
5590 LET A$="BATTERED "+A$
5595 RETURN
5600 PRINT "YOU FIND A BOTTLE FASHIONED OF","CURIOUS, MISTY GLASS...WHAT IS","INSIDE IT ?"
5602 GOSUB 8000
5603 PAUSE 15*D
5604 IF D<7 THEN PRINT "IT HOLDS A %G%E%N%I%E WHO GIVES","YOU $";5*D;"AND INCREASES YOUR","STRENGTH BY ";D
5605 IF D<7 THEN LET CASH=CASH+5*D
5606 IF D<7 THEN LET S=S+D
5607 IF D>6 THEN PRINT "%I%T% %H%E%L%D% %N%O%T%H%I%N%G% %B%U%T% %S%T%A%L%E% %S%M%O%K%E"
5608 IF D<7 THEN LET CAVE=CAVE+1
5609 RETURN
5620 PRINT "A WILD WOLF HAS BEEN TRAPPED FOR YEARS IN THIS CAVE. IT IS","BREAKING FREE...YOUR PARTY RUNS FOR SAFETY %W%I%L%L% %Y%O%U% %M%A%K%E% %I%T% %?"
5622 GOSUB 8000
5623 GOSUB 5562
5624 IF D<12 THEN PRINT "YES, YOU MANAGE TO ESCAPE"
5625 IF D<12 THEN LET CAVE=CAVE+2
5626 IF D>11 THEN PRINT "HORRORS IT HAS CAUGHT","AND WOUNDED ";B$
5627 IF D>11 THEN LET B$="WOUNDED "+B$
5628 IF D>11 THEN LET S=INT (S/2)
5629 RETURN
5640 PRINT "THE CAVE IS FULL OF POISONED","GAS...FLEE FOR YOUR LIVES"
5641 GOSUB 8000
5642 LET CAVE=CAVE-1
5643 LET S=S-INT (D/5)
5650 RETURN
5780 PRINT "IN THE CAVE ARE ";
5782 GOSUB 8000
5784 PRINT D+1;" SACKS...";"WHICH ONE DO YOU DARE OPEN ?"
5786 INPUT K
5787 GOSUB 5562
5788 GOSUB 8000
5789 IF D>12 THEN GOTO 5800
5790 PRINT "%D%E%S%P%A%I%R%,% %J%U%S%T% %S%A%N%D"
5792 IF D<4 THEN PRINT ,"%A%N%D% %S%P%I%D%E%R%S"
5793 LET S=S-2
5797 RETURN
5800 PRINT "YOU ARE LUCKY"
5805 IF D>16 THEN PRINT "DIAMONDS AND RUBIES"
5806 IF D<17 THEN PRINT "%S%I%L%V%E%R%,% %G%O%L%D% %A%N%D% %G%E%M%S"
5810 GOSUB 8000
5812 LET CASH=CASH+7.5*D
5813 LET S=S+1
5814 LET P=P+1
5820 LET CAVE=CAVE+1
5900 RETURN
7000 PRINT " % %C%O%N%G%R%A%T%U%L%A%T%I%O%N%S% "
7010 PRINT
7020 PRINT "YOU, ";A$;" AND ";B$
7030 PRINT "MADE IT SAFELY OUT OF THE"
7040 PRINT TAB (8);"CAVE SYSTEM"
7050 PRINT
7060 PRINT "YOU HAVE $";CASH;" % %T%R%E%A%S%U%R%E% "
7070 PRINT
7080 PRINT
7090 PRINT " AND SCORED ";10*CASH+20*S+30*P;" POINTS"
7100 PRINT
7105 FOR A=1 TO 6
7110 PRINT "..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$..%$"
7130 NEXT A
7999 STOP
8000 REM RANDOM NUNBERS
8010 LET D=INT (RND*16)+1
8020 RETURN
8210 CLS
8220 GOSUB 8000
8230 LET CASH=39.5*D
8240 PRINT "% %T%I%M%E% %T%O% %P%I%C%K% %A% %P%A%R%T%Y% %T%O% %E%X%P%L%O%R%E% %T%H%E% %C%A%V%E%S% %W%I%T%H% %Y%O%U%.%.%."
8250 PRINT
8255 FOR W=1 TO 2
8256 IF W=2 THEN CLS
8260 PRINT "YOU HAVE $";CASH
8270 PRINT
8280 PRINT "YOU CAN HIRE ANY % %2% OF THESE:"
8290 PRINT
8300 PRINT "NAME $ COST STRENGTH POWER"
8310 PRINT
8320 PRINT "1: MORGAL 100 12 0"
8330 PRINT "2: MERLIN 47 2 10"
8340 PRINT "3: MUMBLE 83 6 6"
8350 PRINT "4: MACKTO 90 9 3"
8360 PRINT "5: MINMUK 64 3 9"
8370 PRINT
8380 PRINT "CHOICE ";W
8385 INPUT G(W)
8390 GOSUB 8500+10*G(W)
8410 NEXT W
8412 RETURN
8415 STOP
8510 LET CASH=CASH-100
8511 LET S=S+12
8512 IF W=1 THEN LET A$="MORGAL"
8513 IF W=2 THEN LET B$="MORGAL"
8519 RETURN
8520 IF W=1 THEN LET A$="MERLIN"
8521 LET CASH=CASH-47
8522 LET S=S+2
8523 LET P=P+10
8524 IF W=2 THEN LET B$="MERLIN"
8527 RETURN
8530 IF W=1 THEN LET A$="MUMBLE"
8531 LET CASH=CASH-83
8532 LET S=S+6
8533 LET P=P+6
8534 IF W=2 THEN LET B$="MUMBLE"
8535 RETURN
8540 IF W=1 THEN LET A$="MACKTO"
8541 LET CASH=CASH-90
8542 LET S=S+9
8543 LET P=P+3
8544 IF W=2 THEN LET B$="MACKTO"
8547 RETURN
8550 IF W=1 THEN LET A$="MINMUK"
8551 LET CASH=CASH-64
8552 LET S=S+3
8553 LET P=P+9
8554 IF W=2 THEN LET B$="MINMUK"
8557 RETURN
9490 STOP
9500 DIM G(2)
9540 LET D$=""
9560 LET P=0
9570 LET S=0
9610 LET CASH=0
9620 LET CAVE=1
9890 GOSUB 8200
9900 RETURN
9910 CLEAR
9920 SAVE "1028%7"
9930 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
