--- title: "Monster" id: 70809 type: "computer_media" slug: "monster" url: "http://localhost/computer_media/monster/" markdown_url: "http://localhost/computer_media/monster.md" published_at: "2026-08-23T15:08:02+00:00" modified_at: "2026-08-23T22:46:26+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/monster-1.png" alt: "Monster screen" excerpt: "Guide your character across procedurally built platforms, collect jewels, eliminate monsters, and race a timer that accelerates with each kill in this action game." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Monster%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "Monster (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/monster-1.png" alt: "Monster screen" - url: "http://localhost/wp-content/uploads/2026/08/monster-2.png" alt: "Monster screen" media_type_tags: "Game" --- # Monster Monster is a platform-style maze game in which the player navigates a character around a multi-level screen, collecting jewels, eliminating monsters, and reaching a door before a countdown timer expires. The screen layout is built procedurally each level using UDGs (user-defined graphics) loaded via a DATA/POKE USR loop that defines eight custom characters (codes 144–151). Movement is handled with keys 5, 6, 7, and 8, and the ATTR function is used extensively to detect collisions with colored screen objects, distinguishing platforms, monsters, jewels, and the exit door by their ink and paper attribute bytes. Killing a monster triggers an “invisible gas” mechanic that doubles the rate of timer decay, tracked with a flag variable. A high-score variable persists across games within the same session. *** ### Program Structure The program is organized into clearly delineated functional blocks: 1. **Lines 1–6:** Initialization, high-score reset, and instructions prompt. 2. **Line 7:** Level selection and validation. 3. **Lines 8–120:** Level setup — drawing platforms, monster positions, jewels, and the exit door, plus an intro beep sweep. 4. **Lines 195–300:** Main game loop — player movement, collision detection, scoring, and timer management. 5. **Lines 1000–1010:** Death-by-falling routine. 6. **Lines 2000–2090:** UDG definition subroutine via DATA and POKE USR. 7. **Lines 5000–5040:** End-of-game screen with high-score comparison and replay prompt. 8. **Lines 6000–6030:** Instructions display (note: called as `GO SUB 5500` in line 5, but defined at line 6000 — see Bugs section). ### UDG Definitions Eight UDGs are defined at startup by the subroutine at line 2000, using a nested `FOR` loop that reads eight bytes per character from DATA lines 2010–2080 and POKEs them into memory with `POKE USR CHR$ z+x, a` for `z` running from 144 to 151. The characters and their roles are: | UDG | Code | Role | | --- | --- | --- | | [UDG-A] | 144 | Player character | | [UDG-B] | 145 | Player death sprite | | [UDG-C] | 146 | Jewel / collectible | | [UDG-D] | 147 | Monster (placed on platforms) | | [UDG-E] | 148 | Platform block | | [UDG-F] | 149 | Killable monster (row 1) | | [UDG-G] | 150 | Door left half | | [UDG-H] | 151 | Door right half | ### Level Generation Platforms are drawn in a loop (lines 10–30) that prints INK 5 platform blocks across each row, stepping up three rows at a time from row 21 down to row 3. Monster sprites are scattered at random column positions using `RND *29+1` (line 45), printed in INK 6 pairs two cells tall. Jewels (line 100) are placed at six positions spaced three rows apart, printed BRIGHT 1 INK 7. The exit door (line 110) is fixed at row 20, column 29 in INK 2. ### ATTR-Based Collision Detection The game makes heavy use of `ATTR` to identify objects by their color attributes rather than tracking sprite positions in variables. Key checks in the main loop include: - `ATTR (a-1,b)=6` — detects a monster above the player (INK 6 = yellow), used for jumping onto platforms with monsters (line 275) and for the downward move (line 281). - `ATTR (a-1,b)=4` — detects a killable monster at row 1 in INK 4 (green), awards 100 points (line 280). - `ATTR (a,b)=71` — detects a jewel (attribute byte 71 = BRIGHT 1 + INK 7 + PAPER 0), awards 50 points (line 285). - `ATTR (a,b)=2` — detects the exit door in INK 2 (red), triggering level advance (line 291). - `SCREEN$ (a-1,b)=" "` — checks for empty space above before a simple upward step (line 270). ### Movement and Physics The player position is stored in row `a` and column `b`. Movement keys are 5 (left), 8 (right), 7 (up), and 6 (down). Upward movement on a plain space (line 270) is a short one-cell hop that immediately returns the player to their original row — effectively a cosmetic jump with no sustained elevation. The jump onto a monster platform (line 275) moves the player up three rows at once, matching the three-row platform spacing. The downward move through a monster (line 281) similarly shifts three rows and is gated by `k >= 16`, meaning the player must have collected at least 16 kills. Boundary detection (line 290) triggers the fall subroutine when `b=0` or `b=31`. ### Timer and Gas Mechanic The timer `t` starts at 1000 and is decremented by `l` (the current level) each iteration of the main loop (line 282). When a monster is killed, flag `n` is set to 1 (line 280), and line 287 subtracts an additional `2*l` per loop while `n=1`, effectively tripling the timer drain. The flag is cleared when the player descends through a monster (line 281, `LET n=0`). Timer display is updated each loop at line 288, and exhaustion at line 289 routes to the end-game subroutine. ### Falling Death Routine Lines 1000–1010 implement a falling animation: the player sprite is printed one row lower on each iteration with an accompanying descending BEEP, and the previous position is erased. When row 21 is reached, the death sprite (UDG-B) is displayed with FLASH 1 in INK 2, a long low beep plays, and the routine falls through to the end-game screen at line 5000. ### Notable Techniques - The OVER 1 mode in lines 250 and 260 XORs the player sprite onto the screen when erasing the previous position, a common sprite-movement technique to avoid explicit background redrawing. - The intro music (line 120) is a simple `FOR` sweep from -10 to 20 semitones, producing a rising glide. - The high-score `hs` is initialized once at line 1 and persists for the session, compared at line 5000. - Platform row spacing of 3 is hardcoded throughout and must be consistent between generation (lines 10–30) and movement (lines 275, 281) for gameplay to work correctly. ### Bugs and Anomalies - **Missing subroutine target:** Line 5 calls `GO SUB 5500`, but the instructions routine begins at line 6000. There is no line 5500, so requesting instructions would cause a BASIC error. The instructions are never reachable in normal play. - **Level validation error:** Line 7 checks `IF l<1 OR 1>9` — the second operand should be `l>9` not `1>9`. Since `1>9` is always false, any value of `l` that is not less than 1 (i.e., any positive number) bypasses the FOOL message, allowing levels above 9. - **Variable reuse of `b`:** The variable `b` is used both as a platform-drawing row counter (lines 8–95) and as the player’s column position (lines 195 onward). This is resolved by the explicit reset at line 195 (`LET b=1`), but the dual use is a potential source of confusion. - **Line 270 jump behavior:** The upward hop immediately restores `a` to its original value with `LET a=a+1`, so the jump has no lasting effect on position — it is purely cosmetic. - **Line 95 loop variable conflict:** The loop at line 95 uses `b` as both its `FOR` variable and increments it manually with `LET b=b+1` inside the loop body, which interferes with the `NEXT b` counter and will cause non-standard stepping behavior. ## Source Code ``` 1 LET hs=0 2 INK 3:BORDER 0:PAPER 0:CLS :GO SUB 2000 3 CLS :PRINT AT 10,0; INK 7;"Do you need instructions ? (y/n)" 4 IF INKEY$ ="n" THEN GO TO 7 5 IF INKEY$ ="y" THEN GO SUB 5500 6 GO TO 4 7 CLS :PRINT INK 7;"START LEVEL ? (1-9)":INPUT l:LET sc=0:LET k=0:IF l<1 OR 1>9 THEN CLS :PRINT AT 10,13; FLASH 1; INK 7;"FOOL":PAUSE 100:GO TO 3 8 LET b=21:LET t=1000 9 CLS :PRINT AT 0,0; INK 7;"SCORE=";sc; AT 0,13;"TIME=";t; AT 0,25;"LEVEL=";l 10 FOR a=1 TO 30 11 PRINT AT b,a; INK 5;"[UDG-E]" 20 NEXT a 30 IF b>3 THEN LET b=b-3:GO TO 10 40 FOR m=1 TO 2 45 LET r= RND *29+1 50 FOR s=1 TO 2:PRINT AT b,r; INK 6;"[UDG-D]":LET b=b+1:NEXT s 70 IF b<19 THEN LET b=b+1: GO TO 45 80 LET b=3:NEXT m 90 LET z=5 95 FOR b=1 TO 14:PRINT AT 1,b; INK 4;"[UDG-F]":LET b=b+1:NEXT b:PRINT AT 1,15; INK 4;"[UDG-F][UDG-F]":FOR b=18 TO 30:PRINT AT 1,b; INK 4;"[UDG-F]":LET b=b+1:NEXT b 100 FOR n=0 TO 5:PRINT AT z, RND *29+1; INK 7; BRIGHT 1;"[UDG-C]":LET z=z+3:NEXT n 110 PRINT AT 20,29; INK 2;"[UDG-G][UDG-H]" 120 FOR m=-10 TO 20:BEEP .05,m:NEXT m 195 LET a=20:LET b=1 200 PRINT AT a,b;"[UDG-A]" 201 BEEP .002,0:BEEP .002,10 205 PRINT AT 0,6; INK 7;sc 250 IF INKEY$ ="5" AND b>0 THEN LET b=b-1:PRINT AT a,b+1; OVER 1;"[UDG-A]" 260 IF INKEY$ ="8" AND b<31 THEN LET b=b+1:PRINT AT a,b-1; OVER 1; "[UDG-A]" 270 IF SCREEN$ (a-1,b)=" " AND INKEY$ ="7" THEN PRINT AT a,b;;" ":LET a=a-1:PRINT AT a,b;"[UDG-A]":BEEP .1,2:LET a=a+1:PRINT AT a-1,b;" " 275 IF ATTR (a-1,b)=6 AND INKEY$ ="7" AND a>3 THEN PRINT AT a,b;" ":LET a=a-3:BEEP .01,10:BEEP .01,5 280 IF ATTR (a-1,b) =4 AND INKEY$ ="7" AND a<3 THEN PRINT AT a,b;" ":PRINT AT a-1,b;"[UDG-A]":BEEP .1,-20:PRINT AT a-1,b;" ":LET sc=sc+100:LET n=1:LET k=k+1 281 IF ATTR (a+1,b) =6 AND INKEY$ ="6" AND k >= 16 THEN LET a=a+3:PRINT AT a-3,b;" ":BEEP .01,10:BEEP .01,0:LET n=0 282 LET t=t-l 285 IF ATTR (a,b)=71 THEN BEEP .1,40:LET sc=sc+50 287 IF n=1 THEN LET t=t-(2*l) 288 PRINT AT 0,18;" "; AT 0,18; INK 7;t 289 IF t<0 THEN LET t=0:PRINT AT 0,18;" "; AT 0,18; INK 7;"0":IF t=0 THEN GO SUB 5000 290 IF b=0 OR b=31 THEN GO SUB 1000 291 IF ATTR (a,b)=2 THEN LET l=l+1:GO TO 8 300 GO TO 200 1000 LET a=a+1:PRINT AT a,b;"[UDG-A]":BEEP .1,-a:PRINT AT a,b;" ":IF a <> 21 THEN GO TO 1000 1010 PRINT AT a,b; FLASH 1; INK 2;"[UDG-B]":BEEP 2,-40:GO TO 5000 2000 FOR z=144 TO 151:FOR x=0 TO 7:READ a:POKE USR CHR$ z+x,a:NEXT x:NEXT z 2010 DATA 24,36,24,60,90,24,36,66 2020 DATA 60,92,191,251,190,255,86,24 2030 DATA 0,16,56,84,254,84,56,16 2040 DATA 195,255,255,195,195,255,255,195 2050 DATA 255,255,129,66,36,24,255,255 2060 DATA 102,153,60,90,60,102,255,126 2070 DATA 63,33,33,33,33,33,33,63 2080 DATA 248,248,248,248,232,248,248,248 2090 RETURN 5000 CLS :IF sc>hs THEN PRINT AT 5,8; INK 7; FLASH 1;"CONGRATULATIONS"; AT 7,3;"YOU HAVE BEATEN THE HI-SCORE"; AT 9,10;"of ";hs; AT 11,8;"with a score of ";sc:LET hs=sc:GO TO 5010 5005 PRINT AT 10,7; INK 7;"Your score was ";sc 5010 PRINT AT 15,1; INK 7;"Do you want another go ? (y/n)" 5020 IF INKEY$ ="n" THEN CLS :PRINT AT 10,11; INK 7; FLASH 1;"GOODBYE":STOP 5030 IF INKEY$ ="y" THEN GO TO 3 5040 GO TO 5020 6000 CLS :PRINT INK 7;"Your task is to steer yourself ([UDG-A]) around the screen without falling to your death or runningout of time.You must attempt to collect the jewels ([UDG-C]) and kill all the monsters ([UDG-F]) before moving on to the next level through the door ([UDG-G][UDG-H])." 6005 PRINT INK 7''"Press any key to continue.":PAUSE 0 6010 CLS :PRINT INK 7'"Once you have killed a monster an invisible gas is released and your time decreases more rapidly."''"You score 50 points for each jewel and 100 for each monster." 6020 PRINT AT 10,10; INK 7;"INSTRUCTIONS"; AT 12,5;"5...............left"; AT 14,5;"6...............down"; AT 16,5;"7...............up"; AT 18,5;"8...............right" 6025 PRINT INK 7''"Press any key to continue.":PAUSE 0 6030 GO TO 7 ```