Dungeon Generator

This file is part of and Timex Sinclair Public Domain Library Tape 1004. Download the collection to get this file.
Developer(s): Tony Willing
Date: 198x
Type: Program
Platform(s): TS 1000

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:

  1. Initialisation (lines 4–78): CLS, FAST, draw the border frame with inverse digits and a blank interior.
  2. Room placement (lines 80–220): Define seven room-size categories in R$, prompt the user for counts, and dispatch to subroutines via computed GOSUB.
  3. Pit placement (lines 230–290): Scatter inverse-video pit characters at random coordinates.
  4. 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.
  5. Output (lines 1500–1530): Optional COPY to printer, then STOP.
  6. 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:

QR$(Q)SubroutineRoom footprint
120×3021002 rows × 3 cols
220×4022002 rows × 5 cols
330×5023003 rows × 5 cols
440×6024004 rows × 6 cols
520×2025002 rows × 2 cols
630×3026003 rows × 3 cols
740×4027004 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 PI evaluates to 1 (since PI > 0), used wherever the literal 1 would otherwise appear — saves one byte per occurrence.
  • NOT PI evaluates to 0, used for column 0 in PRINT AT statements.
  • LEN STR$ PI evaluates 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.
  • FAST mode 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

Appears On

Assembled by Tim Ward from many sources. Contains programs 10176 – 10210.

Related Products

Related Articles

Related Content

Image Gallery

Dungeon Generator

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.

Scroll to Top