Beacon Adventure is a text-based adventure game in which the player must locate and power a beacon to win. The game world is represented as a 9×9 grid of location strings stored in the three-dimensional string array `l$(9,9,110)`, where wall/impassable cells are marked with a solid block character. Objects are tracked using parallel arrays `a(9)` and `b(9)` for grid coordinates, with zero-valued coordinates indicating the item is in the player’s inventory. The parser splits input into a verb `a$` and object string `b$` by scanning for a space, supporting commands including CHOP, FEED, SWIM, INSERT, MAKE, LIGHT, OPEN, UNLOCK, GET, DROP, and cardinal movement. Progress flags such as `wo` (wolves), `fed`, `lit`, `tr` (tree chopped), `op` (door opened), and `loc` (door locked) control puzzle state, and the game supports mid-session saving via `SAVE “adventure” LINE 40` to resume at the main game loop.
Program Structure
The program is organized into a main loop and a collection of subroutines. Initialization occupies lines 10–30, the main display/input loop runs from lines 40–290, movement logic is at lines 300–410, and command handlers are implemented as subroutines or inline GO TO targets from lines 420 onward. World data is loaded in subroutine 1030, and object data in subroutine 1540. The exit-display subroutine is at line 1640, and save/quit routines appear at lines 1690–1750.
World Representation
The game map is a 9×9 grid encoded in the three-dimensional string array l$(9,9,110), where each cell holds up to 110 characters of descriptive text. Impassable or undefined cells are filled with the solid block character \:: (█). The outer border (row 1, row 9, column 1, column 9) is initialized to solid blocks in lines 1040–1050, and the interior 7×7 cells are populated from DATA statements via nested FOR loops at line 1060. Movement checks at lines 330–360 compare the first character of adjacent cells to \:: to determine whether travel in a given direction is permitted.
Object and Inventory System
Nine objects are defined using two parallel numeric arrays, a(9) and b(9), representing the row and column of each object on the map. A coordinate of (0,0) — set when the player picks up an item — signals that the object is in the player’s inventory. Object names are stored in o$(9,15). The inventory listing at line 480 prints any object whose a(f) equals zero. The counter ca is incremented on GET but its value is never subsequently used, representing a dead variable.
Parser Design
Input is collected as a full line into c$, which is padded with a trailing space at line 90. Lines 100–120 scan for the first space to split the string into verb a$ and remainder b$. The loop termination trick LET f=LEN c$ inside the FOR loop at line 110 simulates an early exit since ZX BASIC does not have a BREAK statement. Single-character commands such as n, s, e, w, i, r, and d are handled directly; multi-word commands use the split verb/object approach.
Puzzle Flags
Game state is tracked through a set of Boolean integer flags initialized at line 10 and subroutine 1600–1620:
wo— wolves present at (3,6), blocking movement until an onion is droppedfed— dog at (8,3) has been fed; clears the westward movement blocklit— candle has been lit, required to descend undergroundop— door has been opened, enabling thed(down) commandloc— door is locked; must be unlocked with the golden key before openingtr— tree has been chopped, prerequisite for making a raftst— stream blocks eastward travel; cleared by making a raft
Notable Techniques
Location descriptions are prefixed with the string y$="You are " stored at line 10 and concatenated directly inside DATA strings at lines 1090–1520. This allows compact DATA entries while producing full sentences at runtime. The SAVE at line 1720 uses SAVE "adventure" LINE 40 to auto-run the program from the main display loop rather than from line 10, bypassing re-initialization on load — an intentional design for resuming a saved game.
Bugs and Anomalies
- Lines 600 and 650 contain a precedence error:
IF b$="door " AND x<>6 OR y<>8is evaluated as(b$="door " AND x<>6) OR (y<>8), meaning the condition is almost always true regardless of location, making the door commands unreliable. - Lines 960 and 970 are in the wrong order: the
b$<>"raft "check executes before theb$=""check, so “Make what?” is never reached. - Line 540 applies the onion/wolf logic when dropping the onion with
woalready zero (no wolves), whereas line 555 correctly checksAND wo; the line 540 check is missing theAND woguard, causing the wolf-flee message to print even if no wolves are present. - The variable
raftis set at line 1600 but the stream flagstis cleared at line 1000 on raft construction;raftitself is never read, making it a dead variable alongsideca. - Lines 1010–1020 are unreachable dead code: no command dispatch in lines 130–290 routes to line 1010, and line 1020 uses
ORwhere it would needANDto ever fail the condition. - Line 1530 sets a blue border and paper but is never called; the subroutine starting at line 1540 is called from line 30, jumping past the BORDER/PAPER/CLS setup.
- Line 1220 contains a typo: “Threre” instead of “There”.
- Line 840 spells “succesfully” with one ‘s’, a minor spelling error.
Content
Source Code
10 LET i=0:LET ca=i:LET found=i:LET op=i:LET wo=i:LET st=i:LET fed=i:LET tr=i:LET y$="You are "
20 BORDER 0:PAPER 0:INK 7:CLS
30 PRINT "BEACON ADVENTURE"''"OBJECT: Find beacon & light it."''"Please Wait":PAUSE 50:GO SUB 1030:GO SUB 1540
40 PRINT :PRINT l$(x,y):GO SUB 1640
50 FOR f=1 TO 9:IF a(f)=x AND b(f)=y THEN PRINT "Looking around you see a ";o$(f)
60 NEXT f
70 IF x=4 AND y=3 THEN STOP
80 INPUT "What next? "; LINE c$
90 LET c$=c$+" "
100 IF LEN c$=1 THEN LET a$=c$
110 FOR f=1 TO LEN c$:IF c$(f)=" " THEN LET a$=c$( TO f-1):LET b$=c$(f+1 TO ):LET f= LEN c$
120 NEXT f
130 IF a$="n" OR a$="s" OR a$="e" OR a$="w" THEN GO TO 300
140 IF a$="get" OR a$="take" THEN GO SUB 420
150 IF a$="i" THEN GO TO 480
160 IF a$="r" THEN GO TO 40
170 IF a$="d" THEN GO TO 860
180 IF a$="put" OR a$="drop" THEN GO SUB 520
190 IF a$="open" THEN GO SUB 590
200 IF a$="unlock" THEN GO SUB 640
210 IF a$="feed" THEN GO SUB 690
220 IF a$="swim" THEN GO SUB 740
230 IF a$="quit" THEN GO SUB 1690
240 IF a$="save" THEN GO SUB 1710
250 IF a$="chop" THEN GO SUB 910
260 IF a$="make" THEN GO SUB 960
270 IF a$="light" THEN GO SUB 760
280 IF a$="insert" THEN GO SUB 810
290 PRINT "I don't understand. Try again.":GO TO 80
300 IF x=3 AND y=6 AND wo THEN PRINT y$;"surrounded by wolves whowill not let you move.":GO TO 80
310 IF x>4 AND x<9 AND y=7 AND st AND a$="e" THEN PRINT "There is a stream in the way!!":GO TO 80
320 IF x=8 AND y=3 AND NOT fed AND a$="w" THEN PRINT "There is a dog in the way!!":GO TO 80
330 IF a$="w" AND l$(x,y-1,1)="\::" THEN PRINT "You can't go that way!":GO TO 80
340 IF a$="n" AND l$(x-1,y,1)="\::" THEN PRINT "You can't go that way!":GO TO 80
350 IF a$="s" AND l$(x+1,y,1)="\::" THEN PRINT "You can't go that way!":GO TO 80
360 IF a$="e" AND l$(x,y+1,1)="\::" THEN PRINT "You can't go that way!":GO TO 80
370 IF a$="s" THEN LET x=x+1
380 IF a$="n" THEN LET x=x-1
390 IF a$="w" THEN LET y=y-1
400 IF a$="e" THEN LET y=y+1
410 GO TO 40
420 IF b$="" THEN PRINT "Get what?":GO TO 80
430 LET g= LEN b$
440 FOR f=1 TO 9:IF x=a(f) AND y=b(f) AND b$=o$(f, TO g) THEN LET ca=ca+1:LET a(f)=0:LET b(f)=0:PRINT "O.K.":GO TO 80
450 NEXT f
460 PRINT "I can't see a ";b$
470 GO TO 80
480 PRINT "You have:":FOR f=1 TO 9:IF a(f)=0 THEN LET found=1:PRINT o$(f)
490 NEXT f
500 IF NOT found THEN PRINT "Nothing!"
510 LET found=0:GO TO 80
520 LET k1=0:IF b$="" THEN PRINT a$;" what?":GO TO 80
530 LET g= LEN b$
540 IF NOT a(3) AND x=3 AND y=6 AND b$="onion " THEN LET wo=0:PRINT "The wolves run away because of the smell of the onion."
550 FOR f=1 TO 9:IF b$=o$(f, TO g) AND NOT a(f) THEN LET a(f)=x:LET b(f)=y:LET i=i-1:PRINT "O.K..":LET k1=1:IF NOT a(3) AND x=3 AND y=6 AND b$="onion " AND wo THEN PRINT "The wolves run away because of the smell of the onion":LET wo=0
560 IF k1 THEN GO TO 80
570 NEXT f
580 PRINT "You don't have a ";b$:GO TO 80
590 IF b$="" THEN PRINT "Open what?":GO TO 80
600 IF b$="door " AND x <>6 OR y <>8 THEN PRINT "What door?":GO TO 80
610 IF b$ <>"door " THEN PRINT "Don't be silly.":GO TO 80
620 IF loc THEN PRINT "It's locked stupid!":GO TO 80
630 PRINT "O.K..There is a stair going down":LET op=1:GO TO 80
640 IF b$="" THEN PRINT "Unlock what?":GO TO 80
650 IF b$="door " AND x <>6 OR y <>8 THEN PRINT "What door?":GO TO 80
660 IF b$ <>"door " THEN PRINT "Don't be silly.":GO TO 80
670 IF a(2) THEN PRINT "What with?":GO TO 80
680 PRINT "O.K..":LET loc=0:GO TO 80
690 IF b$="" THEN PRINT "Feed what?":GO TO 80
700 IF b$ <>"dog " THEN PRINT "that's silly!!":GO TO 80
710 IF x <>8 OR y <>3 THEN PRINT "There's no dog here!":GO TO 80
720 IF a(7) THEN PRINT "I have no dog food.":GO TO 80
730 PRINT "Munch, munch!":LET fed=1:LET a(7)=45:GO TO 80
740 IF (x <>5 OR y <>5) AND (x <>4 OR y <>8) AND (x<5 OR y <>7) THEN PRINT "There's no water here!":GO TO 80
750 PRINT "Brrr...The water is too cold!":GO TO 80
760 IF b$="" THEN PRINT "Light what?":GO TO 80
770 IF b$ <>"candle " THEN PRINT "That's silly!!":GO TO 80
780 IF a(4) THEN PRINT "You don't have a candle!!":GO TO 80
790 IF NOT a(4) AND NOT a(9) THEN PRINT "It casts a flickering light!!":LET lit=1:GO TO 80
800 IF a(9) THEN PRINT "You don't have anything to light it with!":GO TO 80
810 IF b$="" THEN PRINT "Insert what?":GO TO 80
820 IF b$ <>"battery " THEN PRINT "Don't be nuts!!!":GO TO 80
830 IF a(5) THEN PRINT "You don't have a battery.":GO TO 80
840 IF x=4 AND y=8 THEN PRINT "You insert the battery. The beacon flashes on and off. You have succesfully completed the adventure.":STOP
850 PRINT "There is nothing here that takesbatteries.":GO TO 80
860 IF x=6 AND y=8 AND op AND NOT a(4) AND lit THEN LET x=4:LET y=8:GO TO 40
870 IF x=4 AND y=8 AND op AND (a(4) OR (NOT a(4) AND NOT lit)) THEN PRINT "It's too dark!":GO TO 80
880 IF x=6 AND y=8 AND op AND a(3) THEN PRINT "It's too dark!":GO TO 80
890 IF x=4 AND y=8 AND op AND NOT a(4) AND lit THEN LET x=6:LET y=8:GO TO 40
900 PRINT "You can't go down.":GO TO 80
910 IF a(8) THEN PRINT "You haven't got an axe.":GO TO 80
920 IF b$="" THEN PRINT "Chop what?":GO TO 80
930 IF b$ <>"tree " THEN PRINT "That's a bit silly.":GO TO 80
940 IF x<5 OR y <>7 THEN PRINT "There are no trees worth chopping!":GO TO 80
950 PRINT "Whooshhh...."'"The tree falls!":LET tr=1:GO TO 80
960 IF b$ <>"raft " THEN PRINT "Don't be silly.":GO TO 80
970 IF b$="" THEN PRINT "Make what?":GO TO 80
980 IF NOT tr THEN PRINT "You haven't got any wood.":GO TO 80
990 IF x<5 OR y <>7 THEN PRINT "What do you want a raft for?":GO TO 80
1000 PRINT "O.K. You have a raft.":LET st=0:GO TO 80
1010 IF b$="" THEN PRINT "Use what?":GO TO 80
1020 IF b$ <>"wand " OR b$ <>"phone " THEN PRINT "That's stupid!":GO TO 80
1030 DIM l$(9,9,110)
1040 FOR f=1 TO 9:LET l$(1,f)="\::":NEXT f
1050 FOR f=1 TO 8:LET l$(f,1)="\::":LET l$(f,9)="\::":LET l$(9,f)="\::":NEXT f
1060 FOR f=2 TO 8:FOR g=2 TO 8:READ l$(f,g):NEXT g:NEXT f
1070 DATA "There is a road going south."
1080 DATA "\::"
1090 DATA y$+"on a road running from north to south."
1100 DATA "\::","\::"
1110 DATA y$+"in a field. There are gates to the east and to the south."
1120 DATA y$+"on a road running from east to west."
1130 DATA y$+"on a road running from north to south."
1140 DATA "\::"
1150 DATA y$+"on a road running from north to south."
1160 DATA "\::"
1170 DATA y$+"in the west end of a meadow."
1180 DATA y$+"in the east end of a meadow."
1190 DATA "\::"
1200 DATA y$+"in a big field. There is a swamp to the east."
1210 DATA "Arrgh!!!!....You have just fallen into a swamp."
1220 DATA y$+"in some hills. Threre is a swamp to the west."
1230 DATA "\::"
1240 DATA y$+"on a huge plateau","\::"
1250 DATA y$+"on an island. In front of you is a beacon which lacks a power source. There is a hole in the ground."
1260 DATA y$+"in a shrubbery"
1270 DATA "\::"
1280 DATA y$+"in a rockery. There is a lake to the west."
1290 DATA y$+"at the edge of a lake. In the middle there is a stone with a sword in it."
1300 DATA y$+"on a huge plateau."
1310 DATA y$+"at the edge of a river. There are trees all around you.","\::"
1320 DATA y$+"in a meadow. There is a road to the west."
1330 DATA y$+"on a road running from west to east."
1340 DATA y$+"in a valley. To the eastis a road."
1350 DATA y$+"in a valley."
1360 DATA y$+"on an immense plain."
1370 DATA y$+"at the edge of a river. There are trees all around you."
1380 DATA y$+"in a forest. In front ofyou is a door in the ground."
1390 DATA "\::"
1400 DATA y$+"are in a woods."
1410 DATA "\::"
1420 DATA y$+"in a cave."
1430 DATA y$+"in a meadow."
1440 DATA y$+"at the edge of a river. There are trees all around you."
1450 DATA y$+"in a forest. There is a path running north/south."
1460 DATA y$+"in a clearing. In front of you is a woodcutter's hut."
1470 DATA y$+"in a woods."
1480 DATA y$+"in a meadow.","\::"
1490 DATA y$+"in a field."
1500 DATA y$+"at the edge of a river. There are trees all around you."
1510 DATA y$+"in a forest. There is a path running north/south."
1520 RETURN
1530 BORDER 1:PAPER 1:CLS
1540 LET x=2:LET y=8
1550 DIM o$(9,15):DIM a(9):DIM b(9)
1560 FOR f=1 TO 9:READ o$(f),a(f),b(f):NEXT f
1570 DATA "phone",6,6,"golden key",2,2,"onion",2,7
1580 DATA "candle",3,6,"battery",4,2,"wand",6,4
1590 DATA "bone",7,5,"axe",8,2,"matches",7,3
1600 LET fed=0:LET raft=0
1610 LET loc=1:LET wiz=1
1620 LET lit=0
1630 RETURN
1640 PRINT "Exits:":IF l$(x-1,y,1) <>"\::" THEN PRINT "North"
1650 IF l$(x,y+1,1) <>"\::" THEN PRINT "East"
1660 IF l$(x+1,y,1) <>"\::" THEN PRINT "South"
1670 IF l$(x,y-1,1) <>"\::" THEN PRINT "West"
1680 RETURN
1690 INPUT "Want to quit? ";s$:IF s$ <>"y" THEN GO TO 80
1700 INPUT "Want to save the game first? ";s$:IF s$ <>"y" THEN STOP
1710 CLS :PRINT "Have a blank tape ready."
1720 SAVE "adventure" LINE 40
1730 PRINT "O.K....":PAUSE 200:GO TO 40
1740 RETURN
1750 SAVE "adventure" LINE 10:CLS :REM PRINT AT 10,10;"Verify....":VERIFY ""
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.