Zombies

Developer(s): Hal Renko, Sam Edwards
Date: 1984
Type: Program
Platform(s): TS 2068
Tags: Arcade

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:

  1. Init (line 1100) — Sets up the grid, draws the swamp, and places the player.
  2. Move (line 1200) — Handles player input and movement.
  3. 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:

ValueMeaning
-1Impassable swamp (borders and visited trail)
0Open water (traversable)
1Occupied 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 raft
  • m$ (line 90) — the zombie monster
  • d$ (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:

  1. If the path ahead is clear (cell ≥ 1), continue in the same direction.
  2. If a perpendicular turn is available, randomly try a new direction.
  3. 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$ to z$ 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

Appears On

Related Products

Related Articles

Related Content

Image Gallery

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.

Scroll to Top