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