--- title: "Zombies" id: 51831 type: "computer_media" slug: "zombies" url: "http://localhost/computer_media/zombies/" markdown_url: "http://localhost/computer_media/zombies.md" published_at: "2023-08-13T23:14:34+00:00" modified_at: "2026-04-04T20:17:56+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Guide your survivor across a zombie-infested island grid, luring blind monsters into potholes using eight-directional movement before they track you down by heartbeat." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Artic Computing" slug: "artic-computing" taxonomy: "post_tag" url: "http://localhost/tag/artic-computing/" - 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_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Zombies (1981)(Artic Computing)(UK)(TS1000)(Cassette).zip" mediadate: "1981" producer_company: - id: 10657 title: "Artic Computing" type: "company" url: "http://localhost/company/artic-computing/" related_products: - id: 14159 title: "Zombies/Sword of Peace" type: "product" url: "http://localhost/product/sword-of-peace-and-zombies/" media_type_tags: "Game" --- # Zombies Zombies is a real-time maze-avoidance game in which the player navigates an island grid using the numeric keys 1–8 (representing eight compass directions) while trying to lure blind, sound-detecting zombies into potholes. The playing field is a 10×32 grid of border characters, randomly populated with “Z” zombie characters and at least one “O” pothole during setup, and the display file base address is obtained via PEEKs of system variables 16396–16397 for direct screen manipulation. Zombie movement uses a simple Manhattan-distance heuristic: each zombie shifts one cell horizontally and/or vertically toward the player’s current position each turn. The player’s position and all zombie positions are tracked as linear offsets into the display file, with each screen row being 33 bytes wide (32 characters plus a newline). PAUSE 55555 followed by POKE 16437,255 and INKEY$ forms the standard interrupt-driven keypress detection idiom for this platform. *** ## Program Analysis ### Program Structure The program is organized into a main initialization block, a game loop, and a subroutine for the title/instructions screen: 1. **Lines 0–9:** Declarations, variable initialization, and array allocation (`DIM Z(40)` for up to 40 zombie positions). 2. **Lines 10–181:** Screen construction — draws the border wall of `O` characters, randomly scatters zombies (`Z`) and potholes (`O`), and prints the movement key legend. 3. **Lines 188–246:** Player turn — places the player character (`61` = `=`) at a random empty cell, waits for a valid key (1–8), computes the target cell, and moves or triggers a collision. 4. **Lines 300–435:** Zombie AI turn — iterates over all live zombies, moves each one step toward the player using a coordinate-difference heuristic. 5. **Lines 500–610:** Collision resolution — distinguishes player capture, zombie–zombie collision, and zombie-into-pothole events. 6. **Lines 700–750:** End-of-game screen, replay prompt, and `CLEAR`/restart loop. 7. **Lines 1000–1150:** Title screen and instructions subroutine, called once at startup via `GOSUB 1000`. ### Display File Manipulation Rather than using `PRINT AT` for every game element, the program obtains the display file base address at line 189: ``` LET DF=PEEK 16396+256*PEEK 16397 ``` System variables at addresses 16396–16397 hold the low and high bytes of the display file pointer. All subsequent player and zombie movement is done with `PEEK` and `POKE` directly into this address space, which is considerably faster than interpreted `PRINT AT` calls and essential for a real-time game. Each screen row is treated as 33 bytes wide (32 character cells plus a newline byte), so a zombie’s or player’s screen position is stored as a single linear offset. Row and column are recovered by integer division and modulo with 33 (lines 300–340). ### Character Encoding Used as Game State The program exploits the numeric values of display-file character codes to distinguish game objects without a separate state array: | PEEK value | Character | Game object | | --- | --- | --- | | 0 | (space) | Empty cell | | 52 | `O` (rendered) | Pothole / border wall | | 61 | `=` | Player | | 63 | `Z` | Zombie | Note that the border walls and potholes share the same character code (52 for `O`), so the collision handler at line 250 checks specifically for code 63 (zombie) to distinguish zombie-mouth from pothole collisions; anything else is assumed to be a wall or pothole. ### Zombie AI Heuristic Lines 350–390 implement a step-by-step pursuit algorithm. For each zombie, the row offset `B` is set to +33, −33, or 0 depending on whether the zombie is above, below, or level with the player. Then the column delta (+1, −1, or 0) is added. This produces a diagonal step toward the player in one move, making zombies aggressive and fast. The algorithm is deterministic — every zombie always moves toward the player with no randomness or pathfinding around obstacles. ### Eight-Directional Movement Encoding Line 241 computes the target offset `B` from the current offset `Q` using a compact Boolean arithmetic expression: ``` LET B=Q+(A=1 OR A=2 OR A=3)-(A=7 OR A=6 OR A=5)+33*(A=5 OR A=4 OR A=3)-33*(A=7 OR A=8 OR A=1) ``` On this platform, Boolean expressions evaluate to 1 (true) or 0 (false), so this single line simultaneously computes the column delta (±1) and row delta (±33) for all eight directions from the numpad layout printed on screen. This avoids a lookup table or multi-line conditional block. ### Keypress Detection Idiom Lines 220–231 and 710–720 use the standard pattern: `PAUSE 55555` (a very long pause, effectively waiting for a keypress interrupt), followed by `POKE 16437,255` to re-enable the keyboard, then `INKEY$` to read the key. The `PAUSE 55555` returns early when any key is pressed, making the sequence an efficient blocking key-read without a busy loop. ### Zombie Position Array The array `Z(40)` stores each zombie’s current display-file offset. Dead zombies (eliminated by falling into a pothole) are flagged with `Z(A)=-1` at line 510, and line 325 skips negative entries during the movement loop. The counter `N` tracks surviving zombies; when `N=0`, the player wins (lines 545–560). ### Random Grid Population Lines 80–110 use `Q=INT(RND*2000)` to randomly decide the content of each interior cell. Values in the range 1795–1849 place a zombie; values ≥1850 place a pothole (`O`). This gives approximately a 2.75% chance of a zombie and a 7.5% chance of a pothole per cell, with the remaining ~89.75% left empty. The zombie’s display-file offset is stored as `A*33+B+1`, consistent with the 33-bytes-per-row convention. ### Notable Anomalies - Line 11 defines `A$` as the splash string “SPLASH GOES A ZOMBIE” (using inverse-video block characters for spaces), but this variable is immediately overwritten at line 1140 by the INKEY$ result from the title screen. The intended `A$` splash message is only restored to the correct string if the game is restarted via `GOTO 3`, which does not re-run the `GOSUB 1000` subroutine — so after the first playthrough, `A$` at line 535 correctly prints the splash message set at line 11 on restart. - Line 610 POKEs the zombie’s destination cell with code 63 (zombie) after the player has been eaten, which is cosmetically redundant since the game ends immediately after. - The movement key “9” (center / no-move) is absent; the guard at line 231 rejects keys outside “1”–”8″, so the player must always move. - Border walls share character code 52 with potholes, making it impossible to distinguish walking into a wall from falling into a pothole by PEEK alone — both trigger the “OOPS INTO A POTHOLE” message at line 266, which is technically incorrect for wall collisions. ## Source Code ``` 0 REM (C)1981 ARTIC COMPUTING 1 GOSUB 1000 3 CLS 4 LET P2=0 5 LET Z2=0 6 LET Z1=0 8 DIM Z(40) 9 LET Z=0 10 FAST 11 LET A$="[S][P][L][A][S][H]█[G][O][E][S]█[A]█[Z][O][M][B][I][E]" 16 LET P1=0 18 FOR A=1 TO 32 20 PRINT "O"; 30 NEXT A 40 PRINT 50 FOR A=1 TO 10 60 PRINT "O"; 70 FOR B=1 TO 30 80 LET Q=INT (RND*2000) 90 IF Q<1795 THEN GOTO 120 100 IF Q>=1850 THEN GOTO 110 102 PRINT AT A,B;"Z" 103 LET Z=Z+1 104 LET Z(Z)=A*33+B+1 110 IF Q>=1850 THEN PRINT AT A,B;"O" 120 NEXT B 130 PRINT AT A,31;"O" 140 NEXT A 150 FOR A=1 TO 32 160 PRINT "O"; 170 NEXT A 171 PRINT 172 PRINT 173 PRINT 178 PRINT "MOVEMENT" 179 PRINT "7 8 1" 180 PRINT "6 X 2" 181 PRINT "5 4 3" 182 SLOW 188 LET N=Z 189 LET DF=PEEK 16396+256*PEEK 16397 190 LET Q=INT (RND*320+1) 200 IF PEEK (DF+Q)<>0 THEN GOTO 190 210 POKE DF+Q,61 220 PAUSE 55555 221 POKE 16437,255 230 LET B$=INKEY$ 231 IF B$<"1" OR B$>"8" THEN GOTO 220 240 LET A=VAL B$ 241 LET B=Q+(A=1 OR A=2 OR A=3)-(A=7 OR A=6 OR A=5)+33*(A=5 OR A=4 OR A=3)-33*(A=7 OR A=8 OR A=1) 242 IF PEEK (DF+B)<>0 THEN GOTO 250 243 POKE DF+Q,0 244 POKE DF+B,61 246 LET Q=B 247 GOTO 300 250 IF PEEK (DF+B)=63 THEN GOTO 280 260 POKE DF+B,52 265 POKE DF+Q,0 266 PRINT AT 18,5;"OOPS INTO A POTHOLE" 270 GOTO 700 280 PRINT AT 18,1;"STRAIGHT INTO A ZOMBIES MOUTH" 285 POKE DF+Q,0 290 GOTO 700 300 LET P1=INT (Q/33) 310 LET P2=Q-P1*33 312 PRINT AT 12,0;" " 320 FOR A=1 TO Z 325 IF Z(A)<0 THEN GOTO 435 330 LET Z1=INT (Z(A)/33) 340 LET Z2=Z(A)-Z1*33 350 IF Z1P1 THEN LET B=-33 370 IF Z1=P1 THEN LET B=0 380 IF Z2P2 THEN LET B=B-1 400 POKE DF+Z(A),0 410 IF PEEK (DF+Z(A)+B)<>0 THEN GOTO 500 420 POKE DF+Z(A)+B,63 430 LET Z(A)=Z(A)+B 435 NEXT A 440 GOTO 220 500 IF PEEK (DF+Z(A)+B)=61 THEN GOTO 600 510 LET Z(A)=-1 520 LET N=N-1 530 IF PEEK (DF+Z(A)+B)=63 THEN GOTO 435 535 PRINT AT 12,0;A$ 545 IF N=0 THEN GOTO 560 550 GOTO 435 560 PRINT AT 18,5;"WELL DONE" 562 PRINT "ZOMBIES ARE KILLED" 570 GOTO 700 600 PRINT AT 18,1;"YUM YUM YOU HAVE BEEN EATEN" 610 POKE DF+Z(A)+B,63 700 PRINT 701 PRINT "PRESS N/L TO PLAY AGAIN" 710 PAUSE 55555 711 POKE 16437,255 720 LET B$=INKEY$ 721 IF CODE B$<>118 THEN STOP 730 CLEAR 750 GOTO 3 1000 PRINT AT 0,9;"█[Z][O][M][B][I][E][S]█" 1010 PRINT 1015 PRINT 1020 PRINT "YOU HAVE CRASHED ON A ISLAND" 1025 PRINT 1030 PRINT "THE ISLAND IS INHABITED BY" 1035 PRINT 1045 PRINT "MAN EATING ZOMBIES." 1050 PRINT 1055 PRINT 1060 PRINT "THE ZOMBIES ARE BLIND BUT THEY" 1065 PRINT 1070 PRINT "DETECT YOU BY THE SOUND OF YOUR" 1075 PRINT 1080 PRINT "HEART BEAT. YOUR ONLY HOPE IS" 1085 PRINT 1090 PRINT "LURE THEM INTO THE POTHOLES." 1100 PRINT 1105 PRINT 1110 PRINT "PRESS ANY KEY WHEN READY" 1120 PAUSE 55555 1130 POKE 16437,255 1140 LET A$=INKEY$ 1150 RETURN ```