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