Jump to content
IGNORED

Random Dungeons in TMS9900 Assembly


adamantyr

Recommended Posts

Okay, after abandoning my binary tree efforts, I moved on to something simpler.

 

The maze algorithm first plots corridors, up to 512 squares, only hitting unvisited blocks. I store them in a stack area for easy retrieval later, and it also comes in handle for tracking where the corridors are as opposed to the rooms. Direction changes are set to only occur 1/16 of the time, so it makes very long straight corridors. It also picks up and starts a new corridor if it gets "trapped" anywhere.

 

Room placement is more tricky. I wanted to use a "weighted" algorithm like Jaime Buck's to determine placement. Just randomly placing rooms anywhere on the map creates a lot of processing time, so instead I take a random corridor and try four set points around it for potential room spots. The weight measurement wants the following:

  • Only blocks under the room itself and the immediate ring of squares around it
  • A corridor somwhere within 2 squares of the room's edge

Rooms are set to a hard-coded count of 16. Eventually I'll add door/archway/secret passage placement code to connect rooms to other rooms and corridors, which is why I want rooms to only be one square away from corridors.

 

Issues include:

  • Corridors that can double around and create double-wides... I suppose I could live with that if it happens, but it would look kinda messy.
  • The corridor "start-over" method can create unconnected dungeon areas... which can be seen on the map

Here is the maze generated by the code... the random function uses a set seed so it generates the same content all the time:

 

post-17978-0-38678000-1346200058_thumb.png

 

 

 

 DEF START
 REF VMBW,VSBW,VWTR,KSCAN
RSTACK BSS 32
WS	 EQU >8300
WS2 EQU >8320
SCRADR EQU >0000
COLTAB EQU >0380
PATADR EQU >0800
STATUS EQU >837C
KEYADR EQU >8374
KEYVAL EQU >8375
VDPTMR EQU >8378
DIRX BYTE 0,1,0,-1
DIRY BYTE -1,0,1,0
KEYS BYTE 'E','X','S','D',0
ANYKEY BYTE >20
B1	 BYTE 1
B2	 BYTE 2
B4	 BYTE 4
B8	 BYTE 8
B48 BYTE 48
B63 BYTE 63
B97 BYTE 97
B128 BYTE 128
B129 BYTE 129
 EVEN
ZERO DATA 0
W1	 DATA 1
W4	 DATA 4
W64 DATA 64
MCOUNT DATA 512
RCOUNT DATA 16
SEED DATA >26D5
MAXVAL DATA >FFFF
KSUB DATA MOVEUP,MOVEDN,MOVELF,MOVERT
RVALUE DATA 0,1,-4
CSTACK BSS 1024
MAZE BSS 4096
ROW BSS 2
COL BSS 2
TROW BSS 2
TCOL BSS 2
DIRECT BSS 2
TCOUNT BSS 2
POSY BSS 2
POSX BSS 2
RMDATA BSS 6
CHARS DATA >FFFF,>FFFF,>FFFF,>FFFF
 DATA >0000,>0000,>0000,>0000
 BSS 16
* Main routine
START LWPI WS
 LI R10,RSTACK
 LI R0,COLTAB+16
 LI R1,>1F1F
 BLWP @VSBW
 LI R0,PATADR+1024
 LI R1,CHARS
 LI R2,16
 BLWP @VMBW
 BL @CLRSCR
* Create maze
 BL @MKMAZE
 CLR @POSY
 CLR @POSX
* Maze look routine
MLOOP BL @MZDRAW
KSC1 CLR @KEYADR
KSC2 CLR @STATUS
 LIMI 2
 LIMI 0
KSC3 BLWP @KSCAN
 CB @ANYKEY,@STATUS
 JNE KSC2
 CB @KEYVAL,@B97
 JLT KSC4
 SB @ANYKEY,@KEYVAL
KSC4 LI R2,KEYS
KSC5 CB *R2,@KEYVAL
 JEQ KSC6
 MOVB *R2,*R2+
 JEQ KSC2
 JMP KSC5
KSC6 LI R3,KEYS
 LI R0,KSUB
 S R3,R2
 SLA R2,1
 A R2,R0
 MOV *R0,R1
 BL *R1
 JMP MLOOP
MOVEUP MOV @POSY,@POSY
 JEQ MU1
 DEC @POSY
MU1 RT
MOVEDN MOV @POSY,R0
 CI R0,40
 JEQ MD1
 INC @POSY
MD1 RT
MOVELF MOV @POSX,@POSX
 JEQ ML1
 DEC @POSX
ML1 RT
MOVERT MOV @POSX,R0
 CI R0,32
 JEQ MR1
 INC @POSX
MR1 RT
MZDRAW MOV @POSY,R2
 SLA R2,6
 A @POSX,R2
 LI R0,SCRADR
 LI R1,MAZE
 A R2,R1
 LI R2,32
 LI R3,24
MZD1 BLWP @VMBW
 AI R0,32
 AI R1,64
 DEC R3
 JNE MZD1
 RT
* Make Maze
MKMAZE MOV R11,*R10+
* Fill maze buffer with blocks
 LI R0,MAZE
 LI R1,>8080
 LI R2,2048
MKM1 MOV R1,*R0+
 DEC R2
 JNE MKM1
 CLR @DIRECT
* Choose a random start point (CSTACK contains all corridor locations)
MKM2 LI R8,CSTACK
 CLR @ROW
 CLR @COL
 LI R3,62
 BLWP @RNDNUM
 INC R4
 MOVB @WS+9,@ROW
 BLWP @RNDNUM
 INC R4
 MOVB @WS+9,@COL
 MOVB @ROW,*R8+
 MOVB @COL,*R8+
* Choose a random direction or keep same? (1/16 chance)
MKM3 LI R9,4
 BLWP @RANDOM
 ANDI R4,>000F
 JNE MKM5
MKM4 BLWP @RANDOM
 ANDI R4,>0003
 MOV R4,@DIRECT
MKM5 MOV @DIRECT,R4
 BL @GODIR
 MOV R0,R0
 JNE MKM6
 DEC R9
 JNE MKM4
 JMP MKM2
* Plot in that direction
MKM6 MOVB @TROW,@ROW
 MOVB @TCOL,@COL
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 BL @GRDIDX
 LI R0,MAZE
 A R1,R0
 MOVB @B129,*R0
 DEC @MCOUNT
 JNE MKM3
* Draw rooms
* Determine random size (3-12) on each side
MKM7 LI R3,10
 BLWP @RNDNUM
 AI R4,3
 MOV R4,@RMDATA+2
 BLWP @RNDNUM
 AI R4,3
 MOV R4,@RMDATA+4
* Find a corridor on the map, put into @ROW,@COL
MKM8 BLWP @RANDOM
 ANDI R4,>01FF
 SLA R4,1
 MOVB @CSTACK(R4),@ROW
 MOVB @CSTACK+1(R4),@COL
* Determine 4 random positions of room around corridor
 LI R8,CHARS
 CLR R9
MKM9 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @RMDATA+3,@TROW
 SB @RMDATA+5,@TCOL
 SB @B1,@TROW
 SB @B1,@TCOL
 BL @EDGCHK
 MOV R0,R0
 JEQ MKM9A
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 INC R9
MKM9A MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B2,@TROW
 AB @B2,@TCOL
 BL @EDGCHK
 MOV R0,R0
 JEQ MKM9B
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 INC R9
MKM9B MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @RMDATA+3,@TROW
 SB @B1,@TROW
 AB @B2,@TCOL
 BL @EDGCHK
 MOV R0,R0
 JEQ MKM9C
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 INC R9
MKM9C MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @RMDATA+5,@TCOL
 SB @B1,@TCOL
 AB @B2,@TROW
 BL @EDGCHK
 MOV R0,R0
 JEQ MKM9D
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 INC R9
* Determine "value" of each random room
MKM9D MOV R9,@TCOUNT
 JEQ MKM8
 CLR R3
MKM10 MOVB @CHARS(R3),@ROW
 MOVB @CHARS+1(R3),@COL
 BLWP @ROOMCK
 MOV R0,@CHARS+16(R3)
 INCT R3
 DEC R9
 JNE MKM10
* Pick best value room and draw it
 CLR R3
 MOV @TCOUNT,R9
 CLR R0
 SETO R1
MKM11 C R0,@CHARS+16(R3)
 JGT MKM12
 MOV @CHARS+16(R3),R0
 MOV R3,R1
MKM12 INCT R3
 DEC R9
 JNE MKM11
 C R1,@MAXVAL
 JNE MKM13
 B @MKM7
* Draw room, and decrement max room count
MKM13 MOV @CHARS(R1),@RMDATA
 BL @DRAWRM
 DEC @RCOUNT
 JEQ MKM14
 B @MKM7
MKM14 B @SUBRET
* Room check - Delivers value of room
* @ROW,@COL - Position
* @RMDATA,@RMDATA+2 - Vertical and horizontal width
* Result returned in R0
ROOMCK DATA WS2,RMCK1
RMCK1 CLR R8
 MOV @RMDATA+2,R2
 MOV @RMDATA+4,R3
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B1,@TROW
 SB @B1,@TCOL
 INCT R2
 INCT R3
* First pass - Check underneath room footprint and outer edge; open space is "bad"
RMCK2 BL @RGETVL
 SLA R4,2
 S R4,R8
 AB @B1,@TCOL
 DEC R3
 JNE RMCK2
 AB @B1,@TROW
 MOV @RMDATA+4,R3
 INCT R3
 MOV @COL,@TCOL
 SB @B1,@TCOL
 DEC R2
 JNE RMCK2
* Second pass - Check 2 squares away in cardinal areas; open space is "good"
* Top row
 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TROW
RMCK2A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK3
 BL @RGETVL
 A R4,R8
 AB @B1,@TCOL
 DEC R2
 JNE RMCK2A
* Bottom row
RMCK3 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B2,@TROW
RMCK3A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK4
 BL @RGETVL
 A R4,R8
 AB @B1,@TCOL
 DEC R2
 JNE RMCK3A
* Left column
RMCK4 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TCOL
RMCK4A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK5
 BL @RGETVL
 A R4,R8
 AB @B1,@TROW
 DEC R2
 JNE RMCK4A
* Right column
RMCK5 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B2,@TCOL
RMCK5A BL @EDGCHK
 MOV R0,R0
 JEQ RMCKE
 BL @RGETVL
 A R4,R8
 AB @B1,@TROW
 DEC R2
 JNE RMCK5A
* Return value
RMCKE MOV R8,@>0000(R13)
 RTWP
* Calculate value of square
RGETVL CLR R1
 MOVB @TROW,@WS2+3
 SLA R1,6
 AB @TCOL,@WS2+3
 CLR R4
 MOVB @MAZE(R1),@WS2+9
 ANDI R4,>007F
 RT
* Draw room
* @RMDATA - Row
* @RMDATA+1 - Column
* @RMDATA+2 - vertical width
* @RMDATA+4 - horizontal width
DRAWRM CLR R1
 MOVB @RMDATA,@WS+3
 SLA R1,6
 AB @RMDATA+1,@WS+3
 LI R0,MAZE
 A R1,R0
 MOV @RMDATA+2,R2
 MOV @RMDATA+4,R3
DRWRM1 MOVB @B129,*R0+
 DEC R3
 JNE DRWRM1
 AI R0,64
 MOV @RMDATA+4,R3
 S R3,R0
 DEC R2
 JNE DRWRM1
 RT
* Check a given direction is valid edge-wise
* R0 must not be zero
GODIR MOVB @ROW,@TROW
 MOVB @COL,@TCOL
 AB @DIRY(R4),@TROW
 AB @DIRX(R4),@TCOL
EDGCHK CLR R0
* Check if over edge
 CB @TROW,@B63
 JHE EC1
 CB @TCOL,@B63
 JHE EC1
 MOVB @TROW,@TROW
 JLE EC1
 MOVB @TCOL,@TCOL
 JLE EC1
 SETO R0
EC1 RT

* Get grid index from @ROW,@COL
* Returns in R1
GRDIDX CLR R1
 MOVB @ROW,@WS+3
 SLA R1,6
 AB @COL,@WS+3
 RT
* Clear screen
CLRSCR LI R0,SCRADR
 LI R1,>2000
 LI R4,768
CSLOOP BLWP @VSBW
 INC R0
 DEC R4
 JNE CSLOOP
 RT
* Random number generator (Range in R3, Result in R4)
* Returns 0 to R3-1
RNDNUM DATA WS2,RAND2
RAND2 BL @RNDGEN
 MOV @>0006(R13),R3
 CLR R4
 DIV R3,R4
 MOV R5,@>0008(R13)
 RTWP
* Random number generator 16-bit (Result in R4)
* returns 0-65535
RANDOM DATA WS2,RAND1
RAND1 BL @RNDGEN
 MOV R5,@>0008(R13)
 RTWP
* Random number generation
RNDGEN LI R4,23729
 MPY @SEED,R4
 AI R5,31871
 SRC R5,5
 MOV R5,@SEED
 RT
* Nested return from subroutine
SUBRET DECT R10
 MOV *R10,R11
 RT
* Program end
 END START

 

 

Edited by adamantyr
Link to comment
Share on other sites

Okay, some more revisions and I got a pretty good dungeon generator going!

 

After messing around with several different corridor implementations to try and stop it from creating double-wides, I finally found the answer: Check the parallel blocks when moving a particular direction. This allows it to avoid creating corridors next to each other, and it fills up rather nicely.

 

Room placement had some bugs before; I was checking the upper-left room corner was in boundary but not the lower right, which caused some spillover rooms in the maze array. I also altered placement a bit, and the result is much more drop down pleasing.

 

I don't have time to do screen captures of the results, but you can see them as ASCII code below.

 

Guess I should start thinking about door algorithms next...

 

################################################################	    ################################################################
#........................................#######################	    #........................................#######################
#.###########.##########################.#######################	    #.###########.##########################.#............##########
#.............##########################.#######################	    #.............##########################.#............##########
#.######################################.#######################	    #.######################################.#............##########
#.######################################.#######################	    #.########...........###################.#............##########
#.#################################......#######################	    #.########...........##############......#######################
#.#################################.####.#######################	    #.########...........##############.####.#.......###############
#.#################################.####.#######################	    #.########...........##############.####.#.......###############
#.#################################.####.#######################	    #.#################################.####.#.......###############
#......................................#.#######################	    #......................................#.#.......###############
########.#########.####.#.############.#.#######################	    ########.#########.####.#.############.#.#######################
########.#########.####.#.############.#.#######################	    ########.##....###.####.#.####...#####.#.#######################
#####....#########.####.#.############.#.#######################	    #####....##....###.####.#.####...#####.#.#######################
#####.##.#########.####.#.############.#.#######################	    #####.##.##....###.####.#.####...#####.#.#######################
#####.##.#########.####.#.############.#.#######################	    #####.##.##....###.####.#.####...#####.#.#.........#############
#####....#########.####.#.############.#.#######################	    #####....##....###.####.#.####...#####.#.#.........#############
########.#########.####.#.##############.#######################	    ########.##....###.####.#.####...#######.#.........#############
########.#########.####.#.##############.#######################	    ########.##....###.####.#.####...#######.#.........#############
########.#########.####.#.##############.#######################	    ########.#########.####.#.####...#######.#.........#############
########.#########.####.#.##############.#####################.#	    ########.#......##.####.#.##############.#.........###########.#
########.#########.####.#.##############.#####################.#	    ########.#......##.####.#.##############.#.........###########.#
########.#########.####..................#####################.#	    ########.#......##.####..................#.........###########.#
########.#########.#############.##.##########################.#	    ########.#......##.#############.##.######.........###########.#
########.#########.#############.##.##########################.#	    ########.#......##.###....######.##.######.........###########.#
########.#########.#############.##.##########################.#	    ########.#......##.###....######.##.######.........###########.#
########.#########.#############.##.##########################.#	    ##.....#.#......##.###....######.##.######.........###########.#
########.#########.#############.##.##########################.#	    ##.....#.#......##.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#......##.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#......##.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#########.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.###....######.##.#.........################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.###....######.##.#.........################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.###....######.##.#.........################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.###....######.##.##########################.#
########.#########.#############.##.##########################.#	    ##.....#.#...#####.#############.##.#.......##################.#
########.#########.#############.##.##########################.#	    ########.#...#####.#############.##.#.......##################.#
########.#########.#############.##.##########################.#	    ########.#...#####.#############.##.#.......##################.#
########.#########.#############.##.##########################.#	    ########.#...#####.#############.##.#.......##################.#
########.#########.#############.##.##########################.#	    ########.#...#####.#############.##.##########################.#
########.#########.#############.##.##########################.#	    ########.#########.#############.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#.....#######.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#.....#######.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#.....#######.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#############.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#############.##.#####............#########.#
########.#########.#############.##.##########################.#	    ########.#########.#############.##.##########################.#
########.#########.#############.##............................#	    ########.#########.#############.##............................#
########.#########.#############.#############.#################	    ########.#########.#############.#############.#################
########.#########.#############.#############.#################	    ########.#########.#############.#############.######......#####
########.#########.#############.#############.#################	    ########.#########.#############.#############.######......#####
########.#########.#############.#############.#################	    ########.#########.#############.#############.######......#####
########.#########.#############.#############.#################	    ########.#########.#############.#############.######......#####
#........#########.#############.#############.#################	    #........#########.#############.#############.######......#####
#.###.##.#########.#############.##########.##.#################	    #.###.##.#########.#############.#......###.##.#################
#.....##.#########.#############.##########.##.#################	    #.....##.#########.#############.#......###.##.#################
#.######.####......#############.##########.##.#################	    #.######.####......#############.#......###.##.#################
#.######.####.##################.##########.##.................#	    #.######.####.##################.#......###.##.................#
#........####.##################.##########.##.#.######.######.#	    #........####.##################.#......###.##.#.######.######.#
#############.##################.##########.##.#.######.######.#	    #############.##################.#......###.##.#.######.######.#
#############.##################.##########.##.#.######.######.#	    #############.##################.##########.##.#.######.######.#
#############........###########............##.................#	    #############........###########............##.................#
################################################################	    ################################################################

Edited by adamantyr
Link to comment
Share on other sites

Some more revisions... I added door and stair placement.

 

Stairs are placed at dead-ends, I traverse the stack of corridors to find these by looking for ones that are cardinally surrounded by only a single corridor. I'll eventually add some code in to place them in rooms if no dead-ends are available.

 

Doors are trickier. Checking and storing coordinates for potential doors for each room creates a lot of options. At first I tried random door amounts per room but this was way too messy. I ended up making it a single door, with a distinct possibility (1/16 chance) of a second door. I may need to revisit this to make it smarter and only place a single door on a side of a room, which would make multiple doors more logical.

 

Here's a screenshot:

post-17978-0-07094300-1346297703_thumb.png

 

Adamantyr

Link to comment
Share on other sites

The screenshot reminded me of Tunnels of Doom. Is the algorithm used to generate the ToD dungeons documented anywhere? I'm not ashamed to say I spent an entire summer 'trudging' up and down those 10-level dungeons with my brothers long ago :)

 

There you go:

http://www.atariage.com/forums/topic/187918-tunnels-of-doom-map-generation-algorithm/#entry2373742

Link to comment
Share on other sites

The screenshot reminded me of Tunnels of Doom. Is the algorithm used to generate the ToD dungeons documented anywhere? I'm not ashamed to say I spent an entire summer 'trudging' up and down those 10-level dungeons with my brothers long ago :)

 

There you go:

http://www.atariage....m/#entry2373742

 

Thanks, Retro! I knew I had read about the ToD algorithm somewhere, but I couldn't remember where exactly.

 

Currently my dungeon generator takes the most time doing room placement, several real-time seconds. Still, I think I could generate 10 levels of dungeon pretty quick. I'm definitely leaning towards storing it all on disk rather than trying to make it up as you go along.

 

Adamantyr

Link to comment
Share on other sites

Oh, and here is the listing for the current code (hidden in spoiler so as to not make the thread super-huge):

 

 

 

 DEF START
 REF VMBW,VSBW,VWTR,KSCAN
RSTACK BSS 32
WS	 EQU >8300
WS2 EQU >8320
SCRADR EQU >0000
COLTAB EQU >0380
PATADR EQU >0800
STATUS EQU >837C
KEYADR EQU >8374
KEYVAL EQU >8375
VDPTMR EQU >8378
DIRX BYTE 0,1,0,-1
DIRY BYTE -1,0,1,0
KEYS BYTE 'E','X','S','D',0
ANYKEY BYTE >20
B1	 BYTE 1
B2	 BYTE 2
B4	 BYTE 4
B8	 BYTE 8
B48 BYTE 48
B63 BYTE 63
B97 BYTE 97
B128 BYTE 128
B129 BYTE 129
B130 BYTE 130
 BYTE 131
 BYTE 132
MSG TEXT 'Digging corridors...'
 TEXT 'Building rooms...'
 TEXT 'Adding doors...'
 TEXT 'Adding stairs...'
 EVEN
ZERO DATA 0
W1	 DATA 1
W4	 DATA 4
W64 DATA 64
MCOUNT DATA 512
RCOUNT DATA 16
SEED DATA >26D5
MAXVAL DATA >FFFF
KSUB DATA MOVEUP,MOVEDN,MOVELF,MOVERT
ROW BSS 2
COL BSS 2
TROW BSS 2
TCOL BSS 2
DIRECT BSS 2
TCOUNT BSS 2
POSY BSS 2
POSX BSS 2
RMDATA BSS 6
CHARS DATA >FFFF,>FFFF,>FFFF,>FFFF
 DATA >0000,>0000,>0000,>0000
 DATA >FF81,>BDBD,>BDBD,>BDBD
 DATA >0010,>387C,>1010,>1000
 DATA >0010,>1010,>7C38,>1000
ROOMS BSS 128
DOORS BSS 128
HALLS BSS 1024
MAZE BSS 4096
* Main routine
START LWPI WS
 LI R10,RSTACK
 LI R0,COLTAB+16
 LI R1,>1F1F
 BLWP @VSBW
 LI R0,PATADR+1024
 LI R1,CHARS
 LI R2,40
 BLWP @VMBW
* Create halls
 BL @CLRSCR
 LI R0,SCRADR+130
 LI R1,MSG
 LI R2,20
 BLWP @VMBW
 BL @MKHALL
* Create rooms
 BL @CLRSCR
 LI R0,SCRADR+130
 LI R1,MSG+20
 LI R2,17
 BLWP @VMBW
 BL @MKROOM
* Create doors
 BL @CLRSCR
 LI R0,SCRADR+130
 LI R1,MSG+37
 LI R2,15
 BLWP @VMBW
 BL @MKDOOR
* Create stairs
 BL @CLRSCR
 LI R0,SCRADR+130
 LI R1,MSG+52
 LI R2,16
 BLWP @VMBW
 BL @MKSTRS
* Maze look routine
 CLR @POSY
 CLR @POSX
MLOOP BL @MZDRAW
KSC1 CLR @KEYADR
KSC2 CLR @STATUS
 LIMI 2
 LIMI 0
KSC3 BLWP @KSCAN
 CB @ANYKEY,@STATUS
 JNE KSC2
 CB @KEYVAL,@B97
 JLT KSC4
 SB @ANYKEY,@KEYVAL
KSC4 LI R2,KEYS
KSC5 CB *R2,@KEYVAL
 JEQ KSC6
 MOVB *R2,*R2+
 JEQ KSC2
 JMP KSC5
KSC6 LI R3,KEYS
 LI R0,KSUB
 S R3,R2
 SLA R2,1
 A R2,R0
 MOV *R0,R1
 BL *R1
 JMP MLOOP
MOVEUP MOV @POSY,@POSY
 JEQ MU1
 DEC @POSY
MU1 RT
MOVEDN MOV @POSY,R0
 CI R0,40
 JEQ MD1
 INC @POSY
MD1 RT
MOVELF MOV @POSX,@POSX
 JEQ ML1
 DEC @POSX
ML1 RT
MOVERT MOV @POSX,R0
 CI R0,32
 JEQ MR1
 INC @POSX
MR1 RT
MZDRAW MOV @POSY,R2
 SLA R2,6
 A @POSX,R2
 LI R0,SCRADR
 LI R1,MAZE
 A R2,R1
 LI R2,32
 LI R3,24
MZD1 BLWP @VMBW
 AI R0,32
 AI R1,64
 DEC R3
 JNE MZD1
 RT
* Make Corridors
MKHALL MOV R11,*R10+
* Fill maze buffer with blocks
 LI R0,MAZE
 LI R1,>8080
 LI R2,2048
MKH1 MOV R1,*R0+
 DEC R2
 JNE MKH1
 CLR @DIRECT
* Choose a random start point (HALLS contains all corridor locations)
MKH2 LI R8,HALLS
 CLR @ROW
 CLR @COL
 LI R3,62
 BLWP @RNDNUM
 INC R4
 MOVB @WS+9,@ROW
 BLWP @RNDNUM
 INC R4
 MOVB @WS+9,@COL
 MOVB @ROW,*R8+
 MOVB @COL,*R8+
 DEC @MCOUNT
* Choose a random direction or keep same? (1/16 chance)
MKH3 LI R9,4
 BLWP @RANDOM
 ANDI R4,>000F
 JNE MKH5
MKH4 BLWP @RANDOM
 ANDI R4,>0003
 MOV R4,@DIRECT
MKH5 MOV @DIRECT,R4
 BL @GODIR
 MOV R0,R0
 JEQ MKH5A
 BL @VALCOR
 MOV R0,R0
 JNE MKH6
MKH5A DEC R9
 JNE MKH4
* If no valid direction can be found after 4 tries, retreat to previous corridor point
 LI R3,512
 S @MCOUNT,R3
 BLWP @RNDNUM
 SLA R4,1
 MOVB @HALLS(R4),@ROW
 MOVB @HALLS+1(R4),@COL
 JMP MKH3
* Plot in that direction
MKH6 MOVB @TROW,@ROW
 MOVB @TCOL,@COL
 MOVB @TROW,*R8+
 MOVB @TCOL,*R8+
 BL @GRDIDX
 MOVB @B129,@MAZE(R1)
 DEC @MCOUNT
 JNE MKH3
 B @SUBRET
* Make Rooms
MKROOM MOV R11,*R10+
 LI R6,ROOMS
* Determine random size (3-12) on each side
MKR1 LI R3,10
 BLWP @RNDNUM
 AI R4,3
 MOV R4,@RMDATA+2
 BLWP @RNDNUM
 AI R4,3
 MOV R4,@RMDATA+4
* Find a corridor on the map, put into @ROW,@COL
MKR2 BLWP @RANDOM
 ANDI R4,>01FF
 SLA R4,1
 MOVB @HALLS(R4),@ROW
 MOVB @HALLS+1(R4),@COL
* Determine 4 random positions of room around corridor
 LI R8,CHARS
 CLR R9
 LI R7,6
MKR3 MOV @ROW,@TROW
 MOV @COL,@TCOL
 BL @ROOMPL
* Check upper left corner
 BL @EDGCHK
 MOV R0,R0
 JEQ MKR3A
 MOVB @TROW,R1
 MOVB @TCOL,@WS+3
 AB @RMDATA+3,@TROW
 AB @RMDATA+5,@TCOL
* Check lower right corner
 BL @EDGCHK
 MOV R0,R0
 JEQ MKR3A
 MOV R1,*R8+
 INC R9
MKR3A DECT R7
 JGT MKR3
 JEQ MKR3
* Determine "value" of each random room
 MOV R9,@TCOUNT
 JEQ MKR2
 CLR R3
MKR4 MOVB @CHARS(R3),@ROW
 MOVB @CHARS+1(R3),@COL
 BLWP @ROOMCK
 MOV R0,@CHARS+16(R3)
 INCT R3
 DEC R9
 JNE MKR4
* Pick best value room and draw it
 CLR R3
 MOV @TCOUNT,R9
 CLR R0
 SETO R1
MKR5 C R0,@CHARS+16(R3)
 JGT MKR6
 MOV @CHARS+16(R3),R0
 MOV R3,R1
MKR6 INCT R3
 DEC R9
 JNE MKR5
 C R0,@W4
 JLT MKR1
 C R1,@MAXVAL
 JEQ MKR1
* Draw room, and decrement max room count
MKR7 MOV @CHARS(R1),@RMDATA
 BL @DRAWRM
 MOV @RMDATA,*R6+
 MOVB @RMDATA+3,*R6+
 MOVB @RMDATA+5,*R6+
 DEC @RCOUNT
 JNE MKR1
 B @SUBRET
* Make doors
MKDOOR MOV R11,*R10+
 LI R9,ROOMS
 LI R8,16
* Determine door count per room (1-4)
MKDR1 MOVB *R9+,@ROW
 MOVB *R9+,@COL
 MOVB *R9+,@RMDATA+3
 MOVB *R9+,@RMDATA+5
 MOV @W1,R5
 BLWP @RANDOM
 ANDI R4,>0007
 JNE MKDR2
 INC R5
MKDR2 BLWP @DOORCK
MKDR3 BLWP @RNDNUM
 SLA R4,1
 MOV @DOORS(R4),R0
 CLR R1
 MOVB R0,@WS+3
 SLA R1,6
 AB @WS+1,@WS+3
 CB @B130,@MAZE(R1)
 JEQ MKDR2
 MOVB @B130,@MAZE(R1)
 DEC R5
 JNE MKDR3
 DEC R8
 JNE MKDR1
 B @SUBRET
* Make stairs
MKSTRS MOV R11,*R10+
 LI R9,HALLS
 LI R8,DOORS
 LI R7,512
 CLR R5
* Locate all dead-ends in dungeon corridors
MKS2 MOVB *R9+,@ROW
 MOVB *R9+,@COL
 CLR R4
 LI R1,3
MKS3 CLR R2
 MOVB @ROW,@TROW
 MOVB @COL,@TCOL
 AB @DIRY(R1),@TROW
 AB @DIRX(R1),@TCOL
 MOVB @TROW,@WS+5
 SLA R2,6
 AB @TCOL,@WS+5
 MOVB @MAZE(R2),R0
 ANDI R0,>7F00
 AB R0,R4
 DEC R1
 JGT MKS3
 JEQ MKS3
 CB @B1,R4
 JEQ MKS5
MKS4 DEC R7
 JNE MKS2
 JMP MKS5A
MKS5 MOVB @ROW,*R8+
 MOVB @COL,*R8+
 INC R5
 JMP MKS4
* All dead-ends found, now place stairs
* Are there at least two dead-ends?
MKS5A CI R5,2
 JHE MKS6
* If not, skip
 JMP MKS8
MKS6 LI R2,2
MKS7 MOV R5,R3
 BLWP @RNDNUM
 SLA R4,1
 MOVB @DOORS(R4),@WS+3
 SLA R1,6
 AB @DOORS+1(R4),@WS+3
 CB @MAZE(R1),@B129
 JNE MKS7
 MOVB @B130(R2),@MAZE(R1)
 DEC R2
 JNE MKS7
MKS8 B @SUBRET
* Door check - Finds valid door positions around room
* @ROW,@COL - Position of room
* @RMDATA+2,@RMDATA+4 - Vertical and horizontal width
* Result returned in DOORS array and R3
DOORCK DATA WS2,DOCK1
DOCK1 LI R8,DOORS
 CLR R9
 CLR @DIRECT
* Bottom row
 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B1,@TROW
 AB @RMDATA+3,@TROW
DOCK2 BL @EDGCHK
 MOV R0,R0
 JEQ DOCK3
 BL @DFIND
 AB @B1,@TCOL
 DEC R2
 JNE DOCK2
* Left column
DOCK3 INC @DIRECT
 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TCOL
DOCK4 BL @EDGCHK
 MOV R0,R0
 JEQ DOCK5
 BL @DFIND
 AB @B1,@TROW
 DEC R2
 JNE DOCK4
* Top row
DOCK5 INC @DIRECT
 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TROW
DOCK6 BL @EDGCHK
 MOV R0,R0
 JEQ DOCK7
 BL @DFIND
 AB @B1,@TCOL
 DEC R2
 JNE DOCK6
* Right column
DOCK7 INC @DIRECT
 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B1,@TCOL
 AB @RMDATA+5,@TCOL
DOCK8 BL @EDGCHK
 MOV R0,R0
 JEQ DOCKE
 BL @DFIND
 AB @B1,@TROW
 DEC R2
 JNE DOCK8
* Return value
DOCKE MOV R9,@>0006(R13)
 RTWP
* Find potential door spot
DFIND CLR R1
 MOVB @TROW,@WS2+3
 SLA R1,6
 AB @TCOL,@WS2+3
 CB @MAZE(R1),@B129
 JNE DFIND1
 MOV @DIRECT,R4
 MOVB @TROW,*R8
 AB @DIRY(R4),*R8+
 MOVB @TCOL,*R8
 AB @DIRX(R4),*R8+
 INC R9
DFIND1 RT
* Validate corridor - check block and parallel blocks for other corridors
VALCOR CLR R0
 CLR R3
 MOVB @TROW,@WS+7
 SLA R3,6
 AB @TCOL,@WS+7
 CB @MAZE(R3),@B129
 JEQ VALCR1
 MOV @DIRECT,R2
 INC R2
 ANDI R2,>0003
 CLR R3
 MOVB @TROW,@WS+7
 AB @DIRY(R2),@WS+7
 SLA R3,6
 AB @TCOL,@WS+7
 AB @DIRX(R2),@WS+7
 CB @MAZE(R3),@B129
 JEQ VALCR1
 INCT R2
 ANDI R2,>0003
 CLR R3
 MOVB @TROW,@WS+7
 AB @DIRY(R2),@WS+7
 SLA R3,6
 AB @TCOL,@WS+7
 AB @DIRX(R2),@WS+7
 CB @MAZE(R3),@B129
 JEQ VALCR1
 SETO R0
VALCR1 RT
* Room placement
RMPSEL DATA RMUP,RMDOWN,RMLEFT,RMRGHT
ROOMPL MOV @RMPSEL(R7),R0
 B *R0
* Up
RMUP SB @RMDATA+3,@TROW
 SB @B1,@TROW
 MOVB @RMDATA+5,R0
 SRL R0,1
 SB R0,@TCOL
 JMP RMPEND
* Down
RMDOWN AB @B2,@TROW
 MOVB @RMDATA+5,R0
 SRL R0,1
 SB R0,@TCOL
 JMP RMPEND
* Left	
RMLEFT MOVB @RMDATA+3,R0
 SRL R0,1
 SB R0,@TROW
 SB @RMDATA+5,@TCOL
 SB @B1,@TCOL
 JMP RMPEND
* Right
RMRGHT MOVB @RMDATA+3,R0
 SRL R0,1
 SB R0,@TROW
 AB @B2,@TCOL
 JMP RMPEND
RMPEND RT
* Room check - Delivers value of room
* @ROW,@COL - Position
* @RMDATA,@RMDATA+2 - Vertical and horizontal width
* Result returned in R0
ROOMCK DATA WS2,RMCK1
RMCK1 CLR R8
 MOV @RMDATA+2,R2
 MOV @RMDATA+4,R3
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B1,@TROW
 SB @B1,@TCOL
 INCT R2
 INCT R3
* First pass - Check underneath room footprint and outer edge; open space is "bad"
RMCK2 BL @RGETVL
 SLA R4,2
 S R4,R8
 AB @B1,@TCOL
 DEC R3
 JNE RMCK2
 AB @B1,@TROW
 MOV @RMDATA+4,R3
 INCT R3
 MOV @COL,@TCOL
 SB @B1,@TCOL
 DEC R2
 JNE RMCK2
* Second pass - Check 2 squares away in cardinal areas; open space is "good"
* Top row
 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TROW
RMCK2A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK3
 BL @RGETVL
 A R4,R8
 AB @B1,@TCOL
 DEC R2
 JNE RMCK2A
* Bottom row
RMCK3 MOV @RMDATA+4,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B1,@TROW
 AB @RMDATA+3,@TROW
RMCK3A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK4
 BL @RGETVL
 A R4,R8
 AB @B1,@TCOL
 DEC R2
 JNE RMCK3A
* Left column
RMCK4 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 SB @B2,@TCOL
RMCK4A BL @EDGCHK
 MOV R0,R0
 JEQ RMCK5
 BL @RGETVL
 A R4,R8
 AB @B1,@TROW
 DEC R2
 JNE RMCK4A
* Right column
RMCK5 MOV @RMDATA+2,R2
 MOV @ROW,@TROW
 MOV @COL,@TCOL
 AB @B1,@TCOL
 AB @RMDATA+5,@TCOL
RMCK5A BL @EDGCHK
 MOV R0,R0
 JEQ RMCKE
 BL @RGETVL
 A R4,R8
 AB @B1,@TROW
 DEC R2
 JNE RMCK5A
* Return value
RMCKE MOV R8,@>0000(R13)
 RTWP
* Calculate value of square
RGETVL CLR R1
 MOVB @TROW,@WS2+3
 SLA R1,6
 AB @TCOL,@WS2+3
 CLR R4
 MOVB @MAZE(R1),@WS2+9
 ANDI R4,>007F
 RT
* Draw room
* @RMDATA - Row
* @RMDATA+1 - Column
* @RMDATA+2 - vertical width
* @RMDATA+4 - horizontal width
DRAWRM CLR R1
 MOVB @RMDATA,@WS+3
 SLA R1,6
 AB @RMDATA+1,@WS+3
 LI R0,MAZE
 A R1,R0
 MOV @RMDATA+2,R2
 MOV @RMDATA+4,R3
DRWRM1 MOVB @B129,*R0+
 DEC R3
 JNE DRWRM1
 AI R0,64
 MOV @RMDATA+4,R3
 S R3,R0
 DEC R2
 JNE DRWRM1
 RT
* Check a given direction is valid edge-wise
* R0 must not be zero
GODIR MOVB @ROW,@TROW
 MOVB @COL,@TCOL
 AB @DIRY(R4),@TROW
 AB @DIRX(R4),@TCOL
EDGCHK CLR R0
* Check if over edge
 CB @TROW,@B63
 JHE EC1
 CB @TCOL,@B63
 JHE EC1
 MOVB @TROW,@TROW
 JLE EC1
 MOVB @TCOL,@TCOL
 JLE EC1
 SETO R0
EC1 RT
* Get grid index from @ROW,@COL
* Returns in R1
GRDIDX CLR R1
 MOVB @ROW,@WS+3
 SLA R1,6
 AB @COL,@WS+3
 RT
* Clear screen
CLRSCR LI R0,SCRADR
 LI R1,>2000
 LI R4,768
CSLOOP BLWP @VSBW
 INC R0
 DEC R4
 JNE CSLOOP
 RT
* Random number generator (Range in R3, Result in R4)
* Returns 0 to R3-1
RNDNUM DATA WS2,RAND2
RAND2 BL @RNDGEN
 MOV @>0006(R13),R3
 CLR R4
 DIV R3,R4
 MOV R5,@>0008(R13)
 RTWP
* Random number generator 16-bit (Result in R4)
* returns 0-65535
RANDOM DATA WS2,RAND1
RAND1 BL @RNDGEN
 MOV R5,@>0008(R13)
 RTWP
* Random number generation
RNDGEN LI R4,23729
 MPY @SEED,R4
 AI R5,31871
 SRC R5,5
 MOV R5,@SEED
 RT
* Nested return from subroutine
SUBRET DECT R10
 MOV *R10,R11
 RT
* Program end
 END START

 

 

Edited by adamantyr
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...