Apply the new ground_level method.
[crawl.git] / crawl-ref / source / player.cc
blob49b6028d395366d4f1a699b87980652f676759d7
1 /*
2 * File: player.cc
3 * Summary: Player related functions.
4 * Written by: Linley Henzell
5 */
7 #include "AppHdr.h"
9 #include "player.h"
11 #include <string.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <ctype.h>
15 #include <math.h>
17 #include <sstream>
18 #include <algorithm>
20 #include "areas.h"
21 #include "artefact.h"
22 #include "branch.h"
23 #include "cloud.h"
24 #include "clua.h"
25 #include "coord.h"
26 #include "coordit.h"
27 #include "delay.h"
28 #include "dgnevent.h"
29 #include "directn.h"
30 #include "effects.h"
31 #include "env.h"
32 #include "errors.h"
33 #include "exercise.h"
34 #include "fight.h"
35 #include "godabil.h"
36 #include "godconduct.h"
37 #include "godpassive.h"
38 #include "hints.h"
39 #include "hiscores.h"
40 #include "it_use2.h"
41 #include "item_use.h"
42 #include "itemname.h"
43 #include "itemprop.h"
44 #include "items.h"
45 #include "kills.h"
46 #include "libutil.h"
47 #include "macro.h"
48 #include "map_knowledge.h"
49 #include "message.h"
50 #include "misc.h"
51 #include "mon-util.h"
52 #include "mutation.h"
53 #include "notes.h"
54 #include "options.h"
55 #include "ouch.h"
56 #include "output.h"
57 #include "place.h"
58 #include "player-stats.h"
59 #include "quiver.h"
60 #include "random.h"
61 #include "religion.h"
62 #include "shopping.h"
63 #include "shout.h"
64 #include "skills.h"
65 #include "skills2.h"
66 #include "species.h"
67 #include "spl-other.h"
68 #include "spl-selfench.h"
69 #include "spl-transloc.h"
70 #include "spl-util.h"
71 #include "sprint.h"
72 #include "stairs.h"
73 #include "state.h"
74 #include "status.h"
75 #include "stuff.h"
76 #include "tagstring.h"
77 #include "terrain.h"
78 #ifdef USE_TILE
79 #include "tileview.h"
80 #endif
81 #include "transform.h"
82 #include "traps.h"
83 #include "travel.h"
84 #include "view.h"
85 #include "viewgeom.h"
86 #include "xom.h"
88 static void _moveto_maybe_repel_stairs()
90 const dungeon_feature_type new_grid = env.grid(you.pos());
91 const command_type stair_dir = feat_stair_direction(new_grid);
93 if (stair_dir == CMD_NO_CMD
94 || new_grid == DNGN_ENTER_SHOP
95 || !you.duration[DUR_REPEL_STAIRS_MOVE])
97 return;
100 int pct = you.duration[DUR_REPEL_STAIRS_CLIMB] ? 29 : 50;
102 // When the effect is still strong, the chance to actually catch
103 // a stair is smaller. (Assuming the duration starts out at 1000.)
104 const int dur = std::max(0, you.duration[DUR_REPEL_STAIRS_MOVE] - 700);
105 pct += dur/10;
107 if (x_chance_in_y(pct, 100))
109 if (slide_feature_over(you.pos(), coord_def(-1, -1), false))
111 std::string stair_str =
112 feature_description(new_grid, NUM_TRAPS, "",
113 DESC_CAP_THE, false);
114 std::string prep = feat_preposition(new_grid, true, &you);
116 mprf("%s slides away as you move %s it!", stair_str.c_str(),
117 prep.c_str());
119 if (player_in_a_dangerous_place() && one_chance_in(5))
120 xom_is_stimulated(32);
125 static bool _check_moveto_cloud(const coord_def& p,
126 const std::string &move_verb)
128 const int cloud = env.cgrid(p);
129 if (cloud != EMPTY_CLOUD && !you.confused())
131 const cloud_type ctype = env.cloud[ cloud ].type;
132 // Don't prompt if already in a cloud of the same type.
133 if (is_damaging_cloud(ctype, true)
134 && (env.cgrid(you.pos()) == EMPTY_CLOUD
135 || ctype != env.cloud[ env.cgrid(you.pos()) ].type))
137 std::string prompt = make_stringf(
138 "Really %s into that cloud of %s?",
139 move_verb.c_str(),
140 cloud_name_at_index(cloud).c_str());
142 if (!yesno(prompt.c_str(), false, 'n'))
144 canned_msg(MSG_OK);
145 return (false);
149 return (true);
152 static bool _check_moveto_trap(const coord_def& p, const std::string &move_verb)
154 // If we're walking along, give a chance to avoid traps.
155 const dungeon_feature_type new_grid = env.grid(p);
156 if (new_grid == DNGN_UNDISCOVERED_TRAP)
158 const int skill =
159 (4 + you.traps_skill()
160 + player_mutation_level(MUT_ACUTE_VISION)
161 - 2 * player_mutation_level(MUT_BLURRY_VISION));
163 if (random2(skill) > 6)
165 if (trap_def* ptrap = find_trap(p))
166 ptrap->reveal();
168 viewwindow();
170 mprf(MSGCH_WARN,
171 "Wait a moment, %s! Do you really want to %s there?",
172 you.your_name.c_str(),
173 move_verb.c_str());
175 if (!you.running.is_any_travel())
176 more();
178 practise(EX_TRAP_PASSIVE);
179 print_stats();
180 return (false);
183 else if (new_grid == DNGN_TRAP_MAGICAL
184 #ifdef CLUA_BINDINGS
185 || new_grid == DNGN_TRAP_MECHANICAL
186 && Options.trap_prompt
187 #endif
188 || new_grid == DNGN_TRAP_NATURAL)
190 const trap_type type = get_trap_type(p);
191 if (type == TRAP_ZOT)
193 std::string prompt = make_stringf(
194 "Do you really want to %s into the Zot trap",
195 move_verb.c_str()
197 if (!yes_or_no(prompt.c_str()))
199 canned_msg(MSG_OK);
200 return (false);
203 else if (new_grid != DNGN_TRAP_MAGICAL &&
204 (you.airborne() || you.can_cling_to(p)))
206 // No prompt (shaft and mechanical traps
207 // ineffective, if flying)
209 else if (type == TRAP_TELEPORT
210 && (player_equip(EQ_AMULET, AMU_STASIS, true)
211 || scan_artefacts(ARTP_PREVENT_TELEPORTATION,
212 false)))
214 // No prompt (teleport traps are ineffective if
215 // wearing an amulet of stasis)
217 else
218 #ifdef CLUA_BINDINGS
219 // Prompt for any trap where you might not have enough hp
220 // as defined in init.txt (see trapwalk.lua)
221 if (type != TRAP_SHAFT // Known shafts aren't traps
222 && type != TRAP_GOLUBRIA // don't need a warning here
223 && (new_grid != DNGN_TRAP_MECHANICAL
224 || !clua.callbooleanfn(false, "ch_cross_trap",
225 "s", trap_name_at(p)))
226 && !crawl_state.game_is_zotdef())
227 #endif
229 std::string prompt = make_stringf(
230 "Really %s %s that %s?",
231 move_verb.c_str(),
232 (type == TRAP_ALARM || type == TRAP_PLATE) ? "onto" : "into",
233 feature_description(new_grid, type,
234 "", DESC_BASENAME,
235 false).c_str());
237 if (!yesno(prompt.c_str(), true, 'n'))
239 canned_msg(MSG_OK);
240 return (false);
244 return (true);
247 static bool _check_moveto_dangerous(const coord_def& p,
248 const std::string move_verb)
250 if (you.can_swim() && feat_is_water(env.grid(p))
251 || you.can_cling_to(p)
252 || !is_feat_dangerous(env.grid(p)))
254 return (true);
256 else if (you.species == SP_MERFOLK && feat_is_water(env.grid(p)))
257 mpr("You cannot swim in your current form.");
258 else
259 canned_msg(MSG_UNTHINKING_ACT);
260 return (false);
263 static bool _check_moveto_terrain(const coord_def& p,
264 const std::string &move_verb)
266 // Only consider terrain if player is not levitating.
267 if (you.airborne() || you.can_cling_to(p))
268 return (true);
270 return (_check_moveto_dangerous(p, move_verb));
273 bool check_moveto(const coord_def& p, const std::string &move_verb)
275 return (_check_moveto_terrain(p, move_verb)
276 && _check_moveto_cloud(p, move_verb)
277 && _check_moveto_trap(p, move_verb));
280 void moveto_location_effects(dungeon_feature_type old_feat,
281 bool stepped, bool allow_shift,
282 const coord_def& old_pos)
284 const dungeon_feature_type new_grid = env.grid(you.pos());
286 // Terrain effects.
287 if (is_feat_dangerous(new_grid) && !you.can_cling_to(you.pos()))
289 // Lava and dangerous deep water (ie not merfolk).
290 const coord_def& entry = (stepped) ? old_pos : you.pos();
292 // If true, we were shifted and so we're done.
293 if (fall_into_a_pool(entry, allow_shift, new_grid))
294 return;
297 if (you.ground_level())
299 if (you.species == SP_MERFOLK)
301 if (feat_is_water(new_grid) // We're entering water
302 // We're not transformed, or with a form compatible with tail
303 && (you.form == TRAN_NONE
304 || you.form == TRAN_BLADE_HANDS))
306 merfolk_start_swimming(stepped);
308 else if (!feat_is_water(new_grid) && !is_feat_dangerous(new_grid))
309 merfolk_stop_swimming();
312 if (feat_is_water(new_grid) && !stepped)
314 if (you.can_swim())
315 noisy(4, you.pos(), "Floosh!");
316 else if (!beogh_water_walk())
317 noisy(8, you.pos(), "Splash!");
320 if (feat_is_water(new_grid) && !you.can_swim() && !beogh_water_walk())
322 you.time_taken *= 13 + random2(8);
323 you.time_taken /= 10;
325 if (!feat_is_water(old_feat))
327 mprf("You %s the %s water.",
328 stepped ? "enter" : "fall into",
329 new_grid == DNGN_SHALLOW_WATER ? "shallow" : "deep");
332 if (new_grid == DNGN_DEEP_WATER && old_feat != DNGN_DEEP_WATER)
333 mpr("You sink to the bottom.");
335 if (!feat_is_water(old_feat))
337 mpr("Moving in this stuff is going to be slow.");
338 if (you.invisible())
339 mpr("...and don't expect to remain undetected.");
344 // Icy shield goes down over lava.
345 if (new_grid == DNGN_LAVA)
346 expose_player_to_element(BEAM_LAVA);
348 // Traps go off.
349 if (trap_def* ptrap = find_trap(you.pos()))
350 ptrap->trigger(you, !stepped); // blinking makes it hard to evade
352 if (stepped)
353 _moveto_maybe_repel_stairs();
356 // Use this function whenever the player enters (or lands and thus re-enters)
357 // a grid.
359 // stepped - normal walking moves
360 // allow_shift - allowed to scramble in any direction out of lava/water
361 void move_player_to_grid(const coord_def& p, bool stepped, bool allow_shift)
363 ASSERT(!crawl_state.game_is_arena());
364 ASSERT(in_bounds(p));
366 // assuming that entering the same square means coming from above (levitate)
367 const coord_def old_pos = you.pos();
368 const bool from_above = (old_pos == p);
369 const dungeon_feature_type old_grid =
370 (from_above) ? DNGN_FLOOR : grd(old_pos);
372 // Really must be clear.
373 ASSERT(you.can_pass_through_feat(grd(p)));
375 // Better not be an unsubmerged monster either.
376 ASSERT(!monster_at(p) || monster_at(p)->submerged()
377 || fedhas_passthrough(monster_at(p)));
379 // Move the player to new location.
380 you.moveto(p);
381 viewwindow();
383 // Checking new squares for interesting features.
384 if (!you.running)
385 check_for_interesting_features();
387 you.check_clinging();
388 moveto_location_effects(old_grid, stepped, allow_shift, old_pos);
391 bool is_feat_dangerous(dungeon_feature_type grid, bool permanently)
393 if (you.permanent_flight() || you.permanent_levitation()
394 || you.airborne() && !permanently)
396 return false;
398 else if (grid == DNGN_DEEP_WATER && !player_likes_water(permanently)
399 || grid == DNGN_LAVA)
401 return true;
403 else
404 return false;
407 bool player_in_mappable_area(void)
409 return (!testbits(env.level_flags, LFLAG_NOT_MAPPABLE)
410 && !testbits(get_branch_flags(), BFLAG_NOT_MAPPABLE));
413 bool player_in_branch(int branch)
415 return (you.level_type == LEVEL_DUNGEON && you.where_are_you == branch);
418 bool player_in_level_area(level_area_type area)
420 return (you.level_type == area);
423 bool player_in_hell(void)
425 return (you.level_type == LEVEL_DUNGEON
426 && is_hell_subbranch(you.where_are_you));
429 bool player_likes_water(bool permanently)
431 return (!permanently && beogh_water_walk()
432 || (species_likes_water(you.species) || !permanently)
433 && form_likes_water());
436 bool player_in_bat_form()
438 return (you.form == TRAN_BAT);
441 bool player_can_open_doors()
443 // Bats and pigs can't open/close doors.
444 return (you.form != TRAN_BAT
445 && you.form != TRAN_PIG);
448 bool player_under_penance(void)
450 if (you.religion != GOD_NO_GOD)
451 return (you.penance[you.religion]);
452 else
453 return (false);
456 // TODO: get rid of this.
457 bool player_genus(genus_type which_genus, species_type species)
459 if (species == SP_UNKNOWN)
460 species = you.species;
462 return (species_genus(species) == which_genus);
465 // If transform is true, compare with current transformation instead
466 // of (or in addition to) underlying species.
467 // (See mon-data.h for species/genus use.)
468 bool is_player_same_species(const int mon, bool transform)
470 if (transform)
472 switch (you.form)
474 // Unique monsters.
475 case TRAN_BAT:
476 return (mon == MONS_MEGABAT);
477 case TRAN_ICE_BEAST:
478 return (mon == MONS_ICE_BEAST);
479 // Compare with monster *species*.
480 case TRAN_LICH:
481 return (mons_species(mon) == MONS_LICH);
482 // Compare with monster *genus*.
483 case TRAN_SPIDER:
484 return (mons_genus(mon) == MONS_SPIDER);
485 case TRAN_DRAGON:
486 return (mons_genus(mon) == MONS_DRAGON); // Includes all drakes.
487 case TRAN_PIG:
488 return (mons_genus(mon) == MONS_HOG);
489 case TRAN_STATUE:
490 case TRAN_BLADE_HANDS:
491 case TRAN_NONE:
492 break; // Check real (non-transformed) form.
496 // Genus would include necrophage and rotting hulk.
497 if (you.species == SP_GHOUL)
498 return (mons_species(mon) == MONS_GHOUL);
500 if (you.species == SP_MERFOLK && mons_genus(mon) == MONS_MERMAID)
501 return (true);
503 // Note that these are currently considered to be the same species:
504 // * halflings and humans
505 // * dwarves and deep dwarves
506 // * all elf races
507 return (mons_genus(mon) == mons_genus(player_mons(false)));
510 void update_player_symbol()
512 you.symbol = Options.show_player_species ? player_mons() : transform_mons();
515 monster_type player_mons(bool transform)
517 monster_type mons;
519 if (transform)
521 mons = transform_mons();
522 if (mons != MONS_PLAYER)
523 return (mons);
526 mons = player_species_to_mons_species(you.species);
528 if (mons == MONS_ORC)
530 if (you.religion == GOD_BEOGH)
531 mons = (you.piety >= piety_breakpoint(4)) ? MONS_ORC_HIGH_PRIEST
532 : MONS_ORC_PRIEST;
534 else if (mons == MONS_OGRE)
536 const skill_type sk = best_skill(SK_FIRST_SKILL, SK_LAST_SKILL);
537 if (sk >= SK_SPELLCASTING && sk < SK_INVOCATIONS)
538 mons = MONS_OGRE_MAGE;
541 return (mons);
544 void update_vision_range()
546 you.normal_vision = LOS_RADIUS;
547 you.current_vision = you.normal_vision;
549 // Nightstalker gives -1/-2/-3.
550 if (player_mutation_level(MUT_NIGHTSTALKER))
551 you.current_vision -= player_mutation_level(MUT_NIGHTSTALKER);
553 // Lantern of shadows.
554 if (you.attribute[ATTR_SHADOWS])
555 you.current_vision -= 2;
557 set_los_radius(you.current_vision);
560 // Checks whether the player's current species can use
561 // use (usually wear) a given piece of equipment.
562 // Note that EQ_BODY_ARMOUR and EQ_HELMET only check
563 // the ill-fitting variant (i.e., not caps and robes).
564 // If special_armour is set to true, special cases
565 // such as bardings, light armour and caps are
566 // considered. Otherwise, these simply return false.
567 // ---------------------------------------------------
568 bool you_can_wear(int eq, bool special_armour)
570 if (you.species == SP_CAT)
571 return (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET);
573 switch (eq)
575 case EQ_LEFT_RING:
576 case EQ_RIGHT_RING:
577 case EQ_AMULET:
578 case EQ_CLOAK:
579 return (true);
581 case EQ_GLOVES:
582 if (you.species == SP_TROLL
583 || you.species == SP_SPRIGGAN
584 || player_genus(GENPC_OGREISH)
585 || player_genus(GENPC_DRACONIAN))
587 return (false);
589 if (player_mutation_level(MUT_CLAWS) >= 3)
590 return (false);
591 return (true);
593 case EQ_BOOTS:
594 // Bardings.
595 if (you.species == SP_NAGA || you.species == SP_CENTAUR)
596 return (special_armour);
597 if (player_mutation_level(MUT_HOOVES) >= 3
598 || player_mutation_level(MUT_TALONS) >= 3)
600 return (false);
602 // These species cannot wear boots.
603 if (you.species == SP_TROLL
604 || you.species == SP_SPRIGGAN
605 || player_genus(GENPC_OGREISH)
606 || player_genus(GENPC_DRACONIAN))
608 return (false);
610 return (true);
612 case EQ_BODY_ARMOUR:
613 case EQ_SHIELD:
614 // Anyone can wear robes or a buckler/shield.
615 if (special_armour)
616 return (true);
617 if (you.species == SP_TROLL
618 || you.species == SP_SPRIGGAN
619 || player_genus(GENPC_OGREISH)
620 || player_genus(GENPC_DRACONIAN))
622 return (false);
624 return (true);
626 case EQ_HELMET:
627 // Anyone can wear caps.
628 if (special_armour)
629 return (true);
630 if (player_mutation_level(MUT_HORNS)
631 || player_mutation_level(MUT_BEAK)
632 || player_mutation_level(MUT_ANTENNAE))
634 return (false);
636 if (you.species == SP_TROLL
637 || you.species == SP_SPRIGGAN
638 || player_genus(GENPC_OGREISH)
639 || player_genus(GENPC_DRACONIAN))
641 return (false);
643 return (true);
645 default:
646 return (true);
650 bool player_has_feet()
652 if (you.species == SP_NAGA || you.species == SP_CAT || you.fishtail)
654 return (false);
657 if (player_mutation_level(MUT_HOOVES) >= 3
658 || player_mutation_level(MUT_TALONS) >= 3)
660 return (false);
663 return (true);
666 bool player_wearing_slot(int eq)
668 ASSERT(you.equip[eq] != -1 || !you.melded[eq]);
669 return (you.equip[eq] != -1 && !you.melded[eq]);
672 bool you_tran_can_wear(const item_def &item)
674 switch (item.base_type)
676 case OBJ_WEAPONS:
677 return you_tran_can_wear(EQ_WEAPON);
679 case OBJ_JEWELLERY:
680 return you_tran_can_wear(jewellery_is_amulet(item) ? EQ_AMULET
681 : EQ_LEFT_RING);
682 case OBJ_ARMOUR:
683 if (item.sub_type == ARM_NAGA_BARDING)
684 return (you.species == SP_NAGA && you_tran_can_wear(EQ_BOOTS));
685 else if (item.sub_type == ARM_CENTAUR_BARDING)
686 return (you.species == SP_CENTAUR && you_tran_can_wear(EQ_BOOTS));
688 if (get_armour_slot(item) == EQ_HELMET
689 && !is_hard_helmet(item)
690 && (you.form == TRAN_SPIDER
691 || you.form == TRAN_ICE_BEAST))
693 return (true);
696 if (fit_armour_size(item, you.body_size()) != 0)
697 return (false);
699 return you_tran_can_wear(get_armour_slot(item), true);
701 default:
702 return (true);
706 bool you_tran_can_wear(int eq, bool check_mutation)
708 if (eq == EQ_NONE)
709 return (true);
711 if (eq == EQ_STAFF)
712 eq = EQ_WEAPON;
713 else if (eq >= EQ_RINGS && eq <= EQ_RINGS_PLUS2)
714 eq = EQ_LEFT_RING;
716 // Everybody can wear at least some type of armour.
717 if (eq == EQ_ALL_ARMOUR)
718 return (true);
720 // Not a transformation, but also temporary -> check first.
721 if (check_mutation)
723 if (eq == EQ_GLOVES && you.has_claws(false) >= 3)
724 return (false);
726 if (eq == EQ_BOOTS
727 && (you.fishtail
728 || player_mutation_level(MUT_HOOVES) >= 3
729 || player_mutation_level(MUT_TALONS) >= 3))
731 return (false);
735 // No further restrictions.
736 if (you.form == TRAN_NONE || you.form == TRAN_LICH)
737 return (true);
739 // Bats and pigs cannot wear anything except amulets.
740 if ((you.form == TRAN_BAT || you.form == TRAN_PIG) && eq != EQ_AMULET)
741 return (false);
743 // Everyone else can wear jewellery, at least.
744 if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING || eq == EQ_AMULET)
745 return (true);
747 // These cannot use anything but jewellery.
748 if (you.form == TRAN_SPIDER || you.form == TRAN_DRAGON)
749 return (false);
751 if (you.form == TRAN_BLADE_HANDS)
753 if (eq == EQ_WEAPON || eq == EQ_GLOVES || eq == EQ_SHIELD)
754 return (false);
755 return (true);
758 if (you.form == TRAN_ICE_BEAST)
760 if (eq != EQ_CLOAK)
761 return (false);
762 return (true);
765 if (you.form == TRAN_STATUE)
767 if (eq == EQ_WEAPON || eq == EQ_CLOAK || eq == EQ_HELMET)
768 return (true);
769 return (false);
772 return (true);
775 bool player_weapon_wielded()
777 const int wpn = you.equip[EQ_WEAPON];
779 if (wpn == -1)
780 return (false);
782 if (you.inv[wpn].base_type != OBJ_WEAPONS
783 && you.inv[wpn].base_type != OBJ_STAVES)
785 return (false);
788 return (true);
791 // Returns false if the player is wielding a weapon inappropriate for Berserk.
792 bool berserk_check_wielded_weapon()
794 if (!you.weapon())
795 return (true);
797 const item_def weapon = *you.weapon();
798 if (weapon.defined() && weapon.base_type != OBJ_STAVES
799 && (weapon.base_type != OBJ_WEAPONS || is_range_weapon(weapon))
800 || you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED])
802 std::string prompt = "Do you really want to go berserk while "
803 "wielding " + weapon.name(DESC_NOCAP_YOUR)
804 + "?";
806 if (!yesno(prompt.c_str(), true, 'n'))
808 canned_msg(MSG_OK);
809 return (false);
812 you.attribute[ATTR_WEAPON_SWAP_INTERRUPTED] = 0;
815 return (true);
818 // Looks in equipment "slot" to see if there is an equipped "sub_type".
819 // Returns number of matches (in the case of rings, both are checked)
820 int player_equip(equipment_type slot, int sub_type, bool calc_unid)
822 int ret = 0;
824 item_def* item;
826 switch (slot)
828 case EQ_WEAPON:
829 // Hands can have more than just weapons.
830 if (you.weapon()
831 && you.weapon()->base_type == OBJ_WEAPONS
832 && you.weapon()->sub_type == sub_type)
834 ret++;
836 break;
838 case EQ_STAFF:
839 // Like above, but must be magical staff.
840 if (you.weapon()
841 && you.weapon()->base_type == OBJ_STAVES
842 && you.weapon()->sub_type == sub_type
843 && (calc_unid || item_type_known(*you.weapon())))
845 ret++;
847 break;
849 case EQ_RINGS:
850 if ((item = you.slot_item(EQ_LEFT_RING))
851 && item->sub_type == sub_type
852 && (calc_unid
853 || item_type_known(*item)))
855 ret++;
858 if ((item = you.slot_item(EQ_RIGHT_RING))
859 && item->sub_type == sub_type
860 && (calc_unid
861 || item_type_known(*item)))
863 ret++;
865 break;
867 case EQ_RINGS_PLUS:
868 if ((item = you.slot_item(EQ_LEFT_RING))
869 && item->sub_type == sub_type
870 && (calc_unid
871 || item_type_known(*item)))
873 ret += item->plus;
876 if ((item = you.slot_item(EQ_RIGHT_RING))
877 && item->sub_type == sub_type
878 && (calc_unid
879 || item_type_known(*item)))
881 ret += item->plus;
883 break;
885 case EQ_RINGS_PLUS2:
886 if ((item = you.slot_item(EQ_LEFT_RING))
887 && item->sub_type == sub_type
888 && (calc_unid
889 || item_type_known(*item)))
891 ret += item->plus2;
894 if ((item = you.slot_item(EQ_RIGHT_RING))
895 && item->sub_type == sub_type
896 && (calc_unid
897 || item_type_known(*item)))
899 ret += item->plus2;
901 break;
903 case EQ_ALL_ARMOUR:
904 // Doesn't make much sense here... be specific. -- bwr
905 die("EQ_ALL_ARMOUR is not a proper slot");
906 break;
908 default:
909 if (! (slot > EQ_NONE && slot < NUM_EQUIP))
910 die("invalid slot");
911 if ((item = you.slot_item(slot))
912 && item->sub_type == sub_type
913 && (calc_unid || item_type_known(*item)))
915 ret++;
917 break;
920 return (ret);
923 // Looks in equipment "slot" to see if equipped item has "special" ego-type
924 // Returns number of matches (jewellery returns zero -- no ego type).
925 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
926 // and armour type-id on wield/wear.
927 int player_equip_ego_type(int slot, int special, bool calc_unid)
929 int ret = 0;
930 bool melded = (special == SPARM_PONDEROUSNESS);
932 item_def* item;
933 switch (slot)
935 case EQ_WEAPON:
936 // Hands can have more than just weapons.
937 if ((item = you.slot_item(EQ_WEAPON))
938 && item->base_type == OBJ_WEAPONS
939 && get_weapon_brand(*item) == special)
941 ret++;
943 break;
945 case EQ_LEFT_RING:
946 case EQ_RIGHT_RING:
947 case EQ_AMULET:
948 case EQ_STAFF:
949 case EQ_RINGS:
950 case EQ_RINGS_PLUS:
951 case EQ_RINGS_PLUS2:
952 // no ego types for these slots
953 break;
955 case EQ_ALL_ARMOUR:
956 // Check all armour slots:
957 for (int i = EQ_MIN_ARMOUR; i <= EQ_MAX_ARMOUR; i++)
959 if ((item = you.slot_item(static_cast<equipment_type>(i), melded))
960 && get_armour_ego_type(*item) == special
961 && (calc_unid || item_type_known(*item)))
963 ret++;
966 break;
968 default:
969 if (slot < EQ_MIN_ARMOUR || slot > EQ_MAX_ARMOUR)
970 die("invalid slot: %d", slot);
971 // Check a specific armour slot for an ego type:
972 if ((item = you.slot_item(static_cast<equipment_type>(slot), melded))
973 && get_armour_ego_type(*item) == special
974 && (calc_unid || item_type_known(*item)))
976 ret++;
978 break;
981 return (ret);
984 // Return's true if the indicated unrandart is equipped
985 // [ds] There's no equivalent of calc_unid or req_id because as of now, weapons
986 // and armour type-id on wield/wear.
987 bool player_equip_unrand(int unrand_index)
989 unrandart_entry* entry = get_unrand_entry(unrand_index);
990 equipment_type slot = get_item_slot(entry->base_type,
991 entry->sub_type);
993 item_def* item;
995 switch (slot)
997 case EQ_WEAPON:
998 // Hands can have more than just weapons.
999 if ((item = you.slot_item(slot))
1000 && item->base_type == OBJ_WEAPONS
1001 && is_unrandom_artefact(*item)
1002 && item->special == unrand_index)
1004 return (true);
1006 break;
1008 case EQ_RINGS:
1009 if ((item = you.slot_item(EQ_LEFT_RING))
1010 && is_unrandom_artefact(*item)
1011 && item->special == unrand_index)
1013 return (true);
1016 if ((item = you.slot_item(EQ_RIGHT_RING))
1017 && is_unrandom_artefact(*item)
1018 && item->special == unrand_index)
1020 return (true);
1022 break;
1024 case EQ_NONE:
1025 case EQ_STAFF:
1026 case EQ_LEFT_RING:
1027 case EQ_RIGHT_RING:
1028 case EQ_RINGS_PLUS:
1029 case EQ_RINGS_PLUS2:
1030 case EQ_ALL_ARMOUR:
1031 // no unrandarts for these slots.
1032 break;
1034 default:
1035 if (slot <= EQ_NONE || slot >= NUM_EQUIP)
1036 die("invalid slot: %d", slot);
1037 // Check a specific slot.
1038 if ((item = you.slot_item(slot))
1039 && is_unrandom_artefact(*item)
1040 && item->special == unrand_index)
1042 return (true);
1044 break;
1047 return (false);
1050 int player_evokable_levitation()
1052 return player_equip(EQ_RINGS, RING_LEVITATION)
1053 + player_equip_ego_type(EQ_BOOTS, SPARM_LEVITATION)
1054 + scan_artefacts(ARTP_LEVITATE);
1057 int player_evokable_invis()
1059 return (player_equip(EQ_RINGS, RING_INVISIBILITY)
1060 + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_DARKNESS)
1061 + scan_artefacts(ARTP_INVISIBLE));
1064 // Given an adjacent monster, returns true if the player can hit it (the
1065 // monster should not be submerged, or be submerged in shallow water if
1066 // the player has a polearm).
1067 bool player_can_hit_monster(const monster* mon)
1069 if (!mon->submerged())
1070 return (true);
1072 if (grd(mon->pos()) != DNGN_SHALLOW_WATER)
1073 return (false);
1075 const item_def *weapon = you.weapon();
1076 return (weapon && weapon_skill(*weapon) == SK_POLEARMS);
1079 int player_teleport(bool calc_unid)
1081 ASSERT(!crawl_state.game_is_arena());
1083 // Don't allow any form of teleportation in Sprint.
1084 if (crawl_state.game_is_sprint())
1085 return 0;
1087 int tp = 0;
1089 // rings
1090 tp += 8 * player_equip(EQ_RINGS, RING_TELEPORTATION, calc_unid);
1092 // mutations
1093 tp += player_mutation_level(MUT_TELEPORT) * 3;
1095 // randart weapons only
1096 if (you.weapon()
1097 && you.weapon()->base_type == OBJ_WEAPONS
1098 && is_artefact(*you.weapon()))
1100 tp += scan_artefacts(ARTP_CAUSE_TELEPORTATION, calc_unid);
1103 return tp;
1106 int player_regen()
1108 int rr = you.hp_max / 3;
1110 if (rr > 20)
1111 rr = 20 + ((rr - 20) / 2);
1113 // Rings.
1114 rr += 40 * player_equip(EQ_RINGS, RING_REGENERATION);
1116 // Spell.
1117 if (you.duration[DUR_REGENERATION]
1118 && !you.attribute[ATTR_DIVINE_REGENERATION])
1120 rr += 100;
1123 // Troll leather (except for trolls).
1124 if (player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR)
1125 && you.species != SP_TROLL)
1127 rr += 30;
1130 // Fast heal mutation.
1131 rr += player_mutation_level(MUT_REGENERATION) * 20;
1133 // Before applying other effects, make sure that there's something
1134 // to heal.
1135 rr = std::max(1, rr);
1137 // Healing depending on satiation.
1138 // The better-fed you are, the faster you heal.
1139 if (you.species == SP_VAMPIRE)
1141 if (you.hunger_state == HS_STARVING)
1142 // No regeneration for starving vampires.
1143 rr = 0;
1144 else if (you.hunger_state == HS_ENGORGED)
1145 // More bonus regeneration for engorged vampires.
1146 rr += 20;
1147 else if (you.hunger_state < HS_SATIATED)
1148 // Halved regeneration for hungry vampires.
1149 rr /= 2;
1150 else if (you.hunger_state >= HS_FULL)
1151 // Bonus regeneration for full vampires.
1152 rr += 10;
1155 // Powered By Death mutation, boosts regen by 10 per corpse in
1156 // a mutation_level * 3 (3/6/9) radius, to a maximum of 7
1157 // corpses. If and only if the duration of the effect is
1158 // still active.
1159 if (you.duration[DUR_POWERED_BY_DEATH])
1160 rr += handle_pbd_corpses(false) * 100;
1162 // Slow heal mutation. Each level reduces your natural healing by
1163 // one third.
1164 if (player_mutation_level(MUT_SLOW_HEALING) > 0)
1166 rr *= 3 - player_mutation_level(MUT_SLOW_HEALING);
1167 rr /= 3;
1170 if (you.stat_zero[STAT_STR])
1171 rr /= 4;
1173 // Trog's Hand. This circumvents the slow healing effect.
1174 if (you.attribute[ATTR_DIVINE_REGENERATION])
1175 rr += 100;
1177 return (rr);
1180 int player_hunger_rate(void)
1182 int hunger = 3;
1184 if (player_in_bat_form())
1185 return (1);
1187 if (you.species == SP_TROLL)
1188 hunger += 3; // in addition to the +3 for fast metabolism
1190 if (you.duration[DUR_REGENERATION] && you.hp < you.hp_max)
1191 hunger += 4;
1193 // If Cheibriados has slowed your life processes, you will hunger less.
1194 if (you.religion == GOD_CHEIBRIADOS && you.piety >= piety_breakpoint(0))
1195 hunger--;
1197 // Moved here from main.cc... maintaining the >= 40 behaviour.
1198 if (you.hunger >= 40)
1200 if (you.duration[DUR_INVIS])
1201 hunger += 5;
1203 // Berserk has its own food penalty - excluding berserk haste.
1204 // Doubling the hunger cost for haste so that the per turn hunger
1205 // is consistent now that a hasted turn causes 50% the normal hunger
1206 // -cao
1207 if (you.duration[DUR_HASTE])
1208 hunger += haste_mul(5);
1211 if (you.species == SP_VAMPIRE)
1213 switch (you.hunger_state)
1215 case HS_STARVING:
1216 case HS_NEAR_STARVING:
1217 hunger -= 3;
1218 break;
1219 case HS_VERY_HUNGRY:
1220 hunger -= 2;
1221 break;
1222 case HS_HUNGRY:
1223 hunger--;
1224 break;
1225 case HS_SATIATED:
1226 break;
1227 case HS_FULL:
1228 hunger++;
1229 break;
1230 case HS_VERY_FULL:
1231 hunger += 2;
1232 break;
1233 case HS_ENGORGED:
1234 hunger += 3;
1237 else
1239 hunger += player_mutation_level(MUT_FAST_METABOLISM);
1241 if (player_mutation_level(MUT_SLOW_METABOLISM) > 2)
1242 hunger -= 2;
1243 else if (player_mutation_level(MUT_SLOW_METABOLISM) > 0)
1244 hunger--;
1247 // rings
1248 if (you.hp < you.hp_max
1249 && player_mutation_level(MUT_SLOW_HEALING) < 3)
1251 hunger += 3 * player_equip(EQ_RINGS, RING_REGENERATION);
1254 hunger += 4 * player_equip(EQ_RINGS, RING_HUNGER);
1255 hunger -= 2 * player_equip(EQ_RINGS, RING_SUSTENANCE);
1257 // troll leather armour
1258 if (you.species != SP_TROLL && you.hp < you.hp_max)
1260 if (player_equip(EQ_BODY_ARMOUR, ARM_TROLL_LEATHER_ARMOUR))
1261 hunger += coinflip() ? 2 : 1;
1264 // randarts
1265 hunger += scan_artefacts(ARTP_METABOLISM);
1267 // burden
1268 hunger += you.burden_state;
1270 if (hunger < 1)
1271 hunger = 1;
1273 return (hunger);
1276 int player_spell_levels(void)
1278 int sl = (you.experience_level - 1) + (you.skills[SK_SPELLCASTING] * 2);
1280 bool fireball = false;
1281 bool delayed_fireball = false;
1283 if (sl > 99)
1284 sl = 99;
1286 for (int i = 0; i < MAX_KNOWN_SPELLS; i++)
1288 if (you.spells[i] == SPELL_FIREBALL)
1289 fireball = true;
1290 else if (you.spells[i] == SPELL_DELAYED_FIREBALL)
1291 delayed_fireball = true;
1293 if (you.spells[i] != SPELL_NO_SPELL)
1294 sl -= spell_difficulty(you.spells[i]);
1297 // Fireball is free for characters with delayed fireball
1298 if (fireball && delayed_fireball)
1299 sl += spell_difficulty(SPELL_FIREBALL);
1301 // Note: This can happen because of level drain. Maybe we should
1302 // force random spells out when that happens. -- bwr
1303 if (sl < 0)
1304 sl = 0;
1306 return (sl);
1309 bool player_likes_chunks(bool permanently)
1311 return (player_mutation_level(MUT_GOURMAND) > 0
1312 || player_mutation_level(MUT_CARNIVOROUS) > 0
1313 || (!permanently && wearing_amulet(AMU_THE_GOURMAND)));
1316 // If temp is set to false, temporary sources or resistance won't be counted.
1317 int player_res_fire(bool calc_unid, bool temp, bool items)
1319 int rf = 0;
1321 if (items)
1323 // rings of fire resistance/fire
1324 rf += player_equip(EQ_RINGS, RING_PROTECTION_FROM_FIRE, calc_unid);
1325 rf += player_equip(EQ_RINGS, RING_FIRE, calc_unid);
1327 // rings of ice
1328 rf -= player_equip(EQ_RINGS, RING_ICE, calc_unid);
1330 // Staves
1331 rf += player_equip(EQ_STAFF, STAFF_FIRE, calc_unid);
1333 // body armour:
1334 rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_DRAGON_ARMOUR);
1335 rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1336 rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
1337 rf += 2 * player_equip(EQ_BODY_ARMOUR, ARM_DRAGON_HIDE);
1338 rf += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1339 rf -= player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
1341 // ego armours
1342 rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_FIRE_RESISTANCE);
1343 rf += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
1345 // randart weapons:
1346 rf += scan_artefacts(ARTP_FIRE, calc_unid);
1348 // Che bonus
1349 rf += che_boost(CB_RFIRE);
1352 // species:
1353 if (you.species == SP_MUMMY)
1354 rf--;
1356 // mutations:
1357 rf += player_mutation_level(MUT_HEAT_RESISTANCE);
1358 rf += player_mutation_level(MUT_MOLTEN_SCALES) == 3 ? 1 : 0;
1360 // spells:
1361 if (temp)
1363 if (you.duration[DUR_RESIST_FIRE] > 0)
1364 rf++;
1366 if (you.duration[DUR_FIRE_SHIELD])
1367 rf += 2;
1369 // transformations:
1370 switch (you.form)
1372 case TRAN_ICE_BEAST:
1373 rf--;
1374 break;
1375 case TRAN_DRAGON:
1377 monster_type drag = dragon_form_dragon_type();
1378 if (drag == MONS_DRAGON)
1379 rf += 2;
1380 else if (drag == MONS_ICE_DRAGON)
1381 rf--;
1382 break;
1384 default:
1385 break;
1389 if (rf < -3)
1390 rf = -3;
1391 else if (rf > 3)
1392 rf = 3;
1394 return (rf);
1397 int player_res_steam(bool calc_unid, bool temp, bool items)
1399 int res = 0;
1401 if (you.species == SP_PALE_DRACONIAN)
1402 res += 2;
1404 if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))
1405 res += 2;
1407 if (items && player_equip(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_HIDE))
1408 res += 2;
1410 return (res + player_res_fire(calc_unid, temp, items) / 2);
1413 int player_res_cold(bool calc_unid, bool temp, bool items)
1415 int rc = 0;
1417 if (temp)
1419 // spells:
1420 if (you.duration[DUR_RESIST_COLD] > 0)
1421 rc++;
1423 if (you.duration[DUR_FIRE_SHIELD])
1424 rc -= 2;
1426 // transformations:
1427 switch (you.form)
1429 case TRAN_ICE_BEAST:
1430 rc += 3;
1431 break;
1432 case TRAN_DRAGON:
1434 monster_type form = dragon_form_dragon_type();
1435 if (form == MONS_DRAGON)
1436 rc--;
1437 else if (form == MONS_ICE_DRAGON)
1438 rc += 2;
1439 break;
1441 case TRAN_LICH:
1442 rc++;
1443 break;
1444 default:
1445 break;
1448 if (you.species == SP_VAMPIRE)
1450 if (you.hunger_state <= HS_NEAR_STARVING)
1451 rc += 2;
1452 else if (you.hunger_state < HS_SATIATED)
1453 rc++;
1457 if (items)
1459 // rings of cold resistance/ice
1460 rc += player_equip(EQ_RINGS, RING_PROTECTION_FROM_COLD, calc_unid);
1461 rc += player_equip(EQ_RINGS, RING_ICE, calc_unid);
1463 // rings of fire
1464 rc -= player_equip(EQ_RINGS, RING_FIRE, calc_unid);
1466 // Staves
1467 rc += player_equip(EQ_STAFF, STAFF_COLD, calc_unid);
1469 // body armour:
1470 rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_ARMOUR);
1471 rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1472 rc -= player_equip(EQ_BODY_ARMOUR, ARM_DRAGON_ARMOUR);
1473 rc += 2 * player_equip(EQ_BODY_ARMOUR, ARM_ICE_DRAGON_HIDE);
1474 rc += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1475 rc -= player_equip(EQ_BODY_ARMOUR, ARM_DRAGON_HIDE);
1477 // ego armours
1478 rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_COLD_RESISTANCE);
1479 rc += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_RESISTANCE);
1481 // randart weapons:
1482 rc += scan_artefacts(ARTP_COLD, calc_unid);
1484 // Che bonus
1485 rc += che_boost(CB_RCOLD);
1488 // mutations:
1489 rc += player_mutation_level(MUT_COLD_RESISTANCE);
1490 rc += player_mutation_level(MUT_ICY_BLUE_SCALES) == 3 ? 1 : 0;
1491 rc += player_mutation_level(MUT_SHAGGY_FUR) == 3 ? 1 : 0;
1493 if (rc < -3)
1494 rc = -3;
1495 else if (rc > 3)
1496 rc = 3;
1498 return (rc);
1501 int player_res_corr(bool calc_unid, bool items)
1503 if (items && wearing_amulet(AMU_RESIST_CORROSION, calc_unid))
1504 return 1;
1505 else
1506 return 0;
1509 int player_res_acid(bool calc_unid, bool items)
1511 int res = 0;
1512 if (!form_changed_physiology()
1513 || you.form == TRAN_DRAGON)
1515 if (you.species == SP_YELLOW_DRACONIAN)
1516 res += 2;
1519 if (items)
1521 if (wearing_amulet(AMU_RESIST_CORROSION, calc_unid, true))
1522 res++;
1524 if (player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION))
1525 res++;
1528 // mutations:
1529 res += std::max(0, player_mutation_level(MUT_YELLOW_SCALES) - 1);
1531 if (res > 3)
1532 res = 3;
1534 return (res);
1537 // Returns a factor X such that post-resistance acid damage can be calculated
1538 // as pre_resist_damage * X / 100.
1539 int player_acid_resist_factor()
1541 int res = player_res_acid();
1543 int factor = 100;
1545 if (res == 1)
1546 factor = 50;
1547 else if (res == 2)
1548 factor = 34;
1549 else if (res > 2)
1551 factor = 30;
1552 while (res-- > 2 && factor >= 20)
1553 factor = factor * 90 / 100;
1556 return (factor);
1559 int player_res_electricity(bool calc_unid, bool temp, bool items)
1561 int re = 0;
1563 if (temp)
1565 if (you.duration[DUR_INSULATION])
1566 re++;
1568 // transformations:
1569 if (you.form == TRAN_STATUE)
1570 re += 1;
1572 if (you.attribute[ATTR_DIVINE_LIGHTNING_PROTECTION])
1573 re = 3;
1574 else if (re > 1)
1575 re = 1;
1578 if (items)
1580 // staff
1581 re += player_equip(EQ_STAFF, STAFF_AIR, calc_unid);
1583 // body armour:
1584 re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_ARMOUR);
1585 re += player_equip(EQ_BODY_ARMOUR, ARM_STORM_DRAGON_HIDE);
1587 // randart weapons:
1588 re += scan_artefacts(ARTP_ELECTRICITY, calc_unid);
1591 // mutations:
1592 re += player_mutation_level(MUT_THIN_METALLIC_SCALES) == 3 ? 1 : 0;
1593 re += player_mutation_level(MUT_SHOCK_RESISTANCE);
1595 return (re);
1598 bool player_control_teleport(bool calc_unid, bool temp, bool items)
1600 return ((temp && you.duration[DUR_CONTROL_TELEPORT])
1601 || (items
1602 && player_equip(EQ_RINGS, RING_TELEPORT_CONTROL, calc_unid))
1603 || player_mutation_level(MUT_TELEPORT_CONTROL));
1606 int player_res_torment(bool, bool temp)
1608 return (player_mutation_level(MUT_TORMENT_RESISTANCE)
1609 || you.form == TRAN_LICH
1610 || you.species == SP_VAMPIRE && you.hunger_state == HS_STARVING
1611 || (temp &&
1612 (20 * player_mutation_level(MUT_STOCHASTIC_TORMENT_RESISTANCE)
1613 > random2(100))));
1616 // Funny that no races are susceptible to poisons. {dlb}
1617 // If temp is set to false, temporary sources or resistance won't be counted.
1618 int player_res_poison(bool calc_unid, bool temp, bool items)
1620 int rp = 0;
1622 if (items)
1624 // rings of poison resistance
1625 rp += player_equip(EQ_RINGS, RING_POISON_RESISTANCE, calc_unid);
1627 // Staves
1628 rp += player_equip(EQ_STAFF, STAFF_POISON, calc_unid);
1630 // ego armour:
1631 rp += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POISON_RESISTANCE);
1633 // body armour:
1634 rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_ARMOUR);
1635 rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_ARMOUR);
1636 rp += player_equip(EQ_BODY_ARMOUR, ARM_GOLD_DRAGON_HIDE);
1637 rp += player_equip(EQ_BODY_ARMOUR, ARM_SWAMP_DRAGON_HIDE);
1639 // randart weapons:
1640 rp += scan_artefacts(ARTP_POISON, calc_unid);
1643 // mutations:
1644 rp += player_mutation_level(MUT_POISON_RESISTANCE);
1645 rp += player_mutation_level(MUT_SLIMY_GREEN_SCALES) == 3 ? 1 : 0;
1647 // Only thirsty vampires are naturally poison resistant.
1648 if (you.species == SP_VAMPIRE && you.hunger_state < HS_SATIATED)
1649 rp++;
1651 if (temp)
1653 // spells:
1654 if (you.duration[DUR_RESIST_POISON] > 0)
1655 rp++;
1657 // transformations:
1658 switch (you.form)
1660 case TRAN_LICH:
1661 case TRAN_ICE_BEAST:
1662 case TRAN_STATUE:
1663 case TRAN_DRAGON:
1664 rp++;
1665 break;
1666 default:
1667 break;
1671 if (rp > 1)
1672 rp = 1;
1674 return (rp);
1677 int player_res_sticky_flame(bool calc_unid, bool temp, bool items)
1679 int rsf = 0;
1681 if (you.species == SP_MOTTLED_DRACONIAN)
1682 rsf++;
1684 if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_ARMOUR))
1685 rsf++;
1686 if (items && player_equip(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_HIDE))
1687 rsf++;
1689 if (rsf > 1)
1690 rsf = 1;
1692 return (rsf);
1695 int player_spec_death()
1697 int sd = 0;
1699 // Staves
1700 sd += player_equip(EQ_STAFF, STAFF_DEATH);
1702 // species:
1703 if (you.species == SP_MUMMY)
1705 if (you.experience_level >= 13)
1706 sd++;
1707 if (you.experience_level >= 26)
1708 sd++;
1711 // transformations:
1712 if (you.form == TRAN_LICH)
1713 sd++;
1715 return sd;
1718 int player_spec_holy()
1720 //if (you.char_class == JOB_PRIEST || you.char_class == JOB_PALADIN)
1721 // return 1;
1722 return 0;
1725 int player_spec_fire()
1727 int sf = 0;
1729 // staves:
1730 sf += player_equip(EQ_STAFF, STAFF_FIRE);
1732 // rings of fire:
1733 sf += player_equip(EQ_RINGS, RING_FIRE);
1735 if (you.duration[DUR_FIRE_SHIELD])
1736 sf++;
1738 // if it's raining... {due}
1739 if (in_what_cloud(CLOUD_RAIN))
1740 sf--;
1742 return sf;
1745 int player_spec_cold()
1747 int sc = 0;
1749 // staves:
1750 sc += player_equip(EQ_STAFF, STAFF_COLD);
1752 // rings of ice:
1753 sc += player_equip(EQ_RINGS, RING_ICE);
1755 return sc;
1758 int player_spec_earth()
1760 int se = 0;
1762 // Staves
1763 se += player_equip(EQ_STAFF, STAFF_EARTH);
1765 return se;
1768 int player_spec_air()
1770 int sa = 0;
1772 // Staves
1773 sa += player_equip(EQ_STAFF, STAFF_AIR);
1775 return sa;
1778 int player_spec_conj()
1780 int sc = 0;
1782 // Staves
1783 sc += player_equip(EQ_STAFF, STAFF_CONJURATION);
1785 return sc;
1788 int player_spec_ench()
1790 int se = 0;
1792 // Staves
1793 se += player_equip(EQ_STAFF, STAFF_ENCHANTMENT);
1795 return se;
1798 int player_spec_summ()
1800 int ss = 0;
1802 // Staves
1803 ss += player_equip(EQ_STAFF, STAFF_SUMMONING);
1805 return ss;
1808 int player_spec_poison()
1810 int sp = 0;
1812 // Staves
1813 sp += player_equip(EQ_STAFF, STAFF_POISON);
1815 if (player_equip_unrand(UNRAND_OLGREB))
1816 sp++;
1818 return sp;
1821 int player_energy()
1823 int pe = 0;
1825 // Staves
1826 pe += player_equip(EQ_STAFF, STAFF_ENERGY);
1828 return pe;
1831 // If temp is set to false, temporary sources of resistance won't be
1832 // counted.
1833 int player_prot_life(bool calc_unid, bool temp, bool items)
1835 int pl = 0;
1837 // Hunger is temporary, true, but that's something you can control,
1838 // especially as life protection only increases the hungrier you
1839 // get.
1840 if (you.species == SP_VAMPIRE)
1842 switch (you.hunger_state)
1844 case HS_STARVING:
1845 case HS_NEAR_STARVING:
1846 pl = 3;
1847 break;
1848 case HS_VERY_HUNGRY:
1849 case HS_HUNGRY:
1850 pl = 2;
1851 break;
1852 case HS_SATIATED:
1853 pl = 1;
1854 break;
1855 default:
1856 break;
1860 // Same here. Your piety status, and, hence, TSO's protection, is
1861 // something you can more or less control.
1862 if (you.religion == GOD_SHINING_ONE && you.piety > pl * 50)
1863 pl = you.piety / 50;
1865 if (temp)
1867 // Now, transformations could stop at any time.
1868 switch (you.form)
1870 case TRAN_STATUE:
1871 pl++;
1872 break;
1873 case TRAN_LICH:
1874 pl += 3;
1875 break;
1876 default:
1877 break;
1881 if (items)
1883 if (wearing_amulet(AMU_WARDING, calc_unid))
1884 pl++;
1886 // rings
1887 pl += player_equip(EQ_RINGS, RING_LIFE_PROTECTION, calc_unid);
1889 // armour (checks body armour only)
1890 pl += player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_POSITIVE_ENERGY);
1892 // pearl dragon counts
1893 pl += player_equip(EQ_BODY_ARMOUR, ARM_PEARL_DRAGON_ARMOUR);
1895 // randart wpns
1896 pl += scan_artefacts(ARTP_NEGATIVE_ENERGY, calc_unid);
1898 // Che bonus
1899 pl += che_boost(CB_RNEG);
1902 // undead/demonic power
1903 pl += player_mutation_level(MUT_NEGATIVE_ENERGY_RESISTANCE);
1905 pl = std::min(3, pl);
1907 return (pl);
1910 // New player movement speed system... allows for a bit more than
1911 // "player runs fast" and "player walks slow" in that the speed is
1912 // actually calculated (allowing for centaurs to get a bonus from
1913 // swiftness and other such things). Levels of the mutation now
1914 // also have meaning (before they all just meant fast). Most of
1915 // this isn't as fast as it used to be (6 for having anything), but
1916 // even a slight speed advantage is very good... and we certainly don't
1917 // want to go past 6 (see below). -- bwr
1918 int player_movement_speed(bool ignore_burden)
1920 int mv = 10;
1922 // transformations
1923 if (you.form == TRAN_SPIDER)
1924 mv = 8;
1925 else if (player_in_bat_form())
1926 mv = 5; // but allowed minimum is six
1927 else if (you.form == TRAN_PIG)
1928 mv = 7;
1929 else if (you.fishtail)
1930 mv = 6;
1932 // moving on liquefied ground takes longer
1933 if (liquefied(you.pos()) && you.ground_level())
1934 mv += 3;
1936 // armour
1937 if (player_equip_ego_type(EQ_BOOTS, SPARM_RUNNING))
1938 mv -= 2;
1940 // ponderous brand and artefact property
1941 mv += 2 * player_ponderousness();
1943 // In the air, can fly fast (should be lightly burdened).
1944 if (!ignore_burden && you.light_flight())
1945 mv--;
1947 // Swiftness is an Air spell, it doesn't work in water, but
1948 // flying players will move faster.
1949 if (you.duration[DUR_SWIFTNESS] > 0 && !you.in_water())
1950 mv -= (you.flight_mode() == FL_FLY ? 4 : 2);
1952 // Mutations: -2, -3, -4, unless innate and shapechanged.
1953 // Not when swimming, since it is "cover the ground quickly".
1954 if (player_mutation_level(MUT_FAST) > 0
1955 && (!you.innate_mutations[MUT_FAST] || !player_is_shapechanged())
1956 && !you.swimming())
1958 mv -= player_mutation_level(MUT_FAST) + 1;
1961 if (player_mutation_level(MUT_SLOW) > 0 && !player_is_shapechanged())
1963 mv *= 10 + player_mutation_level(MUT_SLOW) * 2;
1964 mv /= 10;
1967 // Burden
1968 if (!ignore_burden)
1970 if (you.burden_state == BS_ENCUMBERED)
1971 mv++;
1972 else if (you.burden_state == BS_OVERLOADED)
1973 mv += 3;
1976 // We'll use the old value of six as a minimum, with haste this could
1977 // end up as a speed of three, which is about as fast as we want
1978 // the player to be able to go (since 3 is 3.33x as fast and 2 is 5x,
1979 // which is a bit of a jump, and a bit too fast) -- bwr
1980 if (mv < 6)
1981 mv = 6;
1983 return (mv);
1986 // This function differs from the above in that it's used to set the
1987 // initial time_taken value for the turn. Everything else (movement,
1988 // spellcasting, combat) applies a ratio to this value.
1989 int player_speed(void)
1991 int ps = 10;
1993 for (int i = 0; i < NUM_STATS; ++i)
1994 if (you.stat_zero[i] > 0)
1995 ps *= 2;
1997 if (you.duration[DUR_SLOW])
1998 ps = haste_mul(ps);
2000 if (you.duration[DUR_BERSERK] && you.religion != GOD_CHEIBRIADOS)
2001 ps /= 2;
2002 else if (you.duration[DUR_HASTE])
2003 ps = haste_div(ps);
2005 if (you.form == TRAN_STATUE)
2007 ps *= 15;
2008 ps /= 10;
2011 return ps;
2014 int player_ponderousness()
2016 return (scan_artefacts(ARTP_PONDEROUS)
2017 + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PONDEROUSNESS));
2020 static int _player_armour_racial_bonus(const item_def& item)
2022 if (item.base_type != OBJ_ARMOUR)
2023 return 0;
2025 int racial_bonus = 0;
2026 const iflags_t armour_race = get_equip_race(item);
2028 // get the armour race value that corresponds to the character's race:
2029 const iflags_t racial_type
2030 = ((player_genus(GENPC_DWARVEN)) ? ISFLAG_DWARVEN :
2031 (player_genus(GENPC_ELVEN)) ? ISFLAG_ELVEN :
2032 (you.species == SP_HILL_ORC) ? ISFLAG_ORCISH
2033 : 0);
2035 // Dwarven armour is universally good -- bwr
2036 if (armour_race == ISFLAG_DWARVEN)
2037 racial_bonus += 4;
2039 if (racial_type && armour_race == racial_type)
2041 // Elven armour is light, but still gives one level to elves.
2042 // Orcish and Dwarven armour are worth +2 to the correct
2043 // species, plus the plus that anyone gets with dwarven armour.
2044 // -- bwr
2045 if (racial_type == ISFLAG_ELVEN)
2046 racial_bonus += 2;
2047 else
2048 racial_bonus += 4;
2050 // an additional bonus for Beogh worshippers
2051 if (you.religion == GOD_BEOGH && !player_under_penance())
2053 if (you.piety >= 185)
2054 racial_bonus += racial_bonus * 9 / 4;
2055 else if (you.piety >= 160)
2056 racial_bonus += racial_bonus * 2;
2057 else if (you.piety >= 120)
2058 racial_bonus += racial_bonus * 7 / 4;
2059 else if (you.piety >= 80)
2060 racial_bonus += racial_bonus * 5 / 4;
2061 else if (you.piety >= 40)
2062 racial_bonus += racial_bonus * 3 / 4;
2063 else
2064 racial_bonus += racial_bonus / 4;
2068 return racial_bonus;
2071 bool is_effectively_light_armour(const item_def *item)
2073 return (!item
2074 || (abs(property(*item, PARM_EVASION)) < 2));
2077 bool player_effectively_in_light_armour()
2079 const item_def *armour = you.slot_item(EQ_BODY_ARMOUR, false);
2080 return is_effectively_light_armour(armour);
2083 // This function returns true if the player has a radically different
2084 // shape... minor changes like blade hands don't count, also note
2085 // that lich transformation doesn't change the character's shape
2086 // (so we end up with Naga-lichs, Spiggan-lichs, Minotaur-lichs)
2087 // it just makes the character undead (with the benefits that implies). - bwr
2088 bool player_is_shapechanged(void)
2090 if (you.form == TRAN_NONE
2091 || you.form == TRAN_BLADE_HANDS
2092 || you.form == TRAN_LICH)
2094 return (false);
2097 return (true);
2100 // An evasion factor based on the player's body size, smaller == higher
2101 // evasion size factor.
2102 int player_evasion_size_factor()
2104 // XXX: you.body_size() implementations are incomplete, fix.
2105 const size_type size = you.body_size(PSIZE_BODY);
2106 return 2 * (SIZE_MEDIUM - size);
2109 // The EV penalty to the player for wearing their current shield.
2110 int player_adjusted_shield_evasion_penalty(int scale)
2112 const item_def *shield = you.slot_item(EQ_SHIELD, false);
2113 if (!shield)
2114 return (0);
2116 const int base_shield_penalty = -property(*shield, PARM_EVASION);
2117 return std::max(0,
2118 (base_shield_penalty * scale
2119 - you.skill(SK_SHIELDS) * scale
2120 / (5 + player_evasion_size_factor())));
2123 int player_raw_body_armour_evasion_penalty()
2125 const item_def *body_armour = you.slot_item(EQ_BODY_ARMOUR, false);
2126 if (!body_armour)
2127 return (0);
2129 const int base_ev_penalty = -property(*body_armour, PARM_EVASION);
2130 return base_ev_penalty;
2133 int player_size_adjusted_body_armour_evasion_penalty(int scale)
2135 const int base_ev_penalty = player_raw_body_armour_evasion_penalty();
2136 if (!base_ev_penalty)
2137 return (0);
2139 const int size = you.body_size(PSIZE_BODY);
2141 const int size_bonus_factor = (size - SIZE_MEDIUM) * scale / 4;
2143 const int size_adjusted_penalty =
2144 std::max(0,
2145 scale * base_ev_penalty
2146 - size_bonus_factor * base_ev_penalty);
2148 return (size_adjusted_penalty);
2151 // The EV penalty to the player for their worn body armour.
2152 int player_adjusted_body_armour_evasion_penalty(int scale)
2154 const int base_ev_penalty = player_raw_body_armour_evasion_penalty();
2155 if (!base_ev_penalty)
2156 return (0);
2158 return ((base_ev_penalty
2159 + std::max(0, 3 * base_ev_penalty - you.strength()))
2160 * (45 - you.skill(SK_ARMOUR))
2161 * scale
2162 / 45);
2165 // The total EV penalty to the player for all their worn armour items
2166 // with a base EV penalty (i.e. EV penalty as a base armour property,
2167 // not as a randart property).
2168 static int _player_adjusted_evasion_penalty(const int scale)
2170 int piece_armour_evasion_penalty = 0;
2172 // Some lesser armours have small penalties now (barding).
2173 for (int i = EQ_MIN_ARMOUR; i < EQ_MAX_ARMOUR; i++)
2175 if (i == EQ_SHIELD || !player_wearing_slot(i))
2176 continue;
2178 // [ds] Evasion modifiers for armour are negatives, change
2179 // those to positive for penalty calc.
2180 const int penalty = -property(you.inv[you.equip[i]], PARM_EVASION);
2181 if (penalty > 0)
2182 piece_armour_evasion_penalty += penalty;
2185 return (piece_armour_evasion_penalty * scale +
2186 player_adjusted_body_armour_evasion_penalty(scale));
2189 // EV bonuses that work even when helpless.
2190 static int _player_para_evasion_bonuses(ev_ignore_type evit)
2192 int evbonus = 0;
2194 if (you.duration[DUR_PHASE_SHIFT] && !(evit & EV_IGNORE_PHASESHIFT))
2195 evbonus += 8;
2197 if (player_mutation_level(MUT_DISTORTION_FIELD) > 0)
2198 evbonus += player_mutation_level(MUT_DISTORTION_FIELD) + 1;
2200 return (evbonus);
2203 // Player EV bonuses for various effects and transformations. This
2204 // does not include kenku/merfolk EV bonuses for flight/swimming.
2205 int player_evasion_bonuses(ev_ignore_type evit)
2207 int evbonus = _player_para_evasion_bonuses(evit);
2209 if (you.duration[DUR_AGILITY])
2210 evbonus += 5;
2212 if (you.duration[DUR_STONEMAIL])
2213 evbonus -= 2;
2215 evbonus += player_equip(EQ_RINGS_PLUS, RING_EVASION);
2217 if (player_equip_ego_type(EQ_WEAPON, SPWPN_EVASION))
2218 evbonus += 5;
2220 evbonus += scan_artefacts(ARTP_EVASION);
2222 // mutations
2223 if (player_mutation_level(MUT_ICY_BLUE_SCALES) > 1)
2224 evbonus--;
2225 if (player_mutation_level(MUT_MOLTEN_SCALES) > 1)
2226 evbonus--;
2227 evbonus -= std::max(0, player_mutation_level(MUT_SLIMY_GREEN_SCALES) - 1);
2228 evbonus += std::max(0, player_mutation_level(MUT_GELATINOUS_BODY) - 1);
2230 // transformation penalties/bonuses not covered by size alone:
2231 if (you.form == TRAN_STATUE)
2232 evbonus -= 5; // stiff
2234 return (evbonus);
2237 // Player EV scaling for being flying kenku or swimming merfolk.
2238 int player_scale_evasion(const int prescaled_ev, const int scale)
2240 switch (you.species)
2242 case SP_MERFOLK:
2243 // Merfolk get an evasion bonus in water.
2244 if (you.fishtail)
2246 const int ev_bonus =
2247 std::min(9 * scale,
2248 std::max(2 * scale,
2249 prescaled_ev / 4));
2250 return (prescaled_ev + ev_bonus);
2252 break;
2254 case SP_KENKU:
2255 // Flying Kenku get an evasion bonus.
2256 if (you.flight_mode() == FL_FLY)
2258 const int ev_bonus =
2259 std::min(9 * scale,
2260 std::max(1 * scale,
2261 prescaled_ev / 5));
2262 return (prescaled_ev + ev_bonus);
2264 break;
2266 default:
2267 break;
2269 return (prescaled_ev);
2272 // Total EV for player using the revised 0.6 evasion model.
2273 int player_evasion(ev_ignore_type evit)
2275 const int size_factor = player_evasion_size_factor();
2276 // Repulsion fields and size are all that matters when paralysed or
2277 // at 0 dex.
2278 if ((you.cannot_move() || you.stat_zero[STAT_DEX])
2279 && !(evit & EV_IGNORE_HELPLESS))
2281 const int paralysed_base_ev = 2 + size_factor / 2;
2282 const int repulsion_ev = _player_para_evasion_bonuses(evit);
2283 return std::max(1, paralysed_base_ev + repulsion_ev);
2286 const int scale = 100;
2287 const int size_base_ev = (10 + size_factor) * scale;
2289 const int adjusted_evasion_penalty =
2290 _player_adjusted_evasion_penalty(scale);
2292 // The last two parameters are not important.
2293 const int ev_dex = stepdown_value(you.dex(), 10, 24, 72, 72);
2295 const int dodge_bonus =
2296 (7 + you.skill(SK_DODGING) * ev_dex) * scale
2297 / (20 - size_factor);
2299 // [ds] Dodging penalty for being in high EVP armour, almost
2300 // identical to v0.5/4.1 penalty, but with the EVP discount being
2301 // 1 instead of 0.5 so that leather armour is fully discounted.
2302 // The 1 EVP of leather armour may still incur an
2303 // adjusted_evasion_penalty, however.
2304 const int armour_dodge_penalty =
2305 std::max(0,
2306 (30 * player_size_adjusted_body_armour_evasion_penalty(scale)
2307 - 30 * scale)
2308 / std::max(1, (int) you.strength()));
2310 // Adjust dodge bonus for the effects of being suited up in armour.
2311 const int armour_adjusted_dodge_bonus =
2312 std::max(0, dodge_bonus - armour_dodge_penalty);
2314 const int adjusted_shield_penalty =
2315 player_adjusted_shield_evasion_penalty(scale);
2317 const int prestepdown_evasion =
2318 size_base_ev
2319 + armour_adjusted_dodge_bonus
2320 - adjusted_evasion_penalty
2321 - adjusted_shield_penalty;
2323 const int poststepdown_evasion =
2324 stepdown_value(prestepdown_evasion, 20*scale, 30*scale, 60*scale, -1);
2326 const int evasion_bonuses = player_evasion_bonuses(evit) * scale;
2328 const int prescaled_evasion =
2329 poststepdown_evasion + evasion_bonuses;
2331 const int final_evasion =
2332 player_scale_evasion(prescaled_evasion, scale);
2334 return (unscale_round_up(final_evasion, scale));
2337 int player_body_armour_racial_spellcasting_bonus(const int scale)
2339 const item_def *body_armour = you.slot_item(EQ_BODY_ARMOUR, false);
2340 if (!body_armour)
2341 return (0);
2343 const iflags_t armour_race = get_equip_race(*body_armour);
2345 // Get the armour race value that corresponds to the character's
2346 // race:
2347 const iflags_t player_race
2348 = ((player_genus(GENPC_DWARVEN)) ? ISFLAG_DWARVEN :
2349 (player_genus(GENPC_ELVEN)) ? ISFLAG_ELVEN :
2350 (you.species == SP_HILL_ORC) ? ISFLAG_ORCISH
2351 : 0);
2352 int armour_racial_spellcasting_bonus = 0;
2353 if (armour_race & ISFLAG_ELVEN)
2354 armour_racial_spellcasting_bonus += 25;
2356 if (armour_race & ISFLAG_DWARVEN)
2357 armour_racial_spellcasting_bonus -= 15;
2359 if (armour_race & player_race)
2360 armour_racial_spellcasting_bonus += 15;
2362 return (armour_racial_spellcasting_bonus * scale);
2365 // Returns the spellcasting penalty (increase in spell failure) for the
2366 // player's worn body armour and shield.
2367 int player_armour_shield_spell_penalty()
2369 const int scale = 100;
2371 const int body_armour_penalty =
2372 std::max(25 * player_adjusted_body_armour_evasion_penalty(scale)
2373 - player_body_armour_racial_spellcasting_bonus(scale),
2376 const int total_penalty = body_armour_penalty
2377 + 25 * player_adjusted_shield_evasion_penalty(scale)
2378 - 20 * scale;
2380 return (std::max(total_penalty, 0) / scale);
2383 int player_magical_power(void)
2385 int ret = 0;
2387 ret += 13 * player_equip(EQ_STAFF, STAFF_POWER);
2388 ret += 9 * player_equip(EQ_RINGS, RING_MAGICAL_POWER);
2389 ret += scan_artefacts(ARTP_MAGICAL_POWER);
2391 return (ret);
2394 int player_mag_abil(bool is_weighted)
2396 int ma = 0;
2398 // Brilliance Potion
2399 ma += 6 * (you.duration[DUR_BRILLIANCE] ? 1 : 0);
2401 ma += 3 * player_equip(EQ_RINGS, RING_WIZARDRY);
2403 // Staves
2404 ma += 4 * player_equip(EQ_STAFF, STAFF_WIZARDRY);
2406 // armour of the Archmagi (checks body armour only)
2407 ma += 2 * player_equip_ego_type(EQ_BODY_ARMOUR, SPARM_ARCHMAGI);
2409 return ((is_weighted) ? ((ma * you.intel()) / 10) : ma);
2412 int player_shield_class(void) //jmf: changes for new spell
2414 int shield = 0;
2415 int stat = 0;
2417 if (you.incapacitated())
2418 return (0);
2420 if (player_wearing_slot(EQ_SHIELD))
2422 const item_def& item = you.inv[you.equip[EQ_SHIELD]];
2423 int base_shield = property(item, PARM_AC);
2425 int racial_bonus = _player_armour_racial_bonus(item);
2427 // bonus applied only to base, see above for effect:
2428 shield += base_shield * 100;
2429 shield += base_shield * 5 * you.skill(SK_SHIELDS);
2430 shield += base_shield * racial_bonus * 10 / 3;
2432 shield += item.plus * 100;
2434 if (item.sub_type == ARM_BUCKLER)
2435 stat = you.dex() * 38;
2436 else if (item.sub_type == ARM_LARGE_SHIELD)
2437 stat = you.dex() * 12 + you.strength() * 26;
2438 else
2439 stat = you.dex() * 19 + you.strength() * 19;
2441 else
2443 if (you.duration[DUR_MAGIC_SHIELD])
2445 stat = 600 + you.skill(SK_EVOCATIONS) * 50;
2446 shield += 300 + you.skill(SK_EVOCATIONS) * 25;
2449 if (!you.duration[DUR_FIRE_SHIELD]
2450 && you.duration[DUR_CONDENSATION_SHIELD])
2452 shield += 300 + (you.skill(SK_ICE_MAGIC) * 25);
2453 stat = std::max(stat, you.intel() * 38);
2457 if (you.duration[DUR_DIVINE_SHIELD])
2459 shield += you.attribute[ATTR_DIVINE_SHIELD] * 150;
2460 stat = std::max(stat, int(you.attribute[ATTR_DIVINE_SHIELD] * 300));
2463 if (shield + stat > 0)
2464 shield += skill_bump(SK_SHIELDS) * 38;
2466 // mutations
2467 shield += player_mutation_level(MUT_LARGE_BONE_PLATES) > 0 ? 100 + player_mutation_level(MUT_LARGE_BONE_PLATES) * 100 : 0; // +2, +3, +4
2469 return (shield + stat + 50) / 100;
2472 int player_sust_abil(bool calc_unid)
2474 int sa = 0;
2476 sa += player_equip(EQ_RINGS, RING_SUSTAIN_ABILITIES, calc_unid);
2478 return (sa);
2481 int carrying_capacity(burden_state_type bs)
2483 // Yuck. We need this for gameplay - it nerfs small forms too much
2484 // otherwise - but there's no good way to rationalize here... --sorear
2485 int used_weight = std::max(you.body_weight(), you.body_weight(true));
2487 int cap = (2 * used_weight) + (you.strength() * 300)
2488 + (you.airborne() ? 1000 : 0);
2489 // We are nice to the lighter species in that strength adds absolutely
2490 // instead of relatively to body weight. --dpeg
2492 if (you.stat_zero[STAT_STR])
2493 cap /= 2;
2495 if (bs == BS_UNENCUMBERED)
2496 return ((cap * 5) / 6);
2497 else if (bs == BS_ENCUMBERED)
2498 return ((cap * 11) / 12);
2499 else
2500 return (cap);
2503 int burden_change(void)
2505 const burden_state_type old_burdenstate = you.burden_state;
2506 const bool was_flying_light = you.light_flight();
2508 you.burden = 0;
2510 if (you.duration[DUR_STONEMAIL])
2511 you.burden += 800;
2513 for (int bu = 0; bu < ENDOFPACK; bu++)
2515 if (you.inv[bu].quantity < 1)
2516 continue;
2518 you.burden += item_mass(you.inv[bu]) * you.inv[bu].quantity;
2521 you.burden_state = BS_UNENCUMBERED;
2522 set_redraw_status(REDRAW_BURDEN);
2523 you.redraw_evasion = true;
2525 // changed the burdened levels to match the change to max_carried
2526 if (you.burden < carrying_capacity(BS_UNENCUMBERED))
2528 you.burden_state = BS_UNENCUMBERED;
2530 // this message may have to change, just testing {dlb}
2531 if (old_burdenstate != you.burden_state)
2532 mpr("Your possessions no longer seem quite so burdensome.");
2534 else if (you.burden < carrying_capacity(BS_ENCUMBERED))
2536 you.burden_state = BS_ENCUMBERED;
2538 if (old_burdenstate != you.burden_state)
2540 mpr("You are being weighed down by all of your possessions.");
2541 learned_something_new(HINT_HEAVY_LOAD);
2544 else
2546 you.burden_state = BS_OVERLOADED;
2548 if (old_burdenstate != you.burden_state)
2550 mpr("You are being crushed by all of your possessions.");
2551 learned_something_new(HINT_HEAVY_LOAD);
2555 // Stop travel if we get burdened (as from potions of might/levitation
2556 // wearing off).
2557 if (you.burden_state > old_burdenstate)
2558 interrupt_activity(AI_BURDEN_CHANGE);
2560 const bool is_flying_light = you.light_flight();
2562 if (is_flying_light != was_flying_light)
2564 mpr(is_flying_light ? "You feel quicker in the air."
2565 : "You feel heavier in the air.");
2568 return (you.burden);
2571 // force is true for forget_map command on level map.
2572 void forget_map(int chance_forgotten, bool force)
2574 ASSERT(!crawl_state.game_is_arena());
2576 if (force && !yesno("Really forget level map?", true, 'n'))
2577 return;
2579 // The radius is only used in labyrinths.
2580 const bool use_lab_check = (!force && you.level_type == LEVEL_LABYRINTH
2581 && chance_forgotten < 100);
2582 const int radius = (use_lab_check && you.species == SP_MINOTAUR) ? 40*40
2583 : 25*25;
2584 for (rectangle_iterator ri(0); ri; ++ri)
2586 if (!you.see_cell(*ri)
2587 && (force || x_chance_in_y(chance_forgotten, 100)
2588 || use_lab_check && (you.pos()-*ri).abs() > radius))
2590 env.map_knowledge(*ri).clear();
2591 #ifdef USE_TILE
2592 tile_forget_map(*ri);
2593 #endif
2597 ash_detect_portals(player_in_mappable_area());
2598 #ifdef USE_TILE
2599 tiles.update_minimap_bounds();
2600 #endif
2603 void gain_exp(unsigned int exp_gained, unsigned int* actual_gain,
2604 unsigned int* actual_avail_gain)
2606 if (crawl_state.game_is_arena())
2607 return;
2608 if (crawl_state.game_is_sprint() && you.level_type == LEVEL_ABYSS)
2609 return;
2611 if (you.religion == GOD_ASHENZARI && you.piety > piety_breakpoint(0))
2612 exp_gained = div_rand_round(exp_gained * (8 + ash_bondage_level()), 8);
2614 const unsigned int old_exp = you.experience;
2615 const int old_avail = you.exp_available;
2617 dprf("gain_exp: %d", exp_gained);
2619 if (you.transfer_skill_points > 0)
2621 int amount = exp_gained * 10
2622 / calc_skill_cost(you.skill_cost_level,
2623 you.skills[you.transfer_to_skill]);
2624 if (amount >= 20 || one_chance_in(20 - amount))
2626 amount = std::max(20, amount);
2627 transfer_skill_points(you.transfer_from_skill,
2628 you.transfer_to_skill, amount, false);
2632 if (you.experience + exp_gained > (unsigned int)MAX_EXP_TOTAL)
2633 you.experience = MAX_EXP_TOTAL;
2634 else
2635 you.experience += exp_gained;
2637 if (you.duration[DUR_SAGE])
2639 // Bonus skill training from Sage.
2640 you.exp_available =
2641 (exp_gained * you.sage_bonus_degree) / 100 + exp_gained / 2;
2642 practise(EX_SAGE, you.sage_bonus_skill);
2643 you.exp_available = old_avail;
2644 exp_gained /= 2;
2647 if (crawl_state.game_is_sprint())
2649 exp_gained = sprint_modify_exp(exp_gained);
2652 if (you.exp_available + exp_gained > (unsigned int)MAX_EXP_POOL)
2653 you.exp_available = MAX_EXP_POOL;
2654 else
2655 you.exp_available += exp_gained;
2657 level_change();
2659 if (actual_gain != NULL)
2660 *actual_gain = you.experience - old_exp;
2662 if (actual_avail_gain != NULL)
2663 *actual_avail_gain = you.exp_available - old_avail;
2666 static void _draconian_scale_colour_message()
2668 switch (you.species)
2670 case SP_RED_DRACONIAN:
2671 mpr("Your scales start taking on a fiery red colour.",
2672 MSGCH_INTRINSIC_GAIN);
2673 perma_mutate(MUT_HEAT_RESISTANCE, 1);
2674 break;
2676 case SP_WHITE_DRACONIAN:
2677 mpr("Your scales start taking on an icy white colour.",
2678 MSGCH_INTRINSIC_GAIN);
2679 perma_mutate(MUT_COLD_RESISTANCE, 1);
2680 break;
2682 case SP_GREEN_DRACONIAN:
2683 mpr("Your scales start taking on a lurid green colour.",
2684 MSGCH_INTRINSIC_GAIN);
2685 perma_mutate(MUT_POISON_RESISTANCE, 1);
2686 break;
2688 case SP_YELLOW_DRACONIAN:
2689 mpr("Your scales start taking on a golden yellow colour.",
2690 MSGCH_INTRINSIC_GAIN);
2691 break;
2693 case SP_GREY_DRACONIAN:
2694 mpr("Your scales start taking on a dull grey colour.",
2695 MSGCH_INTRINSIC_GAIN);
2696 perma_mutate(MUT_UNBREATHING, 1);
2697 break;
2699 case SP_BLACK_DRACONIAN:
2700 mpr("Your scales start taking on a glossy black colour.",
2701 MSGCH_INTRINSIC_GAIN);
2702 perma_mutate(MUT_SHOCK_RESISTANCE, 1);
2703 break;
2705 case SP_PURPLE_DRACONIAN:
2706 mpr("Your scales start taking on a rich purple colour.",
2707 MSGCH_INTRINSIC_GAIN);
2708 break;
2710 case SP_MOTTLED_DRACONIAN:
2711 mpr("Your scales start taking on a weird mottled pattern.",
2712 MSGCH_INTRINSIC_GAIN);
2713 break;
2715 case SP_PALE_DRACONIAN:
2716 mpr("Your scales start fading to a pale grey colour.",
2717 MSGCH_INTRINSIC_GAIN);
2718 break;
2720 case SP_BASE_DRACONIAN:
2721 mpr("");
2722 break;
2724 default:
2725 break;
2729 static void _felid_extra_life()
2731 if (you.lives + you.deaths < you.max_level/3 && you.lives < 2)
2733 you.lives++;
2734 mpr("Extra life!", MSGCH_INTRINSIC_GAIN);
2736 // Should play the 1UP sound from SMB...
2739 void level_change(bool skip_attribute_increase)
2741 const bool wiz_cmd = crawl_state.prev_cmd == CMD_WIZARD
2742 || crawl_state.repeat_cmd == CMD_WIZARD;
2744 // necessary for the time being, as level_change() is called
2745 // directly sometimes {dlb}
2746 you.redraw_experience = true;
2748 while (you.experience_level < 27
2749 && you.experience > exp_needed(you.experience_level + 2))
2751 if (!skip_attribute_increase && !wiz_cmd)
2753 crawl_state.cancel_cmd_all();
2755 if (is_processing_macro())
2756 flush_input_buffer(FLUSH_ABORT_MACRO);
2759 const int old_hp = you.hp;
2760 const int old_maxhp = you.hp_max;
2762 int hp_adjust = 0;
2763 int mp_adjust = 0;
2765 // [ds] Make sure we increment you.experience_level and apply
2766 // any stat/hp increases only after we've cleared all prompts
2767 // for this experience level. If we do part of the work before
2768 // the prompt, and a player on telnet gets disconnected, the
2769 // SIGHUP will save Crawl in the in-between state and rob the
2770 // player of their level-up perks.
2772 const int new_exp = you.experience_level + 1;
2774 if (new_exp <= you.max_level)
2776 mprf(MSGCH_INTRINSIC_GAIN,
2777 "Welcome back to level %d!", new_exp);
2779 // No more prompts for this XL past this point.
2781 you.experience_level = new_exp;
2782 // Gain back the hp and mp we lose in lose_level(). -- bwr
2783 inc_hp(4, true);
2784 inc_mp(1, true);
2786 else // Character has gained a new level
2788 if (new_exp == 27)
2790 mprf(MSGCH_INTRINSIC_GAIN,
2791 "You have reached level 27, the final one!");
2793 else
2795 mprf(MSGCH_INTRINSIC_GAIN, "You have reached level %d!",
2796 new_exp);
2799 if (!(new_exp % 3) && !skip_attribute_increase)
2800 attribute_increase();
2802 int brek = 0;
2804 if (new_exp > 21)
2805 brek = 2 + new_exp % 2;
2806 else if (new_exp > 12)
2807 brek = 4; // up from 2 + rand(3) -- bwr
2808 else
2809 brek = 5 + new_exp % 2; // up from 3 + rand(4) -- bwr
2811 you.experience_level = new_exp;
2812 inc_hp(brek, true);
2813 inc_mp(1, true);
2815 switch (you.species)
2817 case SP_HUMAN:
2818 if (!(you.experience_level % 5))
2819 modify_stat(STAT_RANDOM, 1, false, "level gain");
2820 break;
2822 case SP_HIGH_ELF:
2823 if (you.experience_level % 3)
2824 hp_adjust--;
2826 if (!(you.experience_level % 2))
2827 mp_adjust++;
2829 if (!(you.experience_level % 3))
2831 modify_stat((coinflip() ? STAT_INT
2832 : STAT_DEX), 1, false,
2833 "level gain");
2835 break;
2837 case SP_DEEP_ELF:
2838 if (you.experience_level < 17)
2839 hp_adjust--;
2841 if (!(you.experience_level % 3))
2842 hp_adjust--;
2844 mp_adjust++;
2846 if (!(you.experience_level % 4))
2847 modify_stat(STAT_INT, 1, false, "level gain");
2848 break;
2850 case SP_SLUDGE_ELF:
2851 if (you.experience_level % 3)
2852 hp_adjust--;
2853 else
2854 mp_adjust++;
2856 if (!(you.experience_level % 4))
2858 modify_stat((coinflip() ? STAT_INT
2859 : STAT_DEX), 1, false,
2860 "level gain");
2862 break;
2864 case SP_MOUNTAIN_DWARF:
2865 if (!(you.experience_level % 2))
2866 hp_adjust++;
2868 if (!(you.experience_level % 3))
2869 mp_adjust--;
2871 if (!(you.experience_level % 4))
2872 modify_stat(STAT_STR, 1, false, "level gain");
2873 break;
2875 case SP_DEEP_DWARF:
2876 hp_adjust++;
2878 if (you.experience_level == 14)
2880 mpr("You feel somewhat more resistant.",
2881 MSGCH_INTRINSIC_GAIN);
2882 perma_mutate(MUT_NEGATIVE_ENERGY_RESISTANCE, 1);
2885 if ((you.experience_level == 9)
2886 || (you.experience_level == 18))
2888 perma_mutate(MUT_PASSIVE_MAPPING, 1);
2891 if (!(you.experience_level % 4))
2893 modify_stat(coinflip() ? STAT_STR
2894 : STAT_INT, 1, false,
2895 "level gain");
2897 break;
2899 case SP_HALFLING:
2900 if (!(you.experience_level % 5))
2901 modify_stat(STAT_DEX, 1, false, "level gain");
2903 if (you.experience_level % 3)
2904 hp_adjust--;
2906 break;
2908 case SP_KOBOLD:
2909 if (!(you.experience_level % 5))
2911 modify_stat((coinflip() ? STAT_STR
2912 : STAT_DEX), 1, false,
2913 "level gain");
2916 if (you.experience_level < 17)
2917 hp_adjust--;
2919 if (!(you.experience_level % 2))
2920 hp_adjust--;
2921 break;
2923 case SP_HILL_ORC:
2924 // lower because of HD raise -- bwr
2925 // if (you.experience_level < 17)
2926 // hp_adjust++;
2928 if (!(you.experience_level % 2))
2929 hp_adjust++;
2931 if (!(you.experience_level % 3))
2932 mp_adjust--;
2934 if (!(you.experience_level % 5))
2935 modify_stat(STAT_STR, 1, false, "level gain");
2936 break;
2938 case SP_MUMMY:
2939 if (you.experience_level == 13 || you.experience_level == 26)
2941 mpr("You feel more in touch with the powers of death.",
2942 MSGCH_INTRINSIC_GAIN);
2945 if (you.experience_level == 13) // level 13 for now -- bwr
2947 mpr("You can now infuse your body with magic to restore "
2948 "decomposition.", MSGCH_INTRINSIC_GAIN);
2950 break;
2952 case SP_VAMPIRE:
2953 if (you.experience_level == 3)
2955 if (you.hunger_state > HS_SATIATED)
2957 mpr("If you weren't so full you could now transform "
2958 "into a vampire bat.", MSGCH_INTRINSIC_GAIN);
2960 else
2962 mpr("You can now transform into a vampire bat.",
2963 MSGCH_INTRINSIC_GAIN);
2966 else if (you.experience_level == 6)
2968 mpr("You can now bottle potions of blood from corpses.",
2969 MSGCH_INTRINSIC_GAIN);
2971 break;
2973 case SP_NAGA:
2974 hp_adjust++;
2976 if (!(you.experience_level % 4))
2977 modify_stat(STAT_RANDOM, 1, false, "level gain");
2979 if (!(you.experience_level % 3))
2981 mpr("Your skin feels tougher.", MSGCH_INTRINSIC_GAIN);
2982 you.redraw_armour_class = true;
2984 break;
2986 case SP_TROLL:
2987 hp_adjust++;
2989 if (!(you.experience_level % 2))
2990 hp_adjust++;
2992 if (you.experience_level % 3)
2993 mp_adjust--;
2995 if (!(you.experience_level % 3))
2996 modify_stat(STAT_STR, 1, false, "level gain");
2997 break;
2999 case SP_OGRE:
3000 hp_adjust++;
3002 if (!(you.experience_level % 3))
3003 modify_stat(STAT_STR, 1, false, "level gain");
3004 break;
3006 case SP_BASE_DRACONIAN:
3007 if (you.experience_level >= 7)
3009 you.species = random_draconian_player_species();
3010 update_player_symbol();
3011 #ifdef USE_TILE
3012 init_player_doll();
3013 #endif
3014 redraw_screen();
3015 _draconian_scale_colour_message();
3017 // We check if any skill has changed level because of
3018 // changed aptitude
3019 for (int i = SK_FIRST_SKILL; i < NUM_SKILLS; ++i)
3020 check_skill_level_change(static_cast<skill_type>(i));
3022 case SP_RED_DRACONIAN:
3023 case SP_WHITE_DRACONIAN:
3024 case SP_GREEN_DRACONIAN:
3025 case SP_YELLOW_DRACONIAN:
3026 case SP_GREY_DRACONIAN:
3027 case SP_BLACK_DRACONIAN:
3028 case SP_PURPLE_DRACONIAN:
3029 case SP_MOTTLED_DRACONIAN:
3030 case SP_PALE_DRACONIAN:
3031 if (!(you.experience_level % 3))
3032 hp_adjust++;
3034 if (!(you.experience_level % 3))
3036 mpr("Your scales feel tougher.", MSGCH_INTRINSIC_GAIN);
3037 you.redraw_armour_class = true;
3040 if (!(you.experience_level % 4) && you.experience_level > 7)
3042 modify_stat(STAT_RANDOM, 1, false, "level gain");
3045 if (you.experience_level == 14)
3047 switch (you.species)
3049 case SP_GREEN_DRACONIAN:
3050 perma_mutate(MUT_STINGER, 1);
3051 break;
3052 case SP_YELLOW_DRACONIAN:
3053 perma_mutate(MUT_ACIDIC_BITE, 1);
3054 break;
3055 case SP_BLACK_DRACONIAN:
3056 perma_mutate(MUT_BIG_WINGS, 1);
3057 break;
3058 default:
3059 break;
3062 break;
3064 case SP_CENTAUR:
3065 if (!(you.experience_level % 4))
3067 modify_stat((coinflip() ? STAT_STR
3068 : STAT_DEX), 1, false,
3069 "level gain");
3072 // lowered because of HD raise -- bwr
3073 // if (you.experience_level < 17)
3074 // hp_adjust++;
3076 if (!(you.experience_level % 2))
3077 hp_adjust++;
3079 if (!(you.experience_level % 3))
3080 mp_adjust--;
3081 break;
3083 case SP_DEMIGOD:
3084 if (!(you.experience_level % 2))
3085 modify_stat(STAT_RANDOM, 1, false, "level gain");
3087 // lowered because of HD raise -- bwr
3088 // if (you.experience_level < 17)
3089 // hp_adjust++;
3091 if (!(you.experience_level % 2))
3092 hp_adjust++;
3094 if (you.experience_level % 3)
3095 mp_adjust++;
3096 break;
3098 case SP_SPRIGGAN:
3099 if (you.experience_level < 17)
3100 hp_adjust--;
3102 if (you.experience_level % 3)
3103 hp_adjust--;
3105 mp_adjust++;
3107 if (!(you.experience_level % 5))
3109 modify_stat((coinflip() ? STAT_INT
3110 : STAT_DEX), 1, false,
3111 "level gain");
3113 break;
3115 case SP_MINOTAUR:
3116 // lowered because of HD raise -- bwr
3117 // if (you.experience_level < 17)
3118 // hp_adjust++;
3120 if (!(you.experience_level % 2))
3121 hp_adjust++;
3123 if (!(you.experience_level % 2))
3124 mp_adjust--;
3126 if (!(you.experience_level % 4))
3128 modify_stat((coinflip() ? STAT_STR
3129 : STAT_DEX), 1, false,
3130 "level gain");
3132 break;
3134 case SP_DEMONSPAWN:
3136 bool gave_message = false;
3137 int level = 0;
3138 mutation_type first_body_facet = NUM_MUTATIONS;
3140 for (unsigned i = 0; i < you.demonic_traits.size(); ++i)
3142 if (is_body_facet(you.demonic_traits[i].mutation))
3144 if (first_body_facet < NUM_MUTATIONS
3145 && you.demonic_traits[i].mutation
3146 != first_body_facet)
3148 if (you.experience_level == level)
3150 mpr("You feel monstrous as your "
3151 "demonic heritage exerts itself.",
3152 MSGCH_MUTATION);
3154 mark_milestone("monstrous", "is a "
3155 "monstrous demonspawn!");
3158 i = you.demonic_traits.size();
3159 break;
3162 if (first_body_facet == NUM_MUTATIONS)
3164 first_body_facet = you.demonic_traits[i].mutation;
3165 level = you.demonic_traits[i].level_gained;
3170 for (unsigned i = 0; i < you.demonic_traits.size(); ++i)
3172 if (you.demonic_traits[i].level_gained
3173 == you.experience_level)
3175 if (!gave_message)
3177 mpr("Your demonic ancestry asserts itself...",
3178 MSGCH_INTRINSIC_GAIN);
3180 gave_message = true;
3182 perma_mutate(you.demonic_traits[i].mutation, 1);
3186 if (!(you.experience_level % 4))
3187 modify_stat(STAT_RANDOM, 1, false, "level gain");
3188 break;
3191 case SP_GHOUL:
3192 // lowered because of HD raise -- bwr
3193 // if (you.experience_level < 17)
3194 // hp_adjust++;
3196 if (!(you.experience_level % 2))
3197 hp_adjust++;
3199 if (!(you.experience_level % 3))
3200 mp_adjust--;
3202 if (!(you.experience_level % 5))
3203 modify_stat(STAT_STR, 1, false, "level gain");
3204 break;
3206 case SP_KENKU:
3207 if (you.experience_level < 17)
3208 hp_adjust--;
3210 if (!(you.experience_level % 3))
3211 hp_adjust--;
3213 if (!(you.experience_level % 4))
3214 modify_stat(STAT_RANDOM, 1, false, "level gain");
3216 if (you.experience_level == 5)
3218 mpr("You have gained the ability to fly.",
3219 MSGCH_INTRINSIC_GAIN);
3221 else if (you.experience_level == 15)
3222 mpr("You can now fly continuously.", MSGCH_INTRINSIC_GAIN);
3223 break;
3225 case SP_MERFOLK:
3226 if (!(you.experience_level % 5))
3227 modify_stat(STAT_RANDOM, 1, false, "level gain");
3228 break;
3230 case SP_CAT:
3231 hp_adjust--;
3232 hp_adjust--;
3234 if (you.experience_level % 2)
3235 mp_adjust++;
3237 if (!(you.experience_level % 5))
3239 modify_stat((coinflip() ? STAT_INT
3240 : STAT_DEX), 1, false,
3241 "level gain");
3244 if (you.experience_level == 6 || you.experience_level == 12)
3245 perma_mutate(MUT_SHAGGY_FUR, 1);
3247 _felid_extra_life();
3248 break;
3251 default:
3252 break;
3256 // // zot defence abilities; must also be updated in abil-show.cc when these levels are changed
3257 if (crawl_state.game_is_zotdef())
3259 if (you.experience_level == 1)
3260 mpr("Your Zot abilities now extend through the making of dart traps.", MSGCH_INTRINSIC_GAIN);
3261 if (you.experience_level == 2)
3262 mpr("Your Zot abilities now extend through the making of oklob saplings.", MSGCH_INTRINSIC_GAIN);
3263 if (you.experience_level == 3)
3264 mpr("Your Zot abilities now extend through the making of arrow traps.", MSGCH_INTRINSIC_GAIN);
3265 if (you.experience_level == 4)
3266 mpr("Your Zot abilities now extend through the making of plants.", MSGCH_INTRINSIC_GAIN);
3267 if (you.experience_level == 4)
3268 mpr("Your Zot abilities now extend through removing curses.", MSGCH_INTRINSIC_GAIN);
3269 if (you.experience_level == 5)
3270 mpr("Your Zot abilities now extend through the making of burning bushes.", MSGCH_INTRINSIC_GAIN);
3271 if (you.experience_level == 6)
3272 mpr("Your Zot abilities now extend through the making of altars and grenades.", MSGCH_INTRINSIC_GAIN);
3273 if (you.experience_level == 7)
3274 mpr("Your Zot abilities now extend through the making of oklob plants.", MSGCH_INTRINSIC_GAIN);
3275 if (you.experience_level == 8)
3276 mpr("Your Zot abilities now extend through the making of net traps.", MSGCH_INTRINSIC_GAIN);
3277 if (you.experience_level == 9)
3278 mpr("Your Zot abilities now extend through the making of ice statues.", MSGCH_INTRINSIC_GAIN);
3279 if (you.experience_level == 10)
3280 mpr("Your Zot abilities now extend through the making of spear traps.", MSGCH_INTRINSIC_GAIN);
3281 if (you.experience_level == 11)
3282 mpr("Your Zot abilities now extend through the making of alarm traps.", MSGCH_INTRINSIC_GAIN);
3283 if (you.experience_level == 12)
3284 mpr("Your Zot abilities now extend through the making of mushroom circles.", MSGCH_INTRINSIC_GAIN);
3285 if (you.experience_level == 13)
3286 mpr("Your Zot abilities now extend through the making of bolt traps.", MSGCH_INTRINSIC_GAIN);
3287 if (you.experience_level == 14)
3288 mpr("Your Zot abilities now extend through the making of orange crystal statues.", MSGCH_INTRINSIC_GAIN);
3289 if (you.experience_level == 15)
3290 mpr("Your Zot abilities now extend through the making of needle traps.", MSGCH_INTRINSIC_GAIN);
3291 if (you.experience_level == 16)
3292 mpr("Your Zot abilities now extend through self-teleportation.", MSGCH_INTRINSIC_GAIN);
3293 if (you.experience_level == 17)
3294 mpr("Your Zot abilities now extend through making water.", MSGCH_INTRINSIC_GAIN);
3295 if (you.experience_level == 18)
3296 mpr("Your Zot abilities now extend through the making of axe traps.", MSGCH_INTRINSIC_GAIN);
3297 if (you.experience_level == 19)
3298 mpr("Your Zot abilities now extend through the making of electric eels.", MSGCH_INTRINSIC_GAIN);
3299 if (you.experience_level == 20)
3300 mpr("Your Zot abilities now extend through the making of silver statues.", MSGCH_INTRINSIC_GAIN);
3301 // gold and bazaars gained together
3302 if (you.experience_level == 21)
3303 mpr("Your Zot abilities now extend through the making of bazaars.", MSGCH_INTRINSIC_GAIN);
3304 if (you.experience_level == 21)
3305 mpr("Your Zot abilities now extend through acquiring gold.", MSGCH_INTRINSIC_GAIN);
3306 if (you.experience_level == 22)
3307 mpr("Your Zot abilities now extend through the making of oklob circles.", MSGCH_INTRINSIC_GAIN);
3308 if (you.experience_level == 23)
3309 mpr("Your Zot abilities now extend through invoking Sage effects.", MSGCH_INTRINSIC_GAIN);
3310 if (you.experience_level == 24)
3311 mpr("Your Zot abilities now extend through acquirement.", MSGCH_INTRINSIC_GAIN);
3312 if (you.experience_level == 25)
3313 mpr("Your Zot abilities now extend through the making of blade traps.", MSGCH_INTRINSIC_GAIN);
3314 if (you.experience_level == 26)
3315 mpr("Your Zot abilities now extend through the making of curse skulls.", MSGCH_INTRINSIC_GAIN);
3316 if (you.experience_level == 27)
3317 mpr("Your Zot abilities now extend through the making of teleport traps.", MSGCH_INTRINSIC_GAIN);
3320 #if TAG_MAJOR_VERSION == 32
3321 note_montiers();
3322 #endif
3323 // add hp and mp adjustments - GDL
3324 inc_max_hp(hp_adjust);
3325 inc_max_mp(mp_adjust);
3327 deflate_hp(you.hp_max, false);
3329 you.hp = old_hp * you.hp_max / old_maxhp;
3330 you.magic_points = std::max(0, you.magic_points);
3332 // Get "real" values for note-taking, i.e. ignore Berserk,
3333 // transformations or equipped items.
3334 const int note_maxhp = get_real_hp(false, false);
3335 const int note_maxmp = get_real_mp(false);
3337 char buf[200];
3338 sprintf(buf, "HP: %d/%d MP: %d/%d",
3339 std::min(you.hp, note_maxhp), note_maxhp,
3340 std::min(you.magic_points, note_maxmp), note_maxmp);
3341 take_note(Note(NOTE_XP_LEVEL_CHANGE, you.experience_level, 0, buf));
3343 // recalculate for game
3344 calc_hp();
3345 calc_mp();
3347 if (you.experience_level > you.max_level)
3348 you.max_level = you.experience_level;
3350 xom_is_stimulated(16);
3352 learned_something_new(HINT_NEW_LEVEL);
3355 while (you.experience > exp_needed(you.max_level + 2))
3357 ASSERT(you.experience_level == 27);
3358 ASSERT(you.max_level < 127);
3359 you.max_level++;
3360 if (you.species == SP_CAT)
3361 _felid_extra_life();
3364 redraw_skill(you.your_name, player_title());
3366 // Hints mode arbitrarily ends at xp 7.
3367 if (crawl_state.game_is_hints() && you.experience_level >= 7)
3368 hints_finished();
3371 // Here's a question for you: does the ordering of mods make a difference?
3372 // (yes) -- are these things in the right order of application to stealth?
3373 // - 12mar2000 {dlb}
3374 int check_stealth(void)
3376 ASSERT(!crawl_state.game_is_arena());
3377 #ifdef WIZARD
3378 // Extreme stealthiness can be enforced by wizmode stealth setting.
3379 if (you.skills[SK_STEALTH] > 27)
3380 return (1000);
3381 #endif
3383 if (you.attribute[ATTR_SHADOWS] || you.berserk() || you.stat_zero[STAT_DEX])
3384 return (0);
3386 int stealth = you.dex() * 3;
3388 int race_mod = 0;
3389 if (player_genus(GENPC_DRACONIAN) && you.species != SP_GREY_DRACONIAN)
3390 race_mod = 12;
3391 else
3393 switch (you.species) // why not use body_size here?
3395 case SP_TROLL:
3396 case SP_OGRE:
3397 case SP_CENTAUR:
3398 race_mod = 9;
3399 break;
3400 case SP_MINOTAUR:
3401 race_mod = 12;
3402 break;
3403 case SP_VAMPIRE:
3404 // Thirsty/bat-form vampires are (much) more stealthy
3405 if (you.hunger_state == HS_STARVING)
3406 race_mod = 21;
3407 else if (player_in_bat_form()
3408 || you.hunger_state <= HS_NEAR_STARVING)
3410 race_mod = 20;
3412 else if (you.hunger_state < HS_SATIATED)
3413 race_mod = 19;
3414 else
3415 race_mod = 18;
3416 break;
3417 case SP_HALFLING:
3418 case SP_KOBOLD:
3419 case SP_SPRIGGAN:
3420 case SP_GREY_DRACONIAN:
3421 case SP_NAGA: // not small but very good at stealth
3422 case SP_CAT:
3423 race_mod = 18;
3424 break;
3425 default:
3426 race_mod = 15;
3427 break;
3431 switch(you.form)
3433 case TRAN_SPIDER:
3434 race_mod = 21;
3435 break;
3436 case TRAN_ICE_BEAST:
3437 race_mod = 15;
3438 break;
3439 case TRAN_STATUE:
3440 race_mod -= 3; // depends on the base race
3441 break;
3442 case TRAN_DRAGON:
3443 race_mod = 6;
3444 break;
3445 case TRAN_PIG:
3446 race_mod = 9; // trotters, oinking...
3447 break;
3448 case TRAN_BAT:
3449 if (you.species != SP_VAMPIRE)
3450 race_mod = 17;
3451 break;
3452 case TRAN_BLADE_HANDS:
3453 if (you.species == SP_CAT && !you.airborne())
3454 stealth -= 50; // a constant penalty
3455 break;
3456 case TRAN_LICH:
3457 race_mod++; // intentionally tiny, lich form is already overpowered
3458 break;
3459 case TRAN_NONE:
3460 break;
3463 stealth += you.skill(SK_STEALTH) * race_mod;
3465 if (you.burden_state > BS_UNENCUMBERED)
3466 stealth /= you.burden_state;
3468 if (you.confused())
3469 stealth /= 3;
3471 const item_def *arm = you.slot_item(EQ_BODY_ARMOUR, false);
3472 const item_def *cloak = you.slot_item(EQ_CLOAK, false);
3473 const item_def *boots = you.slot_item(EQ_BOOTS, false);
3475 if (arm)
3477 // [ds] New stealth penalty formula from rob: SP = 6 * (EP^2)
3478 const int ep = -property(*arm, PARM_EVASION);
3479 const int penalty = 6 * ep * ep;
3480 #if 0
3481 dprf("Stealth penalty for armour (ep: %d): %d", ep, penalty);
3482 #endif
3483 stealth -= penalty;
3486 if (cloak && get_equip_race(*cloak) == ISFLAG_ELVEN)
3487 stealth += 20;
3489 if (boots)
3491 if (get_armour_ego_type(*boots) == SPARM_STEALTH)
3492 stealth += 50;
3494 if (get_equip_race(*boots) == ISFLAG_ELVEN)
3495 stealth += 20;
3498 if (you.duration[DUR_STEALTH])
3499 stealth += 80;
3501 if (you.duration[DUR_AGILITY])
3502 stealth += 50;
3504 stealth += scan_artefacts(ARTP_STEALTH);
3506 if (you.airborne())
3507 stealth += 10;
3508 else if (you.in_water())
3510 // Merfolk can sneak up on monsters underwater -- bwr
3511 if (you.fishtail)
3512 stealth += 50;
3513 else if (!you.can_swim() && !you.extra_balanced())
3514 stealth /= 2; // splashy-splashy
3516 else if (you.species == SP_CAT && !you.form)
3517 stealth += 20; // paws
3519 // Radiating silence is the negative complement of shouting all the
3520 // time... a sudden change from background noise to no noise is going
3521 // to clue anything in to the fact that something is very wrong...
3522 // a personal silence spell would naturally be different, but this
3523 // silence radiates for a distance and prevents monster spellcasting,
3524 // which pretty much gives away the stealth game.
3525 // this penalty is dependent on the actual amount of ambient noise
3526 // in the level -doy
3527 if (you.duration[DUR_SILENCE])
3528 stealth -= 50 + current_level_ambient_noise();
3530 // Mutations.
3531 stealth += 25 * player_mutation_level(MUT_THIN_SKELETAL_STRUCTURE);
3532 stealth += 40 * player_mutation_level(MUT_NIGHTSTALKER);
3533 if (player_mutation_level(MUT_TRANSLUCENT_SKIN) > 1)
3534 stealth += 20 * (player_mutation_level(MUT_TRANSLUCENT_SKIN) - 1);
3536 // it's easier to be stealthy when there's a lot of background noise
3537 stealth += 2 * current_level_ambient_noise();
3539 stealth = std::max(0, stealth);
3541 return (stealth);
3544 // Returns the medium duration value which is usually announced by a special
3545 // message ("XY is about to time out") or a change of colour in the
3546 // status display.
3547 // Note that these values cannot be relied on when playing since there are
3548 // random decrements precisely to avoid this.
3549 int get_expiration_threshold(duration_type dur)
3551 switch (dur)
3553 case DUR_QUAD_DAMAGE:
3554 return (3 * BASELINE_DELAY); // per client.qc
3556 case DUR_FIRE_SHIELD:
3557 case DUR_SILENCE: // no message
3558 return (5 * BASELINE_DELAY);
3560 case DUR_DEFLECT_MISSILES:
3561 case DUR_REPEL_MISSILES:
3562 case DUR_REGENERATION:
3563 case DUR_INSULATION:
3564 case DUR_RESIST_POISON:
3565 case DUR_RESIST_FIRE:
3566 case DUR_RESIST_COLD:
3567 case DUR_STONEMAIL:
3568 case DUR_SWIFTNESS:
3569 case DUR_INVIS:
3570 case DUR_HASTE:
3571 case DUR_BERSERK:
3572 case DUR_ICY_ARMOUR:
3573 case DUR_PHASE_SHIFT:
3574 case DUR_CONTROL_TELEPORT:
3575 case DUR_DEATH_CHANNEL:
3576 case DUR_SEE_INVISIBLE:
3577 return (6 * BASELINE_DELAY);
3579 case DUR_LEVITATION:
3580 case DUR_TRANSFORMATION: // not on status
3581 case DUR_DEATHS_DOOR: // not on status
3582 case DUR_SLIMIFY:
3583 return (10 * BASELINE_DELAY);
3585 // These get no messages when they "flicker".
3586 case DUR_SAGE:
3587 case DUR_BARGAIN:
3588 return (15 * BASELINE_DELAY);
3590 case DUR_CONFUSING_TOUCH:
3591 return (20 * BASELINE_DELAY);
3593 default:
3594 return (0);
3598 // Is a given duration about to expire?
3599 bool dur_expiring(duration_type dur)
3601 const int value = you.duration[dur];
3602 if (value <= 0)
3603 return (false);
3605 return (value <= get_expiration_threshold(dur));
3608 static void _output_expiring_message(duration_type dur, const char* msg)
3610 if (you.duration[dur])
3612 const bool expires = dur_expiring(dur);
3613 mprf("%s%s", expires ? "Expiring: " : "", msg);
3617 static void _display_vampire_status()
3619 std::string msg = "At your current hunger state you ";
3620 std::vector<std::string> attrib;
3622 switch (you.hunger_state)
3624 case HS_STARVING:
3625 attrib.push_back("resist poison");
3626 attrib.push_back("significantly resist cold");
3627 attrib.push_back("strongly resist negative energy");
3628 attrib.push_back("resist torment");
3629 attrib.push_back("do not heal.");
3630 break;
3631 case HS_NEAR_STARVING:
3632 attrib.push_back("resist poison");
3633 attrib.push_back("significantly resist cold");
3634 attrib.push_back("strongly resist negative energy");
3635 attrib.push_back("have an extremely slow metabolism");
3636 attrib.push_back("heal slowly.");
3637 break;
3638 case HS_HUNGRY:
3639 case HS_VERY_HUNGRY:
3640 attrib.push_back("resist poison");
3641 attrib.push_back("resist cold");
3642 attrib.push_back("significantly resist negative energy");
3643 if (you.hunger_state == HS_HUNGRY)
3644 attrib.push_back("have a slow metabolism");
3645 else
3646 attrib.push_back("have a very slow metabolism");
3647 attrib.push_back("heal slowly.");
3648 break;
3649 case HS_SATIATED:
3650 attrib.push_back("resist negative energy.");
3651 break;
3652 case HS_FULL:
3653 attrib.push_back("have a fast metabolism");
3654 attrib.push_back("heal quickly.");
3655 break;
3656 case HS_VERY_FULL:
3657 attrib.push_back("have a very fast metabolism");
3658 attrib.push_back("heal quickly.");
3659 break;
3660 case HS_ENGORGED:
3661 attrib.push_back("have an extremely fast metabolism");
3662 attrib.push_back("heal extremely quickly.");
3663 break;
3666 if (!attrib.empty())
3668 msg += comma_separated_line(attrib.begin(), attrib.end());
3669 mpr(msg.c_str());
3673 static void _display_movement_speed()
3675 const int move_cost = (player_speed() * player_movement_speed()) / 10;
3677 const bool water = you.in_water();
3678 const bool swim = you.swimming();
3680 const bool lev = you.airborne();
3681 const bool fly = (you.flight_mode() == FL_FLY);
3682 const bool swift = (you.duration[DUR_SWIFTNESS] > 0);
3684 mprf("Your %s speed is %s%s%s.",
3685 // order is important for these:
3686 (swim) ? "swimming" :
3687 (water) ? "wading" :
3688 (fly) ? "flying" :
3689 (lev) ? "levitating"
3690 : "movement",
3692 (water && !swim) ? "uncertain and " :
3693 (!water && swift) ? "aided by the wind" : "",
3695 (!water && swift) ? ((move_cost >= 10) ? ", but still "
3696 : " and ")
3697 : "",
3699 (move_cost < 8) ? "very quick" :
3700 (move_cost < 10) ? "quick" :
3701 (move_cost == 10) ? "average" :
3702 (move_cost < 13) ? "slow"
3703 : "very slow");
3706 static void _display_tohit()
3708 const int to_hit = calc_your_to_hit(false) * 2;
3709 dprf("To-hit: %d", to_hit);
3711 // Messages based largely on percentage chance of missing the
3712 // average EV 10 humanoid, and very agile EV 30 (pretty much
3713 // max EV for monsters currently).
3715 // "awkward" - need lucky hit (less than EV)
3716 // "difficult" - worse than 2 in 3
3717 // "hard" - worse than fair chance
3718 mprf("%s given your current equipment.",
3719 (to_hit < 1) ? "You are completely incapable of fighting" :
3720 (to_hit < 5) ? "Hitting even clumsy monsters is extremely awkward" :
3721 (to_hit < 10) ? "Hitting average monsters is awkward" :
3722 (to_hit < 15) ? "Hitting average monsters is difficult" :
3723 (to_hit < 20) ? "Hitting average monsters is hard" :
3724 (to_hit < 30) ? "Very agile monsters are a bit awkward to hit" :
3725 (to_hit < 45) ? "Very agile monsters are a bit difficult to hit" :
3726 (to_hit < 60) ? "Very agile monsters are a bit hard to hit" :
3727 (to_hit < 100) ? "You feel comfortable with your ability to fight"
3728 : "You feel confident with your ability to fight");
3732 static std::string _attack_delay_desc(int attack_delay)
3734 return ((attack_delay >= 200) ? "extremely slow" :
3735 (attack_delay >= 155) ? "very slow" :
3736 (attack_delay >= 125) ? "quite slow" :
3737 (attack_delay >= 105) ? "below average" :
3738 (attack_delay >= 95) ? "average" :
3739 (attack_delay >= 75) ? "above average" :
3740 (attack_delay >= 55) ? "quite fast" :
3741 (attack_delay >= 45) ? "very fast" :
3742 (attack_delay >= 35) ? "extremely fast" :
3743 "blindingly fast");
3746 static void _display_attack_delay()
3748 const random_var delay = calc_your_attack_delay();
3750 // Scale to fit the displayed weapon base delay, i.e.,
3751 // normal speed is 100 (as in 100%).
3752 // We could also compute the variance if desired.
3753 int avg = static_cast<int>(round(10 * delay.expected()));
3755 // Haste wasn't counted here, but let's show finesse.
3756 // Can't be done in the above function because of interactions with
3757 // haste and caps.
3758 if (you.duration[DUR_FINESSE])
3759 avg = std::max(20, avg / 2);
3761 std::string msg = "Your attack speed is " + _attack_delay_desc(avg) + ".";
3763 #ifdef DEBUG_DIAGNOSTICS
3764 if (you.wizard)
3766 const int max = 10 * delay.max();
3768 msg += colour_string(make_stringf(" %d%% (max %d%%)", avg, max),
3769 channel_to_colour(MSGCH_DIAGNOSTICS));
3771 #endif
3773 mpr(msg);
3776 void display_char_status()
3778 if (you.is_undead == US_SEMI_UNDEAD && you.hunger_state == HS_ENGORGED)
3779 mpr("You feel almost alive.");
3780 else if (you.is_undead)
3781 mpr("You are undead.");
3782 else if (you.duration[DUR_DEATHS_DOOR])
3784 _output_expiring_message(DUR_DEATHS_DOOR,
3785 "You are standing in death's doorway.");
3787 else
3788 mpr("You are alive.");
3790 const int halo_size = you.halo_radius2();
3791 if (halo_size >= 0)
3793 if (halo_size > 37)
3794 mpr("You are illuminated by a large divine halo.");
3795 else if (halo_size > 10)
3796 mpr("You are illuminated by a divine halo.");
3797 else
3798 mpr("You are illuminated by a small divine halo.");
3800 else if (you.haloed())
3801 mpr("An external divine halo illuminates you.");
3803 if (you.species == SP_VAMPIRE)
3804 _display_vampire_status();
3806 static int statuses[] = {
3807 STATUS_STR_ZERO, STATUS_INT_ZERO, STATUS_DEX_ZERO,
3808 DUR_TRANSFORMATION, STATUS_BURDEN, DUR_SAGE, DUR_BARGAIN,
3809 DUR_BREATH_WEAPON, DUR_LIQUID_FLAMES, DUR_FIRE_SHIELD, DUR_ICY_ARMOUR,
3810 DUR_REPEL_MISSILES, DUR_DEFLECT_MISSILES, DUR_JELLY_PRAYER,
3811 STATUS_REGENERATION, DUR_SWIFTNESS, DUR_RESIST_POISON,
3812 DUR_RESIST_COLD, DUR_RESIST_FIRE, DUR_INSULATION, DUR_STONEMAIL,
3813 DUR_TELEPORT, DUR_CONTROL_TELEPORT,
3814 DUR_DEATH_CHANNEL, DUR_PHASE_SHIFT, DUR_SILENCE, DUR_STONESKIN,
3815 DUR_SEE_INVISIBLE, DUR_INVIS, DUR_CONF, STATUS_BEHELD,
3816 DUR_PARALYSIS, DUR_PETRIFIED, DUR_SLEEP, DUR_EXHAUSTED,
3817 STATUS_SPEED, DUR_MIGHT, DUR_BRILLIANCE, DUR_AGILITY,
3818 DUR_DIVINE_VIGOUR, DUR_DIVINE_STAMINA, DUR_BERSERK,
3819 STATUS_AIRBORNE, STATUS_NET, DUR_POISONING, STATUS_SICK,
3820 STATUS_ROT, STATUS_GLOW, DUR_CONFUSING_TOUCH, DUR_SURE_BLADE,
3821 DUR_AFRAID, DUR_MIRROR_DAMAGE, DUR_SCRYING, STATUS_CLINGING,
3824 status_info inf;
3825 for (unsigned i = 0; i < ARRAYSZ(statuses); ++i)
3827 fill_status_info(statuses[i], &inf);
3828 if (!inf.long_text.empty())
3829 mpr(inf.long_text);
3832 _display_movement_speed();
3833 _display_tohit();
3834 _display_attack_delay();
3836 // magic resistance
3837 mprf("You are %s resistant to hostile enchantments.",
3838 magic_res_adjective(player_res_magic(false)).c_str());
3840 // character evaluates their ability to sneak around:
3841 mprf("You feel %s.", stealth_desc(check_stealth()).c_str());
3842 dprf("stealth: %d", check_stealth());
3845 bool player_item_conserve(bool calc_unid)
3847 return (player_equip(EQ_AMULET, AMU_CONSERVATION, calc_unid)
3848 || player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION));
3851 int player_mental_clarity(bool calc_unid, bool items)
3853 int ret = 3 * player_equip(EQ_AMULET, AMU_CLARITY, calc_unid) * items
3854 + player_mutation_level(MUT_CLARITY);
3856 if (you.religion == GOD_ASHENZARI && you.piety >= piety_breakpoint(2)
3857 && !player_under_penance())
3859 ret++;
3862 return ((ret > 3) ? 3 : ret);
3865 int player_spirit_shield(bool calc_unid)
3867 return player_equip(EQ_AMULET, AMU_GUARDIAN_SPIRIT, calc_unid)
3868 + player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_SPIRIT_SHIELD);
3871 // Returns whether the player has the effect of the amulet from a
3872 // non-amulet source.
3873 bool extrinsic_amulet_effect(jewellery_type amulet)
3875 switch (amulet)
3877 case AMU_CONTROLLED_FLIGHT:
3878 return (you.duration[DUR_CONTROLLED_FLIGHT]
3879 || player_genus(GENPC_DRACONIAN)
3880 || (you.species == SP_KENKU && you.experience_level >= 5)
3881 || you.form == TRAN_DRAGON
3882 || you.form == TRAN_BAT);
3883 case AMU_CLARITY:
3884 return player_mental_clarity(true, false);
3885 case AMU_RESIST_CORROSION:
3886 if (you.religion == GOD_JIYVA && you.piety >= piety_breakpoint(2))
3887 return (true);
3888 // else fall-through
3889 case AMU_CONSERVATION:
3890 return (player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_PRESERVATION));
3891 case AMU_THE_GOURMAND:
3892 return (player_mutation_level(MUT_GOURMAND) > 0);
3893 default:
3894 return (false);
3898 bool wearing_amulet(jewellery_type amulet, bool calc_unid, bool ignore_extrinsic)
3900 if (!ignore_extrinsic && extrinsic_amulet_effect(amulet))
3901 return (true);
3903 if (!player_wearing_slot(EQ_AMULET))
3904 return (false);
3906 const item_def& amu(you.inv[you.equip[EQ_AMULET]]);
3907 return (amu.sub_type == amulet && (calc_unid || item_type_known(amu)));
3910 static int _species_exp_mod(species_type species)
3912 if (player_genus(GENPC_DRACONIAN, species))
3913 return 14;
3914 else if (player_genus(GENPC_DWARVEN, species))
3915 return 13;
3916 switch (species)
3918 case SP_HUMAN:
3919 case SP_HALFLING:
3920 case SP_HILL_ORC:
3921 case SP_KOBOLD:
3922 return 10;
3923 case SP_OGRE:
3924 return 11;
3925 case SP_SLUDGE_ELF:
3926 case SP_NAGA:
3927 case SP_GHOUL:
3928 case SP_MERFOLK:
3929 return 12;
3930 case SP_SPRIGGAN:
3931 case SP_KENKU:
3932 return 13;
3933 case SP_DEEP_ELF:
3934 case SP_CENTAUR:
3935 case SP_MINOTAUR:
3936 case SP_MUMMY:
3937 return 14;
3938 case SP_HIGH_ELF:
3939 case SP_VAMPIRE:
3940 case SP_TROLL:
3941 case SP_CAT:
3942 case SP_DEMONSPAWN:
3943 return 15;
3944 case SP_DEMIGOD:
3945 return 16;
3946 default:
3947 return 0;
3951 unsigned int exp_needed(int lev)
3953 lev--;
3955 unsigned int level = 0;
3957 // Basic plan:
3958 // Section 1: levels 1- 5, second derivative goes 10-10-20-30.
3959 // Section 2: levels 6-13, second derivative is exponential/doubling.
3960 // Section 3: levels 14-27, second derivative is constant at 6000.
3962 // Section three is constant so we end up with high levels at about
3963 // their old values (level 27 at 850k), without delta2 ever decreasing.
3964 // The values that are considerably different (ie level 13 is now 29000,
3965 // down from 41040 are because the second derivative goes from 9040 to
3966 // 1430 at that point in the original, and then slowly builds back
3967 // up again). This function smoothes out the old level 10-15 area
3968 // considerably.
3970 // Here's a table:
3972 // level xp delta delta2
3973 // ===== ======= ===== ======
3974 // 1 0 0 0
3975 // 2 10 10 10
3976 // 3 30 20 10
3977 // 4 70 40 20
3978 // 5 140 70 30
3979 // 6 270 130 60
3980 // 7 520 250 120
3981 // 8 1010 490 240
3982 // 9 1980 970 480
3983 // 10 3910 1930 960
3984 // 11 7760 3850 1920
3985 // 12 15450 7690 3840
3986 // 13 29000 13550 5860
3987 // 14 48500 19500 5950
3988 // 15 74000 25500 6000
3989 // 16 105500 31500 6000
3990 // 17 143000 37500 6000
3991 // 18 186500 43500 6000
3992 // 19 236000 49500 6000
3993 // 20 291500 55500 6000
3994 // 21 353000 61500 6000
3995 // 22 420500 67500 6000
3996 // 23 494000 73500 6000
3997 // 24 573500 79500 6000
3998 // 25 659000 85500 6000
3999 // 26 750500 91500 6000
4000 // 27 848000 97500 6000
4003 switch (lev)
4005 case 1:
4006 level = 1;
4007 break;
4008 case 2:
4009 level = 10;
4010 break;
4011 case 3:
4012 level = 30;
4013 break;
4014 case 4:
4015 level = 70;
4016 break;
4018 default:
4019 if (lev < 13)
4021 lev -= 4;
4022 level = 10 + 10 * lev + (60 << lev);
4024 else
4026 lev -= 12;
4027 level = 15500 + 10500 * lev + 3000 * lev * lev;
4029 break;
4032 return ((level - 1) * _species_exp_mod(you.species) / 10);
4035 // returns bonuses from rings of slaying, etc.
4036 int slaying_bonus(weapon_property_type which_affected, bool ranged)
4038 int ret = 0;
4040 if (which_affected == PWPN_HIT)
4042 ret += player_equip(EQ_RINGS_PLUS, RING_SLAYING);
4043 ret += scan_artefacts(ARTP_ACCURACY);
4044 if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
4045 ret += ranged ? 5 : -1;
4047 else if (which_affected == PWPN_DAMAGE)
4049 ret += player_equip(EQ_RINGS_PLUS2, RING_SLAYING);
4050 ret += scan_artefacts(ARTP_DAMAGE);
4051 if (player_equip_ego_type(EQ_GLOVES, SPARM_ARCHERY))
4052 ret += ranged ? 3 : -1;
4055 ret += std::min(you.duration[DUR_SLAYING] / (13 * BASELINE_DELAY), 6);
4057 return (ret);
4060 // Checks each equip slot for an evokable item (jewellery or randart).
4061 // Returns true if any of these has the same ability as the one handed in.
4062 bool items_give_ability(const int slot, artefact_prop_type abil)
4064 for (int i = EQ_WEAPON; i < NUM_EQUIP; i++)
4066 if (!player_wearing_slot(i))
4067 continue;
4069 const int eq = you.equip[i];
4071 // skip item to compare with
4072 if (eq == slot)
4073 continue;
4075 // only weapons give their effects when in our hands
4076 if (i == EQ_WEAPON && you.inv[ eq ].base_type != OBJ_WEAPONS)
4077 continue;
4079 if (eq == EQ_LEFT_RING || eq == EQ_RIGHT_RING)
4081 if (abil == ARTP_LEVITATE && you.inv[eq].sub_type == RING_LEVITATION)
4082 return (true);
4083 if (abil == ARTP_INVISIBLE && you.inv[eq].sub_type == RING_INVISIBILITY)
4084 return (true);
4086 else if (eq == EQ_AMULET)
4088 if (abil == ARTP_BERSERK && you.inv[eq].sub_type == AMU_RAGE)
4089 return (true);
4092 // other items are not evokable
4093 if (!is_artefact(you.inv[ eq ]))
4094 continue;
4096 if (artefact_wpn_property(you.inv[ eq ], abil))
4097 return (true);
4100 // none of the equipped items possesses this ability
4101 return (false);
4104 // Checks each equip slot for a randart, and adds up all of those with
4105 // a given property. Slow if any randarts are worn, so avoid where
4106 // possible.
4107 int scan_artefacts(artefact_prop_type which_property, bool calc_unid)
4109 int retval = 0;
4111 for (int i = EQ_WEAPON; i < NUM_EQUIP; ++i)
4113 if (you.melded[i] && which_property != ARTP_PONDEROUS
4114 || you.equip[i] == -1)
4116 continue;
4119 const int eq = you.equip[i];
4121 // Only weapons give their effects when in our hands.
4122 if (i == EQ_WEAPON && you.inv[ eq ].base_type != OBJ_WEAPONS)
4123 continue;
4125 if (!is_artefact(you.inv[ eq ]))
4126 continue;
4128 // Ignore unidentified items [TileCrawl dump enhancements].
4129 if (!item_ident(you.inv[ eq ], ISFLAG_KNOW_PROPERTIES)
4130 && !calc_unid)
4132 continue;
4135 retval += artefact_wpn_property(you.inv[ eq ], which_property);
4138 return (retval);
4141 void dec_hp(int hp_loss, bool fatal, const char *aux)
4143 ASSERT(!crawl_state.game_is_arena());
4145 if (!fatal && you.hp < 1)
4146 you.hp = 1;
4148 if (!fatal && hp_loss >= you.hp)
4149 hp_loss = you.hp - 1;
4151 if (hp_loss < 1)
4152 return;
4154 // If it's not fatal, use ouch() so that notes can be taken. If it IS
4155 // fatal, somebody else is doing the bookkeeping, and we don't want to mess
4156 // with that.
4157 if (!fatal && aux)
4158 ouch(hp_loss, NON_MONSTER, KILLED_BY_SOMETHING, aux);
4159 else
4160 you.hp -= hp_loss;
4162 you.redraw_hit_points = true;
4165 void dec_mp(int mp_loss)
4167 ASSERT(!crawl_state.game_is_arena());
4169 if (mp_loss < 1)
4170 return;
4172 you.magic_points -= mp_loss;
4174 you.magic_points = std::max(0, you.magic_points);
4176 if (Options.magic_point_warning
4177 && you.magic_points < (you.max_magic_points
4178 * Options.magic_point_warning) / 100)
4180 mpr("* * * LOW MAGIC WARNING * * *", MSGCH_DANGER);
4183 take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
4184 you.redraw_magic_points = true;
4187 bool enough_hp(int minimum, bool suppress_msg)
4189 ASSERT(!crawl_state.game_is_arena());
4191 // We want to at least keep 1 HP. -- bwr
4192 if (you.hp < minimum + 1)
4194 if (!suppress_msg)
4195 mpr("You haven't enough vitality at the moment.");
4197 crawl_state.cancel_cmd_again();
4198 crawl_state.cancel_cmd_repeat();
4199 return (false);
4202 return (true);
4205 bool enough_mp(int minimum, bool suppress_msg, bool include_items)
4207 ASSERT(!crawl_state.game_is_arena());
4209 bool rc = false;
4211 if (get_real_mp(include_items) < minimum)
4213 if (!suppress_msg)
4214 mpr("You haven't enough magic capacity.");
4216 else if (you.magic_points < minimum)
4218 if (!suppress_msg)
4219 mpr("You haven't enough magic at the moment.");
4221 else
4222 rc = true;
4224 if (!rc)
4226 crawl_state.cancel_cmd_again();
4227 crawl_state.cancel_cmd_repeat();
4230 return (rc);
4233 bool enough_xp(int minimum, bool suppress_msg)
4235 ASSERT(!crawl_state.game_is_arena());
4237 if (you.exp_available < minimum)
4239 if (!suppress_msg)
4240 mpr("You haven't enough experience in your experience pool.");
4242 crawl_state.cancel_cmd_again();
4243 crawl_state.cancel_cmd_repeat();
4244 return (false);
4246 return (true);
4249 // Note that "max_too" refers to the base potential, the actual
4250 // resulting max value is subject to penalties, bonuses, and scalings.
4251 void inc_mp(int mp_gain, bool max_too)
4253 ASSERT(!crawl_state.game_is_arena());
4255 if (mp_gain < 1)
4256 return;
4258 bool wasnt_max = (you.magic_points < you.max_magic_points);
4260 you.magic_points += mp_gain;
4262 if (max_too)
4263 inc_max_mp(mp_gain);
4265 if (you.magic_points > you.max_magic_points)
4266 you.magic_points = you.max_magic_points;
4268 if (wasnt_max && you.magic_points == you.max_magic_points)
4269 interrupt_activity(AI_FULL_MP);
4271 take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
4272 you.redraw_magic_points = true;
4275 // Note that "max_too" refers to the base potential, the actual
4276 // resulting max value is subject to penalties, bonuses, and scalings.
4277 // To avoid message spam, don't take notes when HP increases.
4278 void inc_hp(int hp_gain, bool max_too)
4280 ASSERT(!crawl_state.game_is_arena());
4282 if (hp_gain < 1)
4283 return;
4285 bool wasnt_max = (you.hp < you.hp_max);
4287 you.hp += hp_gain;
4289 if (max_too)
4290 inc_max_hp(hp_gain);
4292 if (you.hp > you.hp_max)
4293 you.hp = you.hp_max;
4295 if (wasnt_max && you.hp == you.hp_max)
4296 interrupt_activity(AI_FULL_HP);
4298 you.redraw_hit_points = true;
4301 void rot_hp(int hp_loss)
4303 you.base_hp -= hp_loss;
4304 calc_hp();
4306 if (you.species != SP_GHOUL)
4307 xom_is_stimulated(hp_loss * 32);
4309 you.redraw_hit_points = true;
4312 void unrot_hp(int hp_recovered)
4314 if (hp_recovered >= 5000 - you.base_hp)
4315 you.base_hp = 5000;
4316 else
4317 you.base_hp += hp_recovered;
4319 calc_hp();
4321 you.redraw_hit_points = true;
4324 int player_rotted()
4326 return (5000 - you.base_hp);
4329 void rot_mp(int mp_loss)
4331 you.base_magic_points -= mp_loss;
4332 calc_mp();
4334 you.redraw_magic_points = true;
4337 void inc_max_hp(int hp_gain)
4339 you.base_hp2 += hp_gain;
4340 calc_hp();
4342 take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
4343 you.redraw_hit_points = true;
4346 void dec_max_hp(int hp_loss)
4348 you.base_hp2 -= hp_loss;
4349 calc_hp();
4351 take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
4352 you.redraw_hit_points = true;
4355 void inc_max_mp(int mp_gain)
4357 you.base_magic_points2 += mp_gain;
4358 calc_mp();
4360 take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
4361 you.redraw_magic_points = true;
4364 void dec_max_mp(int mp_loss)
4366 you.base_magic_points2 -= mp_loss;
4367 calc_mp();
4369 take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
4370 you.redraw_magic_points = true;
4373 // Use of floor: false = hp max, true = hp min. {dlb}
4374 void deflate_hp(int new_level, bool floor)
4376 ASSERT(!crawl_state.game_is_arena());
4378 if (floor && you.hp < new_level)
4379 you.hp = new_level;
4380 else if (!floor && you.hp > new_level)
4381 you.hp = new_level;
4383 // Must remain outside conditional, given code usage. {dlb}
4384 you.redraw_hit_points = true;
4387 // Note that "max_too" refers to the base potential, the actual
4388 // resulting max value is subject to penalties, bonuses, and scalings.
4389 void set_hp(int new_amount, bool max_too)
4391 ASSERT(!crawl_state.game_is_arena());
4393 you.hp = new_amount;
4395 if (max_too && you.hp_max != new_amount)
4397 you.base_hp2 = 5000 + new_amount;
4398 calc_hp();
4401 if (you.hp > you.hp_max)
4402 you.hp = you.hp_max;
4404 if (max_too)
4405 take_note(Note(NOTE_MAXHP_CHANGE, you.hp_max));
4407 // Must remain outside conditional, given code usage. {dlb}
4408 you.redraw_hit_points = true;
4411 // Note that "max_too" refers to the base potential, the actual
4412 // resulting max value is subject to penalties, bonuses, and scalings.
4413 void set_mp(int new_amount, bool max_too)
4415 ASSERT(!crawl_state.game_is_arena());
4417 you.magic_points = new_amount;
4419 if (max_too && you.max_magic_points != new_amount)
4421 // Note that this gets scaled down for values > 18.
4422 you.base_magic_points2 = 5000 + new_amount;
4423 calc_mp();
4426 if (you.magic_points > you.max_magic_points)
4427 you.magic_points = you.max_magic_points;
4429 take_note(Note(NOTE_MP_CHANGE, you.magic_points, you.max_magic_points));
4430 if (max_too)
4431 take_note(Note(NOTE_MAXMP_CHANGE, you.max_magic_points));
4433 // Must remain outside conditional, given code usage. {dlb}
4434 you.redraw_magic_points = true;
4437 // If trans is true, being berserk and/or transformed is taken into account
4438 // here. Else, the base hp is calculated. If rotted is true, calculate the
4439 // real max hp you'd have if the rotting was cured.
4440 int get_real_hp(bool trans, bool rotted)
4442 int hitp;
4444 hitp = (you.base_hp - 5000) + (you.base_hp2 - 5000);
4445 // Important: we shouldn't add Heroism boosts here.
4446 hitp += (you.experience_level * you.skills[SK_FIGHTING]) /
4447 (you.species == SP_CAT ? 7 : 5);
4449 // Being berserk makes you resistant to damage. I don't know why.
4450 if (trans && you.berserk())
4451 hitp = hitp * 3 / 2;
4453 if (trans)
4455 // Some transformations give you extra hp.
4456 switch (you.form)
4458 case TRAN_STATUE:
4459 hitp *= 15;
4460 hitp /= 10;
4461 break;
4462 case TRAN_ICE_BEAST:
4463 hitp *= 12;
4464 hitp /= 10;
4465 break;
4466 case TRAN_DRAGON:
4467 hitp *= 16;
4468 hitp /= 10;
4469 break;
4470 default:
4471 break;
4475 if (rotted)
4476 hitp += player_rotted();
4478 // Frail and robust mutations, divine vigour, and rugged scale mut.
4479 hitp *= 100 + (player_mutation_level(MUT_ROBUST) * 10)
4480 + (you.attribute[ATTR_DIVINE_VIGOUR] * 5)
4481 + (player_mutation_level(MUT_RUGGED_BROWN_SCALES) ? player_mutation_level(MUT_RUGGED_BROWN_SCALES) * 2 + 1 : 0)
4482 - (player_mutation_level(MUT_FRAIL) * 10);
4483 hitp /= 100;
4485 return (hitp);
4488 int get_real_mp(bool include_items)
4490 // base_magic_points2 accounts for species
4491 int enp = (you.base_magic_points2 - 5000);
4493 int spell_extra = (you.experience_level * you.skills[SK_SPELLCASTING]) / 4;
4494 int invoc_extra = (you.experience_level * you.skills[SK_INVOCATIONS]) / 6;
4496 enp += std::max(spell_extra, invoc_extra);
4497 enp = stepdown_value(enp, 9, 18, 45, 100);
4499 // This is our "rotted" base (applied after scaling):
4500 enp += (you.base_magic_points - 5000);
4502 // Yes, we really do want this duplication... this is so the stepdown
4503 // doesn't truncate before we apply the rotted base. We're doing this
4504 // the nice way. -- bwr
4505 enp = std::min(enp, 50);
4507 // Now applied after scaling so that power items are more useful -- bwr
4508 if (include_items)
4509 enp += player_magical_power();
4511 // Analogous to ROBUST/FRAIL
4512 enp *= 100 + (player_mutation_level(MUT_HIGH_MAGIC) * 10)
4513 + (you.attribute[ATTR_DIVINE_VIGOUR] * 5)
4514 - (player_mutation_level(MUT_LOW_MAGIC) * 10);
4515 enp /= 100;
4517 if (enp > 50)
4518 enp = 50 + ((enp - 50) / 2);
4520 if (include_items && player_equip_ego_type(EQ_WEAPON, SPWPN_ANTIMAGIC))
4521 enp /= 3;
4523 enp = std::max(enp, 0);
4525 return enp;
4528 int get_contamination_level()
4530 const int glow = you.magic_contamination;
4532 if (glow > 60)
4533 return (glow / 20 + 3);
4534 if (glow > 40)
4535 return (5);
4536 if (glow > 25)
4537 return (4);
4538 if (glow > 15)
4539 return (3);
4540 if (glow > 5)
4541 return (2);
4542 if (glow > 0)
4543 return (1);
4545 return (0);
4548 std::string describe_contamination(int cont)
4550 if (cont > 5)
4551 return ("You are engulfed in a nimbus of crackling magics!");
4552 else if (cont == 5)
4553 return ("Your entire body has taken on an eerie glow!");
4554 else if (cont > 1)
4556 return (make_stringf("You are %s with residual magics%s",
4557 (cont == 4) ? "practically glowing" :
4558 (cont == 3) ? "heavily infused" :
4559 (cont == 2) ? "contaminated"
4560 : "lightly contaminated",
4561 (cont == 4) ? "!" : "."));
4563 else if (cont == 1)
4564 return ("You are very lightly contaminated with residual magic.");
4565 else
4566 return ("");
4569 // controlled is true if the player actively did something to cause
4570 // contamination (such as drink a known potion of resistance),
4571 // status_only is true only for the status output
4572 void contaminate_player(int change, bool controlled, bool msg)
4574 ASSERT(!crawl_state.game_is_arena());
4576 int old_amount = you.magic_contamination;
4577 int old_level = get_contamination_level();
4578 int new_level = 0;
4580 you.magic_contamination =
4581 std::max(0, std::min(250, you.magic_contamination + change));
4583 new_level = get_contamination_level();
4585 if (you.magic_contamination != old_amount)
4586 dprf("change: %d radiation: %d", change, you.magic_contamination);
4588 if (msg && new_level >= 1 && old_level <= 1 && new_level != old_level)
4589 mpr(describe_contamination(new_level));
4590 else if (msg && new_level != old_level)
4592 if (old_level == 1 && new_level == 0)
4593 mpr("Your magical contamination has completely faded away.");
4594 else
4596 mprf((change > 0) ? MSGCH_WARN : MSGCH_RECOVERY,
4597 "You feel %s contaminated with magical energies.",
4598 (change > 0) ? "more" : "less");
4601 if (change > 0)
4602 xom_is_stimulated(new_level * 32);
4604 if (old_level > 1 && new_level <= 1
4605 && you.duration[DUR_INVIS] && !you.backlit())
4607 mpr("You fade completely from view now that you are no longer "
4608 "glowing from magical contamination.");
4612 if (you.magic_contamination > 0)
4613 learned_something_new(HINT_GLOWING);
4615 // Zin doesn't like mutations or mutagenic radiation.
4616 if (you.religion == GOD_ZIN)
4618 // Whenever the glow status is first reached, give a warning message.
4619 if (old_level < 2 && new_level >= 2)
4620 did_god_conduct(DID_CAUSE_GLOWING, 0, false);
4621 // If the player actively did something to increase glowing,
4622 // Zin is displeased.
4623 else if (controlled && change > 0 && old_level > 1)
4624 did_god_conduct(DID_CAUSE_GLOWING, 1 + new_level, true);
4628 bool confuse_player(int amount, bool resistable)
4630 ASSERT(!crawl_state.game_is_arena());
4632 if (amount <= 0)
4633 return (false);
4635 if (resistable && player_mental_clarity())
4637 mpr("You feel momentarily confused.");
4638 // Identify the amulet if necessary.
4639 if (player_equip(EQ_AMULET, AMU_CLARITY, true))
4641 item_def* const amu = you.slot_item(EQ_AMULET, false);
4642 if (!item_ident(*amu, ISFLAG_KNOW_TYPE))
4644 set_ident_type(amu->base_type, amu->sub_type, ID_KNOWN_TYPE);
4645 set_ident_flags(*amu, ISFLAG_KNOW_TYPE);
4646 mprf("You are wearing: %s",
4647 amu->name(DESC_INVENTORY_EQUIP).c_str());
4650 return (false);
4653 const int old_value = you.duration[DUR_CONF];
4654 you.increase_duration(DUR_CONF, amount, 40);
4656 if (you.duration[DUR_CONF] > old_value)
4658 you.check_awaken(500);
4660 mprf(MSGCH_WARN, "You are %sconfused.",
4661 old_value > 0 ? "more " : "");
4663 learned_something_new(HINT_YOU_ENCHANTED);
4665 xom_is_stimulated((you.duration[DUR_CONF] - old_value)
4666 / BASELINE_DELAY);
4669 return (true);
4672 bool curare_hits_player(int death_source, int amount, const bolt &beam)
4674 ASSERT(!crawl_state.game_is_arena());
4676 if (player_res_poison() > 0)
4677 return (false);
4679 poison_player(amount, beam.get_source_name(), beam.name);
4681 int hurted = 0;
4683 if (you.res_asphyx() <= 0)
4685 hurted = roll_dice(2, 6);
4687 if (hurted)
4689 mpr("You have difficulty breathing.");
4690 ouch(hurted, death_source, KILLED_BY_CURARE,
4691 "curare-induced apnoea");
4695 potion_effect(POT_SLOWING, 2 + random2(4 + amount));
4697 return (hurted > 0);
4700 bool poison_player(int amount, std::string source, std::string source_aux,
4701 bool force)
4703 ASSERT(!crawl_state.game_is_arena());
4705 if (!force && player_res_poison() > 0 || amount <= 0)
4706 return (false);
4708 const int old_value = you.duration[DUR_POISONING];
4709 you.duration[DUR_POISONING] += amount;
4711 if (you.duration[DUR_POISONING] > 40)
4712 you.duration[DUR_POISONING] = 40;
4714 if (you.duration[DUR_POISONING] > old_value)
4716 mprf(MSGCH_WARN, "You are %spoisoned.",
4717 old_value > 0 ? "more " : "");
4719 learned_something_new(HINT_YOU_POISON);
4722 you.props["poisoner"] = source;
4723 you.props["poison_aux"] = source_aux;
4725 return (true);
4728 void dec_poison_player()
4730 // If Cheibriados has slowed your life processes, there's a
4731 // chance that your poison level is simply unaffected and
4732 // you aren't hurt by poison.
4733 if (GOD_CHEIBRIADOS == you.religion
4734 && you.piety >= piety_breakpoint(0)
4735 && coinflip())
4736 return;
4738 if (you.duration[DUR_POISONING] > 0)
4740 if (x_chance_in_y(you.duration[DUR_POISONING], 5))
4742 int hurted = 1;
4743 msg_channel_type channel = MSGCH_PLAIN;
4744 const char *adj = "";
4746 if (you.duration[DUR_POISONING] > 10
4747 && random2(you.duration[DUR_POISONING]) >= 8)
4749 hurted = random2(10) + 5;
4750 channel = MSGCH_DANGER;
4751 adj = "extremely ";
4753 else if (you.duration[DUR_POISONING] > 5 && coinflip())
4755 hurted = coinflip() ? 3 : 2;
4756 channel = MSGCH_WARN;
4757 adj = "very ";
4760 int oldhp = you.hp;
4761 ouch(hurted, NON_MONSTER, KILLED_BY_POISON);
4762 if (you.hp < oldhp)
4763 mprf(channel, "You feel %ssick.", adj);
4765 if ((you.hp == 1 && one_chance_in(3)) || one_chance_in(8))
4766 reduce_poison_player(1);
4771 void reduce_poison_player(int amount)
4773 if (amount <= 0)
4774 return;
4776 const int old_value = you.duration[DUR_POISONING];
4777 you.duration[DUR_POISONING] -= amount;
4779 if (you.duration[DUR_POISONING] <= 0)
4781 you.duration[DUR_POISONING] = 0;
4782 you.props.erase("poisoner");
4783 you.props.erase("poison_aux");
4786 if (you.duration[DUR_POISONING] < old_value)
4788 mprf(MSGCH_RECOVERY, "You feel %sbetter.",
4789 you.duration[DUR_POISONING] > 0 ? "a little " : "");
4793 bool miasma_player(std::string source, std::string source_aux)
4795 ASSERT(!crawl_state.game_is_arena());
4797 if (you.res_rotting())
4798 return (false);
4800 // Zin's protection.
4801 if (you.religion == GOD_ZIN && x_chance_in_y(you.piety, MAX_PIETY))
4803 simple_god_message(" protects your body from miasma!");
4804 return (false);
4807 bool success = poison_player(1, source, source_aux);
4809 if (you.hp_max > 4 && coinflip())
4811 rot_hp(1);
4812 success = true;
4815 if (one_chance_in(3))
4817 potion_effect(POT_SLOWING, 5);
4818 success = true;
4821 return (success);
4824 bool napalm_player(int amount)
4826 ASSERT(!crawl_state.game_is_arena());
4828 if (player_res_sticky_flame() || amount <= 0)
4829 return (false);
4831 const int old_value = you.duration[DUR_LIQUID_FLAMES];
4832 you.increase_duration(DUR_LIQUID_FLAMES, amount, 100);
4834 if (you.duration[DUR_LIQUID_FLAMES] > old_value)
4835 mpr("You are covered in liquid flames!", MSGCH_WARN);
4837 return (true);
4840 void dec_napalm_player(int delay)
4842 if (you.duration[DUR_LIQUID_FLAMES] > BASELINE_DELAY)
4844 if (feat_is_watery(grd(you.pos())))
4846 mpr("The flames go out!", MSGCH_WARN);
4847 you.duration[DUR_LIQUID_FLAMES] = 0;
4848 return;
4851 mpr("You are covered in liquid flames!", MSGCH_WARN);
4853 expose_player_to_element(BEAM_NAPALM, 12);
4855 const int res_fire = player_res_fire();
4857 if (res_fire > 0)
4859 ouch((((random2avg(9, 2) + 1) * delay) /
4860 (1 + (res_fire * res_fire))) / BASELINE_DELAY, NON_MONSTER,
4861 KILLED_BY_BURNING);
4864 if (res_fire <= 0)
4866 ouch(((random2avg(9, 2) + 1) * delay) / BASELINE_DELAY,
4867 NON_MONSTER, KILLED_BY_BURNING);
4869 if (res_fire < 0)
4871 ouch(((random2avg(9, 2) + 1) * delay)
4872 / BASELINE_DELAY, NON_MONSTER, KILLED_BY_BURNING);
4876 if (you.duration[DUR_CONDENSATION_SHIELD] > 0)
4877 remove_condensation_shield();
4878 if (you.duration[DUR_ICY_ARMOUR] > 0)
4879 remove_ice_armour();
4882 you.duration[DUR_LIQUID_FLAMES] -= delay;
4883 if (you.duration[DUR_LIQUID_FLAMES] < 0)
4884 you.duration[DUR_LIQUID_FLAMES] = 0;
4887 bool slow_player(int turns)
4889 ASSERT(!crawl_state.game_is_arena());
4891 if (turns <= 0)
4892 return (false);
4894 if (stasis_blocks_effect(true, true, "%s rumbles.", 20, "%s rumbles."))
4895 return (false);
4897 // Doubling these values because moving while slowed takes twice the
4898 // usual delay.
4899 turns = haste_mul(turns);
4900 int threshold = haste_mul(100);
4902 if (you.duration[DUR_SLOW] >= threshold * BASELINE_DELAY)
4903 mpr("You already are as slow as you could be.");
4904 else
4906 if (you.duration[DUR_SLOW] == 0)
4907 mpr("You feel yourself slow down.");
4908 else
4909 mpr("You feel as though you will be slow longer.");
4911 you.increase_duration(DUR_SLOW, turns, threshold);
4912 learned_something_new(HINT_YOU_ENCHANTED);
4915 return (true);
4918 void dec_slow_player(int delay)
4920 if (!you.duration[DUR_SLOW])
4921 return;
4923 if (you.duration[DUR_SLOW] > BASELINE_DELAY)
4925 // Make slowing and hasting effects last as long.
4926 you.duration[DUR_SLOW] -= you.duration[DUR_HASTE]
4927 ? haste_mul(delay) : delay;
4929 if (you.duration[DUR_SLOW] <= BASELINE_DELAY)
4931 mpr("You feel yourself speed up.", MSGCH_DURATION);
4932 you.duration[DUR_SLOW] = 0;
4936 // Exhaustion should last as long as slowing.
4937 void dec_exhaust_player(int delay)
4939 if (!you.duration[DUR_EXHAUSTED])
4940 return;
4942 if (you.duration[DUR_EXHAUSTED] > BASELINE_DELAY)
4944 you.duration[DUR_EXHAUSTED] -= you.duration[DUR_HASTE]
4945 ? haste_mul(delay) : delay;
4947 if (you.duration[DUR_EXHAUSTED] <= BASELINE_DELAY)
4949 mpr("You feel less exhausted.", MSGCH_DURATION);
4950 you.duration[DUR_EXHAUSTED] = 0;
4954 bool haste_player(int turns, bool rageext)
4956 ASSERT(!crawl_state.game_is_arena());
4958 if (turns <= 0)
4959 return (false);
4961 if (stasis_blocks_effect(true, true, "%s emits a piercing whistle.", 20,
4962 "%s makes your neck tingle."))
4964 return (false);
4967 // Cutting the nominal turns in half since hasted actions take half the
4968 // usual delay.
4969 turns = haste_div(turns);
4970 const int threshold = 40;
4972 if (!you.duration[DUR_HASTE])
4973 mpr("You feel yourself speed up.");
4974 else if (you.duration[DUR_HASTE] > threshold * BASELINE_DELAY)
4975 mpr("You already have as much speed as you can handle.");
4976 else if (!rageext)
4978 mpr("You feel as though your hastened speed will last longer.");
4979 contaminate_player(1, true); // always deliberate
4982 you.increase_duration(DUR_HASTE, turns, threshold);
4983 did_god_conduct(DID_STIMULANTS, 4 + random2(4));
4985 return (true);
4988 void dec_haste_player(int delay)
4990 if (!you.duration[DUR_HASTE])
4991 return;
4993 if (you.duration[DUR_HASTE] > BASELINE_DELAY)
4995 int old_dur = you.duration[DUR_HASTE];
4997 you.duration[DUR_HASTE] -= delay;
4999 int threshold = 6 * BASELINE_DELAY;
5000 // message if we cross the threshold
5001 if (old_dur > threshold && you.duration[DUR_HASTE] <= threshold)
5003 mpr("Your extra speed is starting to run out.", MSGCH_DURATION);
5004 if (coinflip())
5005 you.duration[DUR_HASTE] -= BASELINE_DELAY;
5008 else if (you.duration[DUR_HASTE] <= BASELINE_DELAY)
5010 if (!you.duration[DUR_BERSERK])
5011 mpr("You feel yourself slow down.", MSGCH_DURATION);
5012 you.duration[DUR_HASTE] = 0;
5016 void dec_disease_player(int delay)
5018 if (you.disease > 0)
5020 // If Cheibriados has slowed your life processes, there's a
5021 // chance that your disease level is unaffected.
5022 if (GOD_CHEIBRIADOS == you.religion
5023 && you.piety >= piety_breakpoint(0)
5024 && coinflip())
5026 return;
5029 you.disease -= delay;
5030 if (you.disease < 0)
5031 you.disease = 0;
5033 // kobolds and regenerators recuperate quickly
5034 if (you.disease > 5 * BASELINE_DELAY
5035 && (you.species == SP_KOBOLD
5036 || you.duration[DUR_REGENERATION]
5037 || player_mutation_level(MUT_REGENERATION) == 3))
5039 you.disease -= 2 * BASELINE_DELAY;
5042 if (you.disease == 0)
5043 mpr("You feel your health improve.", MSGCH_RECOVERY);
5047 void float_player(bool fly)
5049 if (you.fishtail)
5051 mprf("Your tail turns into legs as you %s out of the water.",
5052 fly ? "fly" : "levitate");
5053 merfolk_stop_swimming();
5055 else if (you.light_flight())
5056 mpr("You swoop lightly up into the air.");
5057 else if (fly)
5058 mpr("You fly up into the air.");
5059 else
5060 mpr("You gently float upwards from the floor.");
5062 // Amulet of Controlled Flight can auto-ID.
5063 if (wearing_amulet(AMU_CONTROLLED_FLIGHT)
5064 && !extrinsic_amulet_effect(AMU_CONTROLLED_FLIGHT))
5066 // it's important to do this only if the amulet is not identified yet,
5067 // or you'd get spammed
5068 item_def& amu(you.inv[you.equip[EQ_AMULET]]);
5069 if (!is_artefact(amu) && !item_type_known(amu))
5071 set_ident_type(amu.base_type, amu.sub_type, ID_KNOWN_TYPE);
5072 set_ident_flags(amu, ISFLAG_KNOW_PROPERTIES);
5073 mprf("You are wearing: %s",
5074 amu.name(DESC_INVENTORY_EQUIP).c_str());
5078 burden_change();
5081 void levitate_player(int pow)
5083 bool standing = !you.airborne();
5084 mprf(MSGCH_DURATION,
5085 "You feel %s buoyant.", standing ? "very" : "more");
5087 you.increase_duration(DUR_LEVITATION, 25 + random2(pow), 100);
5089 if (standing)
5090 float_player(false);
5093 bool land_player()
5095 // there was another source keeping you aloft
5096 if (you.airborne())
5097 return false;
5099 mpr("You float gracefully downwards.");
5100 burden_change();
5101 // Landing kills controlled flight.
5102 you.duration[DUR_CONTROLLED_FLIGHT] = 0;
5103 you.attribute[ATTR_LEV_UNCANCELLABLE] = 0;
5104 // Re-enter the terrain.
5105 move_player_to_grid(you.pos(), false, true);
5106 return true;
5109 int count_worn_ego(int which_ego)
5111 int result = 0;
5112 for (int slot = EQ_MIN_ARMOUR; slot <= EQ_MAX_ARMOUR; ++slot)
5114 if (you.equip[slot] != -1 && !you.melded[slot]
5115 && get_armour_ego_type(you.inv[you.equip[slot]]) == which_ego)
5117 result++;
5121 return (result);
5124 player::player()
5125 : kills(0), m_quiver(0)
5127 init();
5130 player::player(const player &other)
5131 : kills(0), m_quiver(0)
5133 init();
5135 // why doesn't this do a copy_from?
5136 player_quiver* saved_quiver = m_quiver;
5137 delete kills;
5138 *this = other;
5139 m_quiver = saved_quiver;
5141 kills = new KillMaster(*(other.kills));
5142 *m_quiver = *(other.m_quiver);
5145 // why is this not called "operator="?
5146 void player::copy_from(const player &other)
5148 if (this == &other)
5149 return;
5151 KillMaster *saved_kills = kills;
5152 player_quiver* saved_quiver = m_quiver;
5154 *this = other;
5156 kills = saved_kills;
5157 *kills = *(other.kills);
5158 m_quiver = saved_quiver;
5159 *m_quiver = *(other.m_quiver);
5163 // player struct initialization
5164 void player::init()
5166 // Permanent data:
5167 your_name.clear();
5168 species = SP_UNKNOWN;
5169 char_class = JOB_UNKNOWN;
5170 class_name.clear();
5171 type = MONS_PLAYER;
5172 mid = MID_PLAYER;
5173 position.reset();
5175 #ifdef WIZARD
5176 wizard = (Options.wiz_mode == WIZ_YES) ? true : false;
5177 #else
5178 wizard = false;
5179 #endif
5180 birth_time = time(0);
5182 // Long-term state:
5183 elapsed_time = 0;
5185 hp = 0;
5186 hp_max = 0;
5187 base_hp = 5000;
5188 base_hp2 = 5000;
5190 magic_points = 0;
5191 max_magic_points = 0;
5192 base_magic_points = 5000;
5193 base_magic_points2 = 5000;
5195 stat_loss.init(0);
5196 base_stats.init(0);
5197 stat_zero.init(0);
5198 stat_zero_cause.init("");
5199 last_chosen = STAT_RANDOM;
5201 hunger = 6000;
5202 hunger_state = HS_SATIATED;
5203 disease = 0;
5204 max_level = 1;
5205 hit_points_regeneration = 0;
5206 magic_points_regeneration = 0;
5207 experience = 0;
5208 experience_level = 1;
5209 gold = 0;
5211 equip.init(-1);
5212 melded.init(false);
5213 unrand_reacts = 0;
5215 symbol = MONS_PLAYER;
5216 form = TRAN_NONE;
5218 for (int i = 0; i < ENDOFPACK; i++)
5219 inv[i].clear();
5221 burden = 0;
5222 burden_state = BS_UNENCUMBERED;
5223 spells.init(SPELL_NO_SPELL);
5224 spell_no = 0;
5225 char_direction = GDT_DESCENDING;
5226 opened_zot = false;
5227 royal_jelly_dead = false;
5228 transform_uncancellable = false;
5229 fishtail = false;
5231 pet_target = MHITNOT;
5233 absdepth0 = 0;
5235 duration.init(0);
5236 rotting = 0;
5237 berserk_penalty = 0;
5239 attribute.init(0);
5240 quiver.init(ENDOFPACK);
5241 sacrifice_value.init(0);
5243 is_undead = US_ALIVE;
5245 friendly_pickup = 0;
5246 #if defined(WIZARD) || defined(DEBUG)
5247 never_die = false;
5248 #endif
5249 dead = false;
5250 lives = 0;
5251 deaths = 0;
5252 xray_vision = false;
5254 skills.init(0);
5255 // In Zot def we turn off all skills with non-zero skill level later
5256 practise_skill.init(true);
5257 skill_points.init(0);
5258 ct_skill_points.init(0);
5259 skill_order.init(MAX_SKILL_ORDER);
5261 transfer_from_skill = SK_NONE;
5262 transfer_to_skill = SK_NONE;
5263 transfer_skill_points = 0;
5264 transfer_total_skill_points = 0;
5266 sage_bonus_skill = NUM_SKILLS;
5267 sage_bonus_degree = 0;
5269 skill_cost_level = 1;
5270 total_skill_points = 0;
5271 exp_available = 0; // new games get 25 or 80 later
5273 item_description.init(255);
5274 unique_items.init(UNIQ_NOT_EXISTS);
5275 unique_creatures.init(false);
5277 if (kills)
5278 delete kills;
5279 kills = new KillMaster();
5281 level_type = LEVEL_DUNGEON;
5282 level_type_name.clear();
5283 level_type_ext.clear();
5284 level_type_name_abbrev.clear();
5285 level_type_origin.clear();
5286 level_type_tag.clear();
5288 where_are_you = BRANCH_MAIN_DUNGEON;
5290 branch_stairs.init(0);
5292 religion = GOD_NO_GOD;
5293 jiyva_second_name.clear();
5294 piety = 0;
5295 piety_hysteresis = 0;
5296 gift_timeout = 0;
5297 penance.init(0);
5298 worshipped.init(0);
5299 num_current_gifts.init(0);
5300 num_total_gifts.init(0);
5302 mutation.init(0);
5303 innate_mutations.init(0);
5304 demonic_traits.clear();
5306 earth_attunement = 0;
5307 magic_contamination = 0;
5309 had_book.init(false);
5310 seen_spell.init(false);
5311 seen_weapon.init(0);
5312 seen_armour.init(0);
5314 normal_vision = LOS_RADIUS;
5315 current_vision = LOS_RADIUS;
5317 hell_branch = NUM_BRANCHES;
5318 hell_exit = 0;
5320 real_time = 0;
5321 num_turns = 0;
5322 exploration = 0;
5324 last_view_update = 0;
5326 spell_letter_table.init(-1);
5327 ability_letter_table.init(ABIL_NON_ABILITY);
5329 uniq_map_tags.clear();
5330 uniq_map_names.clear();
5332 global_info = PlaceInfo();
5333 global_info.make_global();
5334 global_info.assert_validity();
5336 if (m_quiver)
5337 delete m_quiver;
5338 m_quiver = new player_quiver;
5340 props.clear();
5342 beholders.clear();
5343 fearmongers.clear();
5344 dactions.clear();
5346 clinging = 0;
5347 zotdef_wave_name.clear();
5348 last_mid = 0;
5349 last_cast_spell = SPELL_NO_SPELL;
5352 // Non-saved UI state:
5353 prev_targ = MHITNOT;
5354 prev_grd_targ.reset();
5355 prev_move.reset();
5357 travel_x = 0;
5358 travel_y = 0;
5359 travel_z = level_id();
5361 running.clear();
5362 received_weapon_warning = false;
5363 bondage_level = 0;
5365 delay_queue.clear();
5367 last_keypress_time = time(0);
5369 #if TAG_MAJOR_VERSION == 32
5370 for (unsigned int i = 0; i < ARRAYSZ(montiers); i++)
5371 montiers[i] = 0;
5372 #endif
5375 // Volatile (same-turn) state:
5376 turn_is_over = false;
5377 banished = false;
5378 banished_by.clear();
5380 wield_change = false;
5381 redraw_quiver = false;
5382 redraw_status_flags = 0;
5383 redraw_hit_points = false;
5384 redraw_magic_points = false;
5385 redraw_stats.init(false);
5386 redraw_experience = false;
5387 redraw_armour_class = false;
5388 redraw_evasion = false;
5390 flash_colour = BLACK;
5392 time_taken = 0;
5393 shield_blocks = 0;
5395 entry_cause = EC_SELF_EXPLICIT;
5396 entry_cause_god = GOD_NO_GOD;
5398 old_hunger = hunger;
5399 transit_stair = DNGN_UNSEEN;
5400 entering_level = false;
5402 reset_escaped_death();
5403 on_current_level = true;
5404 walking = 0;
5405 seen_portals = 0;
5406 frame_no = 0;
5408 save = 0;
5410 // Protected fields:
5411 for (int i = 0; i < NUM_BRANCHES; i++)
5413 branch_info[i].level_type = LEVEL_DUNGEON;
5414 branch_info[i].branch = i;
5415 branch_info[i].assert_validity();
5418 for (int i = 0; i < (NUM_LEVEL_AREA_TYPES - 1); i++)
5420 non_branch_info[i].level_type = i + 1;
5421 non_branch_info[i].branch = -1;
5422 non_branch_info[i].assert_validity();
5426 player_save_info player_save_info::operator=(const player& rhs)
5428 name = rhs.your_name;
5429 experience = rhs.experience;
5430 experience_level = rhs.experience_level;
5431 wizard = rhs.wizard;
5432 species = rhs.species;
5433 class_name = rhs.class_name;
5434 religion = rhs.religion;
5435 jiyva_second_name = rhs.jiyva_second_name;
5437 // [ds] Perhaps we should move game type to player?
5438 saved_game_type = crawl_state.type;
5440 #ifdef USE_TILE
5441 held_in_net = false;
5442 #endif
5444 return (*this);
5447 bool player_save_info::operator<(const player_save_info& rhs) const
5449 return experience < rhs.experience
5450 || (experience == rhs.experience && name < rhs.name);
5453 std::string player_save_info::short_desc() const
5455 std::ostringstream desc;
5457 const std::string qualifier =
5458 game_state::game_type_name_for(saved_game_type);
5459 if (!qualifier.empty())
5460 desc << "[" << qualifier << "] ";
5462 desc << name << ", a level " << experience_level << ' '
5463 << species_name(species) << ' ' << class_name;
5465 if (religion == GOD_JIYVA)
5466 desc << " of " << god_name_jiyva(true);
5467 else if (religion != GOD_NO_GOD)
5468 desc << " of " << god_name(religion);
5470 #ifdef WIZARD
5471 if (wizard)
5472 desc << " (WIZ)";
5473 #endif
5475 return desc.str();
5478 player::~player()
5480 delete kills;
5481 delete m_quiver;
5482 if (CrawlIsCrashing && save)
5484 save->abort();
5485 delete save;
5486 save = 0;
5488 ASSERT(!save); // the save file should be closed or deleted
5491 bool player::is_levitating() const
5493 return duration[DUR_LEVITATION] || you.attribute[ATTR_PERM_LEVITATION];
5496 void player::clear_clinging()
5498 you.clinging = false;
5499 you.cling_to.clear();
5502 bool player::in_water() const
5504 return (ground_level() && !beogh_water_walk()
5505 && feat_is_water(grd(pos())));
5508 bool player::can_swim(bool permanently) const
5510 // Transforming could be fatal if it would cause unequipment of
5511 // stat-boosting boots or heavy armour.
5512 return (species == SP_MERFOLK
5513 || body_size(PSIZE_BODY) >= SIZE_GIANT
5514 || !permanently)
5515 && form_can_swim();
5518 int player::visible_igrd(const coord_def &where) const
5520 if (grd(where) == DNGN_LAVA
5521 || (grd(where) == DNGN_DEEP_WATER
5522 && species != SP_MERFOLK && species != SP_GREY_DRACONIAN))
5524 return (NON_ITEM);
5527 return (igrd(where));
5530 bool player::has_spell(spell_type spell) const
5532 for (int i = 0; i < MAX_KNOWN_SPELLS; i++)
5534 if (spells[i] == spell)
5535 return (true);
5538 return (false);
5541 bool player::cannot_speak() const
5543 if (silenced(pos()))
5544 return (true);
5546 if (cannot_move()) // we allow talking during sleep ;)
5547 return (true);
5549 // No transform that prevents the player from speaking yet.
5550 return (false);
5553 std::string player::shout_verb() const
5555 switch (you.form)
5557 case TRAN_DRAGON:
5558 return "roar";
5559 case TRAN_SPIDER:
5560 return "hiss";
5561 case TRAN_BAT:
5562 return "squeak";
5563 case TRAN_PIG:
5564 return "squeal";
5565 default:
5566 if (you.species == SP_CAT)
5567 return coinflip() ? "meow" : "yowl";
5568 // depends on SCREAM mutation
5569 int level = player_mutation_level(MUT_SCREAM);
5570 if (level <= 1)
5571 return "shout";
5572 else if (level == 2)
5573 return "yell";
5574 else // level == 3
5575 return "scream";
5579 void player::god_conduct(conduct_type thing_done, int level)
5581 ::did_god_conduct(thing_done, level);
5584 void player::banish(const std::string &who)
5586 ASSERT(!crawl_state.game_is_arena());
5588 banished = true;
5589 banished_by = who;
5592 // For semi-undead species (Vampire!) reduce food cost for spells and abilities
5593 // to 50% (hungry, very hungry) or zero (near starving, starving).
5594 int calc_hunger(int food_cost)
5596 if (you.is_undead == US_SEMI_UNDEAD && you.hunger_state < HS_SATIATED)
5598 if (you.hunger_state <= HS_NEAR_STARVING)
5599 return 0;
5601 return (food_cost/2);
5603 return (food_cost);
5606 int player::warding() const
5608 if (wearing_amulet(AMU_WARDING))
5609 return (30);
5611 return (0);
5614 bool player::paralysed() const
5616 return (duration[DUR_PARALYSIS]);
5619 bool player::cannot_move() const
5621 return (paralysed() || petrified());
5624 bool player::confused() const
5626 return (duration[DUR_CONF]);
5629 bool player::caught() const
5631 return (attribute[ATTR_HELD]);
5634 bool player::petrified() const
5636 return (duration[DUR_PETRIFIED]);
5639 int player::shield_block_penalty() const
5641 return (5 * shield_blocks * shield_blocks);
5644 int player::shield_bonus() const
5646 const int shield_class = player_shield_class();
5647 if (shield_class <= 0)
5648 return (-100);
5650 return random2avg(shield_class * 2, 2) / 3 - 1;
5653 int player::shield_bypass_ability(int tohit) const
5655 return (15 + tohit / 2);
5658 void player::shield_block_succeeded(actor *foe)
5660 actor::shield_block_succeeded(foe);
5662 shield_blocks++;
5663 practise(EX_SHIELD_BLOCK);
5666 int player::skill(skill_type sk) const
5668 if (you.duration[DUR_HEROISM] && sk <= SK_LAST_MUNDANE)
5669 return std::min(skills[sk] + 5, 27);
5671 return skills[sk];
5674 // only for purposes of detection, not disarming
5675 int player::traps_skill() const
5677 int val = skill(SK_TRAPS_DOORS);
5679 if (you.religion == GOD_ASHENZARI && !player_under_penance())
5680 val += you.piety / 15;
5682 return val;
5685 int player_icemail_armour_class()
5687 if (!you.mutation[MUT_ICEMAIL])
5688 return (0);
5690 return (ICEMAIL_MAX
5691 - (you.duration[DUR_ICEMAIL_DEPLETED]
5692 * ICEMAIL_MAX / ICEMAIL_TIME));
5695 int player::armour_class() const
5697 int AC = 0;
5699 for (int eq = EQ_MIN_ARMOUR; eq <= EQ_MAX_ARMOUR; ++eq)
5701 if (eq == EQ_SHIELD)
5702 continue;
5704 if (!player_wearing_slot(eq))
5705 continue;
5707 const item_def& item = inv[equip[eq]];
5708 const int ac_value = property(item, PARM_AC) * 100;
5709 const int racial_bonus = _player_armour_racial_bonus(item);
5711 // [ds] effectively: ac_value * (22 + Arm) / 22, where Arm =
5712 // Armour Skill + racial_skill_bonus / 2.
5713 AC += ac_value * (44 + 2 * skill(SK_ARMOUR) + racial_bonus) / 44;
5714 AC += item.plus * 100;
5716 // The deformed don't fit into body armour very well.
5717 // (This includes nagas and centaurs.)
5718 if (eq == EQ_BODY_ARMOUR && (player_mutation_level(MUT_DEFORMED)
5719 || player_mutation_level(MUT_PSEUDOPODS)))
5720 AC -= ac_value / 2;
5723 AC += player_equip(EQ_RINGS_PLUS, RING_PROTECTION) * 100;
5725 if (player_equip_ego_type(EQ_WEAPON, SPWPN_PROTECTION))
5726 AC += 500;
5728 if (player_equip_ego_type(EQ_SHIELD, SPARM_PROTECTION))
5729 AC += 300;
5731 AC += scan_artefacts(ARTP_AC) * 100;
5733 if (duration[DUR_ICY_ARMOUR])
5734 AC += 400 + 100 * skills[SK_ICE_MAGIC] / 3; // max 13
5736 if (duration[DUR_STONEMAIL])
5737 AC += 500 + 100 * skills[SK_EARTH_MAGIC] / 2; // max 18
5739 if (duration[DUR_STONESKIN])
5740 AC += 200 + 100 * skills[SK_EARTH_MAGIC] / 5; // max 7
5742 if (mutation[MUT_ICEMAIL])
5743 AC += 100 * player_icemail_armour_class();
5745 if (form == TRAN_NONE
5746 || form == TRAN_LICH
5747 || form == TRAN_BLADE_HANDS
5748 || (form == TRAN_DRAGON
5749 && player_genus(GENPC_DRACONIAN)))
5751 // Being a lich doesn't preclude the benefits of hide/scales -- bwr
5753 // Note: Even though necromutation is a high level spell, it does
5754 // allow the character full armour (so the bonus is low). -- bwr
5755 if (form == TRAN_LICH)
5756 AC += (300 + 100 * skills[SK_NECROMANCY] / 6); // max 7
5758 //jmf: only give:
5759 if (player_genus(GENPC_DRACONIAN))
5761 AC += 300 + 100 * (you.experience_level / 3); // max 12
5763 if (form == TRAN_DRAGON)
5764 AC += 700;
5766 else
5768 switch (species)
5770 case SP_NAGA:
5771 AC += 100 * experience_level / 3; // max 9
5772 break;
5774 default:
5775 break;
5779 else
5781 // transformations:
5782 switch (form)
5784 case TRAN_NONE:
5785 case TRAN_BLADE_HANDS:
5786 case TRAN_LICH: // can wear normal body armour (small bonus)
5787 break;
5789 case TRAN_SPIDER: // low level (small bonus), also gets EV
5790 AC += (200 + 100 * skills[SK_POISON_MAGIC] / 6); // max 6
5791 break;
5793 case TRAN_ICE_BEAST:
5794 AC += (500 + 100 * (skills[SK_ICE_MAGIC] + 1) / 4); // max 12
5796 if (duration[DUR_ICY_ARMOUR])
5797 AC += (100 + 100 * skills[SK_ICE_MAGIC] / 4); // max +7
5798 break;
5800 case TRAN_DRAGON: // Draconians handled above
5801 AC += (700 + 100 * skills[SK_FIRE_MAGIC] / 3); // max 16
5802 break;
5804 case TRAN_STATUE: // main ability is armour (high bonus)
5805 AC += (1700 + 100 * skills[SK_EARTH_MAGIC] / 2); // max 30
5807 if (duration[DUR_STONESKIN] || duration[DUR_STONEMAIL])
5808 AC += (100 + 100 * skills[SK_EARTH_MAGIC] / 4); // max +7
5809 break;
5811 default:
5812 break;
5816 // Scale mutations, etc.
5817 AC += player_mutation_level(MUT_TOUGH_SKIN) ? player_mutation_level(MUT_TOUGH_SKIN) * 100 : 0; // +1, +2, +3
5818 AC += player_mutation_level(MUT_SHAGGY_FUR) ? player_mutation_level(MUT_SHAGGY_FUR) * 100 : 0; // +1, +2, +3
5819 AC += player_mutation_level(MUT_IRIDESCENT_SCALES) ? 200 + player_mutation_level(MUT_IRIDESCENT_SCALES) * 200 : 0; // +4, +6, +8
5820 AC += player_mutation_level(MUT_LARGE_BONE_PLATES) ? 100 + player_mutation_level(MUT_LARGE_BONE_PLATES) * 100 : 0; // +2, +3, +4
5821 AC += player_mutation_level(MUT_ROUGH_BLACK_SCALES) ? 100 + player_mutation_level(MUT_ROUGH_BLACK_SCALES) * 300 : 0; // +4, +7, +10
5822 AC += player_mutation_level(MUT_RUGGED_BROWN_SCALES) ? 200 : 0; // +2, +2, +2
5823 AC += player_mutation_level(MUT_ICY_BLUE_SCALES) ? player_mutation_level(MUT_ICY_BLUE_SCALES) * 100 : 0; // +1, +2, +3
5824 AC += player_mutation_level(MUT_MOLTEN_SCALES) ? player_mutation_level(MUT_MOLTEN_SCALES) * 100 : 0; // +1, +2, +3
5825 AC += player_mutation_level(MUT_SLIMY_GREEN_SCALES) ? player_mutation_level(MUT_SLIMY_GREEN_SCALES) * 100 : 0; // +1, +2, +3
5826 AC += player_mutation_level(MUT_THIN_METALLIC_SCALES) ? player_mutation_level(MUT_THIN_METALLIC_SCALES) * 100 : 0; // +1, +2, +3
5827 AC += player_mutation_level(MUT_YELLOW_SCALES) ? player_mutation_level(MUT_YELLOW_SCALES) * 100 : 0; // +1, +2, +3
5828 AC += player_mutation_level(MUT_GELATINOUS_BODY) ? (player_mutation_level(MUT_GELATINOUS_BODY) == 3 ? 200 : 100) : 0; // +1, +1, +2
5829 return (AC / 100);
5832 * Guaranteed damage reduction.
5834 * The percentage of the damage received that is guaranteed to be reduced
5835 * by the armour. As the AC roll is done before GDR is applied, GDR is only
5836 * useful when the AC roll is inferior to it. Therefore a higher GDR means
5837 * more damage reduced, but also more often.
5839 * \f[ GDR = 14 \times (base\_AC - 2)^\frac{1}{2} \f]
5841 * \return GDR as a percentage.
5843 int player::gdr_perc() const
5845 const item_def *body_armour = slot_item(EQ_BODY_ARMOUR, false);
5847 if (!body_armour)
5848 return (0);
5850 const int body_base_AC = property(*body_armour, PARM_AC);
5851 return (14 * pow(std::max(body_base_AC - 2, 0), 0.5));
5854 int player::melee_evasion(const actor *act, ev_ignore_type evit) const
5856 return (player_evasion(evit)
5857 - ((!act || act->visible_to(this)
5858 || (evit & EV_IGNORE_HELPLESS)) ? 0 : 10)
5859 - (you_are_delayed()
5860 && !(evit & EV_IGNORE_HELPLESS)
5861 && !delay_is_run(current_delay_action())? 5 : 0));
5864 bool player::heal(int amount, bool max_too)
5866 ::inc_hp(amount, max_too);
5867 return true; /* TODO Check whether the player was healed. */
5870 mon_holy_type player::holiness() const
5872 if (is_undead)
5873 return (MH_UNDEAD);
5875 if (species == SP_DEMONSPAWN)
5876 return (MH_DEMONIC);
5878 return (MH_NATURAL);
5881 bool player::undead_or_demonic() const
5883 const mon_holy_type holi = holiness();
5885 return (holi == MH_UNDEAD || holi == MH_DEMONIC);
5888 bool player::is_holy() const
5890 if (is_good_god(religion))
5891 return (true);
5893 return (false);
5896 bool player::is_unholy() const
5898 return (holiness() == MH_DEMONIC);
5901 bool player::is_evil() const
5903 if (holiness() == MH_UNDEAD)
5904 return (true);
5906 if (is_evil_god(religion))
5907 return (true);
5909 return (false);
5912 // This is a stub. Check is used only for silver damage. Worship of chaotic
5913 // gods should probably be checked in the non-existing player::is_unclean,
5914 // which could be used for something Zin-related (such as a priestly monster).
5915 bool player::is_chaotic() const
5917 return (false);
5920 bool player::is_artificial() const
5922 return (false);
5925 bool player::is_unbreathing() const
5927 switch (you.form)
5929 case TRAN_LICH:
5930 case TRAN_STATUE:
5931 return (true);
5932 default:
5933 break;
5936 return (player_mutation_level(MUT_UNBREATHING));
5939 // This is a stub. Makes checking for silver damage a little cleaner.
5940 bool player::is_insubstantial() const
5942 return (false);
5945 // Output active level of player mutation.
5946 // Might be lower than real mutation for non-"Alive" Vampires.
5947 int player_mutation_level(mutation_type mut)
5949 const int mlevel = you.mutation[mut];
5951 if (mutation_is_fully_active(mut))
5952 return (mlevel);
5954 // For now, dynamic mutations only apply to semi-undead.
5955 ASSERT(you.is_undead == US_SEMI_UNDEAD);
5957 // Assumption: stat mutations are physical, and thus always fully active.
5958 switch (you.hunger_state)
5960 case HS_ENGORGED:
5961 return (mlevel);
5962 case HS_VERY_FULL:
5963 case HS_FULL:
5964 return (std::min(mlevel, 2));
5965 case HS_SATIATED:
5966 return (std::min(mlevel, 1));
5969 return (0);
5972 int player::res_acid() const
5974 return (player_res_acid());
5977 int player::res_fire() const
5979 return (player_res_fire());
5982 int player::res_steam() const
5984 return (player_res_steam());
5987 int player::res_cold() const
5989 return (player_res_cold());
5992 int player::res_elec() const
5994 return (player_res_electricity() * 2);
5997 int player::res_water_drowning() const
5999 return (is_unbreathing()
6000 || (you.species == SP_MERFOLK && !form_changed_physiology()));
6003 int player::res_asphyx() const
6005 // The unbreathing are immune to asphyxiation.
6006 if (is_unbreathing())
6007 return 1;
6009 return 0;
6012 int player::res_poison(bool temp) const
6014 return (player_res_poison(true, temp));
6017 int player::res_rotting(bool temp) const
6019 switch (is_undead)
6021 default:
6022 case US_ALIVE:
6023 return 0;
6025 case US_HUNGRY_DEAD:
6026 return 1; // rottable by Zin, not by necromancy
6028 case US_SEMI_UNDEAD:
6029 return temp ? 1 : 0;
6031 case US_UNDEAD:
6032 if (!temp && you.form == TRAN_LICH)
6033 return 0;
6034 return 3; // full immunity
6038 int player::res_sticky_flame() const
6040 return (player_res_sticky_flame());
6043 int player::res_holy_energy(const actor *attacker) const
6045 if (undead_or_demonic())
6046 return (-2);
6048 if (is_evil())
6049 return (-1);
6051 if (is_holy())
6052 return (1);
6054 return (0);
6057 int player::res_negative_energy() const
6059 return (player_prot_life());
6062 int player::res_torment() const
6064 return (player_res_torment());
6067 int player::res_wind() const
6069 // Full control of the winds around you can negate a hostile tornado.
6070 return you.duration[DUR_TORNADO] ? 1 : 0;
6073 int player::res_magic() const
6075 return player_res_magic();
6078 int player_res_magic(bool calc_unid, bool temp)
6080 int rm = 0;
6082 switch (you.species)
6084 default:
6085 rm = you.experience_level * 3;
6086 break;
6087 case SP_HIGH_ELF:
6088 case SP_SLUDGE_ELF:
6089 case SP_DEEP_ELF:
6090 case SP_MOUNTAIN_DWARF:
6091 case SP_VAMPIRE:
6092 case SP_DEMIGOD:
6093 case SP_OGRE:
6094 rm = you.experience_level * 4;
6095 break;
6096 case SP_NAGA:
6097 rm = you.experience_level * 5;
6098 break;
6099 case SP_PURPLE_DRACONIAN:
6100 case SP_DEEP_DWARF:
6101 case SP_CAT:
6102 rm = you.experience_level * 6;
6103 break;
6104 case SP_SPRIGGAN:
6105 rm = you.experience_level * 7;
6106 break;
6109 // randarts
6110 rm += scan_artefacts(ARTP_MAGIC, calc_unid);
6112 // armour
6113 rm += 30 * player_equip_ego_type(EQ_ALL_ARMOUR, SPARM_MAGIC_RESISTANCE,
6114 calc_unid);
6116 // rings of magic resistance
6117 rm += 40 * player_equip(EQ_RINGS, RING_PROTECTION_FROM_MAGIC, calc_unid);
6119 // Enchantment skill through staff of enchantment (up to 90).
6120 if (player_equip(EQ_STAFF, STAFF_ENCHANTMENT, calc_unid))
6121 rm += 3 * (3 + std::max(you.skill(SK_CHARMS), you.skill(SK_HEXES)));
6123 // Mutations
6124 rm += 30 * player_mutation_level(MUT_MAGIC_RESISTANCE);
6126 // transformations
6127 if (you.form == TRAN_LICH && temp)
6128 rm += 50;
6130 // Trog's Hand
6131 if (you.attribute[ATTR_DIVINE_REGENERATION] && temp)
6132 rm += 70;
6134 // Enchantment effect
6135 if (you.duration[DUR_LOWERED_MR] && temp)
6136 rm /= 2;
6138 return (rm);
6141 bool player::confusable() const
6143 return (player_mental_clarity() == 0);
6146 bool player::slowable() const
6148 return true;
6151 flight_type player::flight_mode() const
6153 if (form == TRAN_DRAGON
6154 || form == TRAN_BAT)
6156 return (FL_FLY);
6158 else if (is_levitating())
6160 return (duration[DUR_CONTROLLED_FLIGHT]
6161 || wearing_amulet(AMU_CONTROLLED_FLIGHT) ? FL_FLY
6162 : FL_LEVITATE);
6164 else
6165 return (FL_NONE);
6168 bool player::permanent_levitation() const
6170 return you.attribute[ATTR_PERM_LEVITATION]
6171 && player_equip_ego_type(EQ_BOOTS, SPARM_LEVITATION);
6174 bool player::permanent_flight() const
6176 return you.attribute[ATTR_PERM_LEVITATION]
6177 && species == SP_KENKU && experience_level >= 15;
6180 bool player::light_flight() const
6182 // Only Kenku get perks for flying light.
6183 return (species == SP_KENKU
6184 && flight_mode() == FL_FLY && travelling_light());
6187 bool player::travelling_light() const
6189 return (burden < carrying_capacity(BS_UNENCUMBERED) * 70 / 100);
6192 int player::mons_species() const
6194 if (player_genus(GENPC_DRACONIAN))
6195 return (MONS_DRACONIAN);
6197 switch (species)
6199 case SP_HILL_ORC:
6200 return (MONS_ORC);
6201 case SP_HIGH_ELF: case SP_DEEP_ELF: case SP_SLUDGE_ELF:
6202 return (MONS_ELF);
6204 default:
6205 return (MONS_HUMAN);
6209 void player::poison(actor *agent, int amount, bool force)
6211 ::poison_player(amount, agent? agent->name(DESC_NOCAP_A, true) : "");
6214 void player::expose_to_element(beam_type element, int st)
6216 ::expose_player_to_element(element, st);
6219 void player::blink(bool allow_partial_control)
6221 random_blink(allow_partial_control);
6224 void player::teleport(bool now, bool abyss_shift, bool wizard_tele)
6226 ASSERT(!crawl_state.game_is_arena());
6228 if (now)
6229 you_teleport_now(true, abyss_shift, wizard_tele);
6230 else
6231 you_teleport();
6234 int player::hurt(const actor *agent, int amount, beam_type flavour,
6235 bool cleanup_dead)
6237 // We ignore cleanup_dead here.
6238 if (agent->atype() == ACT_MONSTER)
6240 const monster* mon = agent->as_monster();
6241 ouch(amount, mon->mindex(),
6242 KILLED_BY_MONSTER, "", mon->visible_to(&you));
6244 else
6246 // Should never happen!
6247 die("player::hurt() called for self-damage");
6250 if ((flavour == BEAM_NUKE || flavour == BEAM_DISINTEGRATION) && can_bleed())
6251 blood_spray(pos(), type, amount / 5);
6253 return (amount);
6256 void player::drain_stat(stat_type s, int amount, actor *attacker)
6258 if (attacker == NULL)
6259 lose_stat(s, amount, false, "");
6260 else if (attacker->atype() == ACT_MONSTER)
6261 lose_stat(s, amount, attacker->as_monster(), false);
6262 else if (attacker->atype() == ACT_PLAYER)
6263 lose_stat(s, amount, false, "suicide");
6264 else
6265 lose_stat(s, amount, false, "");
6268 bool player::rot(actor *who, int amount, int immediate, bool quiet)
6270 ASSERT(!crawl_state.game_is_arena());
6272 if (amount <= 0 && immediate <= 0)
6273 return (false);
6275 if (res_rotting())
6277 mpr("You feel terrible.");
6278 return (false);
6281 // Zin's protection.
6282 if (religion == GOD_ZIN && x_chance_in_y(piety, MAX_PIETY))
6284 simple_god_message(" protects your body from decay!");
6285 return (false);
6288 if (immediate > 0)
6289 rot_hp(immediate);
6291 if (rotting < 40)
6293 // Either this, or the actual rotting message should probably
6294 // be changed so that they're easier to tell apart. -- bwr
6295 mprf(MSGCH_WARN, "You feel your flesh %s away!",
6296 rotting > 0 ? "rotting" : "start to rot");
6298 rotting += amount;
6300 learned_something_new(HINT_YOU_ROTTING);
6303 if (one_chance_in(4))
6304 sicken(50 + random2(100));
6306 return (true);
6309 bool player::drain_exp(actor *who, bool quiet, int pow)
6311 return (::drain_exp());
6314 void player::confuse(actor *who, int str)
6316 confuse_player(str);
6319 void player::paralyse(actor *who, int str)
6321 ASSERT(!crawl_state.game_is_arena());
6323 // The shock is too mild to do damage.
6324 if (stasis_blocks_effect(true, true, "%s gives you a mild electric shock."))
6325 return;
6327 if (!(who && who->as_monster() && who->as_monster()->type == MONS_RED_WASP)
6328 && (duration[DUR_PARALYSIS] || duration[DUR_PARALYSIS_IMMUNITY]))
6330 canned_msg(MSG_YOU_RESIST);
6331 return;
6334 int &paralysis(duration[DUR_PARALYSIS]);
6336 mprf("You %s the ability to move!",
6337 paralysis ? "still haven't" : "suddenly lose");
6339 str *= BASELINE_DELAY;
6340 if (str > paralysis && (paralysis < 3 || one_chance_in(paralysis)))
6341 paralysis = str;
6343 if (paralysis > 13 * BASELINE_DELAY)
6344 paralysis = 13 * BASELINE_DELAY;
6347 void player::petrify(actor *who, int str)
6349 ASSERT(!crawl_state.game_is_arena());
6351 if (stasis_blocks_effect(true, true, "%s gives you a mild electric shock."))
6352 return;
6354 str *= BASELINE_DELAY;
6355 int &petrif(duration[DUR_PETRIFIED]);
6357 mprf("You %s the ability to move!",
6358 petrif ? "still haven't" : "suddenly lose");
6360 if (str > petrif && (petrif < 3 || one_chance_in(petrif)))
6361 petrif = str;
6363 petrif = std::min(13 * BASELINE_DELAY, petrif);
6366 void player::slow_down(actor *foe, int str)
6368 ::slow_player(str);
6371 int player::has_claws(bool allow_tran) const
6373 if (allow_tran)
6375 // these transformations bring claws with them
6376 if (form == TRAN_DRAGON)
6377 return (3);
6379 // transformations other than these will override claws
6380 if (form != TRAN_NONE
6381 && form != TRAN_STATUE
6382 && form != TRAN_LICH)
6384 return (0);
6388 if (const int c = species_has_claws(you.species))
6389 return (c);
6391 return (player_mutation_level(MUT_CLAWS));
6394 bool player::has_usable_claws(bool allow_tran) const
6396 return (!player_wearing_slot(EQ_GLOVES) && has_claws(allow_tran));
6399 int player::has_talons(bool allow_tran) const
6401 if (allow_tran)
6403 // transformations other than these will override talons
6404 if (form != TRAN_NONE
6405 && form != TRAN_BLADE_HANDS
6406 && form != TRAN_STATUE
6407 && form != TRAN_LICH)
6409 return (0);
6413 // XXX: Do merfolk in water belong under allow_tran?
6414 if (you.fishtail)
6415 return (0);
6417 return (player_mutation_level(MUT_TALONS));
6420 bool player::has_usable_talons(bool allow_tran) const
6422 return (!player_wearing_slot(EQ_BOOTS) && has_talons(allow_tran));
6425 int player::has_fangs(bool allow_tran) const
6427 if (allow_tran)
6429 // these transformations bring fangs with them
6430 if (form == TRAN_DRAGON)
6431 return (3);
6433 // transformations other than these will override fangs
6434 if (form != TRAN_NONE
6435 && form != TRAN_BLADE_HANDS
6436 && form != TRAN_STATUE
6437 && form != TRAN_LICH)
6439 return (0);
6443 return (player_mutation_level(MUT_FANGS));
6446 int player::has_usable_fangs(bool allow_tran) const
6448 const item_def* helmet = you.slot_item(EQ_HELMET);
6449 if (helmet && get_helmet_desc(*helmet) == THELM_DESC_VISORED)
6450 return (0);
6452 return (has_fangs(allow_tran));
6455 int player::has_tail(bool allow_tran) const
6457 if (allow_tran)
6459 // these transformations bring a tail with them
6460 if (form == TRAN_DRAGON)
6461 return (1);
6463 // transformations other than these will override a tail
6464 if (form != TRAN_NONE
6465 && form != TRAN_BLADE_HANDS
6466 && form != TRAN_STATUE
6467 && form != TRAN_LICH)
6469 return (0);
6473 // XXX: Do merfolk in water belong under allow_tran?
6474 if (player_genus(GENPC_DRACONIAN)
6475 || you.fishtail
6476 || player_mutation_level(MUT_STINGER))
6478 return (1);
6481 return (0);
6484 int player::has_usable_tail(bool allow_tran) const
6486 // TSO worshippers don't use their stinger in order
6487 // to avoid poisoning.
6488 if (you.religion == GOD_SHINING_ONE
6489 && player_mutation_level(MUT_STINGER) > 0)
6491 return (0);
6494 return (has_tail(allow_tran));
6497 // Whether the player has a usable offhand for the
6498 // purpose of punching.
6499 // XXX: The weapon check should probably involve HANDS_DOUBLE
6500 // at some point.
6501 bool player::has_usable_offhand() const
6503 if (player_wearing_slot(EQ_SHIELD))
6504 return (false);
6506 const item_def* wp = slot_item(EQ_WEAPON);
6507 return (!wp
6508 || hands_reqd(*wp, body_size()) != HANDS_TWO
6509 || wp->base_type == OBJ_STAVES
6510 || weapon_skill(*wp) == SK_STAVES);
6513 int player::has_pseudopods(bool allow_tran) const
6515 if (allow_tran)
6517 // transformations other than these will override pseudopods
6518 if (form != TRAN_NONE
6519 && form != TRAN_BLADE_HANDS
6520 && form != TRAN_STATUE
6521 && form != TRAN_LICH)
6523 return (0);
6527 return (player_mutation_level(MUT_PSEUDOPODS));
6530 int player::has_usable_pseudopods(bool allow_tran) const
6532 return (has_pseudopods(allow_tran));
6535 bool player::sicken(int amount)
6537 ASSERT(!crawl_state.game_is_arena());
6539 if (res_rotting() || amount <= 0)
6540 return (false);
6542 // Zin's protection.
6543 if (religion == GOD_ZIN && x_chance_in_y(piety, MAX_PIETY))
6545 simple_god_message(" protects your body from disease!");
6546 return (false);
6549 mpr("You feel ill.");
6551 disease += amount * BASELINE_DELAY;
6552 if (disease > 210 * BASELINE_DELAY)
6553 disease = 210 * BASELINE_DELAY;
6555 learned_something_new(HINT_YOU_SICK);
6556 return (true);
6559 bool player::can_see_invisible(bool calc_unid, bool transient) const
6561 if (crawl_state.game_is_arena())
6562 return (true);
6564 int si = 0;
6566 si += player_equip(EQ_RINGS, RING_SEE_INVISIBLE, calc_unid);
6568 // armour: (checks head armour only)
6569 si += player_equip_ego_type(EQ_HELMET, SPARM_SEE_INVISIBLE);
6571 if (player_mutation_level(MUT_ACUTE_VISION) > 0)
6572 si += player_mutation_level(MUT_ACUTE_VISION);
6574 // antennae give sInvis at 3
6575 if (player_mutation_level(MUT_ANTENNAE) == 3)
6576 si++;
6578 if (player_mutation_level(MUT_EYEBALLS) == 3)
6579 si++;
6581 //jmf: added see_invisible spell
6582 if (transient && duration[DUR_SEE_INVISIBLE] > 0)
6583 si++;
6585 // randart wpns
6586 int artefacts = scan_artefacts(ARTP_EYESIGHT, calc_unid);
6588 if (artefacts > 0)
6589 si += artefacts;
6591 if (you.religion == GOD_ASHENZARI && you.piety >= piety_breakpoint(2)
6592 && !player_under_penance())
6594 si++;
6597 if (si > 1)
6598 si = 1;
6600 return (si);
6603 bool player::can_see_invisible() const
6605 return (can_see_invisible(true));
6608 bool player::invisible() const
6610 return (duration[DUR_INVIS] && !backlit());
6613 bool player::misled() const
6615 return (duration[DUR_MISLED]);
6618 bool player::visible_to(const actor *looker) const
6620 if (crawl_state.game_is_arena())
6621 return (false);
6623 if (this == looker)
6624 return (can_see_invisible() || !invisible());
6626 const monster* mon = looker->as_monster();
6627 return (!mon->has_ench(ENCH_BLIND)
6628 && !invisible()
6629 || in_water()
6630 || mon->can_see_invisible()
6631 || mons_sense_invis(mon)
6632 && circle_def(pos(), 4, C_ROUND).contains(mon->pos()));
6635 bool player::backlit(bool check_haloed, bool self_halo) const
6637 if (get_contamination_level() > 1 || duration[DUR_CORONA]
6638 || duration[DUR_LIQUID_FLAMES] || duration[DUR_QUAD_DAMAGE])
6640 return (true);
6642 if (check_haloed)
6643 return (haloed() && (self_halo || halo_radius2() == -1));
6644 return (false);
6647 bool player::glows_naturally() const
6649 return (false);
6652 // This is the imperative version.
6653 void player::backlight()
6655 if (!duration[DUR_INVIS])
6657 if (duration[DUR_CORONA] || you.glows_naturally())
6658 mpr("You glow brighter.");
6659 else
6660 mpr("You are outlined in light.");
6662 you.increase_duration(DUR_CORONA, random_range(15, 35), 250);
6664 else
6666 mpr("You feel strangely conspicuous.");
6668 you.increase_duration(DUR_CORONA, random_range(3, 5), 250);
6672 bool player::has_lifeforce() const
6674 const mon_holy_type holi = holiness();
6676 return (holi == MH_NATURAL || holi == MH_PLANT);
6679 bool player::can_mutate() const
6681 return (true);
6684 bool player::can_safely_mutate() const
6686 if (!can_mutate())
6687 return (false);
6689 return (!is_undead
6690 || is_undead == US_SEMI_UNDEAD
6691 && hunger_state == HS_ENGORGED);
6694 bool player::can_bleed() const
6696 if (is_undead && (species != SP_VAMPIRE
6697 || hunger_state <= HS_SATIATED))
6699 return (false);
6702 // The corresponding monsters don't bleed either.
6703 if (you.form == TRAN_STATUE || you.form == TRAN_ICE_BEAST
6704 || you.form == TRAN_LICH || you.form == TRAN_SPIDER)
6706 return (false);
6708 return (true);
6711 bool player::mutate()
6713 ASSERT(!crawl_state.game_is_arena());
6715 if (!can_mutate())
6716 return (false);
6718 if (one_chance_in(5))
6720 if (::mutate(RANDOM_MUTATION))
6722 learned_something_new(HINT_YOU_MUTATED);
6723 return (true);
6727 return (give_bad_mutation());
6730 bool player::is_icy() const
6732 return (form == TRAN_ICE_BEAST);
6735 bool player::is_fiery() const
6737 return (false);
6740 bool player::is_skeletal() const
6742 return (false);
6745 void player::shiftto(const coord_def &c)
6747 crawl_view.shift_player_to(c);
6748 set_position(c);
6751 void player::reset_prev_move()
6753 prev_move.reset();
6756 bool player::asleep() const
6758 return (duration[DUR_SLEEP]);
6761 bool player::cannot_act() const
6763 return (asleep() || cannot_move());
6766 bool player::can_throw_large_rocks() const
6768 return (player_genus(GENPC_OGREISH) || species == SP_TROLL);
6771 bool player::can_smell() const
6773 return (species != SP_MUMMY);
6776 void player::hibernate(int)
6778 ASSERT(!crawl_state.game_is_arena());
6780 if (!can_hibernate())
6782 canned_msg(MSG_YOU_UNAFFECTED);
6783 return;
6786 mpr("You fall asleep.");
6788 stop_delay();
6789 flash_view(DARKGREY);
6791 // Do this *after* redrawing the view, or viewwindow() will no-op.
6792 set_duration(DUR_SLEEP, 3 + random2avg(5, 2));
6795 void player::put_to_sleep(actor*, int power)
6797 ASSERT(!crawl_state.game_is_arena());
6799 if (!can_sleep())
6801 canned_msg(MSG_YOU_UNAFFECTED);
6802 return;
6805 mpr("You fall asleep.");
6807 stop_delay();
6808 flash_view(DARKGREY);
6810 // As above, do this after redraw.
6811 set_duration(DUR_SLEEP, 5 + random2avg(power/10, 5));
6814 void player::awake()
6816 ASSERT(!crawl_state.game_is_arena());
6818 duration[DUR_SLEEP] = 0;
6819 mpr("You wake up.");
6820 flash_view(BLACK);
6823 void player::check_awaken(int disturbance)
6825 if (asleep() && x_chance_in_y(disturbance + 1, 50))
6826 awake();
6829 int player::beam_resists(bolt &beam, int hurted, bool doEffects,
6830 std::string source)
6832 return check_your_resists(hurted, beam.flavour, source, &beam, doEffects);
6835 void player::set_place_info(PlaceInfo place_info)
6837 place_info.assert_validity();
6839 if (place_info.is_global())
6840 global_info = place_info;
6841 else if (place_info.level_type == LEVEL_DUNGEON)
6842 branch_info[place_info.branch] = place_info;
6843 else
6844 non_branch_info[place_info.level_type - 1] = place_info;
6847 std::vector<PlaceInfo> player::get_all_place_info(bool visited_only,
6848 bool dungeon_only) const
6850 std::vector<PlaceInfo> list;
6852 for (int i = 0; i < NUM_BRANCHES; i++)
6854 if (visited_only && branch_info[i].num_visits == 0
6855 || dungeon_only && branch_info[i].level_type != LEVEL_DUNGEON)
6857 continue;
6859 list.push_back(branch_info[i]);
6862 for (int i = 0; i < (NUM_LEVEL_AREA_TYPES - 1); i++)
6864 if (visited_only && non_branch_info[i].num_visits == 0
6865 || dungeon_only && non_branch_info[i].level_type != LEVEL_DUNGEON)
6867 continue;
6869 list.push_back(non_branch_info[i]);
6872 return list;
6875 bool player::do_shaft()
6877 dungeon_feature_type force_stair = DNGN_UNSEEN;
6879 if (!is_valid_shaft_level())
6880 return (false);
6882 // Handle instances of do_shaft() being invoked magically when
6883 // the player isn't standing over a shaft.
6884 if (get_trap_type(pos()) != TRAP_SHAFT)
6886 switch (grd(pos()))
6888 case DNGN_FLOOR:
6889 case DNGN_OPEN_DOOR:
6890 case DNGN_TRAP_MECHANICAL:
6891 case DNGN_TRAP_MAGICAL:
6892 case DNGN_TRAP_NATURAL:
6893 case DNGN_UNDISCOVERED_TRAP:
6894 case DNGN_ENTER_SHOP:
6895 break;
6897 default:
6898 return (false);
6901 handle_items_on_shaft(pos(), false);
6903 if (!ground_level() || total_weight() == 0)
6904 return (true);
6906 force_stair = DNGN_TRAP_NATURAL;
6909 down_stairs(force_stair);
6911 return (true);
6914 bool player::did_escape_death() const
6916 return (escaped_death_cause != NUM_KILLBY);
6919 void player::reset_escaped_death()
6921 escaped_death_cause = NUM_KILLBY;
6922 escaped_death_aux = "";
6925 void player::add_gold(int delta)
6927 set_gold(gold + delta);
6930 void player::del_gold(int delta)
6932 set_gold(gold - delta);
6935 void player::set_gold(int amount)
6937 ASSERT(amount >= 0);
6939 if (amount != gold)
6941 const int old_gold = gold;
6942 gold = amount;
6943 shopping_list.gold_changed(old_gold, gold);
6947 void player::increase_duration(duration_type dur, int turns, int cap,
6948 const char* msg)
6950 if (msg)
6951 mpr(msg);
6952 cap *= BASELINE_DELAY;
6954 you.duration[dur] += turns * BASELINE_DELAY;
6955 if (cap && you.duration[dur] > cap)
6956 you.duration[dur] = cap;
6959 void player::set_duration(duration_type dur, int turns,
6960 int cap, const char * msg)
6962 you.duration[dur] = 0;
6963 increase_duration(dur, turns, cap, msg);
6966 void player::goto_place(const level_id &lid)
6968 level_type = lid.level_type;
6969 if (level_type == LEVEL_DUNGEON)
6971 where_are_you = static_cast<branch_type>(lid.branch);
6972 absdepth0 = absdungeon_depth(lid.branch, lid.depth);