Decoded: Rogue (1980) by Toy, Arnold, Wichman DOS version (1983) by Mel Sibony and Jon Lane Source file: ROOMS.C Beginner friendly, line-by-line code walkthrough by MaiZure ROOMS.C contructs rooms for a single level. Original code: https://britzl.github.io/roguearchive/ Original code with line numbers http://www.maizure.org/projects/decoded-rogue/ROOMS_linenum.txt 1 COMMENT 2 COMMENT 3 COMMENT 4 COMMENT 5 COMMENT 6 BLANK 7 Include the game header 8 Include the console management header 9 BLANK 10 Define macro for the item group for gold as 1 11 BLANK 12 COMMENT 13 COMMENT 14 COMMENT 15 COMMENT CREATE ALL ROOMS 16 Define do_rooms with no arguments 17 BLOCK START - do_rooms, creates all rooms, including mazes and others 18 Declare integers for the room number and an interator 19 Declare a room pointer 20 Declare an object pointer 21 Declare an integer used to count rooms that won't be created. 22 Declare a coordinate for the top left of a room 23 Declare a coordinate for the maximum size of a room 24 Declare a coordinate for a point within a room 25 Declare an integer for the old level number 26 Declare an integer for the bottom row of the map 27 BLANK 28 The last row is the maximum row plus 1 29 BLANK 30 Save the current level number (not used) 31 COMMENT 32 COMMENT 33 COMMENT 34 The maximum width of a room is 1/3 of the screen width 35 The maximum height of a room is 1/3 of the screen height 36 COMMENT 37 COMMENT 38 COMMENT 39 Loop through all of the rooms 40 Clear all of the room exits and connections 41 COMMENT 42 COMMENT 43 COMMENT 44 Choose a random number of rooms to leave out (possibly become mazes) 45 Loop through the number of choices to set special room flags 46 Loop again... 47 Find a random room 48 Retry room search if it's already a maze (we want a regular room) 49 Set the chosen room to be not there 50 Define check for test mode (not set) 51 Filter levels for a test flag (dead code -- see line 53 for real code) 52 Otherwise... 53 Find a room that isn't top row, above level 10 at 50%+ probability 54 End check for test mode 55 Set the chosen room to be a maze 56 End loop for choosing dead/maze rooms 57 COMMENT 58 COMMENT 59 COMMENT 60 BLOCK START - Loop through all rooms 61 COMMENT 62 COMMENT 63 COMMENT 64 Get the left point of the room - room number mod 3, times width 65 Get the top point of the room - room number mod 3, times height 66 If the current room is gone...(it may be a maze so..) 67 COMMENT 68 COMMENT 69 COMMENT 70 COMMENT 71 Check if it's a maze... 72 Set the room's start x to be the furthest point to the left 73 Set the room's start y to be the furthest point at the top 74 Build the maze 75 Otherwise, it's just a gone room... 76 COMMENT 77 COMMENT 78 COMMENT 79 COMMENT 80 Loop to set a clear passage position in the gone room 81 Choose a random horizonal position within the room 82 Choose a random vertical position within the room 83 Set the gone room to a negative size (ensures no drawing) 84 Same idea for the same variable (This is a bug...should be r_max.y) 85 Loop through all matching but unchanged rooms 86 End check for non-maze rooms 87 Go to next room 88 End check for gone rooms 89 If the room is randomly chosen with 10% probability per level... 90 Set that room to be dark (can't see far inside) 91 COMMENT 92 COMMENT 93 COMMENT 94 Loop through all top row rooms 95 Randomize the room's width with a minimum of size 4 96 Randomize the room's height with a minimum of size 4 97 Randomize the left side of the room (absolute left + random remainder) 98 Randomize the top side of the room (absolute left + random remainder) 99 Repeat loop for all top row rooms 100 Draw the room to the level 101 COMMENT 102 COMMENT 103 COMMENT 104 Prepare to add gold with 50% probability, assuming this isn't endgame... 105 Declare a pointer to a stack of gold 106 BLANK 107 If gold can be initialized... 108 Set the gold to value to a random value, min of 2 max of 50 + 10 * level 109 Loop forever to find a place in the room to put the gold 110 Declare a local type 111 BLANK 112 Find a random position to place the gold 113 Get the map character at that position 114 If the position is empty floor... 115 Escape the loop 116 Otherwise, repeat the loop until an empty position is found 117 Copy the position value to the newly allocated gold object 118 Set the object to have multiple counts (multiple gold coins) 119 Set the object's item group 120 Set the type to gold 121 Add the gold to the level's list of objects 122 Add the gold to the map 123 End check for valid gold allocation 124 End random roll check to place gold 125 COMMENT 126 COMMENT 127 COMMENT 128 Roll to place a monster (80% chance if there's gold, otherwise 20%) 129 Check if we can allocate a new monster 130 Declare a local byte for the monster 131 BLANK 132 Loop to find a position in the room 133 Get a random position in the room 134 Get the character at the room, to include other monsters 135 Repeat loop to find a new space if the space isn't empty 136 Create a new, non-wandering monster at the point 137 Load up the monster with goodies 138 End change for valid allocation 139 End random roll for monsters 140 End loop through all rooms 141 BLOCK END - do_rooms 142 BLANK 143 COMMENT 144 COMMENT 145 COMMENT 146 COMMENT DRAW A ROOM 147 Declare draw_room with one argument 148 Argument 1 is the room pointer 149 BLOCK START - draw_room, loads the symbols on the map as needed 150 Declare temporary intergers for x and y positions 151 BLANK 152 COMMENT 153 COMMENT 154 COMMENT 155 Draw the left side wall (character 0xBA from ASCII code page 437) 156 Draw the right side wall (character 0xBA from ASCII code page 437) 157 Draw the top wall (character 0xCD from ASCII code page 437) 158 Draw the bottom wall (character 0xCD from ASCII code page 437) 159 Draw the upper-left corner (character 0xC9 from ASCII code page 437) 160 Draw the upper-right corner (character 0xBB from ASCII code page 437) 161 Draw the lower-left corner (character 0xBC from ASCII code page 437) 162 Draw the lower-right corner (character 0xC8 from ASCII code page 437) 163 COMMENT 164 COMMENT 165 COMMENT 166 Loop through each column in the room not including the border 167 Loop through each row in the room not including the border 168 Set the map character at the position to the floor 169 BLOCK END - draw_room 170 BLANK 171 COMMENT 172 COMMENT 173 COMMENT 174 COMMENT DRAW VERTICAL WALLS 175 Define vert with two arguments 176 Argument 1 is the room pointer 177 Argument 2 is the fixed horizontal point 178 BLOCK START - vert, draws a vertical wall for a room 179 Declare an integer used for the current vertical position 180 BLANK 181 Loop through each vertical point not including the room border 182 Set the map character to vertical wall (0xBA from ASCII code page 437) 183 BLOCK END - vert 184 BLANK 185 COMMENT 186 COMMENT 187 COMMENT 188 COMMENT DRAW HORIZONAL WALLS 189 Define horiz with two arguments 190 Argument 1 is the room pointer 191 Argument 2 is the fixed vertical point 192 BLOCK START - horiz, draws a horizontal wall for a room 193 Declare an integer used for the current horizontal position 194 BLANK 195 Loop through each horizontal point not including the room border 196 Set the map character to vertical wall (0xCD from ASCII code page 437) 197 BLOCK END - horiz 198 BLANK 199 COMMENT 200 COMMENT 201 COMMENT 202 COMMENT CHOOSE A RANDOM POSITION INSIDE A ROOM 203 Define rnd_pos with two arguments 204 Argument 1 is the room pointer 205 Argument 2 is a coordinate structure that will be modified and returned 206 BLOCK START - rnd_pos, returns a random location in a room 207 Set coordinate x to a random point within the room (base + rnd offset). Note that we don't want a wall so always add one and randomize room size minus 1. 208 Set coordinate y to a random point within the room (base + rnd offset) 209 BLOCK END - rnd_pos 210 BLANK 211 COMMENT 212 COMMENT 213 COMMENT 214 COMMENT PLAYER ENTERS A ROOM 215 Define enter_room with 1 argument 216 Argument is a pointer to the player's position coordinates 217 BLOCK START - enter_room, updates the display when entering a room 218 Declare a local pointer to a room 219 Declare local integers for x and y positions 220 Declare a local pointer to an object 221 BLANK 222 Update all pointers based on the current room the player is in 223 Check for a test case condition (dead code) 224 Check for debug mode (nope) 225 Output a debug message 226 End check for debug mode 227 In all cases, return 228 End test case check 229 Opening the door reveals monsters and items (if flags are appropriate) 230 Check that the room isn't dark or a maze. Also player isn't blind, so... 231 Loop through the room's vertical space (each row) 232 Move the cursor to the new row and room's leftmost space 233 Loop through the row in the room 234 COMMENT 235 COMMENT 236 COMMENT 237 COMMENT 238 Check for a monster as current room position 239 If there isn't a monster, or the player can't see the monster... 240 Draw the floor (or whatever should be there) 241 Otherwise there is a monster... 242 Save the old floor character in the buffer 243 Draw the (possibly disguised) monster 244 End check for monster 245 End loop through room row 246 End loop through room column 247 BLOCK END - enter_room 248 BLANK 249 COMMENT 250 COMMENT 251 COMMENT 252 COMMENT PLAYER LEAVES A ROOM 253 Declare leave_room with one argument 254 Argument 1 is the player's current coordinates 255 BLOCK START - leave_room, updates the display as player exits a room 256 Declare local integers for x and y positions 257 Declare a local room pointer 258 Declare a local char for floor character 259 Declare a local char for a character 260 BLANK 261 Update the room pointer with the current room stored at global 262 Update the global room pointer to the passage associated with the exit 263 Update the floor character based on blindness/darkness (floor or blank) 264 If the room is a maze... 265 Set the floor equal to the passage character 266 Loop through each row of the exiting room (excluding walls) 267 Loop through each column of the exiting room (excluding walls) 268 BLOCK START - SWITCH on character at that position via a direct read from the video buffer (repeated BIOS INT 0x10). There is no way to directly determine what is there other than whatever was printed during the last update. The level map doesn't include any dynamic elements (monsters/objects). 269 CASE blank (fallthrough) 270 CASE passage (fallthrough) 271 CASE traps (fallthrough) 272 CASE stairs (fallthrough) 273 Nothing to update, these are static elements 274 CASE floor 275 Check if the floor is actually a blank space... 276 Re-add the blank space (not a default period) 277 Break from switch 278 Everything else is a dynamic element that must change so... 279 COMMENT 280 COMMENT 281 COMMENT 282 COMMENT 283 Check if the character is upper case (is a monster) 284 Check if the player can see the monster still (infra-tunnel vision!) 285 Draw the monster with more emphasis to be visible inside the passage 286 Add the monster's character 287 Revert to normal color scheme 288 End switch case 289 Otherwise, the player can't see the monster... 290 Revert the monster's character buffer to any value 291 Draw the floor and not the monster 292 BLOCK END - switch on old room characters 293 Update item and monster wakeup via door_open 294 BLOCK END - leave_room 295 EOF˙