This program implements a scrolling maze/labyrinth game where the player navigates a character horizontally along a corridor filled with obstacles. Line 1 contains a REM statement housing machine code: a LDIR-based routine that shifts screen memory, providing smooth vertical scrolling of the playfield. The player position is tracked via a direct PEEK of screen memory at address A, with INKEY$ “0” and “1” used for left/right movement. Obstacles (block graphic characters) are randomly distributed across each new row generated by the GOSUB 200 subroutine, and the score increments each cycle until a collision is detected.
Program Structure
The program is organized into a main loop and three subroutines:
- Initialization (lines 10–20): Calculates the player’s screen address, inputs difficulty
C, draws the initial screen, and sets the score counterBto-18(offsetting the pre-fill rows). - Main loop (lines 50–130): Generates a new row string, prints it, calls the machine code scroller, checks for collision, updates player position, then repeats from line 30 (note: line 30 does not exist — this is a bug; see below).
- Row generator subroutine (lines 200–240): Copies the template string
B$intoA$, then randomly placesCwall characters andCspace characters within it. - Screen fill subroutine (lines 300–340): Fills all 22 rows with the border/corridor template
B$at startup. - Game over handler (lines 1000–1030): Clears screen, prints final score, pauses, then restarts.
Machine Code Usage
Line 1 is a REM statement containing 18 bytes of Z80 machine code. The routine is called via RAND USR 16514 at line 75 (16514 = address of the first byte after the REM token). Disassembled:
| Bytes | Mnemonic | Notes |
|---|---|---|
01 D6 02 | LD BC, $02D6 | Byte count = 726 (22 rows × 33 bytes) |
2A 0C 40 | LD HL, ($400C) | Load display file start address |
09 | ADD HL, BC | HL → one row down from top |
54 | LD D, H | |
5D | LD E, L | DE = source (one row down) |
01 B5 02 | LD BC, $02B5 | Byte count = 693 (21 rows × 33) |
2A 0C 40 | LD HL, ($400C) | HL = destination (top of screen) |
09 | ADD HL, BC | (unused intermediate — likely HL points to end of copy region) |
ED B8 | LDDR | Block copy downward (scroll up) |
C9 | RET |
This LDDR-based scroll moves the entire display buffer up by one text row each game cycle, giving smooth vertical scrolling without redrawing the whole screen from BASIC.
Key BASIC Idioms
LET A=645+PEEK 16396+256*PEEK 16397— computes a screen address relative to the display file base (system variable at 16396/16397), placing the player 645 bytes (about 19 rows × 33 + offset) into the display.LET A=A+(INKEY$="0")-(INKEY$="1")— classic Sinclair idiom using Boolean arithmetic (+1 or -1) to update position in a single expression.LET A$(1+F)="%."andLET A$(1+F)="% "— two-character string slice assignment used to place block graphic pairs (wall/space) into the row template.- Score is initialized to
-18so that it reads 0 only after the 18 pre-scrolled setup rows have passed.
Display Template
The string B$ (line 16) is 33 characters wide. It consists of border characters (\: = ▌ and \ : = ▐ style blocks) at each end, with 28 interior positions filled with \@@ (inverse spaces / solid blocks), forming a solid wall corridor. The row generator (lines 200–240) punches C gaps and C walls randomly into this template to create the navigable maze rows.
Collision Detection
Collision is detected at line 80 by PEEK A: the player’s current screen cell is read directly from display memory. Character code 136 represents an inverse space (solid block — a wall). If the cell is not 136, the game-over subroutine at line 1000 is called. Line 90 then writes 151 (the player character) to that address, and lines 100–104 write wall characters to the three adjacent cells (offsets +32, +33, +34 — i.e., the row below), effectively drawing the player sprite and the approaching wall simultaneously.
Bugs and Anomalies
- LDDR direction: LDDR copies from high to low address. The setup places HL at (base + 693) and DE at (base + 726), but both source and destination adjustments in the machine code warrant careful scrutiny — the exact scroll direction and pixel-row vs. character-row granularity depends on whether the display file is linear (as on the TS2068 in certain modes).
- Score display condition: Line 72 only prints the score when
B>0, consistent with the-18initialization, so the score appears clean from zero.
Content
Source Code
1 REM 1D6 22A C40 9545D 1B5 22A C40 9EDB8C9
10 LET A=645+PEEK 16396+256*PEEK 16397
15 INPUT C
16 LET B$="% : @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ :% "
17 GOSUB 300
20 LET B=-18
50 GOSUB 200
70 PRINT AT 0,0;A$
72 IF B>0 THEN PRINT AT 18,30;B;AT 19,30;" :% "
75 RAND USR 16514
80 IF PEEK A<>136 THEN GOSUB 1000
90 POKE A,151
100 POKE A+33,136
102 POKE A+32,136
104 POKE A+34,136
110 LET B=B+1
120 LET A=A+(INKEY$="0")-(INKEY$="1")
130 GOTO 30
200 LET A$=B$
205 FOR N=1 TO C
206 LET F=INT (RND*28)+2
210 LET A$(1+F)="%."
215 LET F=INT (RND*28)+2
220 LET A$(1+F)="% "
230 NEXT N
240 RETURN
300 FOR N=0 TO 21
310 PRINT AT N,0;B$
330 NEXT N
340 RETURN
1000 CLS
1010 PRINT AT 10,4;"GAME OVER - FINAL SCORE = ";B
1020 PAUSE 1000
1030 RUN
9998 SAVE "LABYRINTH-%2"
9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
