1 /*
2  *  File:       player.cc
3  *  Summary:    Player related functions.
4  *  Written by: Linley Henzell
5  *
6  *  Change History (most recent first):
7  *
8  * <6> 7/30/99 BWR   Added player_spell_levels()
9  * <5> 7/13/99 BWR   Added player_res_electricity()
10  *                   and player_hunger_rate()
11  * <4> 6/22/99 BWR   Racial adjustments to stealth and Armour.
12  * <3> 5/20/99 BWR   Fixed problems with random stat increases, added kobold
13  *                   stat increase.  increased EV recovery for Armour.
14  * <2> 5/08/99 LRH   display_char_status correctly handles magic_contamination.
15  * <1> -/--/-- LRH   Created
16  */
17 
18 #include "AppHdr.h"
19 #include "player.h"
20 
21 #ifdef DOS
22 #include <conio.h>
23 #endif
24 
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <math.h>
29 #include <ctype.h>
30 
31 #include "externs.h"
32 
33 #include "itemname.h"
34 #include "macro.h"
35 #include "misc.h"
36 #include "mon-util.h"
37 #include "mutation.h"
38 #include "output.h"
39 #include "randart.h"
40 #include "religion.h"
41 #include "skills2.h"
42 #include "spl-util.h"
43 #include "spells4.h"
44 #include "stuff.h"
45 #include "view.h"
46 #include "wpn-misc.h"
47 
48 
49 /*
50    you.duration []: //jmf: obsolete, see enum.h instead
51    0 - liquid flames
52    1 - icy armour
53    2 - repel missiles
54    3 - prayer
55    4 - regeneration
56    5 - vorpal blade
57    6 - fire brand
58    7 - ice brand
59    8 - lethal infusion
60    9 - swiftness
61    10 - insulation
62    11 - stonemail
63    12 - controlled flight
64    13 - teleport
65    14 - control teleport
66    15 - poison weapon
67    16 - resist poison
68    17 - breathe something
69    18 - transformation (duration)
70    19 - death channel
71    20 - deflect missiles
72  */
73 
74 /* attributes
75    0 - resist lightning
76    1 - spec_air
77    2 - spec_earth
78    3 - control teleport
79    4 - walk slowly (eg naga)
80    5 - transformation (form)
81    6 - Nemelex card gift countdown
82    7 - Nemelex has given you a card table
83    8 - How many demonic powers a dspawn has
84  */
85 
86 /* armour list
87    0 - wielded
88    1 - cloak
89    2 - helmet
90    3 - gloves
91    4 - boots
92    5 - shield
93    6 - body armour
94    7 - ring 0
95    8 - ring 1
96    9 - amulet
97  */
98 
99 /* Contains functions which return various player state vars,
100    and other stuff related to the player. */
101 
102 int species_exp_mod(char species);
103 void ability_increase(void);
104 
105 //void priest_spells(int priest_pass[10], char religious);    // see actual function for reasoning here {dlb}
player_in_branch(int branch)106 bool player_in_branch( int branch )
107 {
108     return (you.level_type == LEVEL_DUNGEON && you.where_are_you == branch);
109 }
110 
player_in_hell(void)111 bool player_in_hell( void )
112 {
113     return (you.level_type == LEVEL_DUNGEON
114             && (you.where_are_you >= BRANCH_DIS
115                 && you.where_are_you <= BRANCH_THE_PIT)
116             && you.where_are_you != BRANCH_VESTIBULE_OF_HELL);
117 }
118 
player_in_water(void)119 bool player_in_water(void)
120 {
121     return (!player_is_levitating()
122             && (grd[you.x_pos][you.y_pos] == DNGN_DEEP_WATER
123                 || grd[you.x_pos][you.y_pos] == DNGN_SHALLOW_WATER));
124 }
125 
player_is_swimming(void)126 bool player_is_swimming(void)
127 {
128     return (player_in_water() && you.species == SP_MERFOLK);
129 }
130 
player_under_penance(void)131 bool player_under_penance(void)
132 {
133     if (you.religion != GOD_NO_GOD)
134         return (you.penance[you.religion]);
135     else
136         return (false);
137 }
138 
player_genus(unsigned char which_genus,unsigned char species)139 bool player_genus(unsigned char which_genus, unsigned char species)
140 {
141     if (species == SP_UNKNOWN)
142         species = you.species;
143 
144     switch (species)
145     {
146     case SP_RED_DRACONIAN:
147     case SP_WHITE_DRACONIAN:
148     case SP_GREEN_DRACONIAN:
149     case SP_GOLDEN_DRACONIAN:
150     case SP_GREY_DRACONIAN:
151     case SP_BLACK_DRACONIAN:
152     case SP_PURPLE_DRACONIAN:
153     case SP_MOTTLED_DRACONIAN:
154     case SP_PALE_DRACONIAN:
155     case SP_UNK0_DRACONIAN:
156     case SP_UNK1_DRACONIAN:
157     case SP_UNK2_DRACONIAN:
158         return (which_genus == GENPC_DRACONIAN);
159 
160     case SP_ELF:
161     case SP_HIGH_ELF:
162     case SP_GREY_ELF:
163     case SP_DEEP_ELF:
164     case SP_SLUDGE_ELF:
165         return (which_genus == GENPC_ELVEN);
166 
167     case SP_HILL_DWARF:
168     case SP_MOUNTAIN_DWARF:
169         return (which_genus == GENPC_DWARVEN);
170 
171     default:
172         break;
173     }
174 
175     return (false);
176 }                               // end player_genus()
177 
178 // Looks in equipment "slot" to see if there is an equiped "sub_type".
179 // Returns number of matches (in the case of rings, both are checked)
player_equip(int slot,int sub_type)180 int player_equip( int slot, int sub_type )
181 {
182     int ret = 0;
183 
184     switch (slot)
185     {
186     case EQ_WEAPON:
187         // Hands can have more than just weapons.
188         if (you.equip[EQ_WEAPON] != -1
189             && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
190             && you.inv[you.equip[EQ_WEAPON]].sub_type == sub_type)
191         {
192             ret++;
193         }
194         break;
195 
196     case EQ_STAFF:
197         // Like above, but must be magical stave.
198         if (you.equip[EQ_WEAPON] != -1
199             && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_STAVES
200             && you.inv[you.equip[EQ_WEAPON]].sub_type == sub_type)
201         {
202             ret++;
203         }
204         break;
205 
206     case EQ_RINGS:
207         if (you.equip[EQ_LEFT_RING] != -1
208             && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type)
209         {
210             ret++;
211         }
212 
213         if (you.equip[EQ_RIGHT_RING] != -1
214             && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type)
215         {
216             ret++;
217         }
218         break;
219 
220     case EQ_RINGS_PLUS:
221         if (you.equip[EQ_LEFT_RING] != -1
222             && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type)
223         {
224             ret += you.inv[you.equip[EQ_LEFT_RING]].plus;
225         }
226 
227         if (you.equip[EQ_RIGHT_RING] != -1
228             && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type)
229         {
230             ret += you.inv[you.equip[EQ_RIGHT_RING]].plus;
231         }
232         break;
233 
234     case EQ_RINGS_PLUS2:
235         if (you.equip[EQ_LEFT_RING] != -1
236             && you.inv[you.equip[EQ_LEFT_RING]].sub_type == sub_type)
237         {
238             ret += you.inv[you.equip[EQ_LEFT_RING]].plus2;
239         }
240 
241         if (you.equip[EQ_RIGHT_RING] != -1
242             && you.inv[you.equip[EQ_RIGHT_RING]].sub_type == sub_type)
243         {
244             ret += you.inv[you.equip[EQ_RIGHT_RING]].plus2;
245         }
246         break;
247 
248     case EQ_ALL_ARMOUR:
249         // doesn't make much sense here... be specific. -- bwr
250         break;
251 
252     default:
253         if (you.equip[slot] != -1
254             && you.inv[you.equip[slot]].sub_type == sub_type)
255         {
256             ret++;
257         }
258         break;
259     }
260 
261     return (ret);
262 }
263 
264 
265 // Looks in equipment "slot" to see if equiped item has "special" ego-type
266 // Returns number of matches (jewellery returns zero -- no ego type).
player_equip_ego_type(int slot,int special)267 int player_equip_ego_type( int slot, int special )
268 {
269     int ret = 0;
270     int wpn;
271 
272     switch (slot)
273     {
274     case EQ_WEAPON:
275         // This actually checks against the "branding", so it will catch
276         // randart brands, but not fixed artefacts.  -- bwr
277 
278         // Hands can have more than just weapons.
279         wpn = you.equip[EQ_WEAPON];
280         if (wpn != -1
281             && you.inv[wpn].base_type == OBJ_WEAPONS
282             && get_weapon_brand( you.inv[wpn] ) == special)
283         {
284             ret++;
285         }
286         break;
287 
288     case EQ_LEFT_RING:
289     case EQ_RIGHT_RING:
290     case EQ_AMULET:
291     case EQ_STAFF:
292     case EQ_RINGS:
293     case EQ_RINGS_PLUS:
294     case EQ_RINGS_PLUS2:
295         // no ego types for these slots
296         break;
297 
298     case EQ_ALL_ARMOUR:
299         // Check all armour slots:
300         for (int i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++)
301         {
302             if (you.equip[i] != -1
303                 && get_armour_ego_type( you.inv[you.equip[i]] ) == special)
304             {
305                 ret++;
306             }
307         }
308         break;
309 
310     default:
311         // Check a specific armour slot for an ego type:
312         if (you.equip[slot] != -1
313             && get_armour_ego_type( you.inv[you.equip[slot]] ) == special)
314         {
315             ret++;
316         }
317         break;
318     }
319 
320     return (ret);
321 }
322 
player_damage_type(void)323 int player_damage_type( void )
324 {
325     const int wpn = you.equip[ EQ_WEAPON ];
326 
327     if (wpn != -1)
328     {
329         return (damage_type( you.inv[wpn].base_type, you.inv[wpn].sub_type ));
330     }
331     else if (you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
332             || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON
333             || you.mutation[MUT_CLAWS]
334             || you.species == SP_TROLL
335             || you.species == SP_GHOUL)
336     {
337         return (DVORP_SLICING);
338     }
339 
340     return (DVORP_CRUSHING);
341 }
342 
343 // returns band of player's melee damage
player_damage_brand(void)344 int player_damage_brand( void )
345 {
346     int ret = SPWPN_NORMAL;
347     const int wpn = you.equip[ EQ_WEAPON ];
348 
349     if (wpn != -1)
350         ret = get_weapon_brand( you.inv[wpn] );
351     else if (you.confusing_touch)
352         ret = SPWPN_CONFUSE;
353     else if (you.mutation[MUT_DRAIN_LIFE])
354         ret = SPWPN_DRAINING;
355     else
356     {
357         switch (you.attribute[ATTR_TRANSFORMATION])
358         {
359         case TRAN_SPIDER:
360             ret = SPWPN_VENOM;
361             break;
362 
363         case TRAN_ICE_BEAST:
364             ret = SPWPN_FREEZING;
365             break;
366 
367         case TRAN_LICH:
368             ret = SPWPN_DRAINING;
369             break;
370 
371         default:
372             break;
373         }
374     }
375 
376     return (ret);
377 }
378 
player_teleport(void)379 int player_teleport(void)
380 {
381     int tp = 0;
382 
383     /* rings */
384     tp += 8 * player_equip( EQ_RINGS, RING_TELEPORTATION );
385 
386     /* mutations */
387     tp += you.mutation[MUT_TELEPORT] * 3;
388 
389     /* randart weapons only */
390     if (you.equip[EQ_WEAPON] != -1
391         && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
392         && is_random_artefact( you.inv[you.equip[EQ_WEAPON]] ))
393     {
394         tp += scan_randarts(RAP_CAUSE_TELEPORTATION);
395     }
396 
397     return tp;
398 }                               // end player_teleport()
399 
player_regen(void)400 int player_regen(void)
401 {
402     int rr = you.hp_max / 3;
403 
404     if (rr > 20)
405         rr = 20 + ((rr - 20) / 2);
406 
407     /* rings */
408     rr += 40 * player_equip( EQ_RINGS, RING_REGENERATION );
409 
410     /* spell */
411     if (you.duration[DUR_REGENERATION])
412         rr += 100;
413 
414     /* troll or troll leather -- trolls can't get both */
415     if (you.species == SP_TROLL)
416         rr += 40;
417     else if (player_equip( EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR ))
418         rr += 30;
419 
420     /* fast heal mutation */
421     rr += you.mutation[MUT_REGENERATION] * 20;
422 
423     /* ghouls heal slowly */
424     // dematerialized people heal slowly
425     // dematerialized ghouls shouldn't heal any more slowly -- bwr
426     if ((you.species == SP_GHOUL
427             && (you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE
428                 || you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS))
429         || you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR)
430     {
431         rr /= 2;
432     }
433 
434     if (rr < 1)
435         rr = 1;
436 
437     return (rr);
438 }
439 
player_hunger_rate(void)440 int player_hunger_rate(void)
441 {
442     int hunger = 3;
443 
444     // jmf: hunger isn't fair while you can't eat
445     // Actually, it is since you can detransform any time you like -- bwr
446     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR)
447         return 0;
448 
449     switch (you.species)
450     {
451     case SP_HALFLING:
452     case SP_SPRIGGAN:
453         hunger--;
454         break;
455 
456     case SP_OGRE:
457     case SP_OGRE_MAGE:
458     case SP_DEMIGOD:
459         hunger++;
460         break;
461 
462     case SP_CENTAUR:
463         hunger += 2;
464         break;
465 
466     case SP_TROLL:
467         hunger += 6;
468         break;
469     }
470 
471     if (you.duration[DUR_REGENERATION] > 0)
472         hunger += 4;
473 
474     // moved here from acr.cc... maintaining the >= 40 behaviour
475     if (you.hunger >= 40)
476     {
477         if (you.invis > 0)
478             hunger += 5;
479 
480         // berserk has its own food penalty -- excluding berserk haste
481         if (you.haste > 0 && !you.berserker)
482             hunger += 5;
483     }
484 
485     hunger += you.mutation[MUT_FAST_METABOLISM];
486 
487     if (you.mutation[MUT_SLOW_METABOLISM] > 2)
488         hunger -= 2;
489     else if (you.mutation[MUT_SLOW_METABOLISM] > 0)
490         hunger--;
491 
492     // rings
493     hunger += 2 * player_equip( EQ_RINGS, RING_REGENERATION );
494     hunger += 4 * player_equip( EQ_RINGS, RING_HUNGER );
495     hunger -= 2 * player_equip( EQ_RINGS, RING_SUSTENANCE );
496 
497     // weapon ego types
498     hunger += 6 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRICISM );
499     hunger += 9 * player_equip_ego_type( EQ_WEAPON, SPWPN_VAMPIRES_TOOTH );
500 
501     // troll leather armour
502     hunger += player_equip( EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR );
503 
504     // randarts
505     hunger += scan_randarts(RAP_METABOLISM);
506 
507     // burden
508     hunger += you.burden_state;
509 
510     if (hunger < 1)
511         hunger = 1;
512 
513     return (hunger);
514 }
515 
player_spell_levels(void)516 int player_spell_levels(void)
517 {
518     int sl = (you.experience_level - 1) + (you.skills[SK_SPELLCASTING] * 2);
519 
520     bool fireball = false;
521     bool delayed_fireball = false;
522 
523     if (sl > 99)
524         sl = 99;
525 
526     for (int i = 0; i < 25; i++)
527     {
528         if (you.spells[i] == SPELL_FIREBALL)
529             fireball = true;
530         else if (you.spells[i] == SPELL_DELAYED_FIREBALL)
531             delayed_fireball = true;
532 
533         if (you.spells[i] != SPELL_NO_SPELL)
534             sl -= spell_difficulty(you.spells[i]);
535     }
536 
537     // Fireball is free for characters with delayed fireball
538     if (fireball && delayed_fireball)
539         sl += spell_difficulty( SPELL_FIREBALL );
540 
541     // Note: This can happen because of level drain.  Maybe we should
542     // force random spells out when that happens. -- bwr
543     if (sl < 0)
544         sl = 0;
545 
546     return (sl);
547 }
548 
player_res_magic(void)549 int player_res_magic(void)
550 {
551     int rm = 0;
552 
553     switch (you.species)
554     {
555     default:
556         rm = you.experience_level * 3;
557         break;
558     case SP_HIGH_ELF:
559     case SP_GREY_ELF:
560     case SP_ELF:
561     case SP_SLUDGE_ELF:
562     case SP_HILL_DWARF:
563     case SP_MOUNTAIN_DWARF:
564         rm = you.experience_level * 4;
565         break;
566     case SP_NAGA:
567         rm = you.experience_level * 5;
568         break;
569     case SP_PURPLE_DRACONIAN:
570     case SP_GNOME:
571     case SP_DEEP_ELF:
572         rm = you.experience_level * 6;
573         break;
574     case SP_SPRIGGAN:
575         rm = you.experience_level * 7;
576         break;
577     }
578 
579     /* armour  */
580     rm += 30 * player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_MAGIC_RESISTANCE );
581 
582     /* rings of magic resistance */
583     rm += 40 * player_equip( EQ_RINGS, RING_PROTECTION_FROM_MAGIC );
584 
585     /* randarts */
586     rm += scan_randarts(RAP_MAGIC);
587 
588     /* Enchantment skill */
589     rm += 2 * you.skills[SK_ENCHANTMENTS];
590 
591     /* Mutations */
592     rm += 30 * you.mutation[MUT_MAGIC_RESISTANCE];
593 
594     /* transformations */
595     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH)
596         rm += 50;
597 
598     return rm;
599 }
600 
player_res_fire(void)601 int player_res_fire(void)
602 {
603     int rf = 0;
604 
605     /* rings of fire resistance/fire */
606     rf += player_equip( EQ_RINGS, RING_PROTECTION_FROM_FIRE );
607     rf += player_equip( EQ_RINGS, RING_FIRE );
608 
609     /* rings of ice */
610     rf -= player_equip( EQ_RINGS, RING_ICE );
611 
612     /* Staves */
613     rf += player_equip( EQ_STAFF, STAFF_FIRE );
614 
615     // body armour:
616     rf += 2 * player_equip( EQ_BODY_ARMOUR, ARM_DRAGON_ARMOUR );
617     rf += player_equip( EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR );
618     rf -= player_equip( EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR );
619 
620     // ego armours
621     rf += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_FIRE_RESISTANCE );
622     rf += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_RESISTANCE );
623 
624     // randart weapons:
625     rf += scan_randarts(RAP_FIRE);
626 
627     // species:
628     if (you.species == SP_MUMMY)
629         rf--;
630     else if (you.species == SP_RED_DRACONIAN && you.experience_level > 17)
631         rf++;
632 
633     // mutations:
634     rf += you.mutation[MUT_HEAT_RESISTANCE];
635 
636     if (you.fire_shield)
637         rf += 2;
638 
639     // transformations:
640     switch (you.attribute[ATTR_TRANSFORMATION])
641     {
642     case TRAN_ICE_BEAST:
643         rf--;
644         break;
645     case TRAN_DRAGON:
646         rf += 2;
647         break;
648     case TRAN_SERPENT_OF_HELL:
649         rf += 2;
650         break;
651     case TRAN_AIR:
652         rf -= 2;
653         break;
654     }
655 
656     if (rf < -3)
657         rf = -3;
658     else if (rf > 3)
659         rf = 3;
660 
661     return (rf);
662 }
663 
player_res_cold(void)664 int player_res_cold(void)
665 {
666     int rc = 0;
667 
668     /* rings of fire resistance/fire */
669     rc += player_equip( EQ_RINGS, RING_PROTECTION_FROM_COLD );
670     rc += player_equip( EQ_RINGS, RING_ICE );
671 
672     /* rings of ice */
673     rc -= player_equip( EQ_RINGS, RING_FIRE );
674 
675     /* Staves */
676     rc += player_equip( EQ_STAFF, STAFF_COLD );
677 
678     // body armour:
679     rc += 2 * player_equip( EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR );
680     rc += player_equip( EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR );
681     rc -= player_equip( EQ_BODY_ARMOUR, ARM_DRAGON_ARMOUR );
682 
683     // ego armours
684     rc += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_COLD_RESISTANCE );
685     rc += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_RESISTANCE );
686 
687     // randart weapons:
688     rc += scan_randarts(RAP_COLD);
689 
690     // species:
691     if (you.species == SP_MUMMY || you.species == SP_GHOUL)
692         rc++;
693     else if (you.species == SP_WHITE_DRACONIAN && you.experience_level > 17)
694         rc++;
695 
696     // mutations:
697     rc += you.mutation[MUT_COLD_RESISTANCE];
698 
699     if (you.fire_shield)
700         rc -= 2;
701 
702     // transformations:
703     switch (you.attribute[ATTR_TRANSFORMATION])
704     {
705     case TRAN_ICE_BEAST:
706         rc += 3;
707         break;
708     case TRAN_DRAGON:
709         rc--;
710         break;
711     case TRAN_LICH:
712         rc++;
713         break;
714     case TRAN_AIR:
715         rc -= 2;
716         break;
717     }
718 
719     if (rc < -3)
720         rc = -3;
721     else if (rc > 3)
722         rc = 3;
723 
724     return (rc);
725 }
726 
player_res_electricity(void)727 int player_res_electricity(void)
728 {
729     int re = 0;
730 
731     if (you.duration[DUR_INSULATION])
732         re++;
733 
734     // staff
735     re += player_equip( EQ_STAFF, STAFF_AIR );
736 
737     // body armour:
738     re += player_equip( EQ_BODY_ARMOUR, ARM_STORM_DRAGON_ARMOUR );
739 
740     // randart weapons:
741     re += scan_randarts(RAP_ELECTRICITY);
742 
743     // species:
744     if (you.species == SP_BLACK_DRACONIAN && you.experience_level > 17)
745         re++;
746 
747     // mutations:
748     if (you.mutation[MUT_SHOCK_RESISTANCE])
749         re++;
750 
751     // transformations:
752     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_STATUE)
753         re += 1;
754 
755     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR)
756         re += 2;  // mutliple levels currently meaningless
757 
758     if (you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION] > 0)
759         re = 3;
760     else if (re > 1)
761         re = 1;
762 
763     return (re);
764 }                               // end player_res_electricity()
765 
766 // funny that no races are susceptible to poisons {dlb}
player_res_poison(void)767 int player_res_poison(void)
768 {
769     int rp = 0;
770 
771     /* rings of poison resistance */
772     rp += player_equip( EQ_RINGS, RING_POISON_RESISTANCE );
773 
774     /* Staves */
775     rp += player_equip( EQ_STAFF, STAFF_POISON );
776 
777     /* the staff of Olgreb: */
778     if (you.equip[EQ_WEAPON] != -1
779         && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
780         && you.inv[you.equip[EQ_WEAPON]].special == SPWPN_STAFF_OF_OLGREB)
781     {
782         rp++;
783     }
784 
785     // ego armour:
786     rp += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE );
787 
788     // body armour:
789     rp += player_equip( EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR );
790     rp += player_equip( EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_ARMOUR );
791 
792     // spells:
793     if (you.duration[DUR_RESIST_POISON] > 0)
794         rp++;
795 
796     // randart weapons:
797     rp += scan_randarts(RAP_POISON);
798 
799     // species:
800     if (you.species == SP_MUMMY || you.species == SP_NAGA
801         || you.species == SP_GHOUL
802         || (you.species == SP_GREEN_DRACONIAN && you.experience_level > 6))
803     {
804         rp++;
805     }
806 
807     // mutations:
808     rp += you.mutation[MUT_POISON_RESISTANCE];
809 
810     // transformations:
811     switch (you.attribute[ATTR_TRANSFORMATION])
812     {
813     case TRAN_LICH:
814     case TRAN_ICE_BEAST:
815     case TRAN_STATUE:
816     case TRAN_DRAGON:
817     case TRAN_SERPENT_OF_HELL:
818     case TRAN_AIR:
819         rp++;
820         break;
821     }
822 
823     if (rp > 3)
824         rp = 3;
825 
826     return (rp);
827 }                               // end player_res_poison()
828 
player_spec_death(void)829 unsigned char player_spec_death(void)
830 {
831     int sd = 0;
832 
833     /* Staves */
834     sd += player_equip( EQ_STAFF, STAFF_DEATH );
835 
836     // body armour:
837     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI ))
838         sd++;
839 
840     // species:
841     if (you.species == SP_MUMMY)
842     {
843         if (you.experience_level >= 13)
844             sd++;
845         if (you.experience_level >= 26)
846             sd++;
847     }
848 
849     // transformations:
850     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH)
851         sd++;
852 
853     return sd;
854 }
855 
player_spec_holy(void)856 unsigned char player_spec_holy(void)
857 {
858     //if ( you.char_class == JOB_PRIEST || you.char_class == JOB_PALADIN )
859     //  return 1;
860     return 0;
861 }
862 
player_spec_fire(void)863 unsigned char player_spec_fire(void)
864 {
865     int sf = 0;
866 
867     // staves:
868     sf += player_equip( EQ_STAFF, STAFF_FIRE );
869 
870     // rings of fire:
871     sf += player_equip( EQ_RINGS, RING_FIRE );
872 
873     if (you.fire_shield)
874         sf++;
875 
876     return sf;
877 }
878 
player_spec_cold(void)879 unsigned char player_spec_cold(void)
880 {
881     int sc = 0;
882 
883     // staves:
884     sc += player_equip( EQ_STAFF, STAFF_COLD );
885 
886     // rings of ice:
887     sc += player_equip( EQ_RINGS, RING_ICE );
888 
889     return sc;
890 }
891 
player_spec_earth(void)892 unsigned char player_spec_earth(void)
893 {
894     int se = 0;
895 
896     /* Staves */
897     se += player_equip( EQ_STAFF, STAFF_EARTH );
898 
899     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR)
900         se--;
901 
902     return se;
903 }
904 
player_spec_air(void)905 unsigned char player_spec_air(void)
906 {
907     int sa = 0;
908 
909     /* Staves */
910     sa += player_equip( EQ_STAFF, STAFF_AIR );
911 
912     //jmf: this was too good
913     //if (you.attribute[ATTR_TRANSFORMATION] == TRAN_AIR)
914     //  sa++;
915     return sa;
916 }
917 
player_spec_conj(void)918 unsigned char player_spec_conj(void)
919 {
920     int sc = 0;
921 
922     /* Staves */
923     sc += player_equip( EQ_STAFF, STAFF_CONJURATION );
924 
925     // armour of the Archmagi
926     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI ))
927         sc++;
928 
929     return sc;
930 }
931 
player_spec_ench(void)932 unsigned char player_spec_ench(void)
933 {
934     int se = 0;
935 
936     /* Staves */
937     se += player_equip( EQ_STAFF, STAFF_ENCHANTMENT );
938 
939     // armour of the Archmagi
940     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI ))
941         se++;
942 
943     return se;
944 }
945 
player_spec_summ(void)946 unsigned char player_spec_summ(void)
947 {
948     int ss = 0;
949 
950     /* Staves */
951     ss += player_equip( EQ_STAFF, STAFF_SUMMONING );
952 
953     // armour of the Archmagi
954     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI ))
955         ss++;
956 
957     return ss;
958 }
959 
player_spec_poison(void)960 unsigned char player_spec_poison(void)
961 {
962     int sp = 0;
963 
964     /* Staves */
965     sp += player_equip( EQ_STAFF, STAFF_POISON );
966 
967     if (you.equip[EQ_WEAPON] != -1
968         && you.inv[you.equip[EQ_WEAPON]].base_type == OBJ_WEAPONS
969         && you.inv[you.equip[EQ_WEAPON]].special == SPWPN_STAFF_OF_OLGREB)
970     {
971         sp++;
972     }
973 
974     return sp;
975 }
976 
player_energy(void)977 unsigned char player_energy(void)
978 {
979     unsigned char pe = 0;
980 
981     // Staves
982     pe += player_equip( EQ_STAFF, STAFF_ENERGY );
983 
984     return pe;
985 }
986 
player_prot_life(void)987 int player_prot_life(void)
988 {
989     int pl = 0;
990 
991     // rings
992     pl += player_equip( EQ_RINGS, RING_LIFE_PROTECTION );
993 
994     // armour: (checks body armour only)
995     pl += player_equip_ego_type( EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY );
996 
997     if (you.is_undead)
998         pl += 3;
999 
1000     switch (you.attribute[ATTR_TRANSFORMATION])
1001     {
1002     case TRAN_STATUE:
1003         pl += 1;
1004         break;
1005 
1006     case TRAN_SERPENT_OF_HELL:
1007         pl += 2;
1008         break;
1009 
1010     case TRAN_LICH:
1011         pl += 3;
1012         break;
1013 
1014     default:
1015         break;
1016     }
1017 
1018     // randart wpns
1019     pl += scan_randarts(RAP_NEGATIVE_ENERGY);
1020 
1021     // demonic power
1022     pl += you.mutation[MUT_NEGATIVE_ENERGY_RESISTANCE];
1023 
1024     if (pl > 3)
1025         pl = 3;
1026 
1027     return (pl);
1028 }
1029 
1030 // New player movement speed system... allows for a bit more that
1031 // "player runs fast" and "player walks slow" in that the speed is
1032 // actually calculated (allowing for centaurs to get a bonus from
1033 // swiftness and other such things).  Levels of the mutation now
1034 // also have meaning (before they all just meant fast).  Most of
1035 // this isn't as fast as it used to be (6 for having anything), but
1036 // even a slight speed advantage is very good... and we certainly don't
1037 // want to go past 6 (see below). -- bwr
player_movement_speed(void)1038 int player_movement_speed(void)
1039 {
1040     int mv = 10;
1041 
1042     if (you.species == SP_MERFOLK && player_is_swimming())
1043     {
1044         // This is swimming... so it doesn't make sense to really
1045         // apply the other things (the mutation is "cover ground",
1046         // swiftness is an air spell, can't wear boots, can't be
1047         // transformed).
1048         mv = 6;
1049     }
1050     else
1051     {
1052         /* transformations */
1053         if (!player_is_shapechanged())
1054         {
1055             // Centaurs and spriggans are only fast in their regular
1056             // shape (ie untransformed, blade hands, lich form)
1057             if (you.species == SP_CENTAUR)
1058                 mv = 8;
1059             else if (you.species == SP_SPRIGGAN)
1060                 mv = 6;
1061         }
1062         else if (you.attribute[ATTR_TRANSFORMATION] == TRAN_SPIDER)
1063             mv = 8;
1064 
1065         /* armour */
1066         if (player_equip_ego_type( EQ_BOOTS, SPARM_RUNNING ))
1067             mv -= 2;
1068 
1069         if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_PONDEROUSNESS ))
1070             mv += 2;
1071 
1072         // Swiftness is an Air spell, it doesn't work in water...
1073         // but levitating players will move faster. -- bwr
1074         if (you.duration[DUR_SWIFTNESS] > 0 && !player_in_water())
1075             mv -= (player_is_levitating() ? 4 : 2);
1076 
1077         /* Mutations: -2, -3, -4 */
1078         if (you.mutation[MUT_FAST] > 0)
1079             mv -= (you.mutation[MUT_FAST] + 1);
1080 
1081         // Burden
1082         if (you.burden_state == BS_ENCUMBERED)
1083             mv += 1;
1084         else if (you.burden_state == BS_OVERLOADED)
1085             mv += 3;
1086     }
1087 
1088     // We'll use the old value of six as a minimum, with haste this could
1089     // end up as a speed of three, which is about as fast as we want
1090     // the player to be able to go (since 3 is 3.33x as fast and 2 is 5x,
1091     // which is a bit of a jump, and a bit too fast) -- bwr
1092     if (mv < 6)
1093         mv = 6;
1094 
1095     // Nagas move slowly:
1096     if (you.species == SP_NAGA && !player_is_shapechanged())
1097     {
1098         mv *= 14;
1099         mv /= 10;
1100     }
1101 
1102     return (mv);
1103 }
1104 
1105 // This function differs from the above in that it's used to set the
1106 // initial time_taken value for the turn.  Everything else (movement,
1107 // spellcasting, combat) applies a ratio to this value.
player_speed(void)1108 int player_speed(void)
1109 {
1110     int ps = 10;
1111 
1112     if (you.haste)
1113         ps /= 2;
1114 
1115     switch (you.attribute[ATTR_TRANSFORMATION])
1116     {
1117     case TRAN_STATUE:
1118         ps *= 15;
1119         ps /= 10;
1120         break;
1121 
1122     case TRAN_SERPENT_OF_HELL:
1123         ps *= 12;
1124         ps /= 10;
1125         break;
1126 
1127     default:
1128         break;
1129     }
1130 
1131     return ps;
1132 }
1133 
player_AC(void)1134 int player_AC(void)
1135 {
1136     int AC = 0;
1137     int i;                      // loop variable
1138 
1139     // get the armour race value that corresponds to the character's race:
1140     const unsigned long racial_type
1141                             = ((player_genus(GENPC_DWARVEN)) ? ISFLAG_DWARVEN :
1142                                (player_genus(GENPC_ELVEN))   ? ISFLAG_ELVEN :
1143                                (you.species == SP_HILL_ORC)  ? ISFLAG_ORCISH
1144                                                              : 0);
1145 
1146     for (i = EQ_CLOAK; i <= EQ_BODY_ARMOUR; i++)
1147     {
1148         const int item = you.equip[i];
1149 
1150         if (item == -1 || i == EQ_SHIELD)
1151             continue;
1152 
1153         AC += you.inv[ item ].plus;
1154 
1155         // Note that helms and boots have a sub-sub classing system
1156         // which uses "plus2"... since not all members have the same
1157         // AC value, we use special cases. -- bwr
1158         if (i == EQ_HELMET
1159             && (cmp_helmet_type( you.inv[ item ], THELM_CAP )
1160                 || cmp_helmet_type( you.inv[ item ], THELM_WIZARD_HAT )
1161                 || cmp_helmet_type( you.inv[ item ], THELM_SPECIAL )))
1162         {
1163             continue;
1164         }
1165 
1166         if (i == EQ_BOOTS
1167             && (you.inv[ item ].plus2 == TBOOT_NAGA_BARDING
1168                 || you.inv[ item ].plus2 == TBOOT_CENTAUR_BARDING))
1169         {
1170             AC += 3;
1171         }
1172 
1173         int racial_bonus = 0;  // additional levels of armour skill
1174         const unsigned long armour_race = get_equip_race( you.inv[ item ] );
1175         const int ac_value = property( you.inv[ item ], PARM_AC );
1176 
1177         // Dwarven armour is universally good -- bwr
1178         if (armour_race == ISFLAG_DWARVEN)
1179             racial_bonus += 2;
1180 
1181         if (racial_type && armour_race == racial_type)
1182         {
1183             // Elven armour is light, but still gives one level
1184             // to elves.  Orcish and Dwarven armour are worth +2
1185             // to the correct species, plus the plus that anyone
1186             // gets with dwarven armour. -- bwr
1187 
1188             if (racial_type == ISFLAG_ELVEN)
1189                 racial_bonus++;
1190             else
1191                 racial_bonus += 2;
1192         }
1193 
1194         AC += ac_value * (15 + you.skills[SK_ARMOUR] + racial_bonus) / 15;
1195 
1196         /* Nagas/Centaurs/the deformed don't fit into body armour very well */
1197         if ((you.species == SP_NAGA || you.species == SP_CENTAUR
1198              || you.mutation[MUT_DEFORMED] > 0) && i == EQ_BODY_ARMOUR)
1199         {
1200             AC -= ac_value / 2;
1201         }
1202     }
1203 
1204     AC += player_equip( EQ_RINGS_PLUS, RING_PROTECTION );
1205 
1206     if (player_equip_ego_type( EQ_WEAPON, SPWPN_PROTECTION ))
1207         AC += 5;
1208 
1209     if (player_equip_ego_type( EQ_SHIELD, SPARM_PROTECTION ))
1210         AC += 3;
1211 
1212     AC += scan_randarts(RAP_AC);
1213 
1214     if (you.duration[DUR_ICY_ARMOUR])
1215         AC += 4 + you.skills[SK_ICE_MAGIC] / 3;         // max 13
1216 
1217     if (you.duration[DUR_STONEMAIL])
1218         AC += 5 + you.skills[SK_EARTH_MAGIC] / 2;       // max 18
1219 
1220     if (you.duration[DUR_STONESKIN])
1221         AC += 2 + you.skills[SK_EARTH_MAGIC] / 5;       // max 7
1222 
1223     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE
1224         || you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH
1225         || you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS)
1226     {
1227         // Being a lich doesn't preclude the benefits of hide/scales -- bwr
1228         //
1229         // Note: Even though necromutation is a high level spell, it does
1230         // allow the character full armour (so the bonus is low). -- bwr
1231         if (you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH)
1232             AC += (3 + you.skills[SK_NECROMANCY] / 6);          // max 7
1233 
1234         //jmf: only give:
1235         if (player_genus(GENPC_DRACONIAN))
1236         {
1237             if (you.experience_level < 8)
1238                 AC += 2;
1239             else if (you.species == SP_GREY_DRACONIAN)
1240                 AC += 1 + (you.experience_level - 4) / 2;       // max 12
1241             else
1242                 AC += 1 + (you.experience_level / 4);           // max 7
1243         }
1244         else
1245         {
1246             switch (you.species)
1247             {
1248             case SP_NAGA:
1249                 AC += you.experience_level / 3;                 // max 9
1250                 break;
1251 
1252             case SP_OGRE:
1253                 AC++;
1254                 break;
1255 
1256             case SP_TROLL:
1257             case SP_CENTAUR:
1258                 AC += 3;
1259                 break;
1260 
1261             default:
1262                 break;
1263             }
1264         }
1265 
1266         // Scales -- some evil uses of the fact that boolean "true" == 1...
1267         // I'll spell things out with some comments -- bwr
1268 
1269         // mutations:
1270         // these give: +1, +2, +3
1271         AC += you.mutation[MUT_TOUGH_SKIN];
1272         AC += you.mutation[MUT_GREY_SCALES];
1273         AC += you.mutation[MUT_SPECKLED_SCALES];
1274         AC += you.mutation[MUT_IRIDESCENT_SCALES];
1275         AC += you.mutation[MUT_PATTERNED_SCALES];
1276         AC += you.mutation[MUT_BLUE_SCALES];
1277 
1278         // these gives: +1, +3, +5
1279         if (you.mutation[MUT_GREEN_SCALES] > 0)
1280             AC += (you.mutation[MUT_GREEN_SCALES] * 2) - 1;
1281         if (you.mutation[MUT_NACREOUS_SCALES] > 0)
1282             AC += (you.mutation[MUT_NACREOUS_SCALES] * 2) - 1;
1283         if (you.mutation[MUT_BLACK2_SCALES] > 0)
1284             AC += (you.mutation[MUT_BLACK2_SCALES] * 2) - 1;
1285         if (you.mutation[MUT_WHITE_SCALES] > 0)
1286             AC += (you.mutation[MUT_WHITE_SCALES] * 2) - 1;
1287 
1288         // these give: +2, +4, +6
1289         AC += you.mutation[MUT_GREY2_SCALES] * 2;
1290         AC += you.mutation[MUT_YELLOW_SCALES] * 2;
1291         AC += you.mutation[MUT_PURPLE_SCALES] * 2;
1292 
1293         // black gives: +3, +6, +9
1294         AC += you.mutation[MUT_BLACK_SCALES] * 3;
1295 
1296         // boney plates give: +2, +3, +4
1297         if (you.mutation[MUT_BONEY_PLATES] > 0)
1298             AC += you.mutation[MUT_BONEY_PLATES] + 1;
1299 
1300         // red gives +1, +2, +4
1301         AC += you.mutation[MUT_RED_SCALES]
1302                             + (you.mutation[MUT_RED_SCALES] == 3);
1303 
1304         // indigo gives: +2, +3, +5
1305         if (you.mutation[MUT_INDIGO_SCALES] > 0)
1306         {
1307             AC += 1 + you.mutation[MUT_INDIGO_SCALES]
1308                             + (you.mutation[MUT_INDIGO_SCALES] == 3);
1309         }
1310 
1311         // brown gives: +2, +4, +5
1312         AC += (you.mutation[MUT_BROWN_SCALES] * 2)
1313                             - (you.mutation[MUT_METALLIC_SCALES] == 3);
1314 
1315         // orange gives: +1, +3, +4
1316         AC += you.mutation[MUT_ORANGE_SCALES]
1317                             + (you.mutation[MUT_ORANGE_SCALES] > 1);
1318 
1319         // knobbly red gives: +2, +5, +7
1320         AC += (you.mutation[MUT_RED2_SCALES] * 2)
1321                             + (you.mutation[MUT_RED2_SCALES] > 1);
1322 
1323         // metallic gives +3, +7, +10
1324         AC += you.mutation[MUT_METALLIC_SCALES] * 3
1325                             + (you.mutation[MUT_METALLIC_SCALES] > 1);
1326     }
1327     else
1328     {
1329         // transformations:
1330         switch (you.attribute[ATTR_TRANSFORMATION])
1331         {
1332         case TRAN_NONE:
1333         case TRAN_BLADE_HANDS:
1334         case TRAN_LICH:  // can wear normal body armour (small bonus)
1335             break;
1336 
1337 
1338         case TRAN_SPIDER: // low level (small bonus), also gets EV
1339             AC += (2 + you.skills[SK_POISON_MAGIC] / 6);        // max 6
1340             break;
1341 
1342         case TRAN_ICE_BEAST:
1343             AC += (5 + (you.skills[SK_ICE_MAGIC] + 1) / 4);     // max 12
1344 
1345             if (you.duration[DUR_ICY_ARMOUR])
1346                 AC += (1 + you.skills[SK_ICE_MAGIC] / 4);       // max +7
1347             break;
1348 
1349         case TRAN_DRAGON:
1350             AC += (7 + you.skills[SK_FIRE_MAGIC] / 3);          // max 16
1351             break;
1352 
1353         case TRAN_STATUE: // main ability is armour (high bonus)
1354             AC += (17 + you.skills[SK_EARTH_MAGIC] / 2);        // max 30
1355 
1356             if (you.duration[DUR_STONESKIN] || you.duration[DUR_STONEMAIL])
1357                 AC += (1 + you.skills[SK_EARTH_MAGIC] / 4);     // max +7
1358             break;
1359 
1360         case TRAN_SERPENT_OF_HELL:
1361             AC += (10 + you.skills[SK_FIRE_MAGIC] / 3);         // max 19
1362             break;
1363 
1364         case TRAN_AIR:    // air - scales & species ought to be irrelevent
1365             AC = (you.skills[SK_AIR_MAGIC] * 3) / 2;            // max 40
1366             break;
1367 
1368         default:
1369             break;
1370         }
1371     }
1372 
1373     return AC;
1374 }
1375 
is_light_armour(const item_def & item)1376 bool is_light_armour( const item_def &item )
1377 {
1378     if (cmp_equip_race( item, ISFLAG_ELVEN ))
1379         return (true);
1380 
1381     switch (item.sub_type)
1382     {
1383     case ARM_ROBE:
1384     case ARM_ANIMAL_SKIN:
1385     case ARM_LEATHER_ARMOUR:
1386     case ARM_STEAM_DRAGON_HIDE:
1387     case ARM_STEAM_DRAGON_ARMOUR:
1388     case ARM_MOTTLED_DRAGON_HIDE:
1389     case ARM_MOTTLED_DRAGON_ARMOUR:
1390     //case ARM_TROLL_HIDE: //jmf: these are knobbly and stiff
1391     //case ARM_TROLL_LEATHER_ARMOUR:
1392         return (true);
1393 
1394     default:
1395         return (false);
1396     }
1397 }
1398 
player_light_armour(void)1399 bool player_light_armour(void)
1400 {
1401     if (you.equip[EQ_BODY_ARMOUR] == -1)
1402         return true;
1403 
1404     return (is_light_armour( you.inv[you.equip[EQ_BODY_ARMOUR]] ));
1405 }                               // end player_light_armour()
1406 
1407 //
1408 // This function returns true if the player has a radically different
1409 // shape... minor changes like blade hands don't count, also note
1410 // that lich transformation doesn't change the character's shape
1411 // (so we end up with Naga-lichs, Spiggan-lichs, Minotaur-lichs)
1412 // it just makes the character undead (with the benefits that implies). --bwr
1413 //
player_is_shapechanged(void)1414 bool player_is_shapechanged(void)
1415 {
1416     if (you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE
1417         || you.attribute[ATTR_TRANSFORMATION] == TRAN_BLADE_HANDS
1418         || you.attribute[ATTR_TRANSFORMATION] == TRAN_LICH)
1419     {
1420         return (false);
1421     }
1422 
1423     return (true);
1424 }
1425 
player_evasion(void)1426 int player_evasion(void)
1427 {
1428     int ev = 10;
1429 
1430     int armour_ev_penalty;
1431 
1432     if (you.equip[EQ_BODY_ARMOUR] == -1)
1433         armour_ev_penalty = 0;
1434     else
1435     {
1436         armour_ev_penalty = property( you.inv[you.equip[EQ_BODY_ARMOUR]],
1437                                       PARM_EVASION );
1438     }
1439 
1440     // We return 2 here to give the player some chance of not being hit,
1441     // repulsion fields still work while paralysed
1442     if (you.paralysis)
1443         return (2 + you.mutation[MUT_REPULSION_FIELD] * 2);
1444 
1445     if (you.species == SP_CENTAUR)
1446         ev -= 3;
1447 
1448     if (you.equip[EQ_BODY_ARMOUR] != -1)
1449     {
1450         int ev_change = 0;
1451 
1452         ev_change = armour_ev_penalty;
1453         ev_change += you.skills[SK_ARMOUR] / 3;
1454 
1455         if (ev_change > armour_ev_penalty / 3)
1456             ev_change = armour_ev_penalty / 3;
1457 
1458         ev += ev_change;        /* remember that it's negative */
1459     }
1460 
1461     ev += player_equip( EQ_RINGS_PLUS, RING_EVASION );
1462 
1463     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_PONDEROUSNESS ))
1464         ev -= 2;
1465 
1466     if (you.duration[DUR_STONEMAIL])
1467         ev -= 2;
1468 
1469     if (you.duration[DUR_FORESCRY])
1470         ev += 8;                //jmf: is this a reasonable value?
1471 
1472     int emod = 0;
1473 
1474     if (!player_light_armour())
1475     {
1476         // meaning that the armour evasion modifier is often effectively
1477         // applied twice, but not if you're wearing elven armour
1478         emod += (armour_ev_penalty * 14) / 10;
1479     }
1480 
1481     emod += you.skills[SK_DODGING] / 2;
1482 
1483     if (emod > 0)
1484         ev += emod;
1485 
1486     if (you.mutation[MUT_REPULSION_FIELD] > 0)
1487         ev += (you.mutation[MUT_REPULSION_FIELD] * 2) - 1;
1488 
1489     switch (you.attribute[ATTR_TRANSFORMATION])
1490     {
1491     case TRAN_DRAGON:
1492         ev -= 3;
1493         break;
1494 
1495     case TRAN_STATUE:
1496     case TRAN_SERPENT_OF_HELL:
1497         ev -= 5;
1498         break;
1499 
1500     case TRAN_SPIDER:
1501         ev += 3;
1502         break;
1503 
1504     case TRAN_AIR:
1505         ev += 20;
1506         break;
1507 
1508     default:
1509         break;
1510     }
1511 
1512     ev += scan_randarts(RAP_EVASION);
1513 
1514     return ev;
1515 }                               // end player_evasion()
1516 
player_magical_power(void)1517 int player_magical_power( void )
1518 {
1519     int ret = 0;
1520 
1521     ret += 13 * player_equip( EQ_STAFF, STAFF_POWER );
1522     ret +=  9 * player_equip( EQ_RINGS, RING_MAGICAL_POWER );
1523 
1524     return (ret);
1525 }
1526 
player_mag_abil(bool is_weighted)1527 int player_mag_abil(bool is_weighted)
1528 {
1529     int ma = 0;
1530 
1531     ma += 3 * player_equip( EQ_RINGS, RING_WIZARDRY );
1532 
1533     /* Staves */
1534     ma += 4 * player_equip( EQ_STAFF, STAFF_WIZARDRY );
1535 
1536     /* armour of the Archmagi (checks body armour only) */
1537     ma += 2 * player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI );
1538 
1539     return ((is_weighted) ? ((ma * you.intel) / 10) : ma);
1540 }                               // end player_mag_abil()
1541 
player_shield_class(void)1542 int player_shield_class(void)   //jmf: changes for new spell
1543 {
1544     int base_shield = 0;
1545     const int shield = you.equip[EQ_SHIELD];
1546 
1547     if (shield == -1)
1548     {
1549         if (!you.fire_shield && you.duration[DUR_CONDENSATION_SHIELD])
1550             base_shield = 2 + (you.skills[SK_ICE_MAGIC] / 6);  // max 6
1551         else
1552             return (0);
1553     }
1554     else
1555     {
1556         switch (you.inv[ shield ].sub_type)
1557         {
1558         case ARM_BUCKLER:
1559             base_shield = 3;   // +3/20 per skill level    max 7
1560             break;
1561         case ARM_SHIELD:
1562             base_shield = 5;   // +5/20 per skill level    max 11
1563             break;
1564         case ARM_LARGE_SHIELD:
1565             base_shield = 7;   // +7/20 per skill level    max 16
1566             break;
1567         }
1568 
1569         // bonus applied only to base, see above for effect:
1570         base_shield *= (20 + you.skills[SK_SHIELDS]);
1571         base_shield /= 20;
1572 
1573         base_shield += you.inv[ shield ].plus;
1574     }
1575 
1576     return (base_shield);
1577 }                               // end player_shield_class()
1578 
player_see_invis(void)1579 unsigned char player_see_invis(void)
1580 {
1581     unsigned char si = 0;
1582 
1583     si += player_equip( EQ_RINGS, RING_SEE_INVISIBLE );
1584 
1585     /* armour: (checks head armour only) */
1586     si += player_equip_ego_type( EQ_HELMET, SPARM_SEE_INVISIBLE );
1587 
1588     /* Nagas & Spriggans have good eyesight */
1589     if (you.species == SP_NAGA || you.species == SP_SPRIGGAN)
1590         si++;
1591 
1592     if (you.mutation[MUT_ACUTE_VISION] > 0)
1593         si += you.mutation[MUT_ACUTE_VISION];
1594 
1595     //jmf: added see_invisible spell
1596     if (you.duration[DUR_SEE_INVISIBLE] > 0)
1597         si++;
1598 
1599     /* randart wpns */
1600     int artefacts = scan_randarts(RAP_EYESIGHT);
1601 
1602     if (artefacts > 0)
1603         si += artefacts;
1604 
1605     return si;
1606 }
1607 
1608 // This does NOT do line of sight!  It checks the monster's visibility
1609 // with repect to the players perception, but doesn't do walls or range...
1610 // to find if the square the monster is in is visible see mons_near().
player_monster_visible(struct monsters * mon)1611 bool player_monster_visible( struct monsters *mon )
1612 {
1613     if (mons_has_ench( mon, ENCH_SUBMERGED )
1614         || (mons_has_ench( mon, ENCH_INVIS ) && !player_see_invis()))
1615     {
1616         return (false);
1617     }
1618 
1619     return (true);
1620 }
1621 
player_sust_abil(void)1622 unsigned char player_sust_abil(void)
1623 {
1624     unsigned char sa = 0;
1625 
1626     sa += player_equip( EQ_RINGS, RING_SUSTAIN_ABILITIES );
1627 
1628     return sa;
1629 }                               // end player_sust_abil()
1630 
carrying_capacity(void)1631 int carrying_capacity(void)
1632 {
1633     // Originally: 1000 + you.strength * 200 + ( you.levitation ? 1000 : 0 )
1634     return (3500 + (you.strength * 100) + (player_is_levitating() ? 1000 : 0));
1635 }
1636 
burden_change(void)1637 int burden_change(void)
1638 {
1639     char old_burdenstate = you.burden_state;
1640 
1641     you.burden = 0;
1642 
1643     int max_carried = carrying_capacity();
1644 
1645     if (you.duration[DUR_STONEMAIL])
1646         you.burden += 800;
1647 
1648     for (unsigned char bu = 0; bu < ENDOFPACK; bu++)
1649     {
1650         if (you.inv[bu].quantity < 1)
1651             continue;
1652 
1653         if (you.inv[bu].base_type == OBJ_CORPSES)
1654         {
1655             if (you.inv[bu].sub_type == CORPSE_BODY)
1656                 you.burden += mons_weight(you.inv[bu].plus);
1657             else if (you.inv[bu].sub_type == CORPSE_SKELETON)
1658                 you.burden += mons_weight(you.inv[bu].plus) / 2;
1659         }
1660         else
1661         {
1662             you.burden += mass_item( you.inv[bu] ) * you.inv[bu].quantity;
1663         }
1664     }
1665 
1666     you.burden_state = BS_UNENCUMBERED;
1667     set_redraw_status( REDRAW_BURDEN );
1668 
1669     // changed the burdened levels to match the change to max_carried
1670     if (you.burden < (max_carried * 5) / 6)
1671     // (you.burden < max_carried - 1000)
1672     {
1673         you.burden_state = BS_UNENCUMBERED;
1674 
1675         // this message may have to change, just testing {dlb}
1676         if (old_burdenstate != you.burden_state)
1677             mpr("Your possessions no longer seem quite so burdensome.");
1678     }
1679     else if (you.burden < (max_carried * 11) / 12)
1680     // (you.burden < max_carried - 500)
1681     {
1682         you.burden_state = BS_ENCUMBERED;
1683 
1684         if (old_burdenstate != you.burden_state)
1685             mpr("You are being weighed down by all of your possessions.");
1686     }
1687     else
1688     {
1689         you.burden_state = BS_OVERLOADED;
1690 
1691         if (old_burdenstate != you.burden_state)
1692             mpr("You are being crushed by all of your possessions.");
1693     }
1694 
1695     return you.burden;
1696 }                               // end burden_change()
1697 
you_resist_magic(int power)1698 bool you_resist_magic(int power)
1699 {
1700     int ench_power = stepdown_value( power, 30, 40, 100, 120 );
1701 
1702     int mrchance = 100 + player_res_magic();
1703 
1704     mrchance -= ench_power;
1705 
1706     int mrch2 = random2(100) + random2(101);
1707 
1708 #if DEBUG_DIAGNOSTICS
1709     snprintf( info, INFO_SIZE, "Power: %d, player's MR: %d, target: %d, roll: %d",
1710              ench_power, player_res_magic(), mrchance, mrch2 );
1711 
1712     mpr( info, MSGCH_DIAGNOSTICS );
1713 #endif
1714 
1715     if (mrch2 < mrchance)
1716         return true;            // ie saved successfully
1717 
1718     return false;
1719 /* if (random2(power) / 3 + random2(power) / 3 + random2(power) / 3 >= player_res_magic()) return 0;
1720    return 1; */
1721 }
1722 
forget_map(unsigned char chance_forgotten)1723 void forget_map(unsigned char chance_forgotten)
1724 {
1725     unsigned char xcount, ycount = 0;
1726 
1727     for (xcount = 0; xcount < GXM; xcount++)
1728     {
1729         for (ycount = 0; ycount < GYM; ycount++)
1730         {
1731             if (random2(100) < chance_forgotten)
1732             {
1733                 env.map[xcount][ycount] = 0;
1734             }
1735         }
1736     }
1737 }                               // end forget_map()
1738 
gain_exp(unsigned int exp_gained)1739 void gain_exp( unsigned int exp_gained )
1740 {
1741 
1742     if (player_equip_ego_type( EQ_BODY_ARMOUR, SPARM_ARCHMAGI )
1743         && !one_chance_in(20))
1744     {
1745         return;
1746     }
1747 
1748 #if DEBUG_DIAGNOSTICS
1749     snprintf( info, INFO_SIZE, "gain_exp: %d", exp_gained );
1750     mpr( info, MSGCH_DIAGNOSTICS );
1751 #endif
1752 
1753     if (you.experience + exp_gained > 8999999)
1754         you.experience = 8999999;
1755     else
1756         you.experience += exp_gained;
1757 
1758     if (you.exp_available + exp_gained > 20000)
1759         you.exp_available = 20000;
1760     else
1761         you.exp_available += exp_gained;
1762 
1763     level_change();
1764 }                               // end gain_exp()
1765 
level_change(void)1766 void level_change(void)
1767 {
1768     int hp_adjust = 0;
1769     int mp_adjust = 0;
1770 
1771     // necessary for the time being, as level_change() is called
1772     // directly sometimes {dlb}
1773     you.redraw_experience = 1;
1774 
1775     while (you.experience_level < 27
1776             && you.experience > exp_needed(you.experience_level + 2))
1777     {
1778         you.experience_level++;
1779 
1780         if (you.experience_level <= you.max_level)
1781         {
1782             snprintf( info, INFO_SIZE, "Welcome back to level %d!",
1783                       you.experience_level );
1784 
1785             mpr(info, MSGCH_INTRINSIC_GAIN);
1786             more();
1787 
1788             // Gain back the hp and mp we lose in lose_level().  -- bwr
1789             inc_hp( 4, true );
1790             inc_mp( 1, true );
1791         }
1792         else  // character has gained a new level
1793         {
1794             snprintf( info, INFO_SIZE, "You are now a level %d %s!",
1795                       you.experience_level, you.class_name );
1796 
1797             mpr(info, MSGCH_INTRINSIC_GAIN);
1798             more();
1799 
1800             int brek = 0;
1801 
1802             if (you.experience_level > 21)
1803                 brek = (coinflip() ? 3 : 2);
1804             else if (you.experience_level > 12)
1805                 brek = 3 + random2(3);      // up from 2 + rand(3) -- bwr
1806             else
1807                 brek = 4 + random2(4);      // up from 3 + rand(4) -- bwr
1808 
1809             inc_hp( brek, true );
1810             inc_mp( 1, true );
1811 
1812             if (!(you.experience_level % 3))
1813                 ability_increase();
1814 
1815             switch (you.species)
1816             {
1817             case SP_HUMAN:
1818                 if (!(you.experience_level % 5))
1819                     modify_stat(STAT_RANDOM, 1, false);
1820                 break;
1821 
1822             case SP_ELF:
1823                 if (you.experience_level % 3)
1824                     hp_adjust--;
1825                 else
1826                     mp_adjust++;
1827 
1828                 if (!(you.experience_level % 4))
1829                 {
1830                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
1831                                                 : STAT_DEXTERITY), 1, false );
1832                 }
1833                 break;
1834 
1835             case SP_HIGH_ELF:
1836                 if (you.experience_level == 15)
1837                 {
1838                     //jmf: got Glamour ability
1839                     mpr("You feel charming!", MSGCH_INTRINSIC_GAIN);
1840                 }
1841 
1842                 if (you.experience_level % 3)
1843                     hp_adjust--;
1844 
1845                 if (!(you.experience_level % 2))
1846                     mp_adjust++;
1847 
1848                 if (!(you.experience_level % 3))
1849                 {
1850                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
1851                                                 : STAT_DEXTERITY), 1, false );
1852                 }
1853                 break;
1854 
1855             case SP_GREY_ELF:
1856                 if (you.experience_level == 5)
1857                 {
1858                     //jmf: got Glamour ability
1859                     mpr("You feel charming!", MSGCH_INTRINSIC_GAIN);
1860                     mp_adjust++;
1861                 }
1862 
1863                 if (you.experience_level < 14)
1864                     hp_adjust--;
1865 
1866                 if (you.experience_level % 3)
1867                     mp_adjust++;
1868 
1869                 if (!(you.experience_level % 4))
1870                 {
1871                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
1872                                                 : STAT_DEXTERITY), 1, false );
1873                 }
1874 
1875                 break;
1876 
1877             case SP_DEEP_ELF:
1878                 if (you.experience_level < 17)
1879                     hp_adjust--;
1880                 if (!(you.experience_level % 3))
1881                     hp_adjust--;
1882 
1883                 mp_adjust++;
1884 
1885                 if (!(you.experience_level % 4))
1886                     modify_stat(STAT_INTELLIGENCE, 1, false);
1887                 break;
1888 
1889             case SP_SLUDGE_ELF:
1890                 if (you.experience_level % 3)
1891                     hp_adjust--;
1892                 else
1893                     mp_adjust++;
1894 
1895                 if (!(you.experience_level % 4))
1896                 {
1897                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
1898                                                 : STAT_DEXTERITY), 1, false );
1899                 }
1900                 break;
1901 
1902             case SP_HILL_DWARF:
1903                 // lowered because of HD raise -- bwr
1904                 // if (you.experience_level < 14)
1905                 //     hp_adjust++;
1906 
1907                 if (you.experience_level % 3)
1908                     hp_adjust++;
1909 
1910                 if (!(you.experience_level % 2))
1911                     mp_adjust--;
1912 
1913                 if (!(you.experience_level % 4))
1914                     modify_stat(STAT_STRENGTH, 1, false);
1915                 break;
1916 
1917             case SP_MOUNTAIN_DWARF:
1918                 // lowered because of HD raise -- bwr
1919                 // if (you.experience_level < 14)
1920                 //     hp_adjust++;
1921 
1922                 if (!(you.experience_level % 2))
1923                     hp_adjust++;
1924 
1925                 if (!(you.experience_level % 3))
1926                     mp_adjust--;
1927 
1928                 if (!(you.experience_level % 4))
1929                     modify_stat(STAT_STRENGTH, 1, false);
1930                 break;
1931 
1932             case SP_HALFLING:
1933                 if (!(you.experience_level % 5))
1934                     modify_stat(STAT_DEXTERITY, 1, false);
1935 
1936                 if (you.experience_level < 17)
1937                     hp_adjust--;
1938 
1939                 if (!(you.experience_level % 2))
1940                     hp_adjust--;
1941                 break;
1942 
1943             case SP_KOBOLD:
1944                 if (!(you.experience_level % 5))
1945                 {
1946                     modify_stat( (coinflip() ? STAT_STRENGTH
1947                                                 : STAT_DEXTERITY), 1, false );
1948                 }
1949 
1950                 if (you.experience_level < 17)
1951                     hp_adjust--;
1952 
1953                 if (!(you.experience_level % 2))
1954                     hp_adjust--;
1955                 break;
1956 
1957             case SP_HILL_ORC:
1958                 // lower because of HD raise -- bwr
1959                 // if (you.experience_level < 17)
1960                 //     hp_adjust++;
1961 
1962                 if (!(you.experience_level % 2))
1963                     hp_adjust++;
1964 
1965                 if (!(you.experience_level % 3))
1966                     mp_adjust--;
1967 
1968                 if (!(you.experience_level % 5))
1969                     modify_stat(STAT_STRENGTH, 1, false);
1970                 break;
1971 
1972             case SP_MUMMY:
1973                 if (you.experience_level == 13 || you.experience_level == 26)
1974                 {
1975                     mpr( "You feel more in touch with the powers of death.",
1976                          MSGCH_INTRINSIC_GAIN );
1977                 }
1978 
1979                 if (you.experience_level == 13)  // level 13 for now -- bwr
1980                 {
1981                     mpr( "You can now infuse your body with magic to restore decomposition.", MSGCH_INTRINSIC_GAIN );
1982                 }
1983                 break;
1984 
1985             case SP_NAGA:
1986                 // lower because of HD raise -- bwr
1987                 // if (you.experience_level < 14)
1988                 //     hp_adjust++;
1989 
1990                 hp_adjust++;
1991 
1992                 if (!(you.experience_level % 4))
1993                     modify_stat(STAT_RANDOM, 1, false);
1994 
1995                 if (!(you.experience_level % 3))
1996                 {
1997                     mpr("Your skin feels tougher.", MSGCH_INTRINSIC_GAIN);
1998                     you.redraw_armour_class = 1;
1999                 }
2000                 break;
2001 
2002             case SP_GNOME:
2003                 if (you.experience_level < 13)
2004                     hp_adjust--;
2005 
2006                 if (!(you.experience_level % 3))
2007                     hp_adjust--;
2008 
2009                 if (!(you.experience_level % 4))
2010                 {
2011                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
2012                                                 : STAT_DEXTERITY), 1, false );
2013                 }
2014                 break;
2015 
2016             case SP_OGRE:
2017             case SP_TROLL:
2018                 hp_adjust++;
2019 
2020                 // lowered because of HD raise -- bwr
2021                 // if (you.experience_level < 14)
2022                 //     hp_adjust++;
2023 
2024                 if (!(you.experience_level % 2))
2025                     hp_adjust++;
2026 
2027                 if (you.experience_level % 3)
2028                     mp_adjust--;
2029 
2030                 if (!(you.experience_level % 3))
2031                     modify_stat(STAT_STRENGTH, 1, false);
2032                 break;
2033 
2034             case SP_OGRE_MAGE:
2035                 hp_adjust++;
2036 
2037                 // lowered because of HD raise -- bwr
2038                 // if (you.experience_level < 14)
2039                 //     hp_adjust++;
2040 
2041                 if (!(you.experience_level % 5))
2042                 {
2043                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
2044                                                 : STAT_STRENGTH), 1, false );
2045                 }
2046                 break;
2047 
2048             case SP_RED_DRACONIAN:
2049             case SP_WHITE_DRACONIAN:
2050             case SP_GREEN_DRACONIAN:
2051             case SP_GOLDEN_DRACONIAN:
2052 /* Grey is later */
2053             case SP_BLACK_DRACONIAN:
2054             case SP_PURPLE_DRACONIAN:
2055             case SP_MOTTLED_DRACONIAN:
2056             case SP_PALE_DRACONIAN:
2057             case SP_UNK0_DRACONIAN:
2058             case SP_UNK1_DRACONIAN:
2059             case SP_UNK2_DRACONIAN:
2060                 if (you.experience_level == 7)
2061                 {
2062                     switch (you.species)
2063                     {
2064                     case SP_RED_DRACONIAN:
2065                         mpr("Your scales start taking on a fiery red colour.",
2066                             MSGCH_INTRINSIC_GAIN);
2067                         break;
2068                     case SP_WHITE_DRACONIAN:
2069                         mpr("Your scales start taking on an icy white colour.",
2070                             MSGCH_INTRINSIC_GAIN);
2071                         break;
2072                     case SP_GREEN_DRACONIAN:
2073                         mpr("Your scales start taking on a green colour.",
2074                             MSGCH_INTRINSIC_GAIN);
2075                         mpr("You feel resistant to poison.", MSGCH_INTRINSIC_GAIN);
2076                         break;
2077 
2078                     case SP_GOLDEN_DRACONIAN:
2079                         mpr("Your scales start taking on a golden yellow colour.", MSGCH_INTRINSIC_GAIN);
2080                         break;
2081                     case SP_BLACK_DRACONIAN:
2082                         mpr("Your scales start turning black.", MSGCH_INTRINSIC_GAIN);
2083                         break;
2084                     case SP_PURPLE_DRACONIAN:
2085                         mpr("Your scales start taking on a rich purple colour.", MSGCH_INTRINSIC_GAIN);
2086                         break;
2087                     case SP_MOTTLED_DRACONIAN:
2088                         mpr("Your scales start taking on a weird mottled pattern.", MSGCH_INTRINSIC_GAIN);
2089                         break;
2090                     case SP_PALE_DRACONIAN:
2091                         mpr("Your scales start fading to a pale grey colour.", MSGCH_INTRINSIC_GAIN);
2092                         break;
2093                     case SP_UNK0_DRACONIAN:
2094                     case SP_UNK1_DRACONIAN:
2095                     case SP_UNK2_DRACONIAN:
2096                         mpr("");
2097                         break;
2098                     }
2099                     more();
2100                     redraw_screen();
2101                 }
2102 
2103                 if (you.experience_level == 18)
2104                 {
2105                     switch (you.species)
2106                     {
2107                     case SP_RED_DRACONIAN:
2108                         mpr("You feel resistant to fire.", MSGCH_INTRINSIC_GAIN);
2109                         break;
2110                     case SP_WHITE_DRACONIAN:
2111                         mpr("You feel resistant to cold.", MSGCH_INTRINSIC_GAIN);
2112                         break;
2113                     case SP_BLACK_DRACONIAN:
2114                         mpr("You feel resistant to electrical energy.",
2115                             MSGCH_INTRINSIC_GAIN);
2116                         break;
2117                     }
2118                 }
2119 
2120                 if (!(you.experience_level % 3))
2121                     hp_adjust++;
2122 
2123                 if (you.experience_level > 7 && !(you.experience_level % 4))
2124                 {
2125                     mpr("Your scales feel tougher.", MSGCH_INTRINSIC_GAIN);
2126                     you.redraw_armour_class = 1;
2127                     modify_stat(STAT_RANDOM, 1, false);
2128                 }
2129                 break;
2130 
2131             case SP_GREY_DRACONIAN:
2132                 if (you.experience_level == 7)
2133                 {
2134                     mpr("Your scales start turning grey.", MSGCH_INTRINSIC_GAIN);
2135                     more();
2136                     redraw_screen();
2137                 }
2138 
2139                 if (!(you.experience_level % 3))
2140                 {
2141                     hp_adjust++;
2142                     if (you.experience_level > 7)
2143                         hp_adjust++;
2144                 }
2145 
2146                 if (you.experience_level > 7 && !(you.experience_level % 2))
2147                 {
2148                     mpr("Your scales feel tougher.", MSGCH_INTRINSIC_GAIN);
2149                     you.redraw_armour_class = 1;
2150                 }
2151 
2152                 if ((you.experience_level > 7 && !(you.experience_level % 3))
2153                     || you.experience_level == 4 || you.experience_level == 7)
2154                 {
2155                     modify_stat(STAT_RANDOM, 1, false);
2156                 }
2157                 break;
2158 
2159             case SP_CENTAUR:
2160                 if (!(you.experience_level % 4))
2161                 {
2162                     modify_stat( (coinflip() ? STAT_DEXTERITY
2163                                                 : STAT_STRENGTH), 1, false );
2164                 }
2165 
2166                 // lowered because of HD raise -- bwr
2167                 // if (you.experience_level < 17)
2168                 //     hp_adjust++;
2169 
2170                 if (!(you.experience_level % 2))
2171                     hp_adjust++;
2172 
2173                 if (!(you.experience_level % 3))
2174                     mp_adjust--;
2175                 break;
2176 
2177             case SP_DEMIGOD:
2178                 if (!(you.experience_level % 3))
2179                     modify_stat(STAT_RANDOM, 1, false);
2180 
2181                 // lowered because of HD raise -- bwr
2182                 // if (you.experience_level < 17)
2183                 //    hp_adjust++;
2184 
2185                 if (!(you.experience_level % 2))
2186                     hp_adjust++;
2187 
2188                 if (you.experience_level % 3)
2189                     mp_adjust++;
2190                 break;
2191 
2192             case SP_SPRIGGAN:
2193                 if (you.experience_level < 17)
2194                     hp_adjust--;
2195 
2196                 if (you.experience_level % 3)
2197                     hp_adjust--;
2198 
2199                 mp_adjust++;
2200 
2201                 if (!(you.experience_level % 5))
2202                 {
2203                     modify_stat( (coinflip() ? STAT_INTELLIGENCE
2204                                                 : STAT_DEXTERITY), 1, false );
2205                 }
2206                 break;
2207 
2208             case SP_MINOTAUR:
2209                 // lowered because of HD raise -- bwr
2210                 // if (you.experience_level < 17)
2211                 //     hp_adjust++;
2212 
2213                 if (!(you.experience_level % 2))
2214                     hp_adjust++;
2215 
2216                 if (!(you.experience_level % 2))
2217                     mp_adjust--;
2218 
2219                 if (!(you.experience_level % 4))
2220                 {
2221                     modify_stat( (coinflip() ? STAT_DEXTERITY
2222                                                 : STAT_STRENGTH), 1, false );
2223                 }
2224                 break;
2225 
2226             case SP_DEMONSPAWN:
2227                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 0
2228                     && (you.experience_level == 4
2229                         || (you.experience_level < 4 && one_chance_in(3))))
2230                 {
2231                     demonspawn();
2232                 }
2233 
2234                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 1
2235                     && you.experience_level > 4
2236                     && (you.experience_level == 9
2237                         || (you.experience_level < 9 && one_chance_in(3))))
2238                 {
2239                     demonspawn();
2240                 }
2241 
2242                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 2
2243                     && you.experience_level > 9
2244                     && (you.experience_level == 14
2245                         || (you.experience_level < 14 && one_chance_in(3))))
2246                 {
2247                     demonspawn();
2248                 }
2249 
2250                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 3
2251                     && you.experience_level > 14
2252                     && (you.experience_level == 19
2253                         || (you.experience_level < 19 && one_chance_in(3))))
2254                 {
2255                     demonspawn();
2256                 }
2257 
2258                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 4
2259                     && you.experience_level > 19
2260                     && (you.experience_level == 24
2261                         || (you.experience_level < 24 && one_chance_in(3))))
2262                 {
2263                     demonspawn();
2264                 }
2265 
2266                 if (you.attribute[ATTR_NUM_DEMONIC_POWERS] == 5
2267                     && you.experience_level == 27)
2268                 {
2269                     demonspawn();
2270                 }
2271 
2272 /*if (you.attribute [ATTR_NUM_DEMONIC_POWERS] == 6 && (you.experience_level == 8 || (you.experience_level < 8 && one_chance_in(3) ) )
2273    demonspawn(); */
2274                 if (!(you.experience_level % 4))
2275                     modify_stat(STAT_RANDOM, 1, false);
2276                 break;
2277 
2278             case SP_GHOUL:
2279                 // lowered because of HD raise -- bwr
2280                 // if (you.experience_level < 17)
2281                 //     hp_adjust++;
2282 
2283                 if (!(you.experience_level % 2))
2284                     hp_adjust++;
2285 
2286                 if (!(you.experience_level % 3))
2287                     mp_adjust--;
2288 
2289                 if (!(you.experience_level % 5))
2290                     modify_stat(STAT_STRENGTH, 1, false);
2291                 break;
2292 
2293             case SP_KENKU:
2294                 if (you.experience_level < 17)
2295                     hp_adjust--;
2296 
2297                 if (!(you.experience_level % 3))
2298                     hp_adjust--;
2299 
2300                 if (!(you.experience_level % 4))
2301                     modify_stat(STAT_RANDOM, 1, false);
2302 
2303                 if (you.experience_level == 5)
2304                     mpr("You have gained the ability to fly.", MSGCH_INTRINSIC_GAIN);
2305                 else if (you.experience_level == 15)
2306                     mpr("You can now fly continuously.", MSGCH_INTRINSIC_GAIN);
2307                 break;
2308 
2309             case SP_MERFOLK:
2310                 if (you.experience_level % 3)
2311                     hp_adjust++;
2312 
2313                 if (!(you.experience_level % 5))
2314                     modify_stat(STAT_RANDOM, 1, false);
2315                 break;
2316             }
2317         }
2318 
2319         // add hp and mp adjustments - GDL
2320         inc_max_hp( hp_adjust );
2321         inc_max_mp( mp_adjust );
2322 
2323         deflate_hp( you.hp_max, false );
2324 
2325         if (you.magic_points < 0)
2326             you.magic_points = 0;
2327 
2328         calc_hp();
2329         calc_mp();
2330 
2331         if (you.experience_level > you.max_level)
2332             you.max_level = you.experience_level;
2333 
2334         if (you.religion == GOD_XOM)
2335             Xom_acts(true, you.experience_level, true);
2336     }
2337 
2338     redraw_skill( you.your_name, player_title() );
2339 }                               // end level_change()
2340 
2341 // here's a question for you: does the ordering of mods make a difference?
2342 // (yes) -- are these things in the right order of application to stealth?
2343 // - 12mar2000 {dlb}
check_stealth(void)2344 int check_stealth(void)
2345 {
2346     if (you.special_wield == SPWLD_SHADOW)
2347         return (0);
2348 
2349     int stealth = you.dex * 3;
2350 
2351     if (you.skills[SK_STEALTH])
2352     {
2353         if (player_genus(GENPC_DRACONIAN))
2354             stealth += (you.skills[SK_STEALTH] * 12);
2355         else
2356         {
2357             switch (you.species)
2358             {
2359             case SP_TROLL:
2360             case SP_OGRE:
2361             case SP_OGRE_MAGE:
2362             case SP_CENTAUR:
2363                 stealth += (you.skills[SK_STEALTH] * 9);
2364                 break;
2365             case SP_MINOTAUR:
2366                 stealth += (you.skills[SK_STEALTH] * 12);
2367                 break;
2368             case SP_GNOME:
2369             case SP_HALFLING:
2370             case SP_KOBOLD:
2371             case SP_SPRIGGAN:
2372             case SP_NAGA:       // not small but very good at stealth
2373                 stealth += (you.skills[SK_STEALTH] * 18);
2374                 break;
2375             default:
2376                 stealth += (you.skills[SK_STEALTH] * 15);
2377                 break;
2378             }
2379         }
2380     }
2381 
2382     if (you.burden_state == BS_ENCUMBERED)
2383         stealth /= 2;
2384     else if (you.burden_state == BS_OVERLOADED)
2385         stealth /= 5;
2386 
2387     if (you.conf)
2388         stealth /= 3;
2389 
2390     const int arm   = you.equip[EQ_BODY_ARMOUR];
2391     const int cloak = you.equip[EQ_CLOAK];
2392     const int boots = you.equip[EQ_BOOTS];
2393 
2394     if (arm != -1 && !player_light_armour())
2395         stealth -= (mass_item( you.inv[arm] ) / 10);
2396 
2397     if (cloak != -1 && cmp_equip_race( you.inv[cloak], ISFLAG_ELVEN ))
2398         stealth += 20;
2399 
2400     if (boots != -1)
2401     {
2402         if (get_armour_ego_type( you.inv[boots] ) == SPARM_STEALTH)
2403             stealth += 50;
2404 
2405         if (cmp_equip_race( you.inv[boots], ISFLAG_ELVEN ))
2406             stealth += 20;
2407     }
2408 
2409     stealth += scan_randarts( RAP_STEALTH );
2410 
2411     if (player_is_levitating())
2412         stealth += 10;
2413     else if (player_in_water())
2414     {
2415         // Merfolk can sneak up on monsters underwater -- bwr
2416         if (you.species == SP_MERFOLK)
2417             stealth += 50;
2418         else
2419             stealth /= 2;       // splashy-splashy
2420     }
2421 
2422     // Radiating silence is the negative compliment of shouting all the
2423     // time... a sudden change from background noise to no noise is going
2424     // to clue anything in to the fact that something is very wrong...
2425     // a personal silence spell would naturally be different, but this
2426     // silence radiates for a distance and prevents monster spellcasting,
2427     // which pretty much gives away the stealth game.
2428     if (you.duration[DUR_SILENCE])
2429         stealth -= 50;
2430 
2431     if (stealth < 0)
2432         stealth = 0;
2433 
2434     return (stealth);
2435 }                               // end check_stealth()
2436 
ability_increase(void)2437 void ability_increase(void)
2438 {
2439     unsigned char keyin;
2440 
2441     mpr("Your experience leads to an increase in your attributes!",
2442         MSGCH_INTRINSIC_GAIN);
2443 
2444     more();
2445     mesclr();
2446 
2447     mpr("Increase (S)trength, (I)ntelligence, or (D)exterity? ", MSGCH_PROMPT);
2448 
2449   get_key:
2450     keyin = getch();
2451     if (keyin == 0)
2452     {
2453         getch();
2454         goto get_key;
2455     }
2456 
2457     switch (keyin)
2458     {
2459     case 's':
2460     case 'S':
2461         modify_stat(STAT_STRENGTH, 1, false);
2462         return;
2463 
2464     case 'i':
2465     case 'I':
2466         modify_stat(STAT_INTELLIGENCE, 1, false);
2467         return;
2468 
2469     case 'd':
2470     case 'D':
2471         modify_stat(STAT_DEXTERITY, 1, false);
2472         return;
2473     }
2474 
2475     goto get_key;
2476 /* this is an infinite loop because it is reasonable to assume that you're not going to want to leave it prematurely. */
2477 }                               // end ability_increase()
2478 
display_char_status(void)2479 void display_char_status(void)
2480 {
2481     if (you.is_undead)
2482         mpr( "You are undead." );
2483     else if (you.deaths_door)
2484         mpr( "You are standing in death's doorway." );
2485     else
2486         mpr( "You are alive." );
2487 
2488     switch (you.attribute[ATTR_TRANSFORMATION])
2489     {
2490     case TRAN_SPIDER:
2491         mpr( "You are in spider-form." );
2492         break;
2493     case TRAN_BLADE_HANDS:
2494         mpr( "You have blades for hands." );
2495         break;
2496     case TRAN_STATUE:
2497         mpr( "You are a statue." );
2498         break;
2499     case TRAN_ICE_BEAST:
2500         mpr( "You are an ice creature." );
2501         break;
2502     case TRAN_DRAGON:
2503         mpr( "You are in dragon-form." );
2504         break;
2505     case TRAN_LICH:
2506         mpr( "You are in lich-form." );
2507         break;
2508     case TRAN_SERPENT_OF_HELL:
2509         mpr( "You are a huge demonic serpent." );
2510         break;
2511     case TRAN_AIR:
2512         mpr( "You are a cloud of diffuse gas." );
2513         break;
2514     }
2515 
2516     if (you.duration[DUR_BREATH_WEAPON])
2517         mpr( "You are short of breath." );
2518 
2519     if (you.duration[DUR_REPEL_UNDEAD])
2520         mpr( "You have a holy aura protecting you from undead." );
2521 
2522     if (you.duration[DUR_LIQUID_FLAMES])
2523         mpr( "You are covered in liquid flames." );
2524 
2525     if (you.duration[DUR_ICY_ARMOUR])
2526         mpr( "You are protected by an icy shield." );
2527 
2528     if (you.duration[DUR_REPEL_MISSILES])
2529         mpr( "You are protected from missiles." );
2530 
2531     if (you.duration[DUR_DEFLECT_MISSILES])
2532         mpr( "You deflect missiles." );
2533 
2534     if (you.duration[DUR_PRAYER])
2535         mpr( "You are praying." );
2536 
2537     if (you.duration[DUR_REGENERATION])
2538         mpr( "You are regenerating." );
2539 
2540     if (you.duration[DUR_SWIFTNESS])
2541         mpr( "You can move swiftly." );
2542 
2543     if (you.duration[DUR_INSULATION])
2544         mpr( "You are insulated." );
2545 
2546     if (you.duration[DUR_STONEMAIL])
2547         mpr( "You are covered in scales of stone." );
2548 
2549     if (you.duration[DUR_CONTROLLED_FLIGHT])
2550         mpr( "You can control your flight." );
2551 
2552     if (you.duration[DUR_TELEPORT])
2553         mpr( "You are about to teleport." );
2554 
2555     if (you.duration[DUR_CONTROL_TELEPORT])
2556         mpr( "You can control teleportation." );
2557 
2558     if (you.duration[DUR_DEATH_CHANNEL])
2559         mpr( "You are channeling the dead." );
2560 
2561     if (you.duration[DUR_FORESCRY])     //jmf: added 19mar2000
2562         mpr( "You are forewarned." );
2563 
2564     if (you.duration[DUR_SILENCE])      //jmf: added 27mar2000
2565         mpr( "You radiate silence." );
2566 
2567     if (you.duration[DUR_INFECTED_SHUGGOTH_SEED])       //jmf: added 19mar2000
2568         mpr( "You are infected with a shuggoth parasite." );
2569 
2570     if (you.duration[DUR_STONESKIN])
2571         mpr( "Your skin is tough as stone." );
2572 
2573     if (you.duration[DUR_SEE_INVISIBLE])
2574         mpr( "You can see invisible." );
2575 
2576     if (you.invis)
2577         mpr( "You are invisible." );
2578 
2579     if (you.conf)
2580         mpr( "You are confused." );
2581 
2582     if (you.paralysis)
2583         mpr( "You are paralysed." );
2584 
2585     if (you.exhausted)
2586         mpr( "You are exhausted." );
2587 
2588     if (you.slow && you.haste)
2589         mpr( "You are under both slowing and hasting effects." );
2590     else if (you.slow)
2591         mpr( "You are moving very slowly." );
2592     else if (you.haste)
2593         mpr( "You are moving very quickly." );
2594 
2595     if (you.might)
2596         mpr( "You are mighty." );
2597 
2598     if (you.berserker)
2599         mpr( "You are possessed by a berserker rage." );
2600 
2601     if (player_is_levitating())
2602         mpr( "You are hovering above the floor." );
2603 
2604     if (you.poison)
2605     {
2606         snprintf( info, INFO_SIZE, "You are %s poisoned.",
2607                   (you.poison > 10) ? "extremely" :
2608                   (you.poison > 5)  ? "very" :
2609                   (you.poison > 3)  ? "quite"
2610                                     : "mildly" );
2611         mpr(info);
2612     }
2613 
2614     if (you.disease)
2615     {
2616         snprintf( info, INFO_SIZE, "You are %sdiseased.",
2617                   (you.disease > 120) ? "badly " :
2618                   (you.disease >  40) ? ""
2619                                       : "mildly " );
2620         mpr(info);
2621     }
2622 
2623     if (you.rotting || you.species == SP_GHOUL)
2624     {
2625         // I apologize in advance for the horrendous ugliness about to
2626         // transpire.  Avert your eyes!
2627         snprintf( info, INFO_SIZE, "Your flesh is rotting%s",
2628                   (you.rotting > 15) ? " before your eyes!":
2629                   (you.rotting > 8)  ? " away quickly.":
2630                   (you.rotting > 4)  ? " badly."
2631              : ((you.species == SP_GHOUL && you.rotting > 0)
2632                         ? " faster than usual." : ".") );
2633         mpr(info);
2634     }
2635 
2636     contaminate_player( 0, true );
2637 
2638     if (you.confusing_touch)
2639     {
2640         snprintf( info, INFO_SIZE, "Your hands are glowing %s red.",
2641                   (you.confusing_touch > 40) ? "an extremely bright" :
2642                   (you.confusing_touch > 20) ? "bright"
2643                                              : "a soft" );
2644         mpr(info);
2645     }
2646 
2647     if (you.sure_blade)
2648     {
2649         snprintf( info, INFO_SIZE, "You have a %sbond with your blade.",
2650                   (you.sure_blade > 15) ? "strong " :
2651                   (you.sure_blade >  5) ? ""
2652                                         : "weak " );
2653         mpr(info);
2654     }
2655 }                               // end display_char_status()
2656 
redraw_skill(const char your_name[kNameLen],const char class_name[80])2657 void redraw_skill(const char your_name[kNameLen], const char class_name[80])
2658 {
2659     char print_it[80];
2660 
2661     memset( print_it, ' ', sizeof(print_it) );
2662     snprintf( print_it, sizeof(print_it), "%s the %s", your_name, class_name );
2663 
2664     int in_len = strlen( print_it );
2665     if (in_len > 40)
2666     {
2667         in_len -= 3;  // what we're getting back from removing "the"
2668 
2669         const int name_len = strlen(your_name);
2670         char name_buff[kNameLen];
2671         strncpy( name_buff, your_name, kNameLen );
2672 
2673         // squeeze name if required, the "- 8" is too not squueze too much
2674         if (in_len > 40 && (name_len - 8) > (in_len - 40))
2675             name_buff[ name_len - (in_len - 40) - 1 ] = '\0';
2676         else
2677             name_buff[ kNameLen - 1 ] = '\0';
2678 
2679         snprintf( print_it, sizeof(print_it), "%s, %s", name_buff, class_name );
2680     }
2681 
2682     for (int i = strlen(print_it); i < 41; i++)
2683         print_it[i] = ' ';
2684 
2685     print_it[40] = '\0';
2686 
2687 #ifdef DOS_TERM
2688     window(1, 1, 80, 25);
2689 #endif
2690     gotoxy(40, 1);
2691 
2692     textcolor( LIGHTGREY );
2693     cprintf( print_it );
2694 }                               // end redraw_skill()
2695 
2696 // Note that this function only has the one static buffer, so if you
2697 // want to use the results, you'll want to make a copy.
species_name(int speci,int level,bool genus,bool adj,bool cap)2698 char *species_name( int  speci, int level, bool genus, bool adj, bool cap )
2699 // defaults:                               false       false     true
2700 {
2701     static char species_buff[80];
2702 
2703     if (player_genus( GENPC_DRACONIAN, speci ))
2704     {
2705         if (adj || genus)  // adj doesn't care about exact species
2706             strcpy( species_buff, "Draconian" );
2707         else
2708         {
2709             // No longer have problems with ghosts here -- Sharp Aug2002
2710             if (level < 7)
2711                 strcpy( species_buff, "Draconian" );
2712             else
2713             {
2714                 switch (speci)
2715                 {
2716                 case SP_RED_DRACONIAN:
2717                     strcpy( species_buff, "Red Draconian" );
2718                     break;
2719                 case SP_WHITE_DRACONIAN:
2720                     strcpy( species_buff, "White Draconian" );
2721                     break;
2722                 case SP_GREEN_DRACONIAN:
2723                     strcpy( species_buff, "Green Draconian" );
2724                     break;
2725                 case SP_GOLDEN_DRACONIAN:
2726                     strcpy( species_buff, "Yellow Draconian" );
2727                     break;
2728                 case SP_GREY_DRACONIAN:
2729                     strcpy( species_buff, "Grey Draconian" );
2730                     break;
2731                 case SP_BLACK_DRACONIAN:
2732                     strcpy( species_buff, "Black Draconian" );
2733                     break;
2734                 case SP_PURPLE_DRACONIAN:
2735                     strcpy( species_buff, "Purple Draconian" );
2736                     break;
2737                 case SP_MOTTLED_DRACONIAN:
2738                     strcpy( species_buff, "Mottled Draconian" );
2739                     break;
2740                 case SP_PALE_DRACONIAN:
2741                     strcpy( species_buff, "Pale Draconian" );
2742                     break;
2743                 case SP_UNK0_DRACONIAN:
2744                 case SP_UNK1_DRACONIAN:
2745                 case SP_UNK2_DRACONIAN:
2746                 default:
2747                     strcpy( species_buff, "Draconian" );
2748                     break;
2749                 }
2750             }
2751         }
2752     }
2753     else if (player_genus( GENPC_ELVEN, speci ))
2754     {
2755         if (adj)  // doesn't care about species/genus
2756             strcpy( species_buff, "Elven" );
2757         else if (genus)
2758             strcpy( species_buff, "Elf" );
2759         else
2760         {
2761             switch (speci)
2762             {
2763             case SP_ELF:
2764             default:
2765                 strcpy( species_buff, "Elf" );
2766                 break;
2767             case SP_HIGH_ELF:
2768                 strcpy( species_buff, "High Elf" );
2769                 break;
2770             case SP_GREY_ELF:
2771                 strcpy( species_buff, "Grey Elf" );
2772                 break;
2773             case SP_DEEP_ELF:
2774                 strcpy( species_buff, "Deep Elf" );
2775                 break;
2776             case SP_SLUDGE_ELF:
2777                 strcpy( species_buff, "Sludge Elf" );
2778                 break;
2779             }
2780         }
2781     }
2782     else if (player_genus( GENPC_DWARVEN, speci ))
2783     {
2784         if (adj)  // doesn't care about species/genus
2785             strcpy( species_buff, "Dwarven" );
2786         else if (genus)
2787             strcpy( species_buff, "Dwarf" );
2788         else
2789         {
2790             switch (speci)
2791             {
2792             case SP_HILL_DWARF:
2793                 strcpy( species_buff, "Hill Dwarf" );
2794                 break;
2795             case SP_MOUNTAIN_DWARF:
2796                 strcpy( species_buff, "Mountain Dwarf" );
2797                 break;
2798             default:
2799                 strcpy( species_buff, "Dwarf" );
2800                 break;
2801             }
2802         }
2803     }
2804     else
2805     {
2806         switch (speci)
2807         {
2808         case SP_HUMAN:
2809             strcpy( species_buff, "Human" );
2810             break;
2811         case SP_HALFLING:
2812             strcpy( species_buff, "Halfling" );
2813             break;
2814         case SP_HILL_ORC:
2815             strcpy( species_buff, (adj) ? "Orcish" : (genus) ? "Orc"
2816                                                              : "Hill Orc" );
2817             break;
2818         case SP_KOBOLD:
2819             strcpy( species_buff, "Kobold" );
2820             break;
2821         case SP_MUMMY:
2822             strcpy( species_buff, "Mummy" );
2823             break;
2824         case SP_NAGA:
2825             strcpy( species_buff, "Naga" );
2826             break;
2827         case SP_GNOME:
2828             strcpy( species_buff, (adj) ? "Gnomish" : "Gnome" );
2829             break;
2830         case SP_OGRE:
2831             strcpy( species_buff, (adj) ? "Ogreish" : "Ogre" );
2832             break;
2833         case SP_TROLL:
2834             strcpy( species_buff, (adj) ? "Trollish" : "Troll" );
2835             break;
2836         case SP_OGRE_MAGE:
2837             // We've previously declared that these are radically
2838             // different from Ogres... so we're not going to
2839             // refer to them as Ogres.  -- bwr
2840             strcpy( species_buff, "Ogre-Mage" );
2841             break;
2842         case SP_CENTAUR:
2843             strcpy( species_buff, "Centaur" );
2844             break;
2845         case SP_DEMIGOD:
2846             strcpy( species_buff, (adj) ? "Divine" : "Demigod" );
2847             break;
2848         case SP_SPRIGGAN:
2849             strcpy( species_buff, "Spriggan" );
2850             break;
2851         case SP_MINOTAUR:
2852             strcpy( species_buff, "Minotaur" );
2853             break;
2854         case SP_DEMONSPAWN:
2855             strcpy( species_buff, (adj) ? "Demonic" : "Demonspawn" );
2856             break;
2857         case SP_GHOUL:
2858             strcpy( species_buff, (adj) ? "Ghoulish" : "Ghoul" );
2859             break;
2860         case SP_KENKU:
2861             strcpy( species_buff, "Kenku" );
2862             break;
2863         case SP_MERFOLK:
2864             strcpy( species_buff, (adj) ? "Merfolkian" : "Merfolk" );
2865             break;
2866         default:
2867             strcpy( species_buff, (adj) ? "Yakish" : "Yak" );
2868             break;
2869         }
2870     }
2871 
2872     if (!cap)
2873         strlwr( species_buff );
2874 
2875     return (species_buff);
2876 }                               // end species_name()
2877 
wearing_amulet(char amulet)2878 bool wearing_amulet(char amulet)
2879 {
2880     if (amulet == AMU_CONTROLLED_FLIGHT
2881         && (you.duration[DUR_CONTROLLED_FLIGHT]
2882             || player_genus(GENPC_DRACONIAN)
2883             || you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON))
2884     {
2885         return true;
2886     }
2887 
2888     if (amulet == AMU_CLARITY && you.mutation[MUT_CLARITY])
2889         return true;
2890 
2891     if (amulet == AMU_RESIST_CORROSION || amulet == AMU_CONSERVATION)
2892     {
2893         // this is hackish {dlb}
2894         if (player_equip_ego_type( EQ_CLOAK, SPARM_PRESERVATION ))
2895             return true;
2896     }
2897 
2898     if (you.equip[EQ_AMULET] == -1)
2899         return false;
2900 
2901     if (you.inv[you.equip[EQ_AMULET]].sub_type == amulet)
2902         return true;
2903 
2904     return false;
2905 }                               // end wearing_amulet()
2906 
player_is_levitating(void)2907 bool player_is_levitating(void)
2908 {
2909     return (you.attribute[ATTR_TRANSFORMATION] == TRAN_DRAGON || you.levitation);
2910 }
2911 
player_has_spell(int spell)2912 bool player_has_spell( int spell )
2913 {
2914     for (int i = 0; i < 25; i++)
2915     {
2916         if (you.spells[i] == spell)
2917             return (true);
2918     }
2919 
2920     return (false);
2921 }
2922 
species_exp_mod(char species)2923 int species_exp_mod(char species)
2924 {
2925 
2926     if (player_genus(GENPC_DRACONIAN))
2927         return 14;
2928     else if (player_genus(GENPC_DWARVEN))
2929         return 13;
2930     {
2931         switch (species)
2932         {
2933         case SP_HUMAN:
2934         case SP_HALFLING:
2935         case SP_HILL_ORC:
2936         case SP_KOBOLD:
2937             return 10;
2938         case SP_GNOME:
2939             return 11;
2940         case SP_ELF:
2941         case SP_SLUDGE_ELF:
2942         case SP_NAGA:
2943         case SP_GHOUL:
2944         case SP_MERFOLK:
2945             return 12;
2946         case SP_SPRIGGAN:
2947         case SP_KENKU:
2948             return 13;
2949         case SP_GREY_ELF:
2950         case SP_DEEP_ELF:
2951         case SP_OGRE:
2952         case SP_CENTAUR:
2953         case SP_MINOTAUR:
2954         case SP_DEMONSPAWN:
2955             return 14;
2956         case SP_HIGH_ELF:
2957         case SP_MUMMY:
2958         case SP_TROLL:
2959         case SP_OGRE_MAGE:
2960             return 15;
2961         case SP_DEMIGOD:
2962             return 16;
2963         default:
2964             return 0;
2965         }
2966     }
2967 }                               // end species_exp_mod()
2968 
exp_needed(int lev)2969 unsigned long exp_needed(int lev)
2970 {
2971     lev--;
2972 
2973     unsigned long level = 0;
2974 
2975 #if 0
2976     case  1: level = 1;
2977     case  2: level = 10;
2978     case  3: level = 35;
2979     case  4: level = 70;
2980     case  5: level = 120;
2981     case  6: level = 250;
2982     case  7: level = 510;
2983     case  8: level = 900;
2984     case  9: level = 1700;
2985     case 10: level = 3500;
2986     case 11: level = 8000;
2987     case 12: level = 20000;
2988 
2989     default:                    //return 14000 * (lev - 11);
2990         level = 20000 * (lev - 11) + ((lev - 11) * (lev - 11) * (lev - 11)) * 130;
2991         break;
2992 #endif
2993 
2994     // This is a better behaved function than the above.  The above looks
2995     // really ugly when you consider the second derivative, its not smooth
2996     // and has a horrible bump at level 12 followed by comparitively easy
2997     // teen levels.  This tries to sort out those issues.
2998     //
2999     // Basic plan:
3000     // Section 1: levels  1- 5, second derivative goes 10-10-20-30.
3001     // Section 2: levels  6-13, second derivative is exponential/doubling.
3002     // Section 3: levels 14-27, second derivative is constant at 6000.
3003     //
3004     // Section three is constant so we end up with high levels at about
3005     // their old values (level 27 at 850k), without delta2 ever decreasing.
3006     // The values that are considerably different (ie level 13 is now 29000,
3007     // down from 41040 are because the second derivative goes from 9040 to
3008     // 1430 at that point in the original, and then slowly builds back
3009     // up again).  This function smoothes out the old level 10-15 area
3010     // considerably.
3011 
3012     // Here's a table:
3013     //
3014     // level      xp      delta   delta2
3015     // =====   =======    =====   ======
3016     //   1           0        0       0
3017     //   2          10       10      10
3018     //   3          30       20      10
3019     //   4          70       40      20
3020     //   5         140       70      30
3021     //   6         270      130      60
3022     //   7         520      250     120
3023     //   8        1010      490     240
3024     //   9        1980      970     480
3025     //  10        3910     1930     960
3026     //  11        7760     3850    1920
3027     //  12       15450     7690    3840
3028     //  13       29000    13550    5860
3029     //  14       48500    19500    5950
3030     //  15       74000    25500    6000
3031     //  16      105500    31500    6000
3032     //  17      143000    37500    6000
3033     //  18      186500    43500    6000
3034     //  19      236000    49500    6000
3035     //  20      291500    55500    6000
3036     //  21      353000    61500    6000
3037     //  22      420500    67500    6000
3038     //  23      494000    73500    6000
3039     //  24      573500    79500    6000
3040     //  25      659000    85500    6000
3041     //  26      750500    91500    6000
3042     //  27      848000    97500    6000
3043 
3044 
3045     switch (lev)
3046     {
3047     case 1:
3048         level = 1;
3049         break;
3050     case 2:
3051         level = 10;
3052         break;
3053     case 3:
3054         level = 30;
3055         break;
3056     case 4:
3057         level = 70;
3058         break;
3059 
3060     default:
3061         if (lev < 13)
3062         {
3063             lev -= 4;
3064             level = 10 + 10 * lev
3065                        + 30 * (static_cast<int>(pow( 2.0, lev + 1 )));
3066         }
3067         else
3068         {
3069             lev -= 12;
3070             level = 15500 + 10500 * lev + 3000 * lev * lev;
3071         }
3072         break;
3073     }
3074 
3075     return ((level - 1) * species_exp_mod(you.species) / 10);
3076 }                               // end exp_needed()
3077 
3078 // returns bonuses from rings of slaying, etc.
slaying_bonus(char which_affected)3079 int slaying_bonus(char which_affected)
3080 {
3081     int ret = 0;
3082 
3083     if (which_affected == PWPN_HIT)
3084     {
3085         ret += player_equip( EQ_RINGS_PLUS, RING_SLAYING );
3086         ret += scan_randarts(RAP_ACCURACY);
3087     }
3088     else if (which_affected == PWPN_DAMAGE)
3089     {
3090         ret += player_equip( EQ_RINGS_PLUS2, RING_SLAYING );
3091         ret += scan_randarts(RAP_DAMAGE);
3092     }
3093 
3094     return (ret);
3095 }                               // end slaying_bonus()
3096 
3097 /* Checks each equip slot for a randart, and adds up all of those with
3098    a given property. Slow if any randarts are worn, so avoid where possible. */
scan_randarts(char which_property)3099 int scan_randarts(char which_property)
3100 {
3101     int i = 0;
3102     int retval = 0;
3103 
3104     for (i = EQ_WEAPON; i < NUM_EQUIP; i++)
3105     {
3106         const int eq = you.equip[i];
3107 
3108         if (eq == -1)
3109             continue;
3110 
3111         // only weapons give their effects when in our hands
3112         if (i == EQ_WEAPON && you.inv[ eq ].base_type != OBJ_WEAPONS)
3113             continue;
3114 
3115         if (!is_random_artefact( you.inv[ eq ] ))
3116             continue;
3117 
3118         retval += randart_wpn_property( you.inv[ eq ], which_property );
3119     }
3120 
3121     return (retval);
3122 }                               // end scan_randarts()
3123 
modify_stat(unsigned char which_stat,char amount,bool suppress_msg)3124 void modify_stat(unsigned char which_stat, char amount, bool suppress_msg)
3125 {
3126     char *ptr_stat = NULL;
3127     char *ptr_stat_max = NULL;
3128     char *ptr_redraw = NULL;
3129 
3130     // sanity - is non-zero amount?
3131     if (amount == 0)
3132         return;
3133 
3134     if (!suppress_msg)
3135         strcpy(info, "You feel ");
3136 
3137     if (which_stat == STAT_RANDOM)
3138         which_stat = random2(NUM_STATS);
3139 
3140     switch (which_stat)
3141     {
3142     case STAT_STRENGTH:
3143         ptr_stat = &you.strength;
3144         ptr_stat_max = &you.max_strength;
3145         ptr_redraw = &you.redraw_strength;
3146         if (!suppress_msg)
3147             strcat(info, (amount > 0) ? "stronger." : "weaker.");
3148         break;
3149 
3150     case STAT_DEXTERITY:
3151         ptr_stat = &you.dex;
3152         ptr_stat_max = &you.max_dex;
3153         ptr_redraw = &you.redraw_dexterity;
3154         if (!suppress_msg)
3155             strcat(info, (amount > 0) ? "agile." : "clumsy.");
3156         break;
3157 
3158     case STAT_INTELLIGENCE:
3159         ptr_stat = &you.intel;
3160         ptr_stat_max = &you.max_intel;
3161         ptr_redraw = &you.redraw_intelligence;
3162         if (!suppress_msg)
3163             strcat(info, (amount > 0) ? "clever." : "stupid.");
3164         break;
3165     }
3166 
3167     if (!suppress_msg)
3168         mpr( info, (amount > 0) ? MSGCH_INTRINSIC_GAIN : MSGCH_WARN );
3169 
3170     *ptr_stat += amount;
3171     *ptr_stat_max += amount;
3172     *ptr_redraw = 1;
3173 
3174     if (ptr_stat == &you.strength)
3175         burden_change();
3176 
3177     return;
3178 }                               // end modify_stat()
3179 
dec_hp(int hp_loss,bool fatal)3180 void dec_hp(int hp_loss, bool fatal)
3181 {
3182     if (hp_loss < 1)
3183         return;
3184 
3185     you.hp -= hp_loss;
3186 
3187     if (!fatal && you.hp < 1)
3188         you.hp = 1;
3189 
3190     you.redraw_hit_points = 1;
3191 
3192     return;
3193 }                               // end dec_hp()
3194 
dec_mp(int mp_loss)3195 void dec_mp(int mp_loss)
3196 {
3197     if (mp_loss < 1)
3198         return;
3199 
3200     you.magic_points -= mp_loss;
3201 
3202     if (you.magic_points < 0)
3203         you.magic_points = 0;
3204 
3205     you.redraw_magic_points = 1;
3206 
3207     return;
3208 }                               // end dec_mp()
3209 
enough_hp(int minimum,bool suppress_msg)3210 bool enough_hp(int minimum, bool suppress_msg)
3211 {
3212     // We want to at least keep 1 HP -- bwr
3213     if (you.hp < minimum + 1)
3214     {
3215         if (!suppress_msg)
3216             mpr("You haven't enough vitality at the moment.");
3217 
3218         return false;
3219     }
3220 
3221     return true;
3222 }                               // end enough_hp()
3223 
enough_mp(int minimum,bool suppress_msg)3224 bool enough_mp(int minimum, bool suppress_msg)
3225 {
3226     if (you.magic_points < minimum)
3227     {
3228         if (!suppress_msg)
3229             mpr("You haven't enough magic at the moment.");
3230 
3231         return false;
3232     }
3233 
3234     return true;
3235 }                               // end enough_mp()
3236 
3237 // Note that "max_too" refers to the base potential, the actual
3238 // resulting max value is subject to penalties, bonuses, and scalings.
inc_mp(int mp_gain,bool max_too)3239 void inc_mp(int mp_gain, bool max_too)
3240 {
3241     if (mp_gain < 1)
3242         return;
3243 
3244     you.magic_points += mp_gain;
3245 
3246     if (max_too)
3247         inc_max_mp( mp_gain );
3248 
3249     if (you.magic_points > you.max_magic_points)
3250         you.magic_points = you.max_magic_points;
3251 
3252     you.redraw_magic_points = 1;
3253 
3254     return;
3255 }                               // end inc_mp()
3256 
3257 // Note that "max_too" refers to the base potential, the actual
3258 // resulting max value is subject to penalties, bonuses, and scalings.
inc_hp(int hp_gain,bool max_too)3259 void inc_hp(int hp_gain, bool max_too)
3260 {
3261     if (hp_gain < 1)
3262         return;
3263 
3264     you.hp += hp_gain;
3265 
3266     if (max_too)
3267         inc_max_hp( hp_gain );
3268 
3269     if (you.hp > you.hp_max)
3270         you.hp = you.hp_max;
3271 
3272     you.redraw_hit_points = 1;
3273 }                               // end inc_hp()
3274 
rot_hp(int hp_loss)3275 void rot_hp( int hp_loss )
3276 {
3277     you.base_hp -= hp_loss;
3278     calc_hp();
3279 
3280     you.redraw_hit_points = 1;
3281 }
3282 
unrot_hp(int hp_recovered)3283 void unrot_hp( int hp_recovered )
3284 {
3285     if (hp_recovered >= 5000 - you.base_hp)
3286         you.base_hp = 5000;
3287     else
3288         you.base_hp += hp_recovered;
3289 
3290     calc_hp();
3291 
3292     you.redraw_hit_points = 1;
3293 }
3294 
player_rotted(void)3295 int player_rotted( void )
3296 {
3297     return (5000 - you.base_hp);
3298 }
3299 
rot_mp(int mp_loss)3300 void rot_mp( int mp_loss )
3301 {
3302     you.base_magic_points -= mp_loss;
3303     calc_mp();
3304 
3305     you.redraw_magic_points = 1;
3306 }
3307 
inc_max_hp(int hp_gain)3308 void inc_max_hp( int hp_gain )
3309 {
3310     you.base_hp2 += hp_gain;
3311     calc_hp();
3312 
3313     you.redraw_hit_points = 1;
3314 }
3315 
dec_max_hp(int hp_loss)3316 void dec_max_hp( int hp_loss )
3317 {
3318     you.base_hp2 -= hp_loss;
3319     calc_hp();
3320 
3321     you.redraw_hit_points = 1;
3322 }
3323 
inc_max_mp(int mp_gain)3324 void inc_max_mp( int mp_gain )
3325 {
3326     you.base_magic_points2 += mp_gain;
3327     calc_mp();
3328 
3329     you.redraw_magic_points = 1;
3330 }
3331 
dec_max_mp(int mp_loss)3332 void dec_max_mp( int mp_loss )
3333 {
3334     you.base_magic_points2 -= mp_loss;
3335     calc_mp();
3336 
3337     you.redraw_magic_points = 1;
3338 }
3339 
3340 // use of floor: false = hp max, true = hp min {dlb}
deflate_hp(int new_level,bool floor)3341 void deflate_hp(int new_level, bool floor)
3342 {
3343     if (floor && you.hp < new_level)
3344         you.hp = new_level;
3345     else if (!floor && you.hp > new_level)
3346         you.hp = new_level;
3347 
3348     // must remain outside conditional, given code usage {dlb}
3349     you.redraw_hit_points = 1;
3350 
3351     return;
3352 }                               // end deflate_hp()
3353 
3354 // Note that "max_too" refers to the base potential, the actual
3355 // resulting max value is subject to penalties, bonuses, and scalings.
set_hp(int new_amount,bool max_too)3356 void set_hp(int new_amount, bool max_too)
3357 {
3358     if (you.hp != new_amount)
3359         you.hp = new_amount;
3360 
3361     if (max_too && you.hp_max != new_amount)
3362     {
3363         you.base_hp2 = 5000 + new_amount;
3364         calc_hp();
3365     }
3366 
3367     if (you.hp > you.hp_max)
3368         you.hp = you.hp_max;
3369 
3370     // must remain outside conditional, given code usage {dlb}
3371     you.redraw_hit_points = 1;
3372 
3373     return;
3374 }                               // end set_hp()
3375 
3376 // Note that "max_too" refers to the base potential, the actual
3377 // resulting max value is subject to penalties, bonuses, and scalings.
set_mp(int new_amount,bool max_too)3378 void set_mp(int new_amount, bool max_too)
3379 {
3380     if (you.magic_points != new_amount)
3381         you.magic_points = new_amount;
3382 
3383     if (max_too && you.max_magic_points != new_amount)
3384     {
3385         // note that this gets scaled down for values > 18
3386         you.base_magic_points2 = 5000 + new_amount;
3387         calc_mp();
3388     }
3389 
3390     if (you.magic_points > you.max_magic_points)
3391         you.magic_points = you.max_magic_points;
3392 
3393     // must remain outside conditional, given code usage {dlb}
3394     you.redraw_magic_points = 1;
3395 
3396     return;
3397 }                               // end set_mp()
3398 
3399 
3400 static const char * Species_Abbrev_List[ NUM_SPECIES ] =
3401     { "XX", "Hu", "El", "HE", "GE", "DE", "SE", "HD", "MD", "Ha",
3402       "HO", "Ko", "Mu", "Na", "Gn", "Og", "Tr", "OM", "Dr", "Dr",
3403       "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr",
3404       "Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf" };
3405 
get_species_index_by_abbrev(const char * abbrev)3406 int get_species_index_by_abbrev( const char *abbrev )
3407 {
3408     int i;
3409     for (i = SP_HUMAN; i < NUM_SPECIES; i++)
3410     {
3411         if (tolower( abbrev[0] ) == tolower( Species_Abbrev_List[i][0] )
3412             && tolower( abbrev[1] ) == tolower( Species_Abbrev_List[i][1] ))
3413         {
3414             break;
3415         }
3416     }
3417 
3418     return ((i < NUM_SPECIES) ? i : -1);
3419 }
3420 
get_species_index_by_name(const char * name)3421 int get_species_index_by_name( const char *name )
3422 {
3423     int i;
3424     int sp = -1;
3425 
3426     char *ptr;
3427     char lowered_buff[80];
3428 
3429     strncpy( lowered_buff, name, sizeof( lowered_buff ) );
3430     strlwr( lowered_buff );
3431 
3432     for (i = SP_HUMAN; i < NUM_SPECIES; i++)
3433     {
3434         char *lowered_species = species_name( i, 0, false, false, false );
3435         ptr = strstr( lowered_species, lowered_buff );
3436         if (ptr != NULL)
3437         {
3438             sp = i;
3439             if (ptr == lowered_species)  // prefix takes preference
3440                 break;
3441         }
3442     }
3443 
3444     return (sp);
3445 }
3446 
get_species_abbrev(int which_species)3447 const char *get_species_abbrev( int which_species )
3448 {
3449     ASSERT( which_species > 0 && which_species < NUM_SPECIES );
3450 
3451     return (Species_Abbrev_List[ which_species ]);
3452 }
3453 
3454 
3455 static const char * Class_Abbrev_List[ NUM_JOBS ] =
3456     { "Fi", "Wz", "Pr", "Th", "Gl", "Ne", "Pa", "As", "Be", "Hu",
3457       "Cj", "En", "FE", "IE", "Su", "AE", "EE", "Cr", "DK", "VM",
3458       "CK", "Tm", "He", "XX", "Re", "St", "Mo", "Wr", "Wn" };
3459 
3460 static const char * Class_Name_List[ NUM_JOBS ] =
3461     { "Fighter", "Wizard", "Priest", "Thief", "Gladiator", "Necromancer",
3462       "Paladin", "Assassin", "Berserker", "Hunter", "Conjurer", "Enchanter",
3463       "Fire Elementalist", "Ice Elementalist", "Summoner", "Air Elementalist",
3464       "Earth Elementalist", "Crusader", "Death Knight", "Venom Mage",
3465       "Chaos Knight", "Transmuter", "Healer", "Quitter", "Reaver", "Stalker",
3466       "Monk", "Warper", "Wanderer" };
3467 
get_class_index_by_abbrev(const char * abbrev)3468 int get_class_index_by_abbrev( const char *abbrev )
3469 {
3470     int i;
3471 
3472     for (i = 0; i < NUM_JOBS; i++)
3473     {
3474         if (i == JOB_QUITTER)
3475             continue;
3476 
3477         if (tolower( abbrev[0] ) == tolower( Class_Abbrev_List[i][0] )
3478             && tolower( abbrev[1] ) == tolower( Class_Abbrev_List[i][1] ))
3479         {
3480             break;
3481         }
3482     }
3483 
3484     return ((i < NUM_JOBS) ? i : -1);
3485 }
3486 
get_class_abbrev(int which_job)3487 const char *get_class_abbrev( int which_job )
3488 {
3489     ASSERT( which_job < NUM_JOBS && which_job != JOB_QUITTER );
3490 
3491     return (Class_Abbrev_List[ which_job ]);
3492 }
3493 
get_class_index_by_name(const char * name)3494 int get_class_index_by_name( const char *name )
3495 {
3496     int i;
3497     int cl = -1;
3498 
3499     char *ptr;
3500     char lowered_buff[80];
3501     char lowered_class[80];
3502 
3503     strncpy( lowered_buff, name, sizeof( lowered_buff ) );
3504     strlwr( lowered_buff );
3505 
3506     for (i = 0; i < NUM_JOBS; i++)
3507     {
3508         if (i == JOB_QUITTER)
3509             continue;
3510 
3511         strncpy( lowered_class, Class_Name_List[i], sizeof( lowered_class ) );
3512         strlwr( lowered_class );
3513 
3514         ptr = strstr( lowered_class, lowered_buff );
3515         if (ptr != NULL)
3516         {
3517             cl = i;
3518             if (ptr == lowered_class)  // prefix takes preference
3519                 break;
3520         }
3521     }
3522 
3523     return (cl);
3524 }
3525 
get_class_name(int which_job)3526 const char *get_class_name( int which_job )
3527 {
3528     ASSERT( which_job < NUM_JOBS && which_job != JOB_QUITTER );
3529 
3530     return (Class_Name_List[ which_job ]);
3531 }
3532 
3533 /* ******************************************************************
3534 
3535 // this function is solely called by a commented out portion of
3536 // player::level_change() and is a bit outta whack with the
3537 // current codebase - probably should be struck as well 19may2000 {dlb}
3538 
3539 void priest_spells( int priest_pass[10], char religious )
3540 {
3541 
3542     switch ( religious )
3543     {
3544       case GOD_ZIN:
3545         priest_pass[1] = SPELL_LESSER_HEALING;
3546         priest_pass[2] = SPELL_REPEL_UNDEAD;
3547         priest_pass[3] = SPELL_HEAL_OTHER;
3548         priest_pass[4] = SPELL_PURIFICATION;
3549         priest_pass[5] = SPELL_GREATER_HEALING;
3550         priest_pass[6] = SPELL_SMITING;
3551         priest_pass[7] = SPELL_HOLY_WORD;
3552         priest_pass[8] = SPELL_REMOVE_CURSE;
3553         priest_pass[9] = SPELL_GUARDIAN;
3554         break;
3555 
3556      case GOD_SHINING_ONE:
3557        priest_pass[1] = SPELL_REPEL_UNDEAD;
3558        priest_pass[2] = SPELL_LESSER_HEALING;
3559        priest_pass[3] = SPELL_HEAL_OTHER;
3560        priest_pass[4] = SPELL_PURIFICATION;
3561        priest_pass[5] = SPELL_ABJURATION_II;
3562        priest_pass[6] = SPELL_THUNDERBOLT;
3563        priest_pass[7] = SPELL_SHINING_LIGHT;
3564        priest_pass[8] = SPELL_SUMMON_DAEVA;
3565        priest_pass[9] = SPELL_FLAME_OF_CLEANSING;
3566        break;
3567 
3568      case GOD_ELYVILON:
3569        priest_pass[1] = SPELL_LESSER_HEALING;
3570        priest_pass[2] = SPELL_HEAL_OTHER;
3571        priest_pass[3] = SPELL_PURIFICATION;
3572        priest_pass[4] = 93; // restore abilities
3573        priest_pass[5] = SPELL_GREATER_HEALING;
3574        priest_pass[6] = 94; // another healing spell
3575        priest_pass[7] = 95; // something else
3576        priest_pass[8] = -1; //
3577        priest_pass[9] = -1; //
3578        break;
3579     }
3580 
3581 }
3582 
3583 // Spells to be added: (+ renamed!)
3584 //   holy berserker
3585 //   87 Pestilence
3586 //   93 Restore Abilities
3587 //   94 something else healing
3588 //   95 something else
3589 
3590 ****************************************************************** */
3591 
contaminate_player(int change,bool statusOnly)3592 void contaminate_player(int change, bool statusOnly)
3593 {
3594     // get current contamination level
3595     int old_level;
3596     int new_level;
3597 
3598 
3599 #if DEBUG_DIAGNOSTICS
3600     if (change > 0 || (change < 0 && you.magic_contamination))
3601     {
3602         snprintf( info, INFO_SIZE, "change: %d  radiation: %d",
3603                  change, change + you.magic_contamination );
3604 
3605         mpr( info, MSGCH_DIAGNOSTICS );
3606     }
3607 #endif
3608 
3609     old_level = (you.magic_contamination > 60)?(you.magic_contamination / 20 + 2) :
3610                 (you.magic_contamination > 40)?4 :
3611                 (you.magic_contamination > 25)?3 :
3612                 (you.magic_contamination > 15)?2 :
3613                 (you.magic_contamination > 5)?1  : 0;
3614 
3615     // make the change
3616     if (change + you.magic_contamination < 0)
3617         you.magic_contamination = 0;
3618     else
3619     {
3620         if (change + you.magic_contamination > 250)
3621             you.magic_contamination = 250;
3622         else
3623             you.magic_contamination += change;
3624     }
3625 
3626     // figure out new level
3627     new_level = (you.magic_contamination > 60)?(you.magic_contamination / 20 + 2) :
3628                 (you.magic_contamination > 40)?4 :
3629                 (you.magic_contamination > 25)?3 :
3630                 (you.magic_contamination > 15)?2 :
3631                 (you.magic_contamination > 5)?1  : 0;
3632 
3633     if (statusOnly)
3634     {
3635         if (new_level > 0)
3636         {
3637             if (new_level > 3)
3638             {
3639                 strcpy(info, (new_level == 4) ?
3640                     "Your entire body has taken on an eerie glow!" :
3641                     "You are engulfed in a nimbus of crackling magics!");
3642             }
3643             else
3644             {
3645                 snprintf( info, INFO_SIZE, "You are %s with residual magics%c",
3646                     (new_level == 3) ? "practically glowing" :
3647                     (new_level == 2) ? "heavily infused"
3648                                      : "contaminated",
3649                     (new_level == 3) ? '!' : '.');
3650             }
3651 
3652             mpr(info);
3653         }
3654         return;
3655     }
3656 
3657     if (new_level == old_level)
3658         return;
3659 
3660     snprintf( info, INFO_SIZE, "You feel %s contaminated with magical energies.",
3661               (change < 0) ? "less" : "more" );
3662 
3663     mpr( info, (change > 0) ? MSGCH_WARN : MSGCH_RECOVERY );
3664 }
3665 
poison_player(int amount,bool force)3666 void poison_player( int amount, bool force )
3667 {
3668     if ((!force && player_res_poison()) || amount <= 0)
3669         return;
3670 
3671     const int old_value = you.poison;
3672     you.poison += amount;
3673 
3674     if (you.poison > 40)
3675         you.poison = 40;
3676 
3677     if (you.poison > old_value)
3678     {
3679         snprintf( info, INFO_SIZE, "You are %spoisoned.",
3680                   (old_value > 0) ? "more " : "" );
3681 
3682         // XXX: which message channel for this message?
3683         mpr( info );
3684     }
3685 }
3686 
reduce_poison_player(int amount)3687 void reduce_poison_player( int amount )
3688 {
3689     if (you.poison == 0 || amount <= 0)
3690         return;
3691 
3692     you.poison -= amount;
3693 
3694     if (you.poison <= 0)
3695     {
3696         you.poison = 0;
3697         mpr( "You feel better.", MSGCH_RECOVERY );
3698     }
3699     else
3700     {
3701         mpr( "You feel a little better.", MSGCH_RECOVERY );
3702     }
3703 }
3704 
confuse_player(int amount,bool resistable)3705 void confuse_player( int amount, bool resistable )
3706 {
3707     if (amount <= 0)
3708         return;
3709 
3710     if (resistable && wearing_amulet(AMU_CLARITY))
3711     {
3712         mpr( "You feel momentarily confused." );
3713         return;
3714     }
3715 
3716     const int old_value = you.conf;
3717     you.conf += amount;
3718 
3719     if (you.conf > 40)
3720         you.conf = 40;
3721 
3722     if (you.conf > old_value)
3723     {
3724         snprintf( info, INFO_SIZE, "You are %sconfused.",
3725                   (old_value > 0) ? "more " : "" );
3726 
3727         // XXX: which message channel for this message?
3728         mpr( info );
3729     }
3730 }
3731 
reduce_confuse_player(int amount)3732 void reduce_confuse_player( int amount )
3733 {
3734     if (you.conf == 0 || amount <= 0)
3735         return;
3736 
3737     you.conf -= amount;
3738 
3739     if (you.conf <= 0)
3740     {
3741         you.conf = 0;
3742         mpr( "You feel less confused." );
3743     }
3744 }
3745 
slow_player(int amount)3746 void slow_player( int amount )
3747 {
3748     if (amount <= 0)
3749         return;
3750 
3751     if (wearing_amulet( AMU_RESIST_SLOW ))
3752         mpr("You feel momentarily lethargic.");
3753     else if (you.slow >= 100)
3754         mpr( "You already are as slow as you could be." );
3755     else
3756     {
3757         if (you.slow == 0)
3758             mpr( "You feel yourself slow down." );
3759         else
3760             mpr( "You feel as though you will be slow longer." );
3761 
3762         you.slow += amount;
3763 
3764         if (you.slow > 100)
3765             you.slow = 100;
3766     }
3767 }
3768 
dec_slow_player(void)3769 void dec_slow_player( void )
3770 {
3771     if (you.slow > 1)
3772     {
3773         // BCR - Amulet of resist slow affects slow counter
3774         if (wearing_amulet(AMU_RESIST_SLOW))
3775         {
3776             you.slow -= 5;
3777             if (you.slow < 1)
3778                 you.slow = 1;
3779         }
3780         else
3781             you.slow--;
3782     }
3783     else if (you.slow == 1)
3784     {
3785         mpr("You feel yourself speed up.", MSGCH_DURATION);
3786         you.slow = 0;
3787     }
3788 }
3789 
haste_player(int amount)3790 void haste_player( int amount )
3791 {
3792     bool amu_eff = wearing_amulet( AMU_RESIST_SLOW );
3793 
3794     if (amount <= 0)
3795         return;
3796 
3797     if (amu_eff)
3798         mpr( "Your amulet glows brightly." );
3799 
3800     if (you.haste == 0)
3801         mpr( "You feel yourself speed up." );
3802     else if (you.haste > 80 + 20 * amu_eff)
3803         mpr( "You already have as much speed as you can handle." );
3804     else
3805     {
3806         mpr( "You feel as though your hastened speed will last longer." );
3807         contaminate_player(1);
3808     }
3809 
3810     you.haste += amount;
3811 
3812     if (you.haste > 80 + 20 * amu_eff)
3813         you.haste = 80 + 20 * amu_eff;
3814 
3815     naughty( NAUGHTY_STIMULANTS, 4 + random2(4) );
3816 }
3817 
dec_haste_player(void)3818 void dec_haste_player( void )
3819 {
3820     if (you.haste > 1)
3821     {
3822         // BCR - Amulet of resist slow affects haste counter
3823         if (!wearing_amulet(AMU_RESIST_SLOW) || coinflip())
3824             you.haste--;
3825 
3826         if (you.haste == 6)
3827         {
3828             mpr( "Your extra speed is starting to run out.", MSGCH_DURATION );
3829             if (coinflip())
3830                 you.haste--;
3831         }
3832     }
3833     else if (you.haste == 1)
3834     {
3835         mpr( "You feel yourself slow down.", MSGCH_DURATION );
3836         you.haste = 0;
3837     }
3838 }
3839 
disease_player(int amount)3840 void disease_player( int amount )
3841 {
3842     if (you.is_undead || amount <= 0)
3843         return;
3844 
3845     mpr( "You feel ill." );
3846 
3847     const int tmp = you.disease + amount;
3848     you.disease = (tmp > 210) ? 210 : tmp;
3849 }
3850 
dec_disease_player(void)3851 void dec_disease_player( void )
3852 {
3853     if (you.disease > 0)
3854     {
3855         you.disease--;
3856 
3857         if (you.disease > 5
3858             && (you.species == SP_KOBOLD
3859                 || you.duration[ DUR_REGENERATION ]
3860                 || you.mutation[ MUT_REGENERATION ] == 3))
3861         {
3862             you.disease -= 2;
3863         }
3864 
3865         if (!you.disease)
3866             mpr("You feel your health improve.", MSGCH_RECOVERY);
3867     }
3868 }
3869 
rot_player(int amount)3870 void rot_player( int amount )
3871 {
3872     if (amount <= 0)
3873         return;
3874 
3875     if (you.rotting < 40)
3876     {
3877         // Either this, or the actual rotting message should probably
3878         // be changed so that they're easier to tell apart. -- bwr
3879         snprintf( info, INFO_SIZE, "You feel your flesh %s away!",
3880                   (you.rotting) ? "rotting" : "start to rot" );
3881         mpr( info, MSGCH_WARN );
3882 
3883         you.rotting += amount;
3884     }
3885 }
3886