--- title: "Muncher II" id: 57497 type: "computer_media" slug: "muncher-ii" url: "http://localhost/computer_media/muncher-ii/" markdown_url: "http://localhost/computer_media/muncher-ii.md" published_at: "2024-10-05T21:03:33+00:00" modified_at: "2026-04-03T07:58:28+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/252_Mun2.png" excerpt: "A Pac-Man clone that stores its entire maze in a string array and uses character-cell indexing for all collision detection." 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 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/" indiv: - name: "Jim Broaddus" slug: "jim-broaddus" taxonomy: "indiv" url: "http://localhost/indiv/jim-broaddus/" genre: - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_contents: - id: 56737 title: "Timex Sinclair Public Domain Library Tape 1006" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1006/" media_type: "Program" programmers: - name: "Jim Broaddus" slug: "jim-broaddus" taxonomy: "indiv" url: "http://localhost/indiv/jim-broaddus/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/252_Mun2.png" media_type_tags: "Game" --- Muncher II is a Pac-Man–style maze game written in BASIC by James S. Broaddus (1983) in which the player navigates a character through a 21×21 grid collecting dots, power pellets, and bonus items while evading two ghosts. The entire maze is stored as a two-dimensional string array B$(21,21), with each cell representing a wall (“% “), dot (“.”), power pellet (“*”), tunnel (“-“), or space, allowing collision detection by simple string indexing. Two ghosts are tracked by separate coordinate pairs (GX/GY and GX1/GY1) and move by comparing their position to the player’s coordinates, with a skill-level parameter A controlling how often random direction changes override pursuit. Eating a power pellet (line 2000) sets a counter C to −1 and a COUNT timer so that ghosts temporarily display in a vulnerable appearance and are worth bonus points if caught. The tunnel mechanic at the left and right walls is implemented by checking for the “-” character and wrapping the player’s X coordinate between columns 2 and 20. *** ## Program Analysis ### Program Structure The program is organised into several distinct functional blocks reached by `GOTO` and `GOSUB`: - **Lines 1–7:** Variable initialisation and skill-level selection subroutine (`GOSUB 7000`). - **Lines 8–210:** Maze construction — each row of the 21×21 board is assigned to `B$(N)` as a literal string. - **Lines 220–240:** Initial maze render loop. - **Lines 250–600:** Main game loop covering player input, movement, scoring, ghost AI, and win/loss detection. - **Lines 1000–1040:** Bonus item (“£”) spawning subroutine. - **Lines 1500–1650:** Horizontal movement handlers with tunnel-wrap logic. - **Lines 1700–1830:** Vertical movement handlers. - **Lines 2000–2060:** Power-pellet consumption — activates vulnerable ghost mode. - **Lines 3000–3110:** Ghost movement execution — each branch moves a ghost coordinate then jumps into the continuation of the ghost-update block. - **Lines 4000–4020:** Stop-movement handler for unrecognised keys. - **Lines 5000–5080:** Level-clear animation (sweeping line across row 10) and restart. - **Lines 7000–7110:** Title screen and skill-level input. - **Lines 8000–8110:** Ghost-catch scoring — awards points and resets ghost positions. - **Lines 9000–9600:** Death/game-over sequence, high-score update, and `SAVE`. ### Maze Representation The maze is held in a `DIM B$(21,21)` two-dimensional string array where each element is a two-character cell. Wall cells contain `"% "` (percent-space), dots are `"."` plus a space, power pellets are `"*"`, tunnel exits are `"-"`, and the bonus item is represented by `"£"`. Because BASIC’s DIM pads shorter strings, assigning a 42-character string to a 21-element row fills every two-character cell simultaneously. Collision detection is then performed by reading individual cells such as `B$(Y,X+1)` directly. A practical consequence is that the program never builds a separate collision map — the display state *is* the game state. Eating a dot or pellet is effected by `LET B$(Y,X)=" "` at line 400, which simultaneously clears the map and prevents re-collection. ### Player Movement Direction is encoded in two variables: `R` (horizontal delta, −1/0/1) and `E` (vertical delta, −1/0/1). Movement keys 5/6/7/8 route to subroutines at lines 1500–1830 that update `R`, `E`, and the avatar character `A$` (`">"`, `"<"`, `"A"`, `"V"`). Any other non-directional key jumps to line 4000 which zeroes both deltas, halting the player. The actual position update at lines 370–371 tests the destination cell before committing the move. ### Tunnel Mechanic Row 12 of the maze contains `"-"` characters at columns 1 and 21, representing tunnel exits. The movement routines detect a `"-"` in the direction of travel and set `CHECK=0`, which causes lines 1530/1630 to teleport `X` to column 2 or 20 respectively before continuing normal movement processing. ### Ghost AI Two ghosts share coordinate pairs (`GX`,`GY`) and (`GX1`,`GY1`). Each game-loop iteration compares the ghost coordinates to the player’s `Y`,`X` and attempts to step toward them if the destination cell is not a wall. The skill-level parameter `A` (range 0.2–0.6, lower = harder) is used as a probability threshold: `IF RND"-"` instead of `B$(Y+1,X)<>"-"`, making the downward-movement tunnel guard test the wrong row. - Lines 3060 and 3070 incorrectly write `LET GY=GY1+C` (overwriting ghost 1’s Y with ghost 2’s Y plus C) instead of `LET GY1=GY1+C`. This is a variable-name bug causing ghost 1 to be displaced when ghost 2 moves right. - The level-clear animation at lines 5010–5060 prints a sweeping pattern across row 10, using embedded `">"` and `"<"` characters to simulate a wiper effect before restarting at line 8. - `A$` doubles as both the display character and a state indicator for direction — direction-sensitive scoring or behaviour could easily be added by testing `A$`. - Line 8060 contains a logic error: `IF GY>=X OR GX1<>Y` should likely be `GY1>=X` to compare ghost 2’s column against the player, mirroring the ghost-1 check at line 8000. ## Source Code ``` 1 LET S=0 2 LET HS=0 3 LET T=180 4 DIM B$(21,21) 5 LET COUNT=30 6 LET LIVES=3 7 GOSUB 7000 8 LET CHECK=1 9 LET E=0 10 LET R=1 11 LET B$(1)="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % " 20 LET B$(2)="% .........% .........% " 30 LET B$(3)="% .% % % .% % % .% .% % % .% % % .% " 40 LET B$(4)="% *% % % .% % % .% .% % % .% % % *% " 50 LET B$(5)="% .% % % .% % % .% .% % % .% % % .% " 60 LET B$(6)="% ...................% " 70 LET B$(7)="% .% % % .% .% % % % % .% .% % % .% " 80 LET B$(8)="% .....% ...% ...% .....% " 90 LET B$(9)="% % % % % .% .......% .% % % % % " 100 LET B$(10)="% % % % % .% .......% .% % % % % " 110 LET B$(11)="% % % % % .% .% ---% .% .% % % % % " 120 LET B$(12)="-.......% % .......-" 130 LET B$(13)="% % % % % .% .% ---% .% .% % % % % " 140 LET B$(14)="% % % % % .% .... ..% .% % % % % " 150 LET B$(15)="% % % % % .% .% % % % % .% .% % % % % " 160 LET B$(16)="% .........% .........% " 170 LET B$(17)="% *% % % .% % % .% .% % % .% % % *% " 180 LET B$(18)="% ...% ...........% ...% " 190 LET B$(19)="% % % .% .% % % % % % % % % .% .% % % " 200 LET B$(20)="% % % ...............% % % " 210 LET B$(21)="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % " 220 FOR N=1 TO 21 230 PRINT AT N,1;B$(N) 240 NEXT N 250 LET Y=14 255 LET E$=" " 260 LET X=12 265 LET D$=" " 270 LET A$=">" 275 LET C=1 280 LET GX=12 285 LET GY=12 290 LET GX1=12 295 LET GY1=11 300 PRINT AT GX,GY;"%"" 310 PRINT AT GX1,GY1;"%"" 320 PRINT AT Y,X;A$ 325 PRINT AT 0,0;"LIVES:";LIVES;AT 0,19;"HI-SCORE:";HS 330 IF INT (RND*50)=0 THEN GOSUB 1000 335 PRINT AT Y,X;" " 340 IF INKEY$="8" OR (B$(Y,X+1)="-" AND R=1) THEN GOTO 1500 350 IF INKEY$="5" OR (B$(Y,X-1)="-" AND R=-1) THEN GOTO 1600 355 IF INKEY$<>"5" AND INKEY$<>"6" AND INKEY$<>"7" AND INKEY$<>"8" AND INKEY$<>"" THEN GOTO 4000 360 IF INKEY$="7" THEN GOSUB 1700 365 IF INKEY$="6" THEN GOSUB 1800 370 IF B$(Y,X+R)<>"-" AND B$(Y,X+R)<>"% " THEN LET X=X+R 371 IF B$(Y+E,X)<>"% " THEN LET Y=Y+E 375 IF B$(Y,X)="*" THEN GOSUB 2000 380 IF B$(Y,X)="." THEN LET S=S+1 390 IF B$(Y,X)="£" THEN LET S=S+10 395 IF B$(Y,X)="£" THEN LET T=T+10 400 LET B$(Y,X)=" " 405 PRINT AT 0,8;"SCORE:";S 410 PRINT AT Y,X;A$ 415 IF S=T THEN GOTO 5000 420 PRINT AT GX,GY;D$;AT GX1,GY1;E$ 425 IF RND"% " AND B$(GX,GY+C)<>"% " THEN GOTO 3000 436 IF RNDX AND B$(GX,GY-C)<>"% " AND B$(GX,GY-C)<>"-" THEN GOTO 3020 446 IF RND"% " THEN GOTO 3040 456 IF RNDY AND B$(GX-C,GY)<>"% " THEN LET GX=GX-C 465 IF RND"% " AND B$(GX1,GY1+C)<>"-" THEN GOTO 3060 474 IF RNDX AND B$(GX1,GY1-C)<>"% " AND B$(GX1,GY1-C)<>"-" THEN GOTO 3080 478 IF RND"% " THEN GOTO 3100 486 IF RNDY AND B$(GX1-C,GY1)<>"% " THEN LET GX1=GX1-C 500 LET COUNT=COUNT+1 510 IF COUNT>=30 THEN LET C=1 520 IF C=-1 THEN PRINT AT GX,GY;"""" 525 IF C=1 THEN PRINT AT GX,GY;"%"" 530 IF C=-1 THEN PRINT AT GX1,GY1;"""" 535 IF C=1 THEN PRINT AT GX1,GY1;"%"" 540 IF GX=Y AND GY=X THEN GOTO 9000 550 IF GX1=Y AND GY1=X THEN GOTO 9000 560 LET D$=B$(GX,GY) 570 LET E$=B$(GX1,GY1) 580 LET CHECK=1 600 GOTO 330 1000 IF B$(14,11)="£" THEN RETURN 1010 PRINT AT 14,11;"£" 1020 IF B$(14,11)="." THEN LET T=T-1 1030 LET B$(14,11)="£" 1040 RETURN 1500 PRINT AT Y,X;" " 1510 LET A$=">" 1520 IF B$(Y,X+1)="-" THEN LET CHECK=0 1530 IF CHECK=0 THEN LET X=2 1535 IF CHECK=0 THEN GOTO 375 1540 IF B$(Y,X+1)<>"% " THEN LET R=1 1545 IF B$(Y,X+1)<>"% " THEN LET E=0 1550 GOTO 370 1600 PRINT AT Y,X;" " 1610 LET A$="<" 1620 IF B$(Y,X-1)="-" THEN LET CHECK=0 1630 IF CHECK=0 THEN LET X=20 1635 IF CHECK=0 THEN GOTO 375 1640 IF B$(Y,X-1)<>"% " THEN LET R=-1 1645 IF B$(Y,X-1)<>"% " THEN LET E=0 1650 GOTO 370 1700 PRINT AT Y,X;" " 1710 IF B$(Y-1,X)<>"% " AND B$(Y-1,X)<>"-" THEN LET E=-1 1715 IF B$(Y-1,X)<>"% " AND B$(Y-1,X)<>"-" THEN LET R=0 1720 LET A$="A" 1730 RETURN 1800 PRINT AT Y,X;" " 1810 IF B$(Y+1,X)<>"% " AND B$(Y-1,X)<>"-" THEN LET E=1 1815 IF B$(Y+1,X)<>"% " AND B$(Y-1,X)<>"-" THEN LET R=0 1820 LET A$="V" 1830 RETURN 2000 LET S=S+10 2010 LET C=-1 2020 LET B$(Y,X)=" " 2030 PRINT AT Y,X;A$ 2040 LET T=T+10 2050 LET COUNT=0 2060 RETURN 3000 LET GY=GY+C 3010 GOTO 470 3020 LET GY=GY-C 3030 GOTO 470 3040 LET GX=GX+C 3050 GOTO 470 3060 LET GY=GY1+C 3070 GOTO 500 3080 LET GY1=GY1-C 3090 GOTO 500 3100 LET GX1=GX1+C 3110 GOTO 500 4000 LET R=0 4010 LET E=0 4020 GOTO 360 5000 CLS 5005 PRINT AT 10,31;"*" 5010 FOR N=1 TO 27 5020 PRINT AT 10,N;" %" >" 5025 REM SHEET CLEARED 5030 NEXT N 5040 FOR N=27 TO 1 STEP -1 5050 PRINT AT 10,N;""" < " 5060 NEXT N 5070 LET T=T+180 5080 GOTO 8 7000 PRINT AT 0,12;"MUNCHER II";TAB 11;"''''''''''''''''''''" 7010 PRINT AT 9,0;"--------------------------------" 7020 PRINT AT 11,3;"SELECT SKILL LEVEL (1-5)" 7030 PRINT TAB 7;"(5 IS THE EASIEST)" 7040 PRINT AT 14,0;"--------------------------------" 7050 PRINT TAB 5;" JAMES S. BROADDUS 1983" 7060 LET A=CODE INKEY$-28 7070 IF A>5 OR A<1 THEN GOTO 7060 7080 LET A=A/10 7090 LET A=A+.1 7100 CLS 7110 RETURN 8000 IF GY<>X OR GX<>Y THEN GOTO 8060 8010 LET S=S+10 8020 LET T=T+10 8030 LET GY=12 8040 LET GX=12 8045 PRINT AT Y,X;A$ 8050 GOTO 500 8060 IF GY>=X OR GX1<>Y THEN GOTO 500 8070 LET S=S+10 8080 LET T=T+10 8090 LET GY1=11 8100 LET GX1=12 8105 PRINT AT Y,X;A$ 8110 GOTO 500 9000 IF COUNT<=30 THEN GOTO 8000 9005 LET LIVES=LIVES-1 9010 FOR N=1 TO 10 9015 PRINT AT Y,X;A$ 9016 FOR Q=1 TO 2 9017 NEXT Q 9018 PRINT AT Y,X;CHR$ (CODE A$+128) 9019 NEXT N 9020 IF LIVES<=0 THEN GOTO 9500 9025 CLS 9030 GOTO 210 9500 IF HS