Skip to content

Follow a tunnel

Turn a direction key into a validated room change.

  • Sinclair ZX Spectrum
  • BASIC

Let the player follow the room links. For now every room is safe, including the black shaft. The words describe a place; we have not made any description into a rule.

Replace lines 250, 260.

Add lines 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 430, 490, 1020, 1190, 1200, 1210, 8000, 9000, 9010.

Delete lines 280.

To delete a BASIC line, enter its number on its own.

changes.bas
 250 LET rm=1: LET turns=0
 260 LET d$="NSEW": LET e$="nsew": LET h$="Choose a tunnel to explore."
 300 GO SUB 9000
 310 LET k$=INKEY$: IF k$="" THEN GO TO 310
 320 IF k$="q" OR k$="Q" THEN GO TO 8000
 330 IF k$="r" OR k$="R" THEN GO TO 200
 340 LET dir=0: FOR j=1 TO 4: IF k$=d$(j) OR k$=e$(j) THEN LET dir=j
 350 NEXT j
 360 IF dir=0 AND k$<>" " THEN GO TO 300
 370 LET dest=rm
 380 IF dir>0 THEN LET dest=m(rm,dir)
 390 IF dest=0 THEN PRINT AT 18,2; INK 6;"No tunnel in that direction. ": GO TO 300
 400 LET turns=turns+1: LET h$="Your footsteps fade away."
 430 LET rm=dest
 490 GO TO 270
1020 PRINT AT 2,2; INK 6;"TURNS ";turns
1190 PRINT AT 18,2; INK 5;h$
1200 PRINT AT 20,2; INK 7;"N S E W / SPACE waits"
1210 PRINT AT 21,2; INK 7;"R: restart   Q: quit"
8000 PRINT AT 21,2; INK 7;"The Caverns finished.       ": STOP
9000 IF INKEY$<>"" THEN GO TO 9000
9010 RETURN

RUN the changed program.

Complete source at this checkpoint
caverns.bas
  10 BORDER 0: PAPER 0: INK 7: BRIGHT 1: CLS
 200 DIM m(12,4): DIM a$(12,24): DIM b$(12,28)
 210 RESTORE 9500
 220 FOR i=1 TO 12: READ a$(i),b$(i): FOR j=1 TO 4: READ m(i,j): NEXT j: NEXT i
 250 LET rm=1: LET turns=0
 260 LET d$="NSEW": LET e$="nsew": LET h$="Choose a tunnel to explore."
 270 GO SUB 1000
 300 GO SUB 9000
 310 LET k$=INKEY$: IF k$="" THEN GO TO 310
 320 IF k$="q" OR k$="Q" THEN GO TO 8000
 330 IF k$="r" OR k$="R" THEN GO TO 200
 340 LET dir=0: FOR j=1 TO 4: IF k$=d$(j) OR k$=e$(j) THEN LET dir=j
 350 NEXT j
 360 IF dir=0 AND k$<>" " THEN GO TO 300
 370 LET dest=rm
 380 IF dir>0 THEN LET dest=m(rm,dir)
 390 IF dest=0 THEN PRINT AT 18,2; INK 6;"No tunnel in that direction. ": GO TO 300
 400 LET turns=turns+1: LET h$="Your footsteps fade away."
 430 LET rm=dest
 490 GO TO 270
1000 CLS
1010 PRINT AT 0,8; INK 5;"THE CAVERNS"
1020 PRINT AT 2,2; INK 6;"TURNS ";turns
1030 INK 1: PLOT 16,148: DRAW 223,0
1040 PRINT AT 5,2; INK 5;a$(rm)
1050 PRINT AT 7,2; INK 7;b$(rm)
1060 PRINT AT 9,2; INK 6;"TUNNELS"
1070 FOR j=1 TO 4
1080 LET v=m(rm,j): LET y=10 +j
1090 PRINT AT y,2; INK 7;d$(j);"  --"
1100 IF v=0 THEN GO TO 1160
1110 PRINT AT y,2; INK 7;d$(j);"  Open"
1160 NEXT j
1190 PRINT AT 18,2; INK 5;h$
1200 PRINT AT 20,2; INK 7;"N S E W / SPACE waits"
1210 PRINT AT 21,2; INK 7;"R: restart   Q: quit"
1220 RETURN
8000 PRINT AT 21,2; INK 7;"The Caverns finished.       ": STOP
9000 IF INKEY$<>"" THEN GO TO 9000
9010 RETURN
9500 DATA "The entrance","Daylight rims the stone.",0,5,2,0
9510 DATA "Split passage","Two worn paths meet here.",0,6,3,1
9520 DATA "Echo gallery","Every step returns twice.",0,7,4,2
9530 DATA "High ledge","A narrow shelf bends south.",0,8,0,3
9540 DATA "Root chamber","Roots grip the damp ceiling.",1,9,6,0
9550 DATA "Old camp","A torn pack lies in dust.",2,10,7,5
9560 DATA "The black shaft","The floor vanishes below.",3,11,8,6
9570 DATA "Dripping stair","Water counts the seconds.",4,12,0,7
9580 DATA "Still pool","Your lamp trembles in water.",5,0,10,0
9590 DATA "Buried shrine","Carved faces watch the path.",6,0,11,9
9600 DATA "Low arch","You stoop beneath the rock.",7,0,12,10
9610 DATA "Crystal hollow","Crystals catch the lamplight.",8,0,0,11

RUN and press S, then E. You should visit the Root chamber and then the Old camp, with two turns counted. N/S/E/W move; Space waits, R restarts and Q quits. Try north at the entrance: a wall must not spend a turn.

Translate a key into a direction

INKEY$ gives a pressed character, or the empty string when no key is down. The input loop waits for a character, then handles Q and R. The direction loop compares it with each character of "NSEW" and "nsew", so either case works. A match stores the direction’s index in dir.

NEXT sits on a separate line from the IF. A false IF skips the remainder of its own line; the loop must still reach NEXT when a particular direction does not match.

Space is different from no key: " " contains one blank character, while "" contains none. Space is a valid wait action. Other unmatched characters return to input without changing the world.

Decide where to go before going there

Set dest to the current room first. That is where waiting leaves us. For a direction, replace dest with m(rm,dir). A zero destination means a wall, so display a message and return before the turn count changes.

Only after validation do we increment turns and copy dest into rm. GO TO 270 redraws the new room, then waits for another action. This separation gives later hazard checks somewhere to examine a proposed move before accepting it.

The routine at 9000 waits until the key is released. Hold S at the entrance: you should move once into the Root chamber, not continue south into the Still pool. Release it and press again for another action.

Why does Space count a turn when the room number stays the same?

Show the explanation

A turn records an accepted action, not necessarily movement. Waiting will later give the creature a chance to move while you stay put. A wall is rejected before that point.

Explore the names and exits. The map is fixed, so returning by the opposite tunnel should lead back where you came from. If a room is wrong, check its DATA link before changing the input code.

Keyboard notes

In extended mode, N enters INKEY$. Symbol Shift+U enters OR, Symbol Shift+Y enters AND, and Symbol Shift+W enters the not-equal operator <>.

Sources

Steven Vickers, edited by Robin Bradbeer, ZX Spectrum BASIC Programming, second edition (Sinclair Research, 1983), chapter 4, chapter 8, chapter 13, chapter 18.

Run it here

This unit's program, built for you.

Program
caverns.tap
Machine
ZX Spectrum 48K (PAL)

Download caverns.tap