--- title: "Cave" id: 57532 type: "computer_media" slug: "cave" url: "http://localhost/computer_media/cave/" markdown_url: "http://localhost/computer_media/cave.md" published_at: "2024-10-05T21:34:32+00:00" modified_at: "2026-04-03T07:58:22+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/287_Cave.png" excerpt: "Hire two companions, brave nine treacherous caves, and fight ghosts, trolls, and wolves in this complete BASIC text-adventure with block-graphic cave maps." 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: 56737 title: "Timex Sinclair Public Domain Library Tape 1006" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1006/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/287_Cave.png" media_type_tags: "Game" --- # Cave 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 `K` is unused:** The player inputs their sack choice into `K` at line 5786, but `K` is 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<11` at 5568 contradicts the immediately preceding `IF D<11` at 5567 (which already printed the “faded” message); both refer to the same `D` from subroutine 8000. This double-branch is logically redundant but harmless. - **CASH can go negative:** The sand-troll encounter (lines 5586) subtracts `10*D` from `CASH` without 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 8200` at 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. ## 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 ```