Decoded: Rogue (1980) by Toy, Arnold, Wichman DOS version (1983) by Mel Sibony and Jon Lane Source file: FIGHT.C Beginner friendly, line-by-line code walkthrough by MaiZure FIGHT.C handles all the fun monster and player interactions. ROOOAARRR! Original code: https://britzl.github.io/roguearchive/ Original code with line numbers http://www.maizure.org/projects/decoded-rogue/FIGHT_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 COMMENT 11 COMMENT 12 COMMENT 13 COMMENT PLAYER ATTACK 14 Define fight with four arguments 15 Argument 1 is the coordinate of the monster 16 Argument 2 is the monster symbol 17 Argument 3 is the player's weapon 18 Argument 4 is a flag set if the weapon is thrown 19 BLOCK START - fight, player attacks monsters 20 Declare a pointer to an object (monster) 21 Declare a pointer to a char string (monsters name) 22 BLANK 23 COMMENT 24 COMMENT 25 COMMENT 26 If there is no a monster at the attack coordinates... 27 Nothing to fight...return 28 COMMENT 29 COMMENT 30 COMMENT 31 COMMENT 32 Reset flags for passing time (no healing or other daemons) 33 Start up the monster (in case it was inactive/sleeping) 34 COMMENT 35 COMMENT 36 COMMENT 37 If the monster is actually a disguised Xeroc, and the player isn't blind 38 Then undo the disguise 39 If the attack was a throw weapon... 40 Return from combat 41 Print message about seeing a Xeroc 42 End check for disguised Xeroc 43 Get the target monster's name from the global array 44 If the player is blind... 45 The monster's name is 'it' (it pointers to a string called 'it') 46 BLOCK START - player successful hit 47 Declare a cleared flag for player's confusion attack 48 BLANK 49 If the hit was from a missile weapon... 50 Show the hit message for flying weapons 51 Otherwise.. 52 This was a hit from a normal weapon strike 53 If the weapon type was a potion... 54 Apply the potion effect to the monster 55 But if the potion wasn't thrown... 56 If the player had more than one... 57 Decrement the object counter 58 Otherwise, the player is out of the potion 59 Remove the potion from inventory 60 Get rid of the object allocation 61 End check for weapon count 62 In all potion cases, the player now has no current weapon 63 End check for potion throw 64 End check for potion 65 If the player can cause confusion... 66 Set the flag for causing target confusion 67 Set the monster's confused flag 68 Remove the player's confusion ability 69 Send message about loss of confusion ability 70 End check for player confusion ability 71 If the monster has no health remaining... 72 Kill the monster 73 Otherwise, if the player did a confusion attack and isn't blind.. 74 Print the message for monster confusion 75 Return a successful attack 76 BLOCK END - player successful hit 77 If the missed shot was throw... 78 Print the message about weapon misses 79 Other this was a regular attack miss 80 Execute a miss on the monster 81 If the monster is a slime then roll for a 75% chance to... 82 Split the slime 83 Return failed attack 84 BLOCK END - fight 85 BLANK 86 COMMENT 87 COMMENT 88 COMMENT 89 COMMENT MONSTER ATTACK 90 Define attack with one argument 91 Argument one is the monster doing the attack 92 BLOCK START - attack, monster attacks player 93 Declare a character pointer to the monster's name 94 BLANK 95 COMMENT 96 COMMENT 97 COMMENT 98 COMMENT 99 Disable player running 100 Disable counter based daemons, like healing 101 If the monster is a Xeroc and the player isn't blind... 102 Remove the monster's disguise 103 Get the monster's name 104 If the player is blind... 105 Then all monster names are 'it' 106 Roll for a hit on the player 107 Execute the hit 108 If the player's health is gone... 109 Player was killed by the monster 110 If the monster hasn't had abilities dispelled (is still capable)... 111 Then switch on the type of monster... 112 BLOCK START - SWITCH on monster type 113 CASE Aquator 114 COMMENT 115 COMMENT 116 COMMENT 117 COMMENT 118 If the player is wearing armor and it's of decent quality... 119 and isn't leather... 120 If the player is wearing a ring of protect armor... 121 Print a message that the rusting attack failed 122 Otherwise, the player's armor gets rusted 123 BLOCK START - Armor rust 124 Print message that the player's armor is rusting 125 Increase the armor class (worse) 126 BLOCK END - Armor rust 127 CASE Ice monster 128 COMMENT 129 COMMENT 130 COMMENT 131 If the player is frozen... 132 Reduce the duration of the forzen period 133 Break on special attack 134 CASE Rattlesnake 135 COMMENT 136 COMMENT 137 COMMENT 138 If the player fails to save against poison... 139 And the player isn't wearing a ring to protect string... 140 BLOCK START - Poison attack 141 Reduce the player's strength 142 Send a message about a poison attack... 143 Include a terse option 144 BLOCK END - Poison attack 145 Otherwise the player is protected 146 Print a poison defense message 147 CASE Wraith (fallthrough) 148 CASE Vampire 149 COMMENT 150 COMMENT 151 COMMENT 152 COMMENT 153 Roll a check...15% success for wraith and 30% for vampires... 154 BLOCK START - Check for player stats reduction 155 Declare an integer to hold stat reduction 156 BLANK 157 If the monster is a Wraith... 158 BLOCK START - Wraith effects 159 If the player's experience has dropped to 0 due to wraith attack.. 160 Player was killed by a Wraith 161 If the player's level has dropped to zero... 162 BLOCK START - Player level loss 163 Remove all player experience (last chance!) 164 Set the player's level to 1 165 BLOCK END - Player level loss 166 Otherwise the player still dropped a level 167 Set the player's experience to the current level plus 1 168 Roll a hitpoint reduction between 1 and 10 169 BLOCK END - Wraith effects 170 Otherwise, it's a Vampire 171 Roll a hitpoint reduction between 1 and 5 172 Reduce the player's hitpoints by the random roll 173 Reduce the player's max hitpoints by the random roll 174 If the player's hitpoints are below 1... 175 Set hitpoints to 1 176 If the player's max hitpoints are below 1.. 177 Player was killed by either the Wraith or Vampire 178 Print a weakness message 179 BLOCK END - Check for player stats reduction 180 CASE Fungus 181 COMMENT 182 COMMENT 183 COMMENT 184 Set the player is held/trapped flag 185 Get the damage message from the fungus 186 CASE Leprechaun 187 BLOCK START - Leprechaun theft attack 188 COMMENT 189 COMMENT 190 COMMENT 191 Declare a long variable to hold the last player gold value 192 BLANK 193 Store the player's last gold value 194 Reduce player hold based on game level min of 2, max of 50 + 10 * level 195 If the player can't make a magic save... 196 Player's purse gets reduced by up to 4 times that previous roll 197 If the player has negative gold... 198 Set the player's gold to 0 199 Make the leprechaun vanish 200 If gold was lost... 201 Print a message about lost gold 202 BLOCK END - Leprechaun theft attack 203 CASE Nymph 204 BLOCK START - Nyphm item stealing attack 205 Declare pointers to an object and the stolen object 206 Declare an object counter 207 Declare a character string for the stolen action 208 BLANK 209 COMMENT 210 COMMENT 211 COMMENT 212 COMMENT 213 No item stolen yet 214 Loop through all the items in the player's pack 215 If the object isn't the current armor or weapon... 216 or the currently worn rings... 217 And is a random item and passes a random roll... 218 Then the nympth steals the object 219 If we found an object to steal 220 BLOCK START - stolen item 221 Remove the item from the player's inventory 222 Decement the inventory counter 223 If the player had more than one... 224 BLOCK START - multi-item stack theft 225 Declare a counter 226 BLANK 227 Get the stolen count and decrement 228 Set the stolen count to 1 229 Send a message about stolen item 230 Set the item count to the original value 231 BLOCK END - multi-item stack theft 232 Otherwise, there was only one item 233 BLOCK START - single item theft 234 Remove the item from inventory 235 Destroy the item memory (can't get it back) 236 Send message about stolen item 237 BLOCK END - single item theft 238 BLOCK END - stolen item 239 BLOCK END - Nymph item stealing attack 240 CASE Any other monster... 241 Do nothing special 242 BLOCK END - SWITCH on monster type 243 End check for player hit 244 Otherwise, if the player wasn't hit and monster wasnt an ice monster... 245 BLOCK START - Miss by other monsters 246 If the missing monster was a fungi 247 BLOCK START - Fungi miss 248 Reduce player health anyway (fungi won't miss) 249 If the player's health is gone... 250 Player is dead 251 BLOCK END - Fungi miss 252 Print general miss message 253 BLOCK END - Miss by other monsters 254 Clear the message bar 255 Reset counter to 0 256 Update the status bar 257 BLOCK END - attack 258 BLANK 259 COMMENT 260 COMMENT 261 COMMENT 262 COMMENT HIT ATTEMPT 263 Define swing with 3 arguments 264 Arguments are the attack level, armor class, and the weapon bonus 265 BLOCK START - swing, checks for a hit or miss 266 Roll a random resistance number 267 Roll a random needed threshold 268 BLANK 269 Compare roll vs threshold to calculate hit 270 BLOCK END - swing 271 BLANK 272 COMMENT 273 COMMENT 274 COMMENT 275 COMMENT CHECK FOR GAINING LEVEL 276 Define check_level with no arguments 277 BLOCK START - check_level, checks if player levels up 278 Declare a counter, a random offset, and the player's level 279 BLANK 280 Loop through the experience level table 281 If the experience level requirement is greater than the current exp... 282 Break loop at this index. 283 Increment index to the next level 284 Grab the player's current level 285 Set the player's new level to the break 286 If the calculated level greater than the players current level... 287 BLOCK START - calculate level up stats change 288 Roll between level difference nad 10 289 Add this back to maximum hitpoints 290 If the player's hitpoints are greater than max hitpoints 291 Match the hitpoints 292 Send a message about change in level 293 BLOCK END - calculate level up stats change 294 BLOCK END - check_level 295 BLANK 296 COMMENT 297 COMMENT 298 COMMENT 299 COMMENT ATTACK ROLLS 300 Declare roll_em with four arguments 301 Arguments 1, 2, and 3 are the attack, defense, and weapon type 302 Argument 4 is a flag for thrown / launched weapons 303 BLOCK START - roll_em, rolls attack stats 304 Declare pointer to stats structures for attack and defnse 305 Declare a pointer to damage value 306 Declare dice and armor mod variables 307 Declare flag for hit processing 308 Declare bonus hit chance from weapon 309 Declare bonus damage chance from weapon 310 Declare final damage integer 311 Declare pointer to function 312 Get attacker status 313 Get defender status 314 If there is no weapon involved... 315 BLOCK START - No weapon settings 316 Get base attack level 317 No damage bonus 318 No hit bonus 319 BLOCK END - No weapon settings 320 Otherwise, there is a weapon 321 BLOCK START - Weapon attack calculations 322 Get the weapon's hit chance bonus 323 Get the weapon' damage chance bonus 324 COMMENT 325 COMMENT 326 COMMENT 327 If the weapon is enhanced versus this opponent 328 BLOCK START - Vorpal bonus 329 Add 4 to hit bonus 330 Add 4 to damage bonus 331 BLOCK START - Vorpal bonus 332 If the weapon is currently worn (not thrown/launched) 333 BLOCK START - Melee equipment bonuses 334 If the left ring adds to damage 335 Add that damage based on ring's AC 336 If the left ring adds to hit chance 337 Add that hit chance based on the ring's AC 338 If the right ring adds to damage bonus 339 Add that bonus based on ring's AC 340 If the right ring adds to hit chance... 341 Add that hit chance based on ring's AC 342 BLOCK END - Melee equipment bonuses 343 Get the weapon's base damage 344 If weapon is launched but the player still has a weapon worn... 345 And that weapon launched the missile (we call this a bow and arrow) 346 BLOCK START - Arrow damage 347 The base damage comes from the arrow's hurl damage 348 The hit bonus comes from the bow 349 The damage bonus comes from the bow 350 BLOCK END - Arrow damage 351 COMMENT 352 COMMENT 353 COMMENT 354 If the weapon is a staff... 355 And the staff has no more charges left after decrementing 356 BLOCK START - Staff attack calculations 357 The empty staff won't do any damage 358 The empty staff offers no bonus 359 The staff's charge count won't go below zero 360 BLOCK END - Staff attack calculations 361 BLOCK END - Weapon attack calculations 362 COMMENT 363 COMMENT 364 COMMENT 365 COMMENT 366 If the defender isn't running... 367 Attacker get's a hit bonus of 4. 368 Get the defender's armor 369 If the defender is the player... 370 BLOCK START - Player defense calculations 371 If the player has armor 372 Add worn armor to defense 373 If the player has a left ring of protection 374 Add that ring's AC to defense (lower is better) 375 If the player has a right ring of protection 376 Add that ring's AC to defense 377 BLOCK END - Player defense calculations 378 Loop forever (until roll is complete and we break) 379 BLOCK START - Do attack rolls 380 Base the number of dice on the first character in attack (3d5 = 3 die) 381 If the damage value isn't valid...(removes d from the damage value) 382 Return - nothing to roll 383 The number of sides is the next character...get it 384 If there is a successful hit... 385 BLOCK START - Calculate hit damage 386 Declare variable for roll result 387 BLANK 388 Get the roll 389 Offset the roll with bonuses 390 COMMENT 391 COMMENT 392 COMMENT 393 If the player is being attack and is on game level 1... 394 COMMENT 395 COMMENT 396 COMMENT 397 Player takes half damage! 398 COMMENT 399 COMMENT 400 COMMENT 401 If the defender is the player... 402 Multiply damage (supposedly for copy protection, but where is that chk?) 403 Reduce hitpoints by the damage value (0 minimum, no negative damage) 404 Flag that there was a hit to process 405 BLOCK END - Calculate hit damage 406 If there weapon doesn't have extended damage attributes to process... 407 We're done.. 408 Otherwise, we increment to the next damage set and recalculate next hit 409 BLOCK END - Do attack rolls 410 Return successful hit 411 BLOCK END - roll_em 412 BLANK 413 COMMENT 414 COMMENT 415 COMMENT 416 COMMENT PRINT NAME OF ATTACKER 417 prname returns a pointer to a string 418 Define prname with two arguments 419 Argument 1 is the entity to name 420 Argument 2 is a flag to force upper case 421 BLOCK START - prname, prints attacker name 422 Clear the temp buffer (the return value) 423 If there is no input entity... 424 Assume it's the player 425 Otherwise, it's not the player and if the player is blind 426 Player can't see anyone else so call them 'it' 427 Otherwise, there is a monster or object 428 BLOCK START - Get entity name 429 Copy a preamble to the output buffer 430 Copy the monster's name to the output buffer (love the unsafeness here) 431 BLOCK END - Get entity name 432 If we need upper case output 433 Convert the first character to upper case 434 Return the name 435 BLOCK END - prname 436 BLANK 437 COMMENT 438 COMMENT 439 COMMENT 440 COMMENT PRINT HIT MESSAGE 441 Declare hit with two arguments 442 Argument 1 is the attacker name, Argument 2 is the defender name 443 BLOCK START - hit, prints hit message 444 Declare a temporary connection string buffer 445 BLANK 446 Add the attacker's name to the output (don't post yet) 447 SWITCH on 4 possible random outputs 448 BLOCK START - Random attack hit message 449 Possible output message 1 450 Possible output message 2 451 Possible output message 3 452 Possible output message 4 453 BLOCK END - Random attack hit message 454 Put the output message with the defender name and push all to output 455 BLOCK END - hit 456 BLANK 457 COMMENT 458 COMMENT 459 COMMENT 460 COMMENT PRINT MISS MESSAGE 461 Define with two arguments 462 Arguments 1 and 2 are pointers to the attacker and defender 463 BLOCK START - miss, prints miss message 464 Declare temporary string buffer 465 BLANK 466 BLANK 467 Add the attackers name to the output buffer but don't push yet 468 SWITCH on 4 possible output strings 469 BLOCK START - Random attack miss message 470 Possible output message 1 471 Possible output message 2 472 Possible output message 3 473 Possible output message 4 474 BLOCK END - Random attack miss message 475 Put all messages together and push to message buffer 476 BLOCK END - miss 477 BLANK 478 COMMENT 479 COMMENT 480 COMMENT 481 COMMENT ROLL FOR SAVE 482 Define save_throw with two arguments 483 Argument 1 is the type of attack to save against 484 Argument 2 is the entity being attacked 485 BLOCK START - save_throw, rolls an entity's chance to save 486 Declare a variable for the save threshold 487 BLANK 488 Base save chance is 65%. Higher for attack types, lower for target level 489 Roll 490 BLOCK END - save_throw 491 BLANK 492 COMMENT 493 COMMENT 494 COMMENT 495 COMMENT ROLL FOR SAVE EFFECTS (PLAYER) 496 Defines save with one argument 497 Argument 1 is the type of attack 498 BLOCK START - save, roll for save against effects 499 If the attack type is magic... 500 If the player has a protection ring on the left hand... 501 Offset the attack power based on ring's AC 502 If the player has a protection ring on the right hand... 503 Offset the attack power based on ring's AC 504 End of check for magic attack type 505 Return success or failure based on calculation 506 BLOCK END - save 507 BLANK 508 COMMENT 509 COMMENT 510 COMMENT 511 COMMENT COMPUTE STRENGTH-ADJUSTED HIT BONUS 512 Define str_plus with one argument 513 Argument 1 is the strength value 514 BLOCK START - str_plus, calculates strength benefit to hit chance 515 Declare the output result. Max is 4 bonus 516 BLANK 517 If the player's strength is less than 8 518 Bonus is actually a penalty 519 If the player's strength is under 31... 520 Cut bonus by one, down to 3 521 If the player's strength is under 21 522 Cut the bonus by one, down to 2 523 If the player's strength is under 19 524 Cut the bonus by 1, down to 1 525 If the player's strength is under 17 526 Cut the bonus to 0. 527 Return the strength-adjusted hit bonus 528 BLOCK END - save_plus 529 BLANK 530 COMMENT 531 COMMENT 532 COMMENT 533 COMMENT COMPUTER STRENGTH-ADJUSTED DAMAGE BONUS 534 Define add_damn with on argument 535 Argument 1 is the strength value 536 BLOCK START - add_dam, calculates damage benefits based on strength 537 Initialize the return bonus to a maximum of 6 538 BLANK 539 If strength is below 8 540 Bonus is actually a penalty 541 If strength is below 31 542 Decrement bonus by 1, down to 5 543 If strength is below 22 544 Decrement bonus by 1, down to 4 545 If strength is below 20 546 Decrement bonus by 1, down to 3 547 If strength is below 18 548 Decrement bonus by 1, down to 2 549 If strength is below 17 550 Decrement bonus by 1, down to 1 551 If strength is below 16 552 Decrement bonus by 1, down to 0 (no bonus) 553 Return strength-adjusted damage bonus 554 BLOCK END - add_dam 555 BLANK 556 COMMENT 557 COMMENT 558 COMMENT 559 COMMENT GAIN LEVEL 560 Defines raise_level with no arguments 561 BLOCK START - raise_level, levels up the player 562 Set the player's experience points to the level threshold plus 1 563 Run check_level to process level bonuses 564 BLOCK END - raise_level 565 BLANK 566 COMMENT 567 COMMENT 568 COMMENT 569 COMMENT MISSILE HIT CHECK 570 Defines thunk with four arguments 571 Argument 1 is the weapon 572 Arguments 2-4 are the target, present, and past attack phrase tense 573 BLOCK START - thunk, roll for missile hit/miss 574 If the weapon is actually a weapon 575 Add the message based on the input weapon name and present tense 576 Otherwise it's not a weapon... 577 Add the message based on the player attack and past tense 578 If the player is blind... 579 Push the final message with the target as 'it' 580 Otherwise not blind... 581 Push the final message with the target as the monster's name 582 BLOCK END - thunk 583 BLANK 584 COMMENT 585 COMMENT 586 COMMENT 587 COMMENT REMOVE MONSTER 588 Defines remove with three arguments 589 Argument 1 is the monster's position 590 Argument 2 is the pointer to the monster 591 Argument 3 is the flag if the monster was killed (some vanish) 592 BLOCK START - remove, removes monster from game and frees memory 593 Declare pointers to generic objects to iterate over (inventory) 594 BLANK 595 If there is no monster... 596 Then there's nothing to remove 597 BLANK 598 Loop through all object's in the monster's inventory 599 BLOCK START - Monster kill drops 600 Get the next object in inventory 601 Copy the monster's position to the object's position 602 Remove the object from the monster's inventory 603 If the monster was killed... 604 Drop the object at that position 605 Otherwise... 606 Get rid of the object (not dropped) 607 BLOCK END - Monster kill drops 608 If the object was dropped in a passage... 609 Invert the colors to make it stand out 610 If object is on the floor, but the player can't see that position... 611 Draw a blank space (can't see) 612 Otherwise, if the player isn't already standing at that position.. 613 Draw the object at that position 614 End color inversion 615 Remove the monster from the monster list 616 Destroy/free monster object 617 BLOCK END - remove 618 BLANK 619 COMMENT 620 COMMENT 621 COMMENT 622 COMMENT MAGIC OBJECT CHECK 623 Defines is_magic with one argument 624 Argument 1 is a pointer to the target object 625 BLOCK START - is_magic, checks if an object is magical 626 SWITCH on objec type 627 BLOCK START - SWITCH on object type 628 CASE type armor 629 If the armor's final AC doesn't match its base, then return magical 630 CASE weapon 631 If the weapon has hit or damage bonus, then it's magical 632 CASE potion (fallthrough) 633 CASE scroll (fallthrough) 634 CASE wand/staff (fallthrough) 635 CASE ring (fallthrough) 636 CASE amulet 637 All are magical 638 BLOCK END - SWITCH on object type 639 Anything else - return false...not magical 640 BLOCK END - is_magic 641 BLANK 642 COMMENT 643 COMMENT 644 COMMENT 645 COMMENT KILL MONSTER 646 Define killed with two arguments 647 Argument 1 is the monster to kill 648 Argument 2 is a flag if the player can see the monster when it dies 649 BLOCK START - killed, kills a monster 650 Add the monster's experience value to the player 651 COMMENT 652 COMMENT 653 COMMENT 654 SWITCH on monster type 655 BLOCK START - SWITCH on monster type for special deaths 656 CASE fungi monster 657 Remove player held flag 658 Restores monster attack type string 659 CASE Leprechaun monster 660 BLOCK START - Leprechaun death 661 Declare a pointer to a gold drop 662 BLANK 663 If we cannot allocate a new item... 664 Cancel drop -- BUG? The Leprecaun won't be properly deallocated 665 Set the new object type to gold 666 Set the gold drop value to a random number based on level 667 If we pass a save roll... 668 Add a lot more gold to the pile 669 Add the gold to the monster's pack (dropped later) 670 BLOCK END - Leprechaun death 671 BLOCK END - SWITCH on monster type for special deaths 672 COMMENT 673 COMMENT 674 COMMENT 675 Remove the monster from the map 676 If the player witnessed this death... 677 BLOCK START - monster death message 678 Print the preamble for death 679 If the player is blind... 680 Simple call the monster 'it' 681 Otherwise... 682 Call the monster by it's real name 683 BLOCK END - monster death message 684 COMMENT 685 COMMENT 686 COMMENT 687 Check if the player gained a level 688 BLOCK END - killed 689 EOF˙