This program is an interactive dungeon map generator that draws a grid-based layout on screen and lets the user populate it with rooms, pits, lakes, walls, halls, and doors. It begins by rendering a bordered play area using inverse-video digits and block characters, then iterates through seven predefined room size categories stored in a DIM’d string array R$(7,5), dispatching to GOSUB routines via the computed address VAL “100*Q+2000” to draw rooms of varying dimensions with dot-fill patterns. User-placed features (lakes, walls, halls, doors) are entered as row/column coordinates interactively, with bounds checking, and the completed map can be sent to a printer via the COPY command. The FAST mode is engaged during initialisation to speed up screen rendering.
Program Analysis
Program Structure
The program divides into several clearly distinct phases:
- Initialisation (lines 4–78): CLS, FAST, draw the border frame with inverse digits and a blank interior.
- Room placement (lines 80–220): Define seven room-size categories in
R$, prompt the user for counts, and dispatch to subroutines via computed GOSUB. - Pit placement (lines 230–290): Scatter inverse-video pit characters at random coordinates.
- Interactive feature placement (lines 300–500): Four sequential phases for lakes, walls, halls, and doors, each using INPUT for row/column coordinates with bounds checking.
- Output (lines 1500–1530): Optional COPY to printer, then STOP.
- Room-drawing subroutines (lines 2100–2760): Seven subroutines, one per room size, each printing dot-filled rectangles at random positions.
Room Size Categories
The array R$(7,5) stores human-readable size labels displayed in the prompt at line 170. The seven entries correspond to subroutines at lines 2100–2700:
| Q | R$(Q) | Subroutine | Room footprint |
|---|---|---|---|
| 1 | 20×30 | 2100 | 2 rows × 3 cols |
| 2 | 20×40 | 2200 | 2 rows × 5 cols |
| 3 | 30×50 | 2300 | 3 rows × 5 cols |
| 4 | 40×60 | 2400 | 4 rows × 6 cols |
| 5 | 20×20 | 2500 | 2 rows × 2 cols |
| 6 | 30×30 | 2600 | 3 rows × 3 cols |
| 7 | 40×40 | 2700 | 4 rows × 4 cols |
Note that the size labels in R$ use inverse-video digit characters (e.g. %2%0%X%3%0), making the dimensions appear highlighted on screen. The actual dot dimensions in the subroutines do not perfectly match the labels — for example, “20×30” yields a 2×3 dot block rather than 20×30 character cells, suggesting the labels are stylistic rather than literal measurements.
Computed GOSUB Dispatch
Line 200 uses GOSUB VAL "100*Q+2000" to dynamically compute the subroutine address from the loop variable Q. This is a well-known space-saving idiom: a single GOSUB replaces seven explicit IF/GOTO branches. For Q=1 through 7, the targets are lines 2100, 2200, …, 2700. Line 2000 contains a bare STOP as a safety guard in case Q is somehow 0, and line 2800 likewise acts as a sentinel past the last valid subroutine.
Border Drawing
Lines 5–78 construct the map border. Line 7 prints a row of inverse-video digits 0–9 repeating across 32 columns as the top border. Lines 10–30 print 20 rows of inverse spaces to fill the play area with a uniform background. Lines 40–76 use a two-pass loop (C=1 TO 2) with an inner loop over A=0 TO 3 (exploiting NOT PI = 0 and LEN STR$ PI = 4) to print characters CHR$(156) through CHR$(159) — block graphic characters — down both the left side (pass 1) and an offset position (pass 2, AT A+10). Line 78 then places an inverse zero at row 20, column 0 to close the frame.
Interactive Placement and Bounds Checking
The lake, wall, hall, and door phases each prompt the user for a row (M) and column (N). Entry of the value 86 for M acts as a sentinel to advance to the next phase (lines 315, 333, 370, 450). Bounds checks vary slightly between phases — for example, walls allow rows 1–20 and columns 1–30, while halls allow rows 1–20 and columns 1–31. A bounds violation silently re-presents the prompt rather than reporting an error.
There is a minor anomaly in the door-placement phase: a bounds violation at line 470 jumps to GOTO 350 (the hall prompt) rather than back to the door prompt at line 430. This means an out-of-range door entry accidentally drops the user into hall-placement mode instead of retrying the door prompt.
Key BASIC Idioms
SGN PIevaluates to 1 (since PI > 0), used wherever the literal 1 would otherwise appear — saves one byte per occurrence.NOT PIevaluates to 0, used for column 0 in PRINT AT statements.LEN STR$ PIevaluates to 4 (length of “3.14159…” truncated to display form), used as the upper bound of the border character loop.VAL "number"in numeric contexts is a standard token-saving technique on this platform.FASTmode at line 5 suppresses the display refresh interrupt during the initial screen draw to speed up rendering.
Unused / Dead Code
Lines 2800–2830 are unreachable during normal execution. Line 2810 contains a CLEAR and line 2820 a SAVE with an inverse-video filename, which appear to be remnants of a development save-and-autorun stub that was never removed from the listing.
Pit Symbol
Line 280 prints "%X" — a single inverse-video X character — to mark pit locations. The prompt at line 230 also displays this character inline to illustrate the symbol to the user.
Content
Source Code
0 REM % % % %D%U%N%G%E%O%N% %G%E%N%E%R%A%T%O%R% % % BY ANTHONY WILLING 3/84
4 CLS
5 FAST
7 PRINT "%0%1%2%3%4%5%6%7%8%9%0%1%2%3%4%5%6%7%8%9%0%1%2%3%4%5%6%7%8%9%0%1"
10 FOR A=SGN PI TO VAL "20"
20 PRINT "% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
30 NEXT A
40 FOR C=SGN PI TO 2
50 FOR A=NOT PI TO LEN STR$ PI
60 PRINT AT A,NOT PI;CHR$ (A+VAL "156")
70 IF C=2 THEN PRINT AT A+10,NOT PI;CHR$ (A+VAL "156")
75 NEXT A
76 NEXT C
78 PRINT AT 20,0;"%0"
80 DIM R$(7,5)
90 LET R$(1)="20%X30"
100 LET R$(2)="20%X40"
110 LET R$(3)="30%X50"
120 LET R$(4)="40%X60"
130 LET R$(5)="20%X20"
140 LET R$(6)="30%X30"
150 LET R$(7)="40%X40"
160 FOR Q=1 TO 7
170 PRINT AT 21,NOT PI;"HOW MANY ";R$(Q);" ROOMS?"
180 INPUT G
190 FOR B=SGN PI TO G
200 GOSUB VAL "100*Q+2000"
210 NEXT B
220 NEXT Q
230 PRINT AT 21,NOT PI;"HOW MANY PITS? (%X)"
240 INPUT G
250 FOR B=1 TO G
260 LET Z=INT (1+26*RND)
270 LET Y=INT (1+18*RND)
280 PRINT AT Y,Z;"%X"
290 NEXT B
300 PRINT AT 21,0;"PLACE YOUR LAKES (##)%8%6% %T%O% %E%N%D"
310 INPUT M
315 IF M=86 THEN GOTO 331
320 INPUT N
322 IF M>21 OR M<1 THEN GOTO 300
324 IF N>31 OR N<1 THEN GOTO 300
329 PRINT AT M,N;"##"
330 GOTO 300
331 PRINT AT 21,0;"PLACE YOUR WALLS (% )%8%6% %T%O% %E%N%D"
332 INPUT M
333 IF M=86 THEN GOTO 350
334 INPUT N
335 IF M>20 OR M<1 THEN GOTO 350
336 IF N>30 OR N<1 THEN GOTO 350
337 PRINT AT M,N;"% "
339 GOTO 331
350 PRINT AT 21,0;"PLACE YOUR HALLS (.)%8%6% %T%O% %E%N%D"
360 INPUT M
370 IF M=86 THEN GOTO 421
380 INPUT N
390 IF M>20 OR M<1 THEN GOTO 350
400 IF N>31 OR N<1 THEN GOTO 350
410 PRINT AT M,N;"."
420 GOTO 350
430 PRINT AT 21,0;"PLACE YOUR DOORS (%D)%8%6% %T%O% %E%N%D"
440 INPUT M
450 IF M=86 THEN GOTO 1500
460 INPUT N
470 IF M>20 OR M<1 THEN GOTO 350
480 IF N>30 OR N<1 THEN GOTO 350
490 PRINT AT M,N;"%D"
500 GOTO 430
1500 PRINT AT 21,0;"ENTER ""COPY"" TO COPY TO PRINTER"
1510 INPUT G$
1520 IF G$="COPY" THEN COPY
1530 STOP
2000 STOP
2100 LET Z=INT (SGN PI+VAL "28"*RND)
2110 LET Y=INT (SGN PI+VAL "18"*RND)
2120 PRINT AT Y,Z;"..."
2130 PRINT AT Y+1,Z;"..."
2140 RETURN
2200 LET Z=INT (SGN PI+VAL "26"*RND)
2210 LET Y=INT (SGN PI+VAL "18"*RND)
2220 PRINT AT Y,Z;"....."
2230 PRINT AT Y+SGN PI,Z;"....."
2240 RETURN
2300 LET Z=INT (SGN PI+VAL "26"*RND)
2310 LET Y=INT (SGN PI+VAL "17"*RND)
2320 PRINT AT Y,Z;"....."
2330 PRINT AT Y+SGN PI,Z;"....."
2340 PRINT AT Y+2,Z;"....."
2350 RETURN
2400 LET Z=INT (SGN PI+VAL "25"*RND)
2410 LET Y=INT (SGN PI+VAL "16"*RND)
2420 PRINT AT Y,Z;"......"
2430 PRINT AT Y+1,Z;"......"
2440 PRINT AT Y+2,Z;"......"
2450 PRINT AT Y+3,Z;"......"
2460 RETURN
2500 LET Z=INT (SGN PI+VAL "29"*RND)
2510 LET Y=INT (SGN PI+VAL "18"*RND)
2520 PRINT AT Y,Z;".."
2530 PRINT AT Y+SGN PI,Z;".."
2540 RETURN
2600 LET Z=INT (SGN PI+VAL "28"*RND)
2610 LET Y=INT (SGN PI+VAL "17"*RND)
2620 PRINT AT Y,Z;"..."
2630 PRINT AT Y+SGN PI,Z;"..."
2640 PRINT AT Y+2,Z;"..."
2650 RETURN
2700 LET Z=INT (SGN PI+VAL "27"*RND)
2710 LET Y=INT (SGN PI+VAL "16"*RND)
2720 PRINT AT Y,Z;"...."
2730 PRINT AT Y+SGN PI,Z;"...."
2740 PRINT AT Y+2,Z;"...."
2750 PRINT AT Y+3,Z;"...."
2760 RETURN
2800 STOP
2810 CLEAR
2820 SAVE "1020%6"
2830 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
