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