Dj: apply the hover speed penalty only when moving.
[crawl:crawl.git] / crawl-ref / source / player.cc
1 /**
2  * @file
3  * @brief Player related functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "player.h"
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <ctype.h>
14 #include <math.h>
15
16 #include <sstream>
17 #include <algorithm>
18
19 #include "act-iter.h"
20 #include "areas.h"
21 #include "art-enum.h"
22 #include "branch.h"
23 #ifdef DGL_WHEREIS
24  #include "chardump.h"
25 #endif
26 #include "cloud.h"
27 #include "clua.h"
28 #include "coord.h"
29 #include "coordit.h"
30 #include "delay.h"
31 #include "directn.h"
32 #include "effects.h"
33 #include "env.h"
34 #include "errors.h"
35 #include "exercise.h"
36 #include "food.h"
37 #include "godabil.h"
38 #include "godconduct.h"
39 #include "godpassive.h"
40 #include "godwrath.h"
41 #include "hints.h"
42 #include "hiscores.h"
43 #include "invent.h"
44 #include "item_use.h"
45 #include "itemname.h"
46 #include "itemprop.h"
47 #include "items.h"
48 #include "kills.h"
49 #include "libutil.h"
50 #include "macro.h"
51 #include "map_knowledge.h"
52 #include "melee_attack.h"
53 #include "message.h"
54 #include "misc.h"
55 #include "mon-stuff.h"
56 #include "mon-util.h"
57 #include "mutation.h"
58 #include "notes.h"
59 #include "options.h"
60 #include "ouch.h"
61 #include "output.h"
62 #include "player-stats.h"
63 #include "potion.h"
64 #include "quiver.h"
65 #include "random.h"
66 #include "religion.h"
67 #include "shopping.h"
68 #include "shout.h"
69 #include "skills.h"
70 #include "skills2.h"
71 #include "species.h"
72 #include "spl-damage.h"
73 #include "spl-other.h"
74 #include "spl-selfench.h"
75 #include "spl-transloc.h"
76 #include "spl-util.h"
77 #include "sprint.h"
78 #include "stairs.h"
79 #include "stash.h"
80 #include "state.h"
81 #include "status.h"
82 #include "stuff.h"
83 #include "terrain.h"
84 #include "throw.h"
85 #ifdef USE_TILE
86  #include "tileview.h"
87 #endif
88 #include "transform.h"
89 #include "traps.h"
90 #include "travel.h"
91 #include "view.h"
92 #include "viewgeom.h"
93 #include "xom.h"
94
95 static void _moveto_maybe_repel_stairs()
96 {
97     const dungeon_feature_type new_grid = env.grid(you.pos());
98     const command_type stair_dir = feat_stair_direction(new_grid);
99
100     if (stair_dir == CMD_NO_CMD
101         || new_grid == DNGN_ENTER_SHOP
102         ||  !you.duration[DUR_REPEL_STAIRS_MOVE])
103     {
104         return;
105     }
106
107     int pct = you.duration[DUR_REPEL_STAIRS_CLIMB] ? 29 : 50;
108
109     // When the effect is still strong, the chance to actually catch
110     // a stair is smaller. (Assuming the duration starts out at 1000.)
111     const int dur = max(0, you.duration[DUR_REPEL_STAIRS_MOVE] - 700);
112     pct += dur/10;
113
114     if (x_chance_in_y(pct, 100))
115     {
116         if (slide_feature_over(you.pos(), coord_def(-1, -1), false))
117         {
118             string stair_str = feature_description_at(you.pos(), false,
119                                                       DESC_THE, false);
120             string prep = feat_preposition(new_grid, true, &you);
121
122             mprf("%s slides away as you move %s it!", stair_str.c_str(),
123                  prep.c_str());
124
125             if (player_in_a_dangerous_place() && one_chance_in(5))
126                 xom_is_stimulated(25);
127         }
128     }
129 }
130
131 bool check_moveto_cloud(const coord_def& p, const string &move_verb,
132                         bool *prompted)
133 {
134     const int cloud = env.cgrid(p);
135     if (cloud != EMPTY_CLOUD && !you.confused())
136     {
137         const cloud_type ctype = env.cloud[ cloud ].type;
138         // Don't prompt if already in a cloud of the same type.
139         if (is_damaging_cloud(ctype, true)
140             && (env.cgrid(you.pos()) == EMPTY_CLOUD
141                 || ctype != env.cloud[ env.cgrid(you.pos()) ].type)
142             && !crawl_state.disables[DIS_CONFIRMATIONS])
143         {
144             // Don't prompt for steam unless we're at uncomfortably low hp.
145             if (ctype == CLOUD_STEAM)
146             {
147                 int threshold = 20;
148                 if (player_res_steam() < 0)
149                     threshold = threshold * 3 / 2;
150                 threshold = threshold * you.time_taken / BASELINE_DELAY;
151                 // Do prompt if we'd lose icemail, though.
152                 if (you.hp > threshold && !you.mutation[MUT_ICEMAIL])
153                     return true;
154             }
155
156             if (prompted)
157                 *prompted = true;
158             string prompt = make_stringf("Really %s into that cloud of %s?",
159                                          move_verb.c_str(),
160                                          cloud_name_at_index(cloud).c_str());
161             learned_something_new(HINT_CLOUD_WARNING);
162
163             if (!yesno(prompt.c_str(), false, 'n'))
164             {
165                 canned_msg(MSG_OK);
166                 return false;
167             }
168         }
169     }
170     return true;
171 }
172
173 bool check_moveto_trap(const coord_def& p, const string &move_verb,
174                        bool *prompted)
175 {
176     // If there's no trap, let's go.
177     trap_def* trap = find_trap(p);
178     if (!trap || env.grid(p) == DNGN_UNDISCOVERED_TRAP)
179         return true;
180
181     if (trap->type == TRAP_ZOT && !crawl_state.disables[DIS_CONFIRMATIONS])
182     {
183         string msg = (move_verb == "jump-attack"
184                       ? "Do you really want to %s when you might land in "
185                       "the Zot trap"
186                       : "Do you really want to %s into the Zot trap");
187         string prompt = make_stringf(msg.c_str(), move_verb.c_str());
188
189         if (prompted)
190             *prompted = true;
191         if (!yes_or_no("%s", prompt.c_str()))
192         {
193             canned_msg(MSG_OK);
194                 return false;
195         }
196     }
197     else if (!trap->is_safe() && !crawl_state.disables[DIS_CONFIRMATIONS])
198     {
199         string prompt;
200
201         if (prompted)
202             *prompted = true;
203         if (move_verb == "jump-attack")
204         {
205             prompt = make_stringf("Really jump when you might land on that %s?",
206                                   feature_description_at(p, false,
207                                                          DESC_BASENAME,
208                                                          false).c_str());
209         }
210         else
211         {
212             prompt = make_stringf("Really %s %s that %s?",
213                                   move_verb.c_str(),
214                                   (trap->type == TRAP_ALARM
215                                    || trap->type == TRAP_PLATE) ? "onto"
216                                   : "into",
217                                   feature_description_at(p, false,
218                                                          DESC_BASENAME,
219                                                          false).c_str());
220         }
221         if (!yesno(prompt.c_str(), true, 'n'))
222         {
223             canned_msg(MSG_OK);
224             return false;
225         }
226     }
227     return true;
228 }
229
230 static bool _check_moveto_dangerous(const coord_def& p, const string& msg,
231                                     bool cling = true)
232
233 {
234     if (you.can_swim() && feat_is_water(env.grid(p))
235         || you.airborne() || cling && you.can_cling_to(p)
236         || !is_feat_dangerous(env.grid(p)))
237     {
238         return true;
239     }
240
241     if (msg != "")
242         mpr(msg.c_str());
243     else if (you.species == SP_MERFOLK && feat_is_water(env.grid(p)))
244         mpr("You cannot swim in your current form.");
245     else if (you.species == SP_LAVA_ORC && feat_is_lava(env.grid(p))
246              && is_feat_dangerous(env.grid(p)))
247     {
248         mpr("You cannot enter lava in your current form.");
249     }
250     else
251         canned_msg(MSG_UNTHINKING_ACT);
252     return false;
253 }
254
255 bool check_moveto_terrain(const coord_def& p, const string &move_verb,
256                           const string &msg, bool *prompted)
257 {
258     if (you.is_wall_clinging()
259         && (move_verb == "blink" || move_verb == "passwall"))
260     {
261         return _check_moveto_dangerous(p, msg, false);
262     }
263     else if (!_check_moveto_dangerous(p, msg))
264         return false;
265
266     if (!need_expiration_warning() && need_expiration_warning(p)
267         && !crawl_state.disables[DIS_CONFIRMATIONS])
268     {
269         string prompt;
270
271         if (prompted)
272             *prompted = true;
273
274         if (msg != "")
275             prompt = msg + " ";
276
277         prompt += "Are you sure you want to " + move_verb;
278
279         if (you.ground_level())
280             prompt += " into ";
281         else
282             prompt += " over ";
283
284         prompt += env.grid(p) == DNGN_DEEP_WATER ? "deep water" : "lava";
285
286         prompt += need_expiration_warning(DUR_FLIGHT, p)
287             ? " while you are losing your buoyancy?"
288             : " while your transformation is expiring?";
289
290         if (!yesno(prompt.c_str(), false, 'n'))
291         {
292             canned_msg(MSG_OK);
293             return false;
294         }
295     }
296     return true;
297 }
298
299 bool check_moveto_exclusion(const coord_def& p, const string &move_verb,
300                             bool *prompted)
301 {
302     string prompt;
303
304     if (is_excluded(p)
305         && !is_stair_exclusion(p)
306         && !is_excluded(you.pos())
307         && !crawl_state.disables[DIS_CONFIRMATIONS])
308     {
309         if (prompted)
310             *prompted = true;
311         prompt = make_stringf("Really %s into a travel-excluded area?",
312                               move_verb.c_str());
313
314         if (!yesno(prompt.c_str(), false, 'n'))
315         {
316             canned_msg(MSG_OK);
317             return false;
318         }
319     }
320     return true;
321 }
322
323 bool check_moveto(const coord_def& p, const string &move_verb, const string &msg)
324 {
325     return (check_moveto_terrain(p, move_verb, msg)
326             && check_moveto_cloud(p, move_verb)
327             && check_moveto_trap(p, move_verb)
328             && check_moveto_exclusion(p, move_verb));
329 }
330
331 static void _splash()
332 {
333     if (you.can_swim())
334         noisy(4, you.pos(), "Floosh!");
335     else if (!beogh_water_walk())
336         noisy(8, you.pos(), "Splash!");
337 }
338
339 void moveto_location_effects(dungeon_feature_type old_feat,
340                              bool stepped, bool allow_shift,
341                              const coord_def& old_pos)
342 {
343     const dungeon_feature_type new_grid = env.grid(you.pos());
344
345     // Terrain effects.
346     if (is_feat_dangerous(new_grid) && (!you.is_wall_clinging()
347                                         || !cell_is_clingable(you.pos())))
348     {
349         // Lava and dangerous deep water (ie not merfolk).
350         const coord_def& entry = (stepped) ? old_pos : you.pos();
351
352         // If true, we were shifted and so we're done.
353         if (fall_into_a_pool(entry, allow_shift, new_grid))
354             return;
355     }
356
357     if (you.ground_level())
358     {
359         if (player_likes_lava(false))
360         {
361             if (feat_is_lava(new_grid) && !feat_is_lava(old_feat))
362             {
363                 if (!stepped)
364                     noisy(4, you.pos(), "Gloop!");
365
366                 mprf("You %s lava.",
367                      (stepped) ? "slowly immerse yourself in the" : "fall into the");
368
369                 // Extra time if you stepped in.
370                 if (stepped)
371                     you.time_taken *= 2;
372
373                 // This gets called here because otherwise you wouldn't heat
374                 // until your second turn in lava.
375                 if (temperature() < TEMP_FIRE)
376                     mpr("The lava instantly superheats you.");
377                 you.temperature = TEMP_MAX;
378             }
379
380             else if (!feat_is_lava(new_grid) && feat_is_lava(old_feat))
381             {
382                 mpr("You slowly pull yourself out of the lava.");
383                 you.time_taken *= 2;
384             }
385         }
386
387         if (you.species == SP_MERFOLK)
388         {
389             if (feat_is_water(new_grid) // We're entering water
390                 // We're not transformed, or with a form compatible with tail
391                 && (you.form == TRAN_NONE
392                     || you.form == TRAN_APPENDAGE
393                     || you.form == TRAN_BLADE_HANDS))
394             {
395                 merfolk_start_swimming(stepped);
396             }
397             else if (!feat_is_water(new_grid) && !is_feat_dangerous(new_grid))
398                 merfolk_stop_swimming();
399         }
400
401         if (feat_is_water(new_grid) && !stepped)
402             _splash();
403
404         if (feat_is_water(new_grid) && !you.can_swim() && !beogh_water_walk())
405         {
406             if (stepped)
407             {
408                 you.time_taken *= 13 + random2(8);
409                 you.time_taken /= 10;
410             }
411             const bool will_cling = you.can_cling_to_walls()
412                                     && cell_is_clingable(you.pos());
413
414             if (!feat_is_water(old_feat))
415             {
416                 if (stepped && will_cling)
417                 {
418                     mpr("You slowly cross the shallow water and cling to the "
419                         "wall.");
420                 }
421                 else
422                 {
423                     mprf("You %s the %s water.",
424                          stepped ? "enter" : "fall into",
425                          new_grid == DNGN_SHALLOW_WATER ? "shallow" : "deep");
426                 }
427             }
428
429             if (new_grid == DNGN_DEEP_WATER && old_feat != DNGN_DEEP_WATER)
430                 mpr("You sink to the bottom.");
431
432             if (!feat_is_water(old_feat) && !will_cling)
433             {
434                 mpr("Moving in this stuff is going to be slow.");
435                 if (you.invisible())
436                     mpr("...and don't expect to remain undetected.");
437             }
438         }
439     }
440     else if (you.species == SP_DJINNI && !feat_has_dry_floor(new_grid)
441              && feat_has_dry_floor(old_feat))
442     {
443         mprf("You heave yourself high above the %s.", feat_type_name(new_grid));
444     }
445
446     const bool was_clinging = you.is_wall_clinging();
447     const bool is_clinging = stepped && you.check_clinging(stepped);
448
449     if (feat_is_water(new_grid) && was_clinging && !is_clinging)
450         _splash();
451
452     // Traps go off.
453     if (trap_def* ptrap = find_trap(you.pos()))
454         ptrap->trigger(you, !stepped); // blinking makes it hard to evade
455
456     if (stepped)
457         _moveto_maybe_repel_stairs();
458 }
459
460 // Use this function whenever the player enters (or lands and thus re-enters)
461 // a grid.
462 //
463 // stepped     - normal walking moves
464 // allow_shift - allowed to scramble in any direction out of lava/water
465 void move_player_to_grid(const coord_def& p, bool stepped, bool allow_shift)
466 {
467     ASSERT(!crawl_state.game_is_arena());
468     ASSERT_IN_BOUNDS(p);
469
470     if (!stepped)
471     {
472         you.clear_clinging();
473         tornado_move(p);
474     }
475
476     // assuming that entering the same square means coming from above (flight)
477     const coord_def old_pos = you.pos();
478     const bool from_above = (old_pos == p);
479     const dungeon_feature_type old_grid =
480         (from_above) ? DNGN_FLOOR : grd(old_pos);
481
482     // Really must be clear.
483     ASSERT(you.can_pass_through_feat(grd(p)));
484
485     // Better not be an unsubmerged monster either.
486     ASSERT(!monster_at(p) || monster_at(p)->submerged()
487            || fedhas_passthrough(monster_at(p)));
488
489     // Move the player to new location.
490     you.moveto(p, true);
491     viewwindow();
492
493     moveto_location_effects(old_grid, stepped, allow_shift, old_pos);
494 }
495
496 bool is_feat_dangerous(dungeon_feature_type grid, bool permanently,
497                        bool ignore_items)
498 {
499     if (you.permanent_flight() || you.species == SP_DJINNI
500         || you.airborne() && !permanently)
501     {
502         return false;
503     }
504     else if (grid == DNGN_DEEP_WATER && !player_likes_water(permanently)
505              || grid == DNGN_LAVA && !player_likes_lava(permanently))
506     {
507         return true;
508     }
509     else
510         return false;
511 }
512
513 bool is_map_persistent(void)
514 {
515     return !testbits(env.level_flags, LFLAG_NO_MAP);
516 }
517
518 bool player_in_hell(void)
519 {
520     return is_hell_subbranch(you.where_are_you);
521 }
522
523 bool player_in_connected_branch(void)
524 {
525     return is_connected_branch(you.where_are_you);
526 }
527
528 bool player_likes_water(bool permanently)
529 {
530     return (!permanently && beogh_water_walk()
531             || (species_likes_water(you.species) || !permanently)
532                 && form_likes_water());
533 }
534
535 bool player_likes_lava(bool permanently)
536 {
537     return (species_likes_lava(you.species)
538             || (!permanently && form_likes_lava()));
539 }
540
541 bool player_can_open_doors()
542 {
543     return (you.form != TRAN_BAT && you.form != TRAN_JELLY);
544 }
545
546 // TODO: get rid of this.
547 bool player_genus(genus_type which_genus, species_type species)
548 {
549     if (species == SP_UNKNOWN)
550         species = you.species;
551
552     return (species_genus(species) == which_genus);
553 }
554
555 // If transform is true, compare with current transformation instead
556 // of (or in addition to) underlying species.
557 // (See mon-data.h for species/genus use.)
558 bool is_player_same_genus(const monster_type mon, bool transform)
559 {
560     if (transform)
561     {
562         switch (you.form)
563         {
564         // Unique monsters.
565         case TRAN_BAT:
566             return (mon == MONS_BAT);
567         case TRAN_ICE_BEAST:
568             return (mon == MONS_ICE_BEAST);
569         case TRAN_TREE:
570             return (mon == MONS_ANIMATED_TREE);
571         case TRAN_PORCUPINE:
572             return (mon == MONS_PORCUPINE);
573         case TRAN_WISP:
574             return (mon == MONS_INSUBSTANTIAL_WISP);
575         // Compare with monster *species*.
576         case TRAN_LICH:
577             return (mons_species(mon) == MONS_LICH);
578         // Compare with monster *genus*.
579         case TRAN_FUNGUS:
580             return (mons_genus(mon) == MONS_FUNGUS);
581         case TRAN_SPIDER:
582             return (mons_genus(mon) == MONS_SPIDER);
583         case TRAN_DRAGON:
584             return (mons_genus(mon) == MONS_DRAGON); // Includes all drakes.
585         case TRAN_PIG:
586             return (mons_genus(mon) == MONS_HOG);
587         case TRAN_JELLY:
588             return (mons_genus(mon) == MONS_JELLY);
589         case TRAN_STATUE:
590         case TRAN_BLADE_HANDS:
591         case TRAN_NONE:
592         case TRAN_APPENDAGE:
593             break; // Check real (non-transformed) form.
594         }
595     }
596
597     // Genus would include necrophage and rotting hulk.
598     if (you.species == SP_GHOUL)
599         return (mons_species(mon) == MONS_GHOUL);
600
601     if (you.species == SP_MERFOLK && mons_genus(mon) == MONS_MERMAID)
602         return true;
603
604     // Note that these are currently considered to be the same genus:
605     // * humans, demigods, and demonspawn
606     // * ogres and two-headed ogres
607     // * trolls, iron trolls, and deep trolls
608     // * kobolds and big kobolds
609     // * dwarves and deep dwarves
610     // * all elf races
611     // * all orc races
612     return (mons_genus(mon) == mons_genus(player_mons(false)));
613 }
614
615 void update_player_symbol()
616 {
617     you.symbol = Options.show_player_species ? player_mons() : transform_mons();
618 }
619
620 monster_type player_mons(bool transform)
621 {
622     monster_type mons;
623
624     if (transform)
625     {
626         mons = transform_mons();
627         if (mons != MONS_PLAYER)
628             return mons;
629     }
630
631     mons = player_species_to_mons_species(you.species);
632
633     if (mons == MONS_ORC)
634     {
635         if (you_worship(GOD_BEOGH))
636             mons = (you.piety >= piety_breakpoint(4)) ? MONS_ORC_HIGH_PRIEST
637                                                       : MONS_ORC_PRIEST;
638     }
639     else if (mons == MONS_OGRE)
640     {
641         const skill_type sk = best_skill(SK_FIRST_SKILL, SK_LAST_SKILL);
642         if (sk >= SK_SPELLCASTING && sk < SK_INVOCATIONS)
643             mons = MONS_OGRE_MAGE;
644     }
645
646     return mons;
647 }
648
649 void update_vision_range()
650 {
651     you.normal_vision = LOS_RADIUS;
652     int nom   = 1;
653     int denom = 1;
654
655     // Nightstalker gives -1/-2/-3.
656     if (player_mutation_level(MUT_NIGHTSTALKER))
657     {
658         nom *= LOS_RADIUS - player_mutation_level(MUT_NIGHTSTALKER);
659         denom *= LOS_RADIUS;
660     }
661
662     // Lantern of shadows.
663     if (you.attribute[ATTR_SHADOWS])
664         nom *= 3, denom *= 4;
665
666     // the Darkness spell.
667     if (you.duration[DUR_DARKNESS])
668         nom *= 3, denom *= 4;
669
670     // robe of Night.
671     if (player_equip_unrand(UNRAND_NIGHT))
672         nom *= 3, denom *= 4;
673
674     you.current_vision = (you.normal_vision * nom + denom / 2) / denom;
675     ASSERT(you.current_vision > 0);
676     set_los_radius(you.current_vision);
677 }
678
679 // Checks whether the player's current species can
680 // use (usually wear) a given piece of equipment.
681 // Note that EQ_BODY_ARMOUR and EQ_HELMET only check
682 // the ill-fitting variant (i.e., not caps and robes).
683 // If special_armour is set to true, special cases
684 // such as bardings, light armour and caps are
685 // considered. Otherwise, these simply return false.
686 // ---------------------------------------------------
687 bool you_can_wear(int eq, bool special_armour)
688 {
689     // Amulet provides another slot
690     if (eq == EQ_RING_AMULET && player_equip_unrand(UNRAND_FINGER_AMULET))
691         return true;
692
693     if (you.species == SP_FELID)
694         return (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET);
695
696     // Octopodes can wear soft helmets, eight rings, and an amulet.
697     if (you.species == SP_OCTOPODE)
698     {
699         if (special_armour && eq == EQ_HELMET)
700             return true;
701         else
702             return (eq >= EQ_RING_ONE && eq <= EQ_RING_EIGHT
703                     || eq == EQ_AMULET || eq == EQ_SHIELD || eq == EQ_WEAPON);
704     }
705
706     switch (eq)
707     {
708     case EQ_LEFT_RING:
709     case EQ_RIGHT_RING:
710     case EQ_AMULET:
711     case EQ_CLOAK:
712         return true;
713
714     case EQ_GLOVES:
715         if (player_mutation_level(MUT_CLAWS, false) == 3)
716             return false;
717         // These species cannot wear gloves.
718         if (you.species == SP_TROLL
719             || you.species == SP_SPRIGGAN
720             || you.species == SP_OGRE)
721         {
722             return false;
723         }
724         return true;
725
726     case EQ_BOOTS:
727         // Bardings.
728         if (you.species == SP_NAGA || you.species == SP_CENTAUR)
729             return special_armour;
730         if (player_mutation_level(MUT_HOOVES, false) == 3
731             || player_mutation_level(MUT_TALONS, false) == 3)
732         {
733             return false;
734         }
735         // These species cannot wear boots.
736         if (you.species == SP_TROLL
737             || you.species == SP_SPRIGGAN
738             || you.species == SP_OGRE
739             || you.species == SP_DJINNI)
740         {
741             return false;
742         }
743         return true;
744
745     case EQ_BODY_ARMOUR:
746         if (player_genus(GENPC_DRACONIAN))
747             return false;
748
749     case EQ_SHIELD:
750         // Most races can wear robes or a buckler/shield.
751         if (special_armour)
752             return true;
753         if (you.species == SP_TROLL
754             || you.species == SP_SPRIGGAN
755             || you.species == SP_OGRE)
756         {
757             return false;
758         }
759         return true;
760
761     case EQ_HELMET:
762         // No caps or hats with Horns 3 or Antennae 3.
763         if (player_mutation_level(MUT_HORNS, false) == 3
764             || player_mutation_level(MUT_ANTENNAE, false) == 3)
765         {
766             return false;
767         }
768         // Anyone else can wear caps.
769         if (special_armour)
770             return true;
771         if (player_mutation_level(MUT_HORNS, false)
772             || player_mutation_level(MUT_BEAK, false)
773             || player_mutation_level(MUT_ANTENNAE, false))
774         {
775             return false;
776         }
777         if (you.species == SP_TROLL
778             || you.species == SP_SPRIGGAN
779             || you.species == SP_OGRE
780             || player_genus(GENPC_DRACONIAN))
781         {
782             return false;
783         }
784         return true;
785
786     case EQ_WEAPON:
787     case EQ_STAFF:
788         return true; // kittehs were handled earlier
789
790     default:
791         return false;
792     }
793 }
794
795 bool player_has_feet(bool temp)
796 {
797     if (you.species == SP_NAGA
798         || you.species == SP_FELID
799         || you.species == SP_OCTOPODE
800         || you.species == SP_DJINNI
801         || you.fishtail && temp)
802     {
803         return false;
804     }
805
806     if (player_mutation_level(MUT_HOOVES, temp) == 3
807         || player_mutation_level(MUT_TALONS, temp) == 3)
808     {
809         return false;
810     }
811
812     return true;
813 }
814
815 bool player_wearing_slot(int eq)
816 {
817     ASSERT(you.equip[eq] != -1 || !you.melded[eq]);
818     return (you.equip[eq] != -1 && !you.melded[eq]);
819 }
820
821 bool you_tran_can_wear(const item_def &item)
822 {
823     switch (item.base_type)
824     {
825     case OBJ_WEAPONS:
826         return you_tran_can_wear(EQ_WEAPON);
827
828     case OBJ_JEWELLERY:
829         return you_tran_can_wear(jewellery_is_amulet(item) ? EQ_AMULET
830                                                            : EQ_RINGS);
831     case OBJ_ARMOUR:
832         if (item.sub_type == ARM_NAGA_BARDING)
833             return (you.species == SP_NAGA && you_tran_can_wear(EQ_BOOTS));
834         else if (item.sub_type == ARM_CENTAUR_BARDING)
835             return (you.species == SP_CENTAUR && you_tran_can_wear(EQ_BOOTS));
836
837         if (fit_armour_size(item, you.body_size()) != 0)
838             return false;
839
840         return you_tran_can_wear(get_armour_slot(item), true);
841
842     default:
843         return true;
844     }
845 }
846
847 bool you_tran_can_wear(int eq, bool check_mutation)
848 {
849     if (eq == EQ_NONE)
850         return true;
851
852     if (you.form == TRAN_JELLY
853         || you.form == TRAN_PORCUPINE
854         || you.form == TRAN_WISP)
855     {
856         return false;
857     }
858
859     if (eq == EQ_STAFF)
860         eq = EQ_WEAPON;
861     else if (eq >= EQ_RINGS && eq <= EQ_RINGS_PLUS2)
862         eq = EQ_RINGS;
863
864     // Everybody but jellies and porcupines can wear at least some type of armour.
865     if (eq == EQ_ALL_ARMOUR)
866         return true;
867
868     // Not a transformation, but also temporary -> check first.
869     if (check_mutation)
870     {
871         if (eq == EQ_GLOVES && you.has_claws(false) == 3)
872             return false;
873
874         if (eq == EQ_HELMET && player_mutation_level(MUT_HORNS) == 3)
875             return false;
876
877         if (eq == EQ_HELMET && player_mutation_level(MUT_ANTENNAE) == 3)
878             return false;
879
880         if (eq == EQ_BOOTS
881             && (you.fishtail
882                 || player_mutation_level(MUT_HOOVES) == 3
883                 || you.has_talons(false) == 3))
884         {
885             return false;
886         }
887     }
888
889     // No further restrictions.
890     if (you.form == TRAN_NONE
891         || you.form == TRAN_LICH
892         || you.form == TRAN_APPENDAGE)
893     {
894         return true;
895     }
896
897     // Bats and pigs cannot wear anything except amulets.
898     if ((you.form == TRAN_BAT || you.form == TRAN_PIG) && eq != EQ_AMULET)
899         return false;
900
901     // Everyone else can wear jewellery...
902     if (eq == EQ_AMULET || eq == EQ_RINGS
903         || eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING
904         || eq == EQ_RING_ONE || eq == EQ_RING_TWO
905         || eq == EQ_RING_AMULET)
906     {
907         return true;
908     }
909
910     // ...but not necessarily in all slots.
911     if (eq >= EQ_RING_THREE && eq <= EQ_RING_EIGHT)
912     {
913         return (you.species == SP_OCTOPODE
914                 && (form_keeps_mutations() || you.form == TRAN_SPIDER));
915     }
916
917     // These cannot use anything but jewellery.
918     if (you.form == TRAN_SPIDER || you.form == TRAN_DRAGON)
919         return false;
920
921     if (you.form == TRAN_BLADE_HANDS)
922     {
923         if (eq == EQ_WEAPON || eq == EQ_GLOVES || eq == EQ_SHIELD)
924             return false;
925         return true;
926     }
927
928     if (you.form == TRAN_ICE_BEAST)
929     {
930         if (eq != EQ_CLOAK)
931             return false;
932         return true;
933     }
934
935     if (you.form == TRAN_STATUE)
936     {
937         if (eq == EQ_WEAPON || eq == EQ_SHIELD
938             || eq == EQ_CLOAK || eq == EQ_HELMET)
939         {
940             return true;
941         }
942         return false;
943     }
944
945     if (you.form == TRAN_FUNGUS)
946         return (eq == EQ_HELMET);
947
948     if (you.form == TRAN_TREE)
949         return (eq == EQ_WEAPON || eq == EQ_SHIELD || eq == EQ_HELMET);
950
951     return true;
952 }
953
954 bool player_weapon_wielded()
955 {
956     if (you.melded[EQ_WEAPON])
957         return false;
958
959     const int wpn = you.equip[EQ_WEAPON];
960
961     if (wpn == -1)
962         return false;
963
964     if (!is_weapon(you.inv[wpn]))
965         return false;
966
967     return true;
968 }
969
970 // Returns false if the player is wielding a weapon inappropriate for Berserk.
971 bool berserk_check_wielded_weapon()
972 {
973     const item_def * const wpn = you.weapon();
974     if (wpn && (wpn->defined() && (!is_melee_weapon(*wpn)
975                                    || needs_handle_warning(*wpn, OPER_ATTACK))
976                 || you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED]))
977     {
978         string prompt = "Do you really want to go berserk while wielding "
979                         + wpn->name(DESC_YOUR) + "?";
980
981         if (!yesno(prompt.c_str(), true, 'n'))
982         {
983             canned_msg(MSG_OK);
984             return false;
985         }
986
987         you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
988     }
989
990     return true;
991 }
992
993 // Looks in equipment "slot" to see if there is an equipped "sub_type".
994 // Returns number of matches (in the case of rings, both are checked)
995 int player::wearing(equipment_type slot, int sub_type, bool calc_unid) const
996 {
997     int ret = 0;
998
999     const item_def* item;
1000
1001     switch (slot)
1002     {
1003     case EQ_WEAPON:
1004         // Hands can have more than just weapons.
1005         if (weapon()
1006             && weapon()->base_type == OBJ_WEAPONS
1007             && weapon()->sub_type == sub_type)
1008         {
1009             ret++;
1010         }
1011         break;
1012
1013     case EQ_STAFF:
1014         // Like above, but must be magical staff.
1015         if (weapon()
1016             && weapon()->base_type == OBJ_STAVES
1017             && weapon()->sub_type == sub_type
1018             && (calc_unid || item_type_known(*weapon())))
1019         {
1020             ret++;
1021         }
1022         break;
1023
1024     case EQ_RINGS:
1025         for (int slots = EQ_LEFT_RING; slots < NUM_EQUIP; slots++)
1026         {
1027             if (slots == EQ_AMULET)
1028                 continue;
1029
1030             if ((item = slot_item(static_cast<equipment_type>(slots)))
1031                 && item->sub_type == sub_type
1032                 && (calc_unid
1033                     || item_type_known(*item)))
1034             {
1035                 ret++;
1036             }
1037         }
1038         break;
1039
1040     case EQ_RINGS_PLUS:
1041         for (int slots = EQ_LEFT_RING; slots < NUM_EQUIP; slots++)
1042         {
1043             if (slots == EQ_AMULET)
1044                 continue;
1045
1046             if ((item = slot_item(static_cast<equipment_type>(slots)))
1047                 && item->sub_type == sub_type
1048                 && (calc_unid
1049                     || item_type_known(*item)))
1050             {
1051                 ret += item->plus;
1052             }
1053         }
1054         break;
1055
1056     case EQ_RINGS_PLUS2:
1057         for (int slots = EQ_LEFT_RING; slots < NUM_EQUIP; ++slots)
1058         {
1059             if (slots == EQ_AMULET)
1060                 continue;
1061
1062             if ((item = slot_item(static_cast<equipment_type>(slots)))
1063                 && item->sub_type == sub_type
1064                 && (calc_unid
1065                     || item_type_known(*item)))
1066             {
1067                 ret += item->plus2;
1068             }
1069         }
1070         break;
1071
1072     case EQ_ALL_ARMOUR:
1073         // Doesn't make much sense here... be specific. -- bwr
1074         die("EQ_ALL_ARMOUR is not a proper slot");
1075         break;
1076
1077     default:
1078         if (! (slot > EQ_NONE && slot < NUM_EQUIP))
1079             die("invalid slot");
1080         if ((item = slot_item(slot))
1081             && item->sub_type == sub_type
1082             && (calc_unid || item_type_known(*item)))
1083         {
1084             ret++;
1085         }
1086         break;
1087     }
1088
1089     return ret;
1090 }
1091
1092 // Looks in equipment "slot" to see if equipped item has "special" ego-type
1093 // Returns number of matches (jewellery returns zero -- no ego type).
1094 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
1095 // and armour type-id on wield/wear.
1096 int player::wearing_ego(equipment_type slot, int special, bool calc_unid) const
1097 {
1098     int ret = 0;
1099
1100     const item_def* item;
1101     switch (slot)
1102     {
1103     case EQ_WEAPON:
1104         // Hands can have more than just weapons.
1105         if ((item = slot_item(EQ_WEAPON))
1106             && item->base_type == OBJ_WEAPONS
1107             && get_weapon_brand(*item) == special)
1108         {
1109             ret++;
1110         }
1111         break;
1112
1113     case EQ_LEFT_RING:
1114     case EQ_RIGHT_RING:
1115     case EQ_AMULET:
1116     case EQ_STAFF:
1117     case EQ_RINGS:
1118     case EQ_RINGS_PLUS:
1119     case EQ_RINGS_PLUS2:
1120         // no ego types for these slots
1121         break;
1122
1123     case EQ_ALL_ARMOUR:
1124         // Check all armour slots:
1125         for (int i = EQ_MIN_ARMOUR; i <= EQ_MAX_ARMOUR; i++)
1126         {
1127             if ((item = slot_item(static_cast<equipment_type>(i)))
1128                 && get_armour_ego_type(*item) == special
1129                 && (calc_unid || item_type_known(*item)))
1130             {
1131                 ret++;
1132             }
1133         }
1134         break;
1135
1136     default:
1137         if (slot < EQ_MIN_ARMOUR || slot > EQ_MAX_ARMOUR)
1138             die("invalid slot: %d", slot);
1139         // Check a specific armour slot for an ego type:
1140         if ((item = slot_item(static_cast<equipment_type>(slot)))
1141             && get_armour_ego_type(*item) == special
1142             && (calc_unid || item_type_known(*item)))
1143         {
1144             ret++;
1145         }
1146         break;
1147     }
1148
1149     return ret;
1150 }
1151
1152 bool player_equip_unrand_effect(int unrand_index)
1153 {
1154     if (you.suppressed())
1155         return false;
1156     else
1157         return player_equip_unrand(unrand_index);
1158 }
1159
1160 // Return's true if the indicated unrandart is equipped
1161 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
1162 // and armour type-id on wield/wear.
1163 bool player_equip_unrand(int unrand_index)
1164 {
1165     const unrandart_entry* entry = get_unrand_entry(unrand_index);
1166     equipment_type   slot  = get_item_slot(entry->base_type,
1167                                            entry->sub_type);
1168
1169     item_def* item;
1170
1171     switch (slot)
1172     {
1173     case EQ_WEAPON:
1174         // Hands can have more than just weapons.
1175         if ((item = you.slot_item(slot))
1176             && item->base_type == OBJ_WEAPONS
1177             && is_unrandom_artefact(*item)
1178             && item->special == unrand_index)
1179         {
1180             return true;
1181         }
1182         break;
1183
1184     case EQ_RINGS:
1185         for (int slots = EQ_LEFT_RING; slots < NUM_EQUIP; ++slots)
1186         {
1187             if (slots == EQ_AMULET)
1188                 continue;
1189
1190             if ((item = you.slot_item(static_cast<equipment_type>(slots)))
1191                 && is_unrandom_artefact(*item)
1192                 && item->special == unrand_index)
1193             {
1194                 return true;
1195             }
1196         }
1197         break;
1198
1199     case EQ_NONE:
1200     case EQ_STAFF:
1201     case EQ_LEFT_RING:
1202     case EQ_RIGHT_RING:
1203     case EQ_RINGS_PLUS:
1204     case EQ_RINGS_PLUS2:
1205     case EQ_ALL_ARMOUR:
1206         // no unrandarts for these slots.
1207         break;
1208
1209     default:
1210         if (slot <= EQ_NONE || slot >= NUM_EQUIP)
1211             die("invalid slot: %d", slot);
1212         // Check a specific slot.
1213         if ((item = you.slot_item(slot))
1214             && is_unrandom_artefact(*item)
1215             && item->special == unrand_index)
1216         {
1217             return true;
1218         }
1219         break;
1220     }
1221
1222     return false;
1223 }
1224
1225 // Given an adjacent monster, returns true if the player can hit it (the
1226 // monster should not be submerged, or be submerged in shallow water if
1227 // the player has a polearm).
1228 bool player_can_hit_monster(const monster* mon)
1229 {
1230     if (!mon->submerged())
1231         return true;
1232
1233     if (grd(mon->pos()) != DNGN_SHALLOW_WATER)
1234         return false;
1235
1236     const item_def *weapon = you.weapon();
1237     return (weapon && weapon_skill(*weapon) == SK_POLEARMS);
1238 }
1239
1240 bool player_can_hear(const coord_def& p, int hear_distance)
1241 {
1242     return (!silenced(p)
1243             && !silenced(you.pos())
1244             && you.pos().distance_from(p) <= hear_distance);
1245 }
1246
1247 int player_teleport(bool calc_unid)
1248 {
1249     ASSERT(!crawl_state.game_is_arena());
1250
1251     // Don't allow any form of teleportation in Sprint.
1252     if (crawl_state.game_is_sprint())
1253         return 0;
1254
1255     int tp = 0;
1256
1257     // All effects negated by magical suppression should go in here.
1258     if (!you.suppressed())
1259     {
1260         // rings (keep in sync with _equip_jewellery_effect)
1261         tp += 8 * you.wearing(EQ_RINGS, RING_TELEPORTATION, calc_unid);
1262
1263         // randart weapons only
1264         if (you.weapon()
1265             && you.weapon()->base_type == OBJ_WEAPONS
1266             && is_artefact(*you.weapon()))
1267         {
1268             tp += you.scan_artefacts(ARTP_CAUSE_TELEPORTATION, calc_unid);
1269         }
1270     }
1271
1272     // mutations
1273     tp += player_mutation_level(MUT_TELEPORT) * 3;
1274
1275     return tp;
1276 }
1277
1278 // Computes bonuses to regeneration from most sources. Does not handle
1279 // slow healing, vampireness, or Trog's Hand.
1280 static int _player_bonus_regen()
1281 {
1282     int rr = 0;
1283
1284     // Trog's Hand is handled separately so that it will bypass slow healing,
1285     // and it overrides the spell.
1286     if (you.duration[DUR_REGENERATION]
1287         && !you.attribute[ATTR_DIVINE_REGENERATION])
1288     {
1289         rr += 100;
1290     }
1291
1292     // All effects negated by magical suppression should go in here.
1293     if (!you.suppressed())
1294     {
1295         // Rings.
1296         rr += 40 * you.wearing(EQ_RINGS, RING_REGENERATION);
1297
1298         // Artefacts
1299         rr += you.scan_artefacts(ARTP_REGENERATION);
1300
1301         // Troll leather (except for trolls).
1302         if ((you.wearing(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
1303              || you.wearing(EQ_BODY_ARMOUR, ARM_TROLL_HIDE))
1304             && you.species != SP_TROLL)
1305         {
1306             rr += 30;
1307         }
1308     }
1309
1310     // Fast heal mutation.
1311     rr += player_mutation_level(MUT_REGENERATION) * 20;
1312
1313     // Powered By Death mutation, boosts regen by 10 per corpse in
1314     // a mutation_level * 3 (3/6/9) radius, to a maximum of 7
1315     // corpses.  If and only if the duration of the effect is
1316     // still active.
1317     if (you.duration[DUR_POWERED_BY_DEATH])
1318         rr += handle_pbd_corpses(false) * 100;
1319
1320     return rr;
1321 }
1322
1323 // Slow healing mutation: slows or stops regeneration when monsters are
1324 // visible at level 1 or 2 respectively, stops regeneration at level 3.
1325 static int _slow_heal_rate()
1326 {
1327     if (player_mutation_level(MUT_SLOW_HEALING) == 3)
1328         return 0;
1329
1330     for (monster_near_iterator mi(&you); mi; ++mi)
1331     {
1332         if (!mons_is_firewood(*mi)
1333             && !mi->wont_attack()
1334             && !mi->neutral())
1335         {
1336             return 2 - player_mutation_level(MUT_SLOW_HEALING);
1337         }
1338     }
1339     return 2;
1340 }
1341
1342 int player_regen()
1343 {
1344     int rr = you.hp_max / 3;
1345
1346     if (rr > 20)
1347         rr = 20 + ((rr - 20) / 2);
1348
1349     // Add in miscellaneous bonuses
1350     rr += _player_bonus_regen();
1351
1352     // Before applying other effects, make sure that there's something
1353     // to heal.
1354     rr = max(1, rr);
1355
1356     // Healing depending on satiation.
1357     // The better-fed you are, the faster you heal.
1358     if (you.species == SP_VAMPIRE)
1359     {
1360         if (you.hunger_state == HS_STARVING)
1361             rr = 0;   // No regeneration for starving vampires.
1362         else if (you.hunger_state == HS_ENGORGED)
1363             rr += 20; // More bonus regeneration for engorged vampires.
1364         else if (you.hunger_state < HS_SATIATED)
1365             rr /= 2;  // Halved regeneration for hungry vampires.
1366         else if (you.hunger_state >= HS_FULL)
1367             rr += 10; // Bonus regeneration for full vampires.
1368     }
1369
1370     // Compared to other races, a starting djinni would have regen of 4 (hp)
1371     // plus 17 (mp).  So let's compensate them early; they can stand getting
1372     // shafted on the total regen rates later on.
1373     if (you.species == SP_DJINNI)
1374         if (you.hp_max < 100)
1375             rr += (100 - you.hp_max) / 6;
1376
1377     // Slow heal mutation.
1378     if (player_mutation_level(MUT_SLOW_HEALING) > 0)
1379     {
1380         rr *= _slow_heal_rate();
1381         rr /= 2;
1382     }
1383     if (you.stat_zero[STAT_STR])
1384         rr /= 4;
1385
1386     if (you.disease)
1387         rr = 0;
1388
1389     // Trog's Hand.  This circumvents the slow healing effect.
1390     if (you.attribute[ATTR_DIVINE_REGENERATION])
1391         rr += 100;
1392
1393     return rr;
1394 }
1395
1396 int player_hunger_rate(bool temp)
1397 {
1398     int hunger = 3;
1399
1400     if (temp && you.form == TRAN_BAT)
1401         return 1;
1402
1403     if (you.species == SP_TROLL)
1404         hunger += 3;            // in addition to the +3 for fast metabolism
1405
1406     if (temp && you.duration[DUR_REGENERATION] && you.hp < you.hp_max)
1407         hunger += 4;
1408
1409     if (temp)
1410     {
1411         if (you.duration[DUR_INVIS])
1412             hunger += 5;
1413
1414         // Berserk has its own food penalty - excluding berserk haste.
1415         // Doubling the hunger cost for haste so that the per turn hunger
1416         // is consistent now that a hasted turn causes 50% the normal hunger
1417         // -cao
1418         if (you.duration[DUR_HASTE])
1419             hunger += haste_mul(5);
1420     }
1421
1422     if (you.species == SP_VAMPIRE)
1423     {
1424         switch (you.hunger_state)
1425         {
1426         case HS_STARVING:
1427         case HS_NEAR_STARVING:
1428             hunger -= 3;
1429             break;
1430         case HS_VERY_HUNGRY:
1431             hunger -= 2;
1432             break;
1433         case HS_HUNGRY:
1434             hunger--;
1435             break;
1436         case HS_SATIATED:
1437             break;
1438         case HS_FULL:
1439             hunger++;
1440             break;
1441         case HS_VERY_FULL:
1442             hunger += 2;
1443             break;
1444         case HS_ENGORGED:
1445             hunger += 3;
1446         }
1447     }
1448     else
1449     {
1450         hunger += player_mutation_level(MUT_FAST_METABOLISM)
1451                 - player_mutation_level(MUT_SLOW_METABOLISM);
1452     }
1453
1454     // burden
1455     if (temp)
1456         hunger += you.burden_state;
1457
1458     // All effects negated by magical suppression should go in here.
1459     if (!you.suppressed())
1460     {
1461         if (you.hp < you.hp_max
1462             && player_mutation_level(MUT_SLOW_HEALING) < 3)
1463         {
1464             // rings
1465             hunger += 3 * you.wearing(EQ_RINGS, RING_REGENERATION);
1466
1467             // troll leather
1468             if (you.species != SP_TROLL
1469                 && (you.wearing(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
1470                     || you.wearing(EQ_BODY_ARMOUR, ARM_TROLL_HIDE)))
1471             {
1472                 hunger += coinflip() ? 2 : 1;
1473             }
1474         }
1475
1476         hunger += 4 * you.wearing(EQ_RINGS, RING_HUNGER);
1477
1478         // randarts
1479         hunger += you.scan_artefacts(ARTP_METABOLISM);
1480
1481         // sustenance affects things at the end, because it is multiplicative
1482         for (int s = you.wearing(EQ_RINGS, RING_SUSTENANCE); s > 0; s--)
1483             hunger = hunger * 3 / 5;
1484     }
1485
1486     // If Cheibriados has slowed your life processes, you will hunger less.
1487     if (you_worship(GOD_CHEIBRIADOS) && you.piety >= piety_breakpoint(0))
1488         hunger = hunger * 3 / 4;
1489
1490     if (hunger < 1)
1491         hunger = 1;
1492
1493     return hunger;
1494 }
1495
1496 int player_spell_levels(void)
1497 {
1498     int sl = you.experience_level - 1 + you.skill(SK_SPELLCASTING, 2, true);
1499
1500     bool fireball = false;
1501     bool delayed_fireball = false;
1502
1503     if (sl > 99)
1504         sl = 99;
1505
1506     for (int i = 0; i < MAX_KNOWN_SPELLS; i++)
1507     {
1508         if (you.spells[i] == SPELL_FIREBALL)
1509             fireball = true;
1510         else if (you.spells[i] == SPELL_DELAYED_FIREBALL)
1511             delayed_fireball = true;
1512
1513         if (you.spells[i] != SPELL_NO_SPELL)
1514             sl -= spell_difficulty(you.spells[i]);
1515     }
1516
1517     // Fireball is free for characters with delayed fireball
1518     if (fireball && delayed_fireball)
1519         sl += spell_difficulty(SPELL_FIREBALL);
1520
1521     // Note: This can happen because of level drain.  Maybe we should
1522     // force random spells out when that happens. -- bwr
1523     if (sl < 0)
1524         sl = 0;
1525
1526     return sl;
1527 }
1528
1529 int player_likes_chunks(bool permanently)
1530 {
1531     return you.gourmand(true, !permanently)
1532            ? 3 : player_mutation_level(MUT_CARNIVOROUS);
1533 }
1534
1535 // If temp is set to false, temporary sources or resistance won't be counted.
1536 int player_res_fire(bool calc_unid, bool temp, bool items)
1537 {
1538     if (you.species == SP_DJINNI)
1539         return 4; // full immunity
1540
1541     int rf = 0;
1542
1543     // All effects negated by magical suppression should go in here.
1544     if (!you.suppressed())
1545     {
1546         if (items)
1547         {
1548             // rings of fire resistance/fire
1549             rf += you.wearing(EQ_RINGS, RING_PROTECTION_FROM_FIRE, calc_unid);
1550             rf += you.wearing(EQ_RINGS, RING_FIRE, calc_unid);
1551
1552             // rings of ice
1553             rf -= you.wearing(EQ_RINGS, RING_ICE, calc_unid);
1554
1555             // Staves
1556             rf += you.wearing(EQ_STAFF, STAFF_FIRE, calc_unid);
1557
1558             // body armour:
1559             rf += 2 * you.wearing(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
1560             rf += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1561             rf -= you.wearing(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
1562             rf += 2 * you.wearing(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
1563             rf += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1564             rf -= you.wearing(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
1565
1566             // ego armours
1567             rf += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_FIRE_RESISTANCE);
1568             rf += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
1569
1570             // randart weapons:
1571             rf += you.scan_artefacts(ARTP_FIRE, calc_unid);
1572
1573             // dragonskin cloak: 0.5 to draconic resistances
1574             if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN)
1575                 && coinflip())
1576             {
1577                 rf++;
1578             }
1579         }
1580     }
1581
1582     // species:
1583     if (you.species == SP_MUMMY)
1584         rf--;
1585
1586     if (you.species == SP_LAVA_ORC)
1587     {
1588         if (temperature_effect(LORC_FIRE_RES_I))
1589             rf++;
1590         if (temperature_effect(LORC_FIRE_RES_II))
1591             rf++;
1592         if (temperature_effect(LORC_FIRE_RES_III))
1593             rf++;
1594     }
1595
1596     // mutations:
1597     rf += player_mutation_level(MUT_HEAT_RESISTANCE, temp);
1598     rf += player_mutation_level(MUT_MOLTEN_SCALES, temp) == 3 ? 1 : 0;
1599
1600     // spells:
1601     if (temp)
1602     {
1603         if (you.duration[DUR_RESISTANCE])
1604             rf++;
1605
1606         if (you.duration[DUR_FIRE_SHIELD])
1607             rf += 2;
1608
1609         if (you.duration[DUR_FIRE_VULN])
1610             rf--;
1611
1612         // transformations:
1613         switch (you.form)
1614         {
1615         case TRAN_TREE:
1616             if (you_worship(GOD_FEDHAS) && !player_under_penance())
1617                 rf++;
1618             break;
1619         case TRAN_ICE_BEAST:
1620             rf--;
1621             break;
1622         case TRAN_WISP:
1623             rf += 2;
1624             break;
1625         case TRAN_DRAGON:
1626         {
1627             monster_type drag = dragon_form_dragon_type();
1628             if (drag == MONS_DRAGON)
1629                 rf += 2;
1630             else if (drag == MONS_ICE_DRAGON)
1631                 rf--;
1632             break;
1633         }
1634         default:
1635             break;
1636         }
1637     }
1638
1639     if (rf < -3)
1640         rf = -3;
1641     else if (rf > 3)
1642         rf = 3;
1643
1644     return rf;
1645 }
1646
1647 int player_res_steam(bool calc_unid, bool temp, bool items)
1648 {
1649     int res = 0;
1650     const int rf = player_res_fire(calc_unid, temp, items);
1651
1652     if (you.species == SP_PALE_DRACONIAN)
1653         res += 2;
1654
1655     // All effects negated by magical suppression should go in here.
1656     if (!you.suppressed())
1657     {
1658         if (items && you.wearing(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))
1659             res += 2;
1660
1661         if (items && you.wearing(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_HIDE))
1662             res += 2;
1663     }
1664
1665     res += (rf < 0) ? rf
1666                     : (rf + 1) / 2;
1667
1668     if (res > 3)
1669         res = 3;
1670
1671     return res;
1672 }
1673
1674 int player_res_cold(bool calc_unid, bool temp, bool items)
1675 {
1676     int rc = 0;
1677
1678     if (temp)
1679     {
1680         if (you.duration[DUR_RESISTANCE])
1681             rc++;
1682
1683         if (you.duration[DUR_FIRE_SHIELD])
1684             rc -= 2;
1685
1686         // transformations:
1687         switch (you.form)
1688         {
1689         case TRAN_TREE:
1690             if (you_worship(GOD_FEDHAS) && !player_under_penance())
1691                 rc++;
1692             break;
1693         case TRAN_ICE_BEAST:
1694             rc += 3;
1695             break;
1696         case TRAN_WISP:
1697             rc += 2;
1698             break;
1699         case TRAN_DRAGON:
1700         {
1701             monster_type form = dragon_form_dragon_type();
1702             if (form == MONS_DRAGON)
1703                 rc--;
1704             else if (form == MONS_ICE_DRAGON)
1705                 rc += 2;
1706             break;
1707         }
1708         case TRAN_LICH:
1709             rc++;
1710             break;
1711         default:
1712             break;
1713         }
1714
1715         if (you.species == SP_VAMPIRE)
1716         {
1717             if (you.hunger_state <= HS_NEAR_STARVING)
1718                 rc += 2;
1719             else if (you.hunger_state < HS_SATIATED)
1720                 rc++;
1721         }
1722
1723         if (you.species == SP_LAVA_ORC && temperature_effect(LORC_COLD_VULN))
1724             rc--;
1725     }
1726
1727     // All effects negated by magical suppression should go in here.
1728     if (!you.suppressed())
1729     {
1730         if (items)
1731         {
1732             // rings of cold resistance/ice
1733             rc += you.wearing(EQ_RINGS, RING_PROTECTION_FROM_COLD, calc_unid);
1734             rc += you.wearing(EQ_RINGS, RING_ICE, calc_unid);
1735
1736             // rings of fire
1737             rc -= you.wearing(EQ_RINGS, RING_FIRE, calc_unid);
1738
1739             // Staves
1740             rc += you.wearing(EQ_STAFF, STAFF_COLD, calc_unid);
1741
1742             // body armour:
1743             rc += 2 * you.wearing(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
1744             rc += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1745             rc -= you.wearing(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_ARMOUR);
1746             rc += 2 * you.wearing(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
1747             rc += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1748             rc -= you.wearing(EQ_BODY_ARMOUR, ARM_FIRE_DRAGON_HIDE);
1749
1750             // ego armours
1751             rc += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_COLD_RESISTANCE);
1752             rc += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
1753
1754             // randart weapons:
1755             rc += you.scan_artefacts(ARTP_COLD, calc_unid);
1756
1757             // dragonskin cloak: 0.5 to draconic resistances
1758             if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
1759                 rc++;
1760         }
1761     }
1762
1763     // species:
1764     if (you.species == SP_DJINNI)
1765         rc--;
1766
1767     // mutations:
1768     rc += player_mutation_level(MUT_COLD_RESISTANCE, temp);
1769     rc += player_mutation_level(MUT_ICY_BLUE_SCALES, temp) == 3 ? 1 : 0;
1770     rc += player_mutation_level(MUT_SHAGGY_FUR, temp) == 3 ? 1 : 0;
1771
1772     if (rc < -3)
1773         rc = -3;
1774     else if (rc > 3)
1775         rc = 3;
1776
1777     return rc;
1778 }
1779
1780 bool player::res_corr(bool calc_unid, bool items) const
1781 {
1782     if (religion == GOD_JIYVA && piety >= piety_breakpoint(2))
1783         return true;
1784
1785     if (form == TRAN_JELLY || form == TRAN_WISP)
1786         return 1;
1787
1788     if (items && !suppressed())
1789     {
1790         // dragonskin cloak: 0.5 to draconic resistances
1791         if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN)
1792             && coinflip())
1793         {
1794             return true;
1795         }
1796     }
1797
1798     if ((form_keeps_mutations() || form == TRAN_DRAGON)
1799         && species == SP_YELLOW_DRACONIAN)
1800     {
1801         return true;
1802     }
1803
1804     if (form_keeps_mutations()
1805         && player_mutation_level(MUT_YELLOW_SCALES) >= 3)
1806     {
1807         return true;
1808     }
1809
1810     return actor::res_corr(calc_unid, items);
1811 }
1812
1813 int player_res_acid(bool calc_unid, bool items)
1814 {
1815     if (you.form == TRAN_JELLY || you.form == TRAN_WISP)
1816         return 3;
1817
1818     return you.res_corr(calc_unid, items) ? 1 : 0;
1819 }
1820
1821 // Returns a factor X such that post-resistance acid damage can be calculated
1822 // as pre_resist_damage * X / 100.
1823 int player_acid_resist_factor()
1824 {
1825     int rA = player_res_acid();
1826     if (rA >= 3)
1827         return 0;
1828     else if (rA >= 1)
1829         return 50;
1830     return 100;
1831 }
1832
1833 int player_res_electricity(bool calc_unid, bool temp, bool items)
1834 {
1835     int re = 0;
1836
1837     // All effects negated by magical suppression should go in here.
1838     if (!you.suppressed())
1839     {
1840         if (items)
1841         {
1842             // staff
1843             re += you.wearing(EQ_STAFF, STAFF_AIR, calc_unid);
1844
1845             // body armour:
1846             re += you.wearing(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_ARMOUR);
1847             re += you.wearing(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_HIDE);
1848
1849             // randart weapons:
1850             re += you.scan_artefacts(ARTP_ELECTRICITY, calc_unid);
1851
1852             // dragonskin cloak: 0.5 to draconic resistances
1853             if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
1854                 re++;
1855         }
1856     }
1857
1858     // mutations:
1859     re += player_mutation_level(MUT_THIN_METALLIC_SCALES, temp) == 3 ? 1 : 0;
1860     re += player_mutation_level(MUT_SHOCK_RESISTANCE, temp);
1861
1862     if (temp)
1863     {
1864         if (you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION])
1865             return 3;
1866
1867         if (you.duration[DUR_RESISTANCE])
1868             re++;
1869
1870         // transformations:
1871         if (you.form == TRAN_STATUE || you.form == TRAN_WISP)
1872             re += 1;
1873
1874         if (re > 1)
1875             re = 1;
1876     }
1877
1878     return re;
1879 }
1880
1881 bool player_control_teleport(bool temp)
1882 {
1883     return ((temp && you.duration[DUR_CONTROL_TELEPORT])
1884             || crawl_state.game_is_zotdef());
1885 }
1886
1887 int player_res_torment(bool, bool temp)
1888 {
1889     return (player_mutation_level(MUT_TORMENT_RESISTANCE)
1890             || you.form == TRAN_LICH
1891             || you.form == TRAN_FUNGUS
1892             || you.form == TRAN_TREE
1893             || you.form == TRAN_WISP
1894             || you.species == SP_VAMPIRE && you.hunger_state == HS_STARVING
1895             || you.petrified()
1896             || (temp && player_mutation_level(MUT_STOCHASTIC_TORMENT_RESISTANCE)
1897                 && coinflip()));
1898 }
1899
1900 // Kiku protects you from torment to a degree.
1901 int player_kiku_res_torment()
1902 {
1903     return (you_worship(GOD_KIKUBAAQUDGHA)
1904             && !player_under_penance()
1905             && you.piety >= piety_breakpoint(3)
1906             && !you.gift_timeout); // no protection during pain branding weapon
1907 }
1908
1909 // If temp is set to false, temporary sources or resistance won't be counted.
1910 int player_res_poison(bool calc_unid, bool temp, bool items)
1911 {
1912     if (you.is_undead == US_SEMI_UNDEAD ? you.hunger_state == HS_STARVING
1913             : you.is_undead && (temp || you.form != TRAN_LICH)
1914               || you.is_artificial())
1915     {
1916         return 3;
1917     }
1918
1919     int rp = 0;
1920
1921     // All effects negated by magical suppression should go in here.
1922     if (!you.suppressed())
1923     {
1924         if (items)
1925         {
1926             // rings of poison resistance
1927             rp += you.wearing(EQ_RINGS, RING_POISON_RESISTANCE, calc_unid);
1928
1929             // Staves
1930             rp += you.wearing(EQ_STAFF, STAFF_POISON, calc_unid);
1931
1932             // ego armour:
1933             rp += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE);
1934
1935             // body armour:
1936             rp += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1937             rp += you.wearing(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_ARMOUR);
1938             rp += you.wearing(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1939             rp += you.wearing(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_HIDE);
1940
1941             // randart weapons:
1942             rp += you.scan_artefacts(ARTP_POISON, calc_unid);
1943
1944             // dragonskin cloak: 0.5 to draconic resistances
1945             if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
1946                 rp++;
1947         }
1948     }
1949
1950     // mutations:
1951     rp += player_mutation_level(MUT_POISON_RESISTANCE, temp);
1952     rp += player_mutation_level(MUT_SLIMY_GREEN_SCALES, temp) == 3 ? 1 : 0;
1953
1954     // Only thirsty vampires are naturally poison resistant.
1955     if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED)
1956         rp++;
1957
1958     if (temp)
1959     {
1960         // potions/cards:
1961         if (you.duration[DUR_RESISTANCE])
1962             rp++;
1963
1964         // transformations:
1965         switch (you.form)
1966         {
1967         case TRAN_ICE_BEAST:
1968         case TRAN_STATUE:
1969         case TRAN_DRAGON:
1970         case TRAN_FUNGUS:
1971         case TRAN_TREE:
1972         case TRAN_JELLY:
1973         case TRAN_WISP:
1974             rp++;
1975             break;
1976         default:
1977             break;
1978         }
1979
1980         if (you.petrified())
1981             rp++;
1982     }
1983
1984     // Give vulnerability for Spider Form, and only let one level of rP to make
1985     // up for it (never be poison resistant in Spider Form).
1986     rp = (rp > 0 ? 1 : 0);
1987
1988     if (temp)
1989     {
1990         if (you.form == TRAN_SPIDER)
1991             rp--;
1992     }
1993
1994     return rp;
1995 }
1996
1997 static int _maybe_reduce_poison(int amount)
1998 {
1999     int rp = player_res_poison(true, true, true);
2000
2001     if (rp <= 0)
2002         return amount;
2003
2004     int reduction = binomial_generator(amount, 90);
2005     int new_amount = amount - reduction;
2006
2007     if (amount != new_amount)
2008         dprf("Poison reduced (%d -> %d)", amount, new_amount);
2009     else
2010         dprf("Poison not reduced (%d)", amount);
2011
2012     return new_amount;
2013 }
2014
2015 int player_res_sticky_flame(bool calc_unid, bool temp, bool items)
2016 {
2017     int rsf = 0;
2018
2019     if (you.species == SP_MOTTLED_DRACONIAN)
2020         rsf++;
2021
2022     // All effects negated by magical suppression should go in here.
2023     if (!you.suppressed())
2024     {
2025         if (items && you.wearing(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_ARMOUR))
2026             rsf++;
2027         if (items && you.wearing(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_HIDE))
2028             rsf++;
2029
2030         // dragonskin cloak: 0.5 to draconic resistances
2031         if (items && calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
2032             rsf++;
2033     }
2034
2035     if (you.form == TRAN_WISP)
2036         rsf++;
2037
2038     if (rsf > 1)
2039         rsf = 1;
2040
2041     return rsf;
2042 }
2043
2044 int player_spec_death()
2045 {
2046     int sd = 0;
2047
2048     // All effects negated by magical suppression should go in here.
2049     if (!you.suppressed())
2050     {
2051         // Staves
2052         sd += you.wearing(EQ_STAFF, STAFF_DEATH);
2053     }
2054
2055     // species:
2056     if (you.species == SP_MUMMY)
2057     {
2058         if (you.experience_level >= 13)
2059             sd++;
2060         if (you.experience_level >= 26)
2061             sd++;
2062     }
2063
2064     // transformations:
2065     if (you.form == TRAN_LICH)
2066         sd++;
2067
2068     return sd;
2069 }
2070
2071 int player_spec_fire()
2072 {
2073     int sf = 0;
2074
2075     // All effects negated by magical suppression should go in here.
2076     if (!you.suppressed())
2077     {
2078         // staves:
2079         sf += you.wearing(EQ_STAFF, STAFF_FIRE);
2080
2081         // rings of fire:
2082         sf += you.wearing(EQ_RINGS, RING_FIRE);
2083     }
2084
2085     if (you.species == SP_LAVA_ORC && temperature_effect(LORC_FIRE_BOOST))
2086         sf++;
2087
2088     if (you.duration[DUR_FIRE_SHIELD])
2089         sf++;
2090
2091     return sf;
2092 }
2093
2094 int player_spec_cold()
2095 {
2096     int sc = 0;
2097
2098     // All effects negated by magical suppression should go in here.
2099     if (!you.suppressed())
2100     {
2101         // staves:
2102         sc += you.wearing(EQ_STAFF, STAFF_COLD);
2103
2104         // rings of ice:
2105         sc += you.wearing(EQ_RINGS, RING_ICE);
2106     }
2107
2108     if (you.species == SP_LAVA_ORC
2109         && (temperature_effect(LORC_LAVA_BOOST)
2110             || temperature_effect(LORC_FIRE_BOOST)))
2111     {
2112         sc--;
2113     }
2114
2115     return sc;
2116 }
2117
2118 int player_spec_earth()
2119 {
2120     int se = 0;
2121
2122     // All effects negated by magical suppression should go in here.
2123     if (!you.suppressed())
2124     {
2125         // Staves
2126         se += you.wearing(EQ_STAFF, STAFF_EARTH);
2127     }
2128
2129     return se;
2130 }
2131
2132 int player_spec_air()
2133 {
2134     int sa = 0;
2135
2136     // All effects negated by magical suppression should go in here.
2137     if (!you.suppressed())
2138     {
2139         // Staves
2140         sa += you.wearing(EQ_STAFF, STAFF_AIR);
2141     }
2142
2143     return sa;
2144 }
2145
2146 int player_spec_conj()
2147 {
2148     int sc = 0;
2149
2150     // All effects negated by magical suppression should go in here.
2151     if (!you.suppressed())
2152     {
2153         // Staves
2154         sc += you.wearing(EQ_STAFF, STAFF_CONJURATION);
2155     }
2156
2157     return sc;
2158 }
2159
2160 int player_spec_hex()
2161 {
2162     int sh = 0;
2163
2164     // All effects negated by magical suppression should go in here.
2165     if (!you.suppressed())
2166     {
2167         // Unrands
2168         if (player_equip_unrand(UNRAND_BOTONO))
2169             sh++;
2170     }
2171
2172     return sh;
2173 }
2174
2175 int player_spec_charm()
2176 {
2177     // Nothing, for the moment.
2178     return 0;
2179 }
2180
2181 int player_spec_summ()
2182 {
2183     int ss = 0;
2184
2185     // All effects negated by magical suppression should go in here.
2186     if (!you.suppressed())
2187     {
2188         // Staves
2189         ss += you.wearing(EQ_STAFF, STAFF_SUMMONING);
2190     }
2191
2192     return ss;
2193 }
2194
2195 int player_spec_poison()
2196 {
2197     int sp = 0;
2198
2199     // All effects negated by magical suppression should go in here.
2200     if (!you.suppressed())
2201     {
2202         // Staves
2203         sp += you.wearing(EQ_STAFF, STAFF_POISON);
2204
2205         if (player_equip_unrand(UNRAND_OLGREB))
2206             sp++;
2207     }
2208
2209     return sp;
2210 }
2211
2212 int player_energy()
2213 {
2214     int pe = 0;
2215
2216     // All effects negated by magical suppression should go in here.
2217     if (!you.suppressed())
2218     {
2219         // Staves
2220         pe += you.wearing(EQ_STAFF, STAFF_ENERGY);
2221     }
2222
2223     return pe;
2224 }
2225
2226 // If temp is set to false, temporary sources of resistance won't be
2227 // counted.
2228 int player_prot_life(bool calc_unid, bool temp, bool items)
2229 {
2230     int pl = 0;
2231
2232     // Hunger is temporary, true, but that's something you can control,
2233     // especially as life protection only increases the hungrier you
2234     // get.
2235     if (you.species == SP_VAMPIRE)
2236     {
2237         switch (you.hunger_state)
2238         {
2239         case HS_STARVING:
2240         case HS_NEAR_STARVING:
2241             pl = 3;
2242             break;
2243         case HS_VERY_HUNGRY:
2244         case HS_HUNGRY:
2245             pl = 2;
2246             break;
2247         case HS_SATIATED:
2248             pl = 1;
2249             break;
2250         default:
2251             break;
2252         }
2253     }
2254
2255     // Same here.  Your piety status, and, hence, TSO's protection, is
2256     // something you can more or less control.
2257     if (you_worship(GOD_SHINING_ONE) && you.piety > pl * 50)
2258         pl = you.piety / 50;
2259
2260     if (temp)
2261     {
2262         // Now, transformations could stop at any time.
2263         switch (you.form)
2264         {
2265         case TRAN_STATUE:
2266             pl++;
2267             break;
2268         case TRAN_FUNGUS:
2269         case TRAN_TREE:
2270         case TRAN_WISP:
2271         case TRAN_LICH:
2272             pl += 3;
2273             break;
2274         default:
2275            break;
2276         }
2277
2278         // completely stoned, unlike statue which has some life force
2279         if (you.petrified())
2280             pl += 3;
2281     }
2282
2283     // All effects negated by magical suppression should go in here.
2284     if (!you.suppressed())
2285     {
2286         if (items)
2287         {
2288             if (you.wearing(EQ_AMULET, AMU_WARDING, calc_unid))
2289                 pl++;
2290
2291             // rings
2292             pl += you.wearing(EQ_RINGS, RING_LIFE_PROTECTION, calc_unid);
2293
2294             // armour (checks body armour only)
2295             pl += you.wearing_ego(EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY);
2296
2297             // pearl dragon counts
2298             pl += you.wearing(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_ARMOUR);
2299             pl += you.wearing(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_HIDE);
2300
2301             // randart wpns
2302             pl += you.scan_artefacts(ARTP_NEGATIVE_ENERGY, calc_unid);
2303
2304             // dragonskin cloak: 0.5 to draconic resistances
2305             // this one is dubious (no pearl draconians)
2306             if (calc_unid && player_equip_unrand(UNRAND_DRAGONSKIN) && coinflip())
2307                 pl++;
2308
2309             pl += you.wearing(EQ_STAFF, STAFF_DEATH, calc_unid);
2310         }
2311     }
2312
2313     // undead/demonic power
2314     pl += player_mutation_level(MUT_NEGATIVE_ENERGY_RESISTANCE, temp);
2315
2316     pl = min(3, pl);
2317
2318     return pl;
2319 }
2320
2321 // New player movement speed system... allows for a bit more than
2322 // "player runs fast" and "player walks slow" in that the speed is
2323 // actually calculated (allowing for centaurs to get a bonus from
2324 // swiftness and other such things).  Levels of the mutation now
2325 // also have meaning (before they all just meant fast).  Most of
2326 // this isn't as fast as it used to be (6 for having anything), but
2327 // even a slight speed advantage is very good... and we certainly don't
2328 // want to go past 6 (see below). -- bwr
2329 int player_movement_speed(bool ignore_burden)
2330 {
2331     int mv = 10;
2332
2333     // transformations
2334     if (you.form == TRAN_SPIDER)
2335         mv = 8;
2336     else if (you.form == TRAN_BAT)
2337         mv = 5; // but allowed minimum is six
2338     else if (you.form == TRAN_PIG)
2339         mv = 7;
2340     else if (you.form == TRAN_PORCUPINE || you.form == TRAN_WISP)
2341         mv = 8;
2342     else if (you.form == TRAN_JELLY)
2343         mv = 11;
2344     else if (you.fishtail)
2345         mv = 6;
2346
2347     // moving on liquefied ground takes longer
2348     if (you.liquefied_ground())
2349         mv += 3;
2350
2351     // armour
2352     if (you.run())
2353         mv -= 1;
2354     if (!you.suppressed())
2355         mv += 2 * you.wearing_ego(EQ_ALL_ARMOUR, SPARM_PONDEROUSNESS);
2356
2357     // Cheibriados
2358     if (you_worship(GOD_CHEIBRIADOS))
2359         mv += 2 + min(div_rand_round(you.piety, 20), 8);
2360
2361     // Tengu can move slightly faster when flying.
2362     if (you.tengu_flight())
2363         mv--;
2364
2365     // Swiftness doesn't work in liquid.
2366     if (you.duration[DUR_SWIFTNESS] > 0 && !you.in_liquid())
2367         mv -= 2;
2368
2369     if (you.duration[DUR_GRASPING_ROOTS])
2370         mv += 5;
2371
2372     // Unpowered djinn flight is cumbersome.
2373     if (is_hovering())
2374         mv += 5;
2375
2376     // Mutations: -2, -3, -4, unless innate and shapechanged.
2377     // Not when swimming, since it is "cover the ground quickly".
2378     if (player_mutation_level(MUT_FAST) > 0 && !you.swimming())
2379         mv -= player_mutation_level(MUT_FAST) + 1;
2380
2381     if (player_mutation_level(MUT_SLOW) > 0 && !you.swimming())
2382     {
2383         mv *= 10 + player_mutation_level(MUT_SLOW) * 2;
2384         mv /= 10;
2385     }
2386
2387     // Burden
2388     if (!ignore_burden)
2389     {
2390         if (you.burden_state == BS_ENCUMBERED)
2391             mv++;
2392         else if (you.burden_state == BS_OVERLOADED)
2393             mv += 3;
2394     }
2395
2396     // We'll use the old value of six as a minimum, with haste this could
2397     // end up as a speed of three, which is about as fast as we want
2398     // the player to be able to go (since 3 is 3.33x as fast and 2 is 5x,
2399     // which is a bit of a jump, and a bit too fast) -- bwr
2400     if (mv < 6)
2401         mv = 6;
2402
2403     return mv;
2404 }
2405
2406 // This function differs from the above in that it's used to set the
2407 // initial time_taken value for the turn.  Everything else (movement,
2408 // spellcasting, combat) applies a ratio to this value.
2409 int player_speed(void)
2410 {
2411     int ps = 10;
2412
2413     // When paralysed, speed is irrelevant.
2414     if (you.cannot_act())
2415         return ps;
2416
2417     for (int i = 0; i < NUM_STATS; ++i)
2418         if (you.stat_zero[i])
2419             ps *= 2;
2420
2421     if (you.duration[DUR_SLOW])
2422         ps = haste_mul(ps);
2423
2424     if (you.duration[DUR_BERSERK] && !you_worship(GOD_CHEIBRIADOS))
2425         ps = berserk_div(ps);
2426     else if (you.duration[DUR_HASTE])
2427         ps = haste_div(ps);
2428
2429     if (you.form == TRAN_STATUE || you.duration[DUR_PETRIFYING])
2430     {
2431         ps *= 15;
2432         ps /= 10;
2433     }
2434
2435     if (you.form == TRAN_TREE)
2436     {
2437         ps *= 15 - you.experience_level / 5;
2438         ps /= 10;
2439     }
2440
2441     return ps;
2442 }
2443
2444 // Get level of player mutation, ignoring mutations with an activity level
2445 // less than minact (unless they have MUTACT_HUNGER, in which case check
2446 // the player's hunger state).
2447 static int _mut_level(mutation_type mut, mutation_activity_type minact)
2448 {
2449     const int mlevel = you.mutation[mut];
2450
2451     const mutation_activity_type active = mutation_activity_level(mut);
2452
2453     if (active >= minact)
2454         return mlevel;
2455     else if (active == MUTACT_HUNGER)
2456     {
2457         switch (you.hunger_state)
2458         {
2459         case HS_ENGORGED:
2460             return mlevel;
2461         case HS_VERY_FULL:
2462         case HS_FULL:
2463             return min(mlevel, 2);
2464         case HS_SATIATED:
2465             return min(mlevel, 1);
2466         default:
2467             return 0;
2468         }
2469     }
2470
2471     return 0;
2472 }
2473
2474 // Output level of player mutation.  If temp is true (the default), take into
2475 // account the suppression of mutations by non-"Alive" Vampires and by changes
2476 // of form.
2477 int player_mutation_level(mutation_type mut, bool temp)
2478 {
2479     return _mut_level(mut, temp ? MUTACT_PARTIAL : MUTACT_INACTIVE);
2480 }
2481
2482 static int _player_armour_racial_bonus(const item_def& item)
2483 {
2484     if (item.base_type != OBJ_ARMOUR)
2485         return 0;
2486
2487     int racial_bonus = 0;
2488     const iflags_t armour_race = get_equip_race(item);
2489     const iflags_t racial_type = get_species_race(you.species);
2490
2491     // Dwarven armour is universally good -- bwr
2492     if (armour_race == ISFLAG_DWARVEN)
2493         racial_bonus += 4;
2494
2495     if (racial_type && armour_race == racial_type)
2496     {
2497         // Elven armour is light, but still gives one level to elves.
2498         // Orcish and Dwarven armour are worth +2 to the correct
2499         // species, plus the plus that anyone gets with dwarven armour.
2500         // -- bwr
2501         if (racial_type == ISFLAG_ELVEN)
2502             racial_bonus += 2;
2503         else
2504             racial_bonus += 4;
2505
2506         // an additional bonus for Beogh worshippers
2507         if (you_worship(GOD_BEOGH) && !player_under_penance())
2508         {
2509             if (you.piety >= piety_breakpoint(5))
2510                 racial_bonus += racial_bonus * 9 / 4;
2511             else if (you.piety >= piety_breakpoint(4))
2512                 racial_bonus += racial_bonus * 7 / 4;
2513             else if (you.piety >= piety_breakpoint(2))
2514                 racial_bonus += racial_bonus * 5 / 4;
2515             else if (you.piety >= piety_breakpoint(0))
2516                 racial_bonus += racial_bonus * 3 / 4;
2517             else
2518                 racial_bonus += racial_bonus / 4;
2519         }
2520     }
2521
2522     return racial_bonus;
2523 }
2524
2525 bool is_effectively_light_armour(const item_def *item)
2526 {
2527     return (!item
2528             || (abs(property(*item, PARM_EVASION)) < 6));
2529 }
2530
2531 bool player_effectively_in_light_armour()
2532 {
2533     const item_def *armour = you.slot_item(EQ_BODY_ARMOUR, false);
2534     return is_effectively_light_armour(armour);
2535 }
2536
2537 // This function returns true if the player has a radically different
2538 // shape... minor changes like blade hands don't count, also note
2539 // that lich transformation doesn't change the character's shape
2540 // (so we end up with Naga-liches, Spiggan-liches, Minotaur-liches)
2541 // it just makes the character undead (with the benefits that implies). - bwr
2542 bool player_is_shapechanged(void)
2543 {
2544     if (you.form == TRAN_NONE
2545         || you.form == TRAN_BLADE_HANDS
2546         || you.form == TRAN_LICH
2547         || you.form == TRAN_APPENDAGE)
2548     {
2549         return false;
2550     }
2551
2552     return true;
2553 }
2554
2555 // An evasion factor based on the player's body size, smaller == higher
2556 // evasion size factor.
2557 static int _player_evasion_size_factor()
2558 {
2559     // XXX: you.body_size() implementations are incomplete, fix.
2560     const size_type size = you.body_size(PSIZE_BODY);
2561     return 2 * (SIZE_MEDIUM - size);
2562 }
2563
2564 // The total EV penalty to the player for all their worn armour items
2565 // with a base EV penalty (i.e. EV penalty as a base armour property,
2566 // not as a randart property).
2567 static int _player_adjusted_evasion_penalty(const int scale)
2568 {
2569     int piece_armour_evasion_penalty = 0;
2570
2571     // Some lesser armours have small penalties now (barding).
2572     for (int i = EQ_MIN_ARMOUR; i < EQ_MAX_ARMOUR; i++)
2573     {
2574         if (i == EQ_SHIELD || !player_wearing_slot(i))
2575             continue;
2576
2577         // [ds] Evasion modifiers for armour are negatives, change
2578         // those to positive for penalty calc.
2579         const int penalty = (-property(you.inv[you.equip[i]], PARM_EVASION))/3;
2580         if (penalty > 0)
2581             piece_armour_evasion_penalty += penalty;
2582     }
2583
2584     return (piece_armour_evasion_penalty * scale +
2585             you.adjusted_body_armour_penalty(scale));
2586 }
2587
2588 // EV bonuses that work even when helpless.
2589 static int _player_para_evasion_bonuses(ev_ignore_type evit)
2590 {
2591     int evbonus = 0;
2592
2593     if (you.duration[DUR_PHASE_SHIFT] && !(evit & EV_IGNORE_PHASESHIFT))
2594         evbonus += 8;
2595
2596     if (player_mutation_level(MUT_DISTORTION_FIELD) > 0)
2597         evbonus += player_mutation_level(MUT_DISTORTION_FIELD) + 1;
2598
2599     return evbonus;
2600 }
2601
2602 // Player EV bonuses for various effects and transformations. This
2603 // does not include tengu/merfolk EV bonuses for flight/swimming.
2604 static int _player_evasion_bonuses(ev_ignore_type evit)
2605 {
2606     int evbonus = _player_para_evasion_bonuses(evit);
2607
2608     if (you.duration[DUR_AGILITY])
2609         evbonus += 5;
2610
2611     // All effects negated by magical suppression should go in here.
2612     if (!you.suppressed())
2613     {
2614         evbonus += you.wearing(EQ_RINGS_PLUS, RING_EVASION);
2615
2616         if (you.wearing_ego(EQ_WEAPON, SPWPN_EVASION))
2617             evbonus += 5;
2618
2619         evbonus += you.scan_artefacts(ARTP_EVASION);
2620     }
2621
2622     // mutations
2623     if (_mut_level(MUT_ICY_BLUE_SCALES, MUTACT_FULL) > 1)
2624         evbonus--;
2625     if (_mut_level(MUT_MOLTEN_SCALES, MUTACT_FULL) > 1)
2626         evbonus--;
2627     evbonus += max(0, player_mutation_level(MUT_GELATINOUS_BODY) - 1);
2628
2629     // transformation penalties/bonuses not covered by size alone:
2630     if (you.form == TRAN_STATUE)
2631         evbonus -= 10;               // stiff and slow
2632
2633     return evbonus;
2634 }
2635
2636 // Player EV scaling for being flying tengu or swimming merfolk.
2637 static int _player_scale_evasion(int prescaled_ev, const int scale)
2638 {
2639     if (you.duration[DUR_PETRIFYING] || you.duration[DUR_GRASPING_ROOTS]
2640         || you.caught())
2641     {
2642         prescaled_ev /= 2;
2643     }
2644
2645     switch (you.species)
2646     {
2647     case SP_MERFOLK:
2648         // Merfolk get an evasion bonus in water.
2649         if (you.fishtail)
2650         {
2651             const int ev_bonus = min(9 * scale,
2652                                      max(2 * scale, prescaled_ev / 4));
2653             return (prescaled_ev + ev_bonus);
2654         }
2655         break;
2656
2657     case SP_TENGU:
2658         // Flying Tengu get an evasion bonus.
2659         if (you.flight_mode())
2660         {
2661             const int ev_bonus = min(9 * scale,
2662                                      max(1 * scale, prescaled_ev / 5));
2663             return (prescaled_ev + ev_bonus);
2664         }
2665         break;
2666
2667     default:
2668         break;
2669     }
2670     return prescaled_ev;
2671 }
2672
2673 // Total EV for player using the revised 0.6 evasion model.
2674 int player_evasion(ev_ignore_type evit)
2675 {
2676     const int size_factor = _player_evasion_size_factor();
2677     // Repulsion fields and size are all that matters when paralysed or
2678     // at 0 dex.
2679     if ((you.cannot_move() || you.stat_zero[STAT_DEX] || you.form == TRAN_TREE)
2680         && !(evit & EV_IGNORE_HELPLESS))
2681     {
2682         const int paralysed_base_ev = 2 + size_factor / 2;
2683         const int repulsion_ev = _player_para_evasion_bonuses(evit);
2684         return max(1, paralysed_base_ev + repulsion_ev);
2685     }
2686
2687     const int scale = 100;
2688     const int size_base_ev = (10 + size_factor) * scale;
2689
2690     const int adjusted_evasion_penalty =
2691         _player_adjusted_evasion_penalty(scale);
2692
2693     // The last two parameters are not important.
2694     const int ev_dex = stepdown_value(you.dex(), 10, 24, 72, 72);
2695
2696     const int dodge_bonus =
2697         (70 + you.skill(SK_DODGING, 10) * ev_dex) * scale
2698         / (20 - size_factor) / 10;
2699
2700     // [ds] Dodging penalty for being in high EVP armour, almost
2701     // identical to v0.5/4.1 penalty, but with the EVP discount being
2702     // 1 instead of 0.5 so that leather armour is fully discounted.
2703     // The 1 EVP of leather armour may still incur an
2704     // adjusted_evasion_penalty, however.
2705     const int armour_dodge_penalty = max(0,
2706         (10 * you.adjusted_body_armour_penalty(scale, true)
2707          - 30 * scale)
2708         / max(1, (int) you.strength()));
2709
2710     // Adjust dodge bonus for the effects of being suited up in armour.
2711     const int armour_adjusted_dodge_bonus =
2712         max(0, dodge_bonus - armour_dodge_penalty);
2713
2714     const int adjusted_shield_penalty = you.adjusted_shield_penalty(scale);
2715
2716     const int prestepdown_evasion =
2717         size_base_ev
2718         + armour_adjusted_dodge_bonus
2719         - adjusted_evasion_penalty
2720         - adjusted_shield_penalty;
2721
2722     const int poststepdown_evasion =
2723         stepdown_value(prestepdown_evasion, 20*scale, 30*scale, 60*scale, -1);
2724
2725     const int evasion_bonuses = _player_evasion_bonuses(evit) * scale;
2726
2727     const int prescaled_evasion =
2728         poststepdown_evasion + evasion_bonuses;
2729
2730     const int final_evasion =
2731         _player_scale_evasion(prescaled_evasion, scale);
2732
2733     return unscale_round_up(final_evasion, scale);
2734 }
2735
2736 static int _player_body_armour_racial_spellcasting_bonus(const int scale)
2737 {
2738     const item_def *body_armour = you.slot_item(EQ_BODY_ARMOUR, false);
2739     if (!body_armour)
2740         return 0;
2741
2742     const iflags_t armour_race = get_equip_race(*body_armour);
2743     const iflags_t player_race = get_species_race(you.species);
2744
2745     int armour_racial_spellcasting_bonus = 0;
2746     if (armour_race & ISFLAG_ELVEN)
2747         armour_racial_spellcasting_bonus += 25;
2748
2749     if (armour_race & ISFLAG_DWARVEN)
2750         armour_racial_spellcasting_bonus -= 15;
2751
2752     if (armour_race & player_race)
2753         armour_racial_spellcasting_bonus += 15;
2754
2755     return (armour_racial_spellcasting_bonus * scale);
2756 }
2757
2758 // Returns the spellcasting penalty (increase in spell failure) for the
2759 // player's worn body armour and shield.
2760 int player_armour_shield_spell_penalty()
2761 {
2762     const int scale = 100;
2763
2764     const int body_armour_penalty =
2765         max(25 * you.adjusted_body_armour_penalty(scale)
2766             - _player_body_armour_racial_spellcasting_bonus(scale), 0);
2767
2768     const int total_penalty = body_armour_penalty
2769                  + 25 * you.adjusted_shield_penalty(scale)
2770                  - 20 * scale;
2771
2772     return (max(total_penalty, 0) / scale);
2773 }
2774
2775 int player_mag_abil(bool is_weighted)
2776 {
2777     int ma = 0;
2778
2779     // Brilliance Potion
2780     ma += 6 * (you.duration[DUR_BRILLIANCE] ? 1 : 0);
2781
2782     // All effects negated by magical suppression should go in here.
2783     if (!you.suppressed())
2784     {
2785         // Rings
2786         ma += 3 * you.wearing(EQ_RINGS, RING_WIZARDRY);
2787
2788         // Staves
2789         ma += 4 * you.wearing(EQ_STAFF, STAFF_WIZARDRY);
2790     }
2791
2792     return ((is_weighted) ? ((ma * you.intel()) / 10) : ma);
2793 }
2794
2795 int player_shield_class(void)
2796 {
2797     int shield = 0;
2798     int stat = 0;
2799
2800     if (you.incapacitated())
2801         return 0;
2802
2803     if (player_wearing_slot(EQ_SHIELD))
2804     {
2805         const item_def& item = you.inv[you.equip[EQ_SHIELD]];
2806         int size_factor = (you.body_size(PSIZE_TORSO) - SIZE_MEDIUM)
2807                         * (item.sub_type - ARM_LARGE_SHIELD);
2808         int base_shield = property(item, PARM_AC) * 2 + size_factor;
2809
2810         int racial_bonus = _player_armour_racial_bonus(item);
2811
2812         // bonus applied only to base, see above for effect:
2813         shield += base_shield * 50;
2814         shield += base_shield * you.skill(SK_SHIELDS, 5) / 2;
2815         shield += base_shield * racial_bonus * 10 / 6;
2816
2817         shield += item.plus * 100;
2818
2819         if (item.sub_type == ARM_BUCKLER)
2820             stat = you.dex() * 38;
2821         else if (item.sub_type == ARM_LARGE_SHIELD)
2822             stat = you.dex() * 12 + you.strength() * 26;
2823         else
2824             stat = you.dex() * 19 + you.strength() * 19;
2825         stat = stat * (base_shield + 13) / 26;
2826     }
2827     else
2828     {
2829         if (you.duration[DUR_MAGIC_SHIELD])
2830             shield += 900 + you.skill(SK_EVOCATIONS, 75);
2831
2832         if (!you.duration[DUR_FIRE_SHIELD]
2833             && you.duration[DUR_CONDENSATION_SHIELD])
2834         {
2835             shield += 800 + you.skill(SK_ICE_MAGIC, 60);
2836         }
2837     }
2838
2839     if (you.duration[DUR_DIVINE_SHIELD])
2840     {
2841         shield += you.attribute[ATTR_DIVINE_SHIELD] * 150;
2842         stat = max(stat, int(you.attribute[ATTR_DIVINE_SHIELD] * 300));
2843     }
2844
2845     if (shield + stat > 0
2846         && (player_wearing_slot(EQ_SHIELD) || you.duration[DUR_DIVINE_SHIELD]))
2847     {
2848         shield += you.skill(SK_SHIELDS, 38)
2849                 + min(you.skill(SK_SHIELDS, 38), 3 * 38);
2850     }
2851
2852     // mutations
2853     // +2, +4, +6
2854     shield += (player_mutation_level(MUT_LARGE_BONE_PLATES) > 0
2855                ? player_mutation_level(MUT_LARGE_BONE_PLATES) * 200
2856                : 0);
2857
2858     return (shield + stat + 50) / 100;
2859 }
2860
2861 int player_sust_abil(bool calc_unid)
2862 {
2863     int sa = 0;
2864
2865     // All effects negated by magical suppression should go in here.
2866     if (!you.suppressed())
2867         sa += you.wearing(EQ_RINGS, RING_SUSTAIN_ABILITIES, calc_unid);
2868
2869     if (sa > 2)
2870         sa = 2;
2871
2872     return sa;
2873 }
2874
2875 int carrying_capacity(burden_state_type bs)
2876 {
2877     // Use untransformed body weight, to prevent transformations
2878     // causing frequent large changes in carrying capacity.
2879     int cap = 2 * you.body_weight(true) + you.strength() * 250 + 1000;
2880     // We are nice to the lighter species in that strength adds absolutely
2881     // instead of relatively to body weight. --dpeg
2882
2883     if (you.stat_zero[STAT_STR])
2884         cap /= 2;
2885
2886     if (bs == BS_UNENCUMBERED)
2887         return cap * 5 / 6;
2888     else if (bs == BS_ENCUMBERED)
2889         return cap * 11 / 12;
2890     else
2891         return cap;
2892 }
2893
2894 int burden_change(void)
2895 {
2896     const burden_state_type old_burdenstate = you.burden_state;
2897
2898     // XXX: the 600 here is the weight of the Orb.
2899     // TODO: make this use a dummy item or similar?
2900     you.burden = (you.char_direction == GDT_ASCENDING) ? 600 : 0;
2901
2902     for (int bu = 0; bu < ENDOFPACK; bu++)
2903     {
2904         if (you.inv[bu].quantity < 1)
2905             continue;
2906
2907         you.burden += item_mass(you.inv[bu]) * you.inv[bu].quantity;
2908     }
2909
2910     you.burden_state = BS_UNENCUMBERED;
2911     set_redraw_status(REDRAW_BURDEN);
2912     you.redraw_evasion = true;
2913
2914     // changed the burdened levels to match the change to max_carried
2915     if (you.burden <= carrying_capacity(BS_UNENCUMBERED))
2916     {
2917         you.burden_state = BS_UNENCUMBERED;
2918
2919         // this message may have to change, just testing {dlb}
2920         if (old_burdenstate != you.burden_state)
2921             mpr("Your possessions no longer seem quite so burdensome.");
2922     }
2923     else if (you.burden <= carrying_capacity(BS_ENCUMBERED))
2924     {
2925         you.burden_state = BS_ENCUMBERED;
2926
2927         if (old_burdenstate != you.burden_state)
2928         {
2929             mpr("You are being weighed down by all of your possessions.");
2930             learned_something_new(HINT_HEAVY_LOAD);
2931         }
2932     }
2933     else
2934     {
2935         you.burden_state = BS_OVERLOADED;
2936
2937         if (old_burdenstate != you.burden_state)
2938         {
2939             mpr("You are being crushed by all of your possessions.");
2940             learned_something_new(HINT_HEAVY_LOAD);
2941         }
2942     }
2943
2944     // Stop travel if we get burdened (as from potions of might wearing off).
2945     if (you.burden_state > old_burdenstate)
2946         interrupt_activity(AI_BURDEN_CHANGE);
2947
2948     return you.burden;
2949 }
2950
2951 void forget_map(bool rot)
2952 {
2953     ASSERT(!crawl_state.game_is_arena());
2954
2955     // If forgetting was intentional, clear the travel trail.
2956     if (!rot)
2957         clear_travel_trail();
2958
2959     // Labyrinth and the Abyss use special rotting rules.
2960     const bool rot_resist = player_in_branch(BRANCH_LABYRINTH)
2961                                 && you.species == SP_MINOTAUR
2962                             || player_in_branch(BRANCH_ABYSS)
2963                                 && you_worship(GOD_LUGONU);
2964     const double geometric_chance = 0.99;
2965     const int radius = (rot_resist ? 200 : 100);
2966
2967     const int scalar = 0xFF;
2968     for (rectangle_iterator ri(0); ri; ++ri)
2969     {
2970         const coord_def &p = *ri;
2971         if (!env.map_knowledge(p).known() || you.see_cell(p))
2972             continue;
2973
2974         if (rot)
2975         {
2976             const int dist = distance2(you.pos(), p);
2977             int chance = pow(geometric_chance,
2978                              max(1, (dist - radius) / 40)) * scalar;
2979             if (x_chance_in_y(chance, scalar))
2980                 continue;
2981         }
2982
2983         if (you.see_cell(p))
2984             continue;
2985
2986         env.map_knowledge(p).clear();
2987         if (env.map_forgotten.get())
2988             (*env.map_forgotten.get())(p).clear();
2989         StashTrack.update_stash(p);
2990 #ifdef USE_TILE
2991         tile_forget_map(p);
2992 #endif
2993     }
2994
2995     ash_detect_portals(is_map_persistent());
2996 #ifdef USE_TILE
2997     tiles.update_minimap_bounds();
2998 #endif
2999 }
3000
3001 static void _remove_temp_mutations()
3002 {
3003     int num_remove = min(you.attribute[ATTR_TEMP_MUTATIONS],
3004         max(you.attribute[ATTR_TEMP_MUTATIONS] * 5 / 12 - random2(3),
3005         2 + random2(3)));
3006
3007     if (num_remove >= you.attribute[ATTR_TEMP_MUTATIONS])
3008         mpr("You feel the corruption within you wane completely.", MSGCH_DURATION);
3009     else
3010         mpr("You feel the corruption within you wane somewhat.", MSGCH_DURATION);
3011
3012     for (int i = 0; i < num_remove; ++i)
3013         delete_temp_mutation();
3014
3015     if (you.attribute[ATTR_TEMP_MUTATIONS] > 0)
3016     {
3017         you.attribute[ATTR_TEMP_MUT_XP] +=
3018             min(you.experience_level, 17) * (350 + roll_dice(5, 350)) / 17;
3019     }
3020 }
3021
3022 int get_exp_progress()
3023 {
3024     if (you.experience_level >= 27)
3025         return 0;
3026
3027     const int current = exp_needed(you.experience_level);
3028     const int next    = exp_needed(you.experience_level + 1);
3029     if (next == current)
3030         return 0;
3031     return ((you.experience - current) * 100 / (next - current));
3032 }
3033
3034 void gain_exp(unsigned int exp_gained, unsigned int* actual_gain)
3035 {
3036     if (crawl_state.game_is_arena())
3037         return;
3038
3039     if (crawl_state.game_is_zotdef())
3040     {
3041         you.zot_points += exp_gained;
3042         // All XP, for some reason Sprint speeds up only skill training,
3043