Zombies in the Swamp is a grid-based maze game in which the player guides a raft from the bottom-right corner to the exit at the top-left while being pursued by a zombie monster. The play field is a 9×9 array `a()` where values of -1 represent impassable swamp, 0 represents open water, and 1 marks cells where the player has already been. Movement is controlled with keys 5–8 (the arrow keys), and the game checks for valid moves using computed GO TO targets based on the cell value (`GO TO 1300+100*a(px+dx,py+dy)`). The zombie’s pathfinding logic uses a direction-preference system with subroutines at lines 2100–2130 that set dx/dy deltas, trying to continue straight, turn, or pick a random direction when swamp blocks the path. Characters are rendered as 2×3-cell block graphic sprites stored in string variables `p$` (player), `m$` (monster), and `d$` (drowned monster), each printed in two halves via a shared display subroutine at line 1000.
Program Structure
The program is organized into clearly labeled subroutine blocks, each preceded by a REM comment. The main loop begins at line 3000 and calls three major subroutines in sequence:
- Init (line 1100) — Sets up the grid, draws the swamp, and places the player.
- Move (line 1200) — Handles player input and movement.
- Monster (line 1600) — Executes the zombie’s AI move.
The monster is only summoned when the probabilistic condition at line 3040 is met ((px+py)*RND>4 OR m<5), suppressing it for the first 5 player moves and then triggering it stochastically thereafter, increasing tension as the player approaches the exit.
Grid Representation
The 9×9 array a() uses three sentinel values to encode cell state:
| Value | Meaning |
|---|---|
| -1 | Impassable swamp (borders and visited trail) |
| 0 | Open water (traversable) |
| 1 | Occupied by player or already visited |
The border cells (row/column 1 and 9) are all initialized to -1 in the loop at lines 20–50. The player’s starting cell a(8,8) and the two exit-adjacent cells a(2,1) and a(1,2) are seeded to 1 at lines 60 and 1110, carving a valid corridor.
Computed GO TO for Move Dispatch
A key idiom appears at line 1260:
GO TO 1300+100*a(px+dx,py+dy)
This uses the cell value (-1, 0, or 1) as an arithmetic offset to dispatch to one of three handlers: line 1200 (re-prompt, cell value -1 → 1300-100), line 1300 (trail/throw, value 1 → 1400), or an implicit fall-through. In practice, movement onto swamp (-1) goes back to 1200 to re-read input, while movement onto a previously visited cell (1) goes to 1300 to handle the “throw” mechanic. This compact dispatch avoids multiple IF statements.
Sprite Rendering
Each sprite occupies a 2-row × 3-column block graphic cell on screen. Three sprites are defined as 6-character strings using block graphic escape sequences:
p$(line 80) — the player’s raftm$(line 90) — the zombie monsterd$(line 100) — a drowned monster (solid blocks)
The shared print subroutine at line 1000 splits the string at character 3 and prints the first half at row 2*y, column 3*x, and the second half one row below, using PAPER 5 (cyan background) for contrast. The blank sprite e$ (six spaces) erases a cell before redrawing it in a new position.
Zombie Pathfinding AI
The zombie’s movement logic (lines 1600–2230) implements a simple directional preference algorithm using four direction-setting subroutines at lines 2100–2130 (up, left, down, right). On each turn:
- If the path ahead is clear (cell ≥ 1), continue in the same direction.
- If a perpendicular turn is available, randomly try a new direction.
- If blocked by swamp, pick a random direction and retry until valid.
A zombie that steps onto a cell with value 0 (open water) is considered drowned: its cell is set to -1 and it is drawn with the d$ sprite, then control returns without further movement. Crucially, only one zombie (mx, my) is tracked per game; if it drowns, no new zombie spawns, effectively ending the threat. The initial zombie position is hardcoded to (7,7) each time the monster subroutine is called.
Notable Anomalies and Observations
- Line 6 assigns
INKEY$toz$but this value is never used; it exists purely as a dummy read before the actual wait loop at line 7. - Line 3990 (
GO TO 4000) and line 4000 (STOP) are dead code, never reachable from the main loop flow. - Line 5555 (
RUN) is also unreachable dead code, likely a safety remnant. - The “throw” mechanic at line 1300 (when the player tries to move to a previously visited cell) erases the destination cell’s sprite without advancing the player — effectively a no-op move that consumes a turn.
- The zombie’s initial position (7,7) is always reset at line 1610 on each monster call, so if a zombie drowns, the next monster activation spawns a fresh one at the same starting location.
- Lines 3 and 4 contain intentional line-wrap artifacts in the text strings (“infestedswamp” and “persuit” — also a misspelling of “pursuit”) that are baked into the PRINT statements.
Content
Source Code
1 REM ZOMBIES IN THE SWAMP
2 PRINT AT 4,0;" ZOMBIES IN THE SWAMP"; TAB 0;" "
3 PRINT " You are trying to guide your raft through the zombie infestedswamp."
4 PRINT " Using the arrows above keys 5thru 8, you will avoid zombies who are in desperate persuit."
5 PRINT " Beware, if they catch you, they will eat you!!! Press any key to begin your journey."
6 LET z$= INKEY$
7 IF INKEY$="" THEN GO TO 7
8 CLS
9 PRINT " ZOMBIES IN THE SWAMP"; AT 3,4;"EXIT"; AT 18,24;"ENTER"
10 DIM a(9,9)
20 FOR c=1 TO 9
30 LET a(1,c)=-1:LET a(c,1)=-1
40 LET a(9,c)=-1:LET a(c,9)=-1
50 NEXT c
60 LET a(2,1)=1:LET a(1,2)=1
70 LET e$=" "
80 LET p$="\ .\..\. \ '\''\' "
90 LET m$="\'.\..\.'\.'\''\'."
100 LET d$="\:'\''\':\:.\..\.:"
110 LET b$="\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::\::"
120 GO TO 3000
1000 REM Print t$ at x,y
1010 PRINT AT (2*y),(3*x); PAPER 5;t$( TO 3)
1020 PRINT AT 2*y+1,3*x; PAPER 5;t$(4 TO )
1030 RETURN
1100 REM Init
1110 LET m=0:LET px=8:LET py=8:LET a(8,8)=1
1120 FOR k=4 TO 17:PRINT AT k,6;b$:NEXT k
1130 LET x=px:LET y=py:LET t$=p$:GO SUB 1000
1140 RETURN
1200 REM Move
1210 REM Input Instruction
1220 LET t$= INKEY$
1230 LET dx=(t$="8")-(t$="5")
1240 LET dy=(t$="6")-(t$="7")
1250 IF (dx+dy)=0 THEN GO TO 1220
1260 GO TO 1300+100*a(px+dx,py+dy)
1300 REM Throw
1310 LET x=px+dx:LET y=py+dy:LET a(x,y)=1
1320 LET t$=e$
1330 GO SUB 1000
1340 RETURN
1400 REM Move
1410 LET x=px:LET y=py:LET t$=e$:GO SUB 1000
1420 LET px=px+dx:LET py=py+dy
1430 IF (px=1) OR (py=1) THEN GO TO 1500
1440 LET x=px:LET y=py:LET t$=p$:GO SUB 1000
1450 RETURN
1500 REM Succeeded
1510 PRINT AT 20,0;" YOU MADE IT, NO DOUBT YOU ARE A TRUE SWAMPHUNTER!!!"
1512 PAUSE 90:CLS
1515 PRINT AT 10,0;"Press Any Key For Another Trip"
1520 LET s$= INKEY$
1530 IF s$="" THEN GO TO 1520
1540 RUN
1600 REM Monster Moves
1610 LET mx=7:LET my=7
1620 LET x=mx:LET y=my:LET t$=m$:GO SUB 1000
1630 GO SUB 2100+10* INT (RND*2)
1640 LET lx=dx:LET ly=dy
1700 REM Choose New Direction
1710 IF a(mx+lx,my+ly)<1 THEN GO TO 1900
1720 IF a(mx+ly,my-lx)=1 OR a(mx-ly,my+lx)=1 THEN GO TO 2000
1800 REM Same Direction
1810 LET dx=lx:LET dy=ly:GO TO 2200
1900 REM Swamp Ahead
1910 GO SUB 2100+10* INT (RND*4)
1920 IF a(mx+dx,my+dy)=-1 THEN GO TO 1910
1930 GO TO 2200
2000 REM Possible Turn
2010 GO SUB 2100+10* INT (RND*4)
2020 IF (dx=-lx AND dy=-ly) OR (a(mx+dx,my+dy)<1) THEN GO TO 1800
2030 GO TO 2200
2100 LET dx=0:LET dy=-1:RETURN
2110 LET dx=-1:LET dy=0:RETURN
2120 LET dx=0:LET dy=1:RETURN
2130 LET dx=1:LET dy=0:RETURN
2200 REM Execute Move
2210 LET x=mx:LET y=my:LET t$=e$:GO SUB 1000
2220 LET mx=mx+dx:LET my=my+dy
2230 LET lx=dx:LET ly=dy
2240 IF a(mx,my)=0 THEN GO TO 2300
2250 LET x=mx:LET y=my:LET t$=m$:GO SUB 1000
2260 IF mx=px AND my=py THEN GO TO 2400
2270 GO TO 1700
2300 REM Monster Drowned
2310 LET a(mx,my)=-1
2320 LET x=mx:LET y=my:LET t$=d$:GO SUB 1000
2330 RETURN
2400 REM Player Caught
2410 PRINT AT 20,0;"YOU'RE DEAD MEAT!!!!!!!!!!!"
2420 LET s$= INKEY$
2430 IF s$="" THEN GO TO 2420
2440 RUN
3000 REM Main Program
3010 GO SUB 1100:REM Init
3020 GO SUB 1200:REM Move
3030 LET m=m+1
3040 IF (px+py)* RND>4 OR m<5 THEN GO TO 3020
3050 GO SUB 1600:REM Monster
3060 GO TO 3020
3990 GO TO 4000
3995 SAVE "SWAMP" LINE 0
4000 STOP
5555 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

