Decoded: Rogue (1980) by Toy, Arnold, Wichman DOS version (1983) by Mel Sibony and Jon Lane Source file: CHASE.C Beginner friendly, line-by-line code walkthrough by MaiZure CHASE.C defines the basic AI procedure for monsters chasing the player Original code: https://britzl.github.io/roguearchive/ Original code with line numbers http://www.maizure.org/projects/decoded-rogue/CHASE_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 a probability basis for dragons shooting flames 11 BLANK 12 Global holding the position monster is running to 13 BLANK 14 COMMENT 15 COMMENT 16 COMMENT 17 COMMENT UPDATE MOVING MONSTERS 18 Defines runners with no arguments 19 BLOCK START - runners, each running monster takes a step 20 Declare a pointer to a monster 21 Declare a variable for distance 22 BLANK 23 Loop through all monsters on the level 24 If the monster isn't held but is running... 25 Calculate the distance between the monster and the player 26 If the monster isn't slow, is a slime with distance, or is a slow turn.. 27 Allow the mosnter to make a make 28 If the monster is hasted.. 29 Allow it to move 30 Update the distance after the possible move 31 If the monster is flying... 32 It gets another amonter 33 In all cases, it's time to move again 34 End check for running monster 35 End check for all monsters 36 BLOCK END - runners 37 BLANK 38 COMMENT 39 COMMENT 40 COMMENT 41 COMMENT CHASE AI 42 Define do_chase with one argument 43 Argument 1 is a pointer to the monster doing the casing 44 BLOCK START - do_chase, set one mosnter off chasing a target 45 Declare an iterator and distance. Init a minimum distance of 2^15-1 46 Declare an unused character 47 Declare a flag for a door 48 Declare a pointer to an object 49 Declare a pointer to a room 50 Declare two pointers to rooms, one for the chasee and chaser 51 Declare a temporary coordinate 52 BLANK 53 Get the chaser's room 54 If the monster is guarding gold that's gone... 55 Chase the player 56 Find the target's room 57 If the monster isn't chasing the player... 58 Find the room of the target 59 If the target isn't in a room.. 60 Don't chase at all 61 COMMENT 62 COMMENT 63 COMMENT 64 Check and grab the chase target if it's a door 65 BLANK 66 BLANK 67 COMMENT 68 COMMENT 69 COMMENT 70 COMMENT 71 COMMENT 72 Label for repeated search 73 If the chaser is not in the same room as a target and isn't in a maze.. 74 BLOCK START - Find room exit 75 Loop through all the exits 76 Get the distance between the exit and the target (player) 77 If the distance is better than the min found so far... 78 Heard towards this exit 79 Match distances 80 End check for best exit 81 Repeat loop for exits 82 If this target is a door... 83 Get the passage number 84 Set door to false 85 Repeat this search 86 End check for door 87 BLOCK END - Find room exit 88 Otherwise, player is near - get the destination 89 COMMENT 90 COMMENT 91 COMMENT 92 COMMENT 93 COMMENT 94 If the monster is a Dragon or Ice monster... 95 And the monster is in the same row/column as the player... 96 Or in the same diagonal... 97 And is more than one square away... 98 But less than the maximum range of a flame/frost bolt attack... 99 and hasn't been interrupt while rolling a 20% chance... 100 START BLOCK - Shoot at the player 101 Monster stops running 102 Get the y offset 103 Get the x offset 104 Select name of attack type and FIRE! 105 Return from monster chase 106 BLOCK END - Shoot at the player 107 End of check for near/far hero 108 COMMENT 109 COMMENT 110 COMMENT 111 COMMENT 112 COMMENT 113 If we've made it this far...time to chase the player 114 If the monster is at the hero.. 115 Attack the player 116 Return from chase 117 Otherwise, monster might want to pick up an object 118 Loop through all objects on the level 119 If the monster is on the object... 120 Declare a character byte 121 BLANK 122 Remove the object from the level 123 Put the object in the monster's inventory 124 Get the map character at that location.. 125 ...which may be a floor or passage if we're in a room 126 If the player can see the position... 127 Draw that character on the floor 128 The monster needs a new target 129 Break from the object loop 130 End check for object position match 131 End check for objects to pick up 132 If the monster is a flytrap... 133 Return from further movement 134 COMMENT 135 COMMENT 136 COMMENT 137 If the old character in the position is not the player... 138 and it's a blank space that the player can see... 139 And the space is actually a floor... 140 Then draw the floor in the position 141 Otherwise if it's a space that the plac can't see... 142 and there's no monster there... 143 Draw the blank space again 144 Otherwise.. 145 Just draw the old character that used to be there 146 End check for drawing non-player floor space 147 Get the room the chaser is currently in 148 If the monster isn't at the same position as the destination 149 BLOCK START - Update destination 150 If the destination isn't in a room... 151 Update the monster's room to the previously stored room (no null ptrs) 152 Finished with chase 153 BLOCK 154 If the room's still don't match 155 The monster needs to find a new destination 156 The monster's position is at the old destination 157 BLOCK START - Update destination 158 BLANK 159 If the player can see the monster 160 If the target destination is a passage... 161 Invert color output to stand out 162 Draw the old character at the destination position 163 Add the monster's disguise character to the position 164 End check if the player can see the monster 165 If the player can see all monsters 166 BLOCK START - See all monsters 167 Invert color output for emphasis 168 Get the old character at the position 169 Write the monster's true symbol at the position 170 BLOCK END - See all monsters 171 In all other cases... 172 The player must have been at the position 173 If the old character was a floor and the old room is dark... 174 Draw a space 175 End extended output formats 176 BLOCK END - do_chase 177 BLANK 178 COMMENT 179 COMMENT 180 COMMENT 181 COMMENT MONSTER VISIBILITY CHECK 182 Defines see_monst with one argument 183 Argument 1 is a pointer to a monster 184 BLOCK START - see_monst, checks if the player can see a monster 185 If the player is blind... 186 The player definitely can't see the monster - return false 187 If the monster is inivisble and the player can't see inivisible 188 The player definitely can't see the monster - return false 189 The monster is beyond the player's dark room sight distance... 190 and not in the same room or the room is dark... 191 Or the room is a maze 192 The player definitely can't see the monster - return false 193 COMMENT 194 COMMENT 195 COMMENT 196 COMMENT 197 If the player is wearing a weapon that does extra damage to this enemy.. 198 And the weapon hasn't shown that power yet... 199 BLOCK START - Vorpal hint 200 Set the weapon flash flag 201 Print a hint that this weapon hates this monster 202 BLOCK END - Vorpal hint 203 If we've made it this far, the player sees the monster. 204 BLOCK END - see_monst 205 BLANK 206 COMMENT 207 COMMENT 208 COMMENT 209 COMMENT 210 COMMENT WAKE UP A MONSTER 211 Define start_run with one argument 212 Argument 1 is a coordinate for a monster 213 BLOCK START - start_run, wakes up a monster 214 Declare a pointer to an object (monster) 215 BLANK 216 COMMENT 217 COMMENT 218 COMMENT 219 Get the monster at the input coordinate 220 If the monster exists... 221 COMMENT 222 COMMENT 223 COMMENT 224 Set the monster to run 225 Set the monster free 226 Search for a target 227 End check for monster to enable 228 If we're in debug mode... 229 Otherwise...there is no monster! 230 Send error about that 231 End check for debug mode 232 BLOCK END - start_run 233 BLANK 234 COMMENT 235 COMMENT 236 COMMENT 237 COMMENT 238 COMMENT 239 COMMENT CHASE NEXT STEP 240 Define chase with two arguments 241 Argument 1 is the monster doing the chasing 242 Argument 2 is the coordinate of the target 243 BLOCK START - chase, finds the next step during a chase 244 Declare x and y position variables 245 Declare integers for distances 246 Declare a pointer to a game object 247 Declare a coordinate for the chasing monster 248 Declare a character 249 Initialize a counter to 1 250 BLANK 251 Get the position of the chasing monster 252 COMMENT 253 COMMENT 254 COMMENT 255 COMMENT 256 COMMENT 257 If the chaser is confused and with an 80% chance (20% if a phantom)... 258 or 50% of it's a bat 259 BLOCK START - Find a move to make 260 COMMENT 261 COMMENT 262 COMMENT 263 Get a random move and store it in ch_ret 264 Get the distance between the move and the target 265 COMMENT 266 COMMENT 267 COMMENT 268 There is a ~3% chance that... 269 The monster loses confusion state 270 BLOCK END - Find a move to make 271 COMMENT 272 COMMENT 273 COMMENT 274 COMMENT 275 Otherwise we can search for a position towards the target 276 BLOCK START - Random move one space towards target 277 Declare target x and y positions 278 COMMENT 279 COMMENT 280 COMMENT 281 COMMENT 282 Get the distance between the chaser and target 283 Return a pointer to the chaster 284 BLANK 285 Assume next position is down one row... 286 and right one row... 287 Loop from the left of the monster to the right.. 288 BLOCK START - Scan for next step by columns... 289 And loop from above the mosnter to below... 290 BLOCK START - Scan for next step by rows 291 Declare the testing coordinate 292 BLANK 293 Match to the x position (outer loop) 294 Match to the y position (inner loop) 295 If this position is off the map or an unaccessible diagonal... 296 Skip to the next position 297 Get the floor character at that position 298 If the monster is allowed to move to this position... 299 BLOCK START - Movement candidate 300 COMMENT 301 COMMENT 302 COMMENT 303 COMMENT 304 If the position has a scroll... 305 BLOCK START - Check for scare monster scroll 306 Loop through all objects on the level 307 BLOCK START - Check for scroll 308 If this object is at the test position 309 Exit loop to test scroll type 310 BLOCK END - Check for scroll 311 This is scroll is a scare monster scroll... 312 Monsters are afraid of it - skip this position 313 BLOCK END - Check for scare monster scroll 314 COMMENT 315 COMMENT 316 COMMENT 317 COMMENT 318 Get the distance between the testing position and the target 319 If the distance is less than the current distance (it's closer)... 320 BLOCK START - Choose this position 321 Set choice counter to 1 322 Set the target 323 Get the distance 324 BLOCK END - Choose this position 325 Otherwise...randomly choose a bad position <=33% of the time... 326 BLOCK START - Bad choice 327 Set the target 328 Get the distance 329 BLOCK END - Bad choice 330 BLOCK END - Movement candidate 331 BLOCK END - Scan for next step by rows 332 BLOCK END - Scan for next step by columns... 333 End of movement towards target 334 BLOCK END - chase 335 BLANK 336 COMMENT 337 COMMENT 338 COMMENT 339 COMMENT 340 COMMENT FIND ROOM BASED ON COORDINATES 341 roomin returns a pointer to a room 342 Define roomin with one argument 343 Argument 1 is a map coordinate 344 BLOCK START - roomin, returns a room by input coordinates 345 Declare a pointer to a room (success return value) 346 Declare a pointer to a floor character 347 BLANK 348 Loop through all the rooms 349 Compare the input coordinate falls between the room left and right... 350 ...and within the top and the bottom... 351 Return that room pointer 352 Otherwise, get the floor type 353 If this is a passage... 354 Get the passage index and return it 355 Check for debug mode 356 Print out a debug message for an unknown position 357 End check for debug made 358 Increment the failure exit counter 359 Return fail 360 BLOCK END - roomin 361 BLANK 362 COMMENT 363 COMMENT 364 COMMENT 365 COMMENT CHECK DIAGONAL MOVEMENT 366 Define diag_ok with two arguments 367 Arguments 1 and 2 are coordinates for player and target 368 BLOCK START - diag_ok, checks if diagonal movement is possible 369 If the coordinates are the same... 370 The move must be ok 371 Otherwise make sure the cardinal positions are both clear as well 372 BLOCK END - diag_ok 373 BLANK 374 COMMENT 375 COMMENT 376 COMMENT 377 COMMENT CHECK COORDINATE VISIBILITY 378 Define cansee with two arguments 379 Arguments 1 and 2 are x and y positions on the map 380 BLOCK START - cansee, checks if player can see the input coordinates 381 Declare a pointer to a room 382 Declare coordinates 383 BLANK 384 If the player is blind... 385 They can never see anything...false 386 If the target is within the lamp distance of the player... 387 Then player can see the spot, even in a dark room 388 COMMENT 389 COMMENT 390 COMMENT 391 COMMENT 392 Set a coordinate y position with the actual y 393 Set a coordinate x potition with the actual x 394 Get the pointer to the room 395 If the player isn't in the room, then they can't see the point 396 BLOCK END - cansee 397 BLANK 398 COMMENT 399 COMMENT 400 COMMENT 401 COMMENT FIND DESTINATION 402 find_dest returns a pointer to coordinates 403 Define find_dest with one argument 404 Argument 1 is a pointer to the target 405 BLOCK START - find_dest, returns a target destination for a chaser 406 Declare an object pointer 407 Declare a probability variable 408 Declare a pointer to a room 409 BLANK 410 If the target isn't a monster, is in the same room as player... 411 And the player can see the monster... 412 The target is the player 413 Set the room pointer to the current room 414 Loop through all objects 415 BLOCK START - Check all objects for a possible target 416 If the object is a scare monster scroll... 417 Monsters ignore it 418 If the object is in the same room and if a probability check succeeds... 419 BLOCK START - Monster goes for object 420 Loop through all the monsters 421 If sanother moster is already chasing the object... 422 Break 423 If nothing was already chasing the object... 424 Send this monster after the object 425 BLOCK END - Monster goes for object 426 BLOCK END - Check all objects for a possible target 427 Return the player's position as the target 428 BLOCK END - find_dest 429 EOF˙