Decoded: Rogue (1980) by Toy, Arnold, Wichman
DOS version (1983) by Mel Sibony and Jon Lane
Source file: STICKS.C
Beginner friendly, line-by-line code walkthrough by MaiZure

STICKS.C provides everything about wands and staves

Original code:
https://britzl.github.io/roguearchive/

Original code with line numbers
http://www.maizure.org/projects/decoded-rogue/STICKS_linenum.txt



1     COMMENT
2     COMMENT
3     COMMENT
4     COMMENT
5     COMMENT
6     COMMENT
7     BLANK
8     Include the game header
9     Inclue the console management header
10    BLANK
11    COMMENT
12    COMMENT
13    COMMENT
14    COMMENT

INITIALIZE A NEW WAND/STAFF

15    Defines fix_stick with one argument
16    Argument 1 is a pointer to a wand/staff
17    BLOCK START - fix_stick, initializes wand/staff
18    If the item is a staff...
19    Set the damage to 2d3
20    Otherwise it's a wand...
21    Set the damage to 1d1
22    In both cases, hurl damage is 1d1
23    BLANK
24    Add a random number of charges between 3 and 7
25    Switch on the type of magic
26    BLOCK START - Initialize wand/staff magic
27    CASE stick of striking
28    Add a huge hit chance bonus
29    Add some hit damage bonus
30    Change base damage to 1d8
31    CASE stick of light
32    Reroll charges between 10 and 19
33    BLOCK END - Initialize wand/staff magic
34    BLOCK END - fix_stick
35    BLANK
36    COMMENT
37    COMMENT
38    COMMENT
39    COMMENT

ZAP A WAND

40    Defines do_zap with no arguments
41    BLOCK START - do_zap, magic attack with wand
42    Declare a pointer to an object (the wand to zap)
43    Declare a pointer to the target (usually a monster)
44    Declare position interfers
45    Declare a pointer to a name string
46    Declare an interger for wand magic type
47    BLANK
48    Ask the player to choose a wand, but if they don't choose one...
49    Return failed
50    Get the wand's magic type
51    If the wand's type isn't a wand for some reason...
52    BLOCK START - Not a wand but item may be vorpal
53    But it has a hated enemy with charges...
54    Then it may be a vorpal weapon, set that case
55    Otherwise...
56    BLOCK START - Not zappable
57    Message the player about invalid zapping item
58    Don't pass time
59    Return fail
60    BLOCK END - Not zappable
61    BLOCK END - Not a wand but item may be vorpal
62    If the wand has no charges left...
63    BLOCK START - No charges
64    Send a fail message
65    Return failure
66    BLOCK END - No charges
67    Switch one wand's magic type...
68    BLOCK START - SWITCH on wand magic type
69    CASE magic light
70    COMMENT
71    COMMENT
72    COMMENT
73    If the player is blind
74    Print a message about warmth
75    Otherwise the player can see...
76    BLOCK START - Zap light magic
77    The player knows about light magic wands
78    If the player is in a passagway  
79    Print a passageway light up message
80    Otherwise the player is in a room
81    Print a room light up message
82    BLOCK END - Zap light magic
83    If the player is in a room...
84    BLOCK START - Light up dark room
85    Toggle the room darkness flag
86    COMMENT
87    COMMENT
88    COMMENT
89    Execute the full room entrance code
90    BLOCK END - Light up dark room
91    CASE drain magic
92    COMMENT
93    COMMENT
94    COMMENT
95    COMMENT
96    COMMENT
97    If the player only has 1 hitpoint left...
98    BLOCK START - Can't drain
99    Print failure message
100   Return fail
101   BLOCK END - Can't drain
102   Otherwise...
103   Perform drain magic
104   CASE polymorph magic (fallthrough)
105   CASE teleport away magic (fallthrough)
106   CASE controlled teleport magic (fallthrough)
107   CASE interrupt magic (fallthrough)
108   CASE special
109   BLOCK START - vorpal and teleport zap
110   Declare two bytes to characters
111   Declare a room number
112   Declare new coordiantes for teleporting
113   BLANK
114   Get the player's y position
115   Get the palyer's x position
116   While the path is clear...
117   BLOCK START seeking first blocked coordinate
118   Move y down
119   Move x right
120   BLOCK END - seeking first blocked coordinate
121   If there is a monster at the blocked coordinate...
122   BLOCK START - teleport monster
123   Declare another monster character
124   BLANK
125   Match all the monster characters to the current type
126   If the monster is a venus fly trap
127   Remove the held effect from the player
128   If the wand magic is vorpal or teleport
129   BLOCK START - special zap
130   If the monster is the hated enemy of the zapping item...
131   BLOCK START - teleport monster
132   Send teleport message
133   Change monster type
134   Kill the target monster
135   BLOCK END - teleport monster
136   Otherwise, no effect
137   Failed message
138   BLOCK END - special zap
139   If the magic type is polymorph
140   BLOCK START - monster polymorph
141   Declare pointer to a monster's inventory
142   BLANK
143   Get the old monster's inventory
144   Remove the monster
145   If the player can see the polymorphing monster...
146   Add the old floor character to the postion
147   Get the monster's buffered character
148   Set the delta y coordinate
149   Set the delta x coordinate
150   Create a new monster of a random type at the new coordinates
151   If the player can see the monster...  
152   Add the character to the position
153   Match the old monster's character
154   Math the old monsters inventory
155   The player now knows about polymorph magic
156   BLOCK END - monster polymorph
157   But if the wand is an interrupt attack
158   BLOCK START - monster interrupt
159   Set the monster's cancel flag
160   Remove the monster's inivisibilty and confusion capability
161   Remove monster's disguise
162   BLOCK END - monster interrupt
163   Otherwise if this is a teleport type zip
164   BLOCK START - player teleport zap
165   If player can see the monster
166   Draw the floor where the monster should be
167   If the staff is a teleport away staff
168   BLOCK START - teleport monster
169   Set the monster's old char to a default value
170   Loop while we select a new room
171   BLOCK START - random room select
172   Get a random room
173   Initialize new coordinates to the monsters current coordinates
174   Get a random position within the room
175   BLOCK END - random room select
176   Set the monster to the new position
177   If the player can see the monster
178   Add its character to the room at the new position
179   Otherwise, if player has the see monster effect active
180   BLOCK START - See monster effect
181   Enable output character emphasis
182   Add the monster at the new position
183   End extended formatting effects
184   BLOCK END - See monster effect
185   BLOCK END - teleport monster
186   Finally, the last possible spell to zap is player teleport to  
187   BLOCK START - monster teleport to player
188   Teleport monster y to calculate offset from earlier
189   Teleport monster x to calculate offset from earlier
190   BLOCK END - monster teleport to player
191   If the teleport monster is a flytrap..
192   Remove the player's held flag
193   If the the position changed...
194   Cache the old value
195   BLOCK END - player teleport zap
196   The monster should target the hero
197   And start chasing
198   BLOCK END - teleport monster
199   BLOCK END - vorpal and teleport zap
200   CASE magic missile
201   BLOCK START - zapping magic missile
202   Declare a missile
203   BLANK
204   Player now knows about magive missle
205   Set the bolt character to asterisk
206   Set hurl damage
207   Set hit chance bonus
208   Set damage bonus
209   Set flags for missile
210   If the player has a weapon...
211   Set the current weapon as the launcher
212   Move the missile
213   If the missile hits a monster and the monster doesn't save...
214   Execute the hit
215   Otherwise it's a miss
216   Print the miss message
217   BLOCK END - zapping magic missile
218   CASE striking
219   Offset y to the monster
220   Offset x to the monster 
221   If there is a monster at this location...
222   BLOCK START - Roll for striking bonus
223   There's a 5% chance that...
224   BLOCK START - large bonus
225   Add a larger base damage
226   And a larger bonus to damage
227   BLOCK END - large bonus
228   Otherwise we get the default bonus
229   BLOCK START - small bonus
230   Add a smaller base damage
231   Add a smaller damage bonus
232   BLOCK END - small bonus
233   Attack!
234   BLOCK START - Roll for striking bonus
235   CASE haste magic (fallthrough)
236   CASE slow magic
237   Get the player's y position
238   Get the player's x position
239   While the path is clear...
240   BLOCK START - Find a blocked coordinate
241   Advance y coordinate
242   Advance x coordinate
243   BLOCK END - Find a blocked coordinate
244   If we find a monster...
245   BLOCK START - Haste or slow monster
246   If the magic is haste
247   BLOCK START - Haste monster
248   If the monste is slow...
249   Bring it back to normal speed
250   Otherwise
251   Haste it
252   BLOCK END - Haste monster
253   Otherwise this is slow
254   BLOCK START - Slow monster
255   If the monster is hasted...
256   Remove haste
257   Otherwise, it's normal..
258   Slow it down
259   Monster will take it's next turn
260   BLOCK END - Slow monster
261   Update the y position difference
262   Update the x position difference
263   Activate the monster that was just hasted/slowed
264   BLOCK END - Haste or slow monster
265   CASE lightening bolt (fallthrough)
266   CASE fire bolt (fallthrough)
267   CASE frost bolt 
268   If this is a lightening zap...
269   Projectile name is 'bolt'
270   If this is a fire zap...
271   Projectile name is 'flame'
272   The only other option is...
273   Projectile name is 'ice'
274   In all cases, execute the bolt procedure with the name and player
275   Player knows about this wand magic
276   Check for debug mode
277   If we didn't recognize this zap...
278   Print a debug message
279   End check for debug mode
280   BLOCK END - SWITCH on wand magic type
281   Check if the number of charges went negative...
282   If so, then set it to zero
283   BLOCK START - do_zap
284   BLANK
285   COMMENT
286   COMMENT
287   COMMENT
288   COMMENT

DEAL HEALTH DAMAGE

289   Define drain with no arguments
290   BLOCK START - drain, deals health damage all around, including player
291   Declare a pointer to a monster
292   Declare a counter
293   Declare a pointer to a room
294   Declare a pointer to a target to drain
295   Declare a flag to denote player in passage status
296   Declare an array of pointers for monsters to drain
297   BLANK
298   COMMENT
299   COMMENT
300   COMMENT
301   Initialize counter to zero
302   IF the hero is standing in a doorway
303   Get the passage that the hero is in
304   Otherwise
305   We don't need the direct passage pointer
306   Check if player is in a passage
307   Point to drain target to the drain buffer (currently empty)
308   Loop through all the monsters
309   If the monster is in the room with the player...  
310   Or in the passage / passage doorway with the player
311   Or player is in a doorway with a monster nearby...
312   Add this monster to the drain array and increment
313   If there are no monsters to drain...
314   BLOCK START - Failed drain
315   Send failure message
316   Return - nothing happens
317   BLOCK END - Failed drain
318   Clear the drain pointer
319   Half the player's hitpointers
320   Allocate player's remaining health among the number of monsters
321   COMMENT
322   COMMENT
323   COMMENT
324   Loop through all drain targets
325   BLOCK START - drain loop
326   Point to the target
327   Remove allocated damage and if monster's health is gone...
328   Kill the monster
329   Otherwise, they survived...
330   So set them off to chase the player
331   BLOCK END - drain loop
332   BLOCK START - drain
333   BLANK
334   COMMENT
335   COMMENT
336   COMMENT
337   COMMENT

FIRE BOLT ATTACK

338   Define fire_bolt with three arguments
339   Arguments 1 and 2 are coordinates for start position and motion vector
340   Argument three is the name of the bolt
341   BLOCK START - fire_bolt, ranged fire attack
342   Declare a character for bolt appearance and floor space
343   Declare a pointer to a target
344   Declare flags for bolt state
345   Declare iterators
346   Declare a position
347   Declare a struct to buffer a stream of bolt positions
348   One struct element is a position
349   Another element is the floor character
350   This struct is called spotpos and has two elements per floor space used
351   Declare a pointer to a bolt
352   Declare a flag for ice attack
353   BLANK
354   Set flag if this is a frost bolt using the name
355   Bolts are weapons
356   Bolts are flames
357   Bolt damage, including thrown damage, is 6d6
358   Hit bonus is 30 points
359   No damage bonus
360   Set the name of the zap
361   Switch on the sum of the direction offsets
362   CASE 0, bolt is going UR or DL, set character accordingly
363   CASE -1 or 1, it must be horizonal or vertical
364   CASE 2 or -2, it must be UL or DR
365   End check for bolt direction and setting graphic
366   Position is at the start
367   The bolt can't hit the player on its starting move...but later...
368   Set flag for saving check to false
369   Set update flag to false
370   Loop through the total length of the bolt (calculate each position)
371   The y position advances in its y direction
372   The x position advances in its x direction
373   Get the character under the position
374   Set the position of this bolt fragment
375   Store the floor character unless it is equal to another bolt...
376   Then store nothing (some other part of the bolt is storing it)
377   BLOCK START - Switch on floor type under bolt
378   CASE door (fallthrough)
379   CASE horizontal wall (fallthrough)
380   CASE vertical wall (fallthrough)
381   CASE corner wall (fallthrough)
382   CASE corner wall (fallthrough)
383   CASE corner wall (fallthrough)
384   CASE corner wall (fallthrough)
385   CASE empty space:
386   If the bolt hasn't moved...ricochet!
387   Then toggle ability to hit the player
388   The bolt hasn't changed position
389   Reverse y direction
390   Reverse x direction
391   Redo this calculation
392   Print message that the bolt bounced off a wall
393   End this update
394   CASE any other hit case
395   If the bolt can't hit the hero but there's a monster here...  
396   The bolt is free to hit the player
397   Toggle the changed value
398   If the bolt character cache isn't using the default value...
399   Save the floor character under the bolt
400   If a saving check failed or the bolt is made of frost...
401   Cache the bolt's current position
402   Something attempted to save against this bolt
403   If the bolt hit a dragon and the bolt is fire
404   Print a message that the flame is useless against dragons
405   Otherwise this is a normal monster hit
406   Calculate the hit and damage
407   If the character under the bolt isn't another bolt (floor, etc)...
408   Save the floor character at this position
409   End check for monster hit
410   Otherwise, the bolt missed the monster so if the player sees that...
411   If the bolt came from the player...
412   Set off the monster to chase the player
413   Print a message about the miss...
414   Including the monster's name
415   End check for player witnessing a missed shot
416   The final hit case is if the bolt hits the player...
417   Set the player hit check to false
418   Toggle the change flag
419   If the save fails...
420   And the bolt is frost...
421   Print a message that the player is now frozen
422   If the player hasn't already lost more than 20 turns...
423   Player now loses up the 6 turns
424   For all other bolt types that hit the player...if the player dies...
425   If the bolt came from the player himself...
426   Set the death condition as the bolt
427   Otherwise the bolt came from a monster
428   Set the death conditions as the monster
429   Player is still alive and the bolt has been used
430   If this isn't a frost bolt...
431   Print that the player has been hit (frost bolts already had a msg)
432   End check for player hit, this bolt must have missed
433   Print a bolt missing message
434   End check for hitting/missing the player
435   If this is a frost bolt
436   Change print color to blue
437   Otherwise...
438   All other bolts are red
439   Pause time passing
440   Add the bolt character to its position
441   End extended format printing
442   BLOCK END - Switch on floor type under bolt
443   Retry loop through all bolt positions
444   Loop through all the bolt positions  
445   Pause time
446   If the bolt has a floor space under it...
447   Reapply the old floor space
448   Redo loop through all bolt positions
449   BLOCK START - fire_bolt
450   BLANK
451   COMMENT
452   COMMENT
453   COMMENT
454   COMMENT

GET WAND CHARGE COUNT

455   charge_str returns a string
456   Defines charge_str with one argument
457   Agument 1 is a pointer to a wand
458   BLOCK START - charge_str, returns the text of magic charges remaining
459   Declare a text buffer
460   BLANK
461   If the player doesn't know the item...
462   Then the player knows nothing about it....blank buffer
463   Otherwise...
464   Print the number of wand charges to the buffer
465   Return buffer
466   BLOCK END - charge_str
467   EOF