summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/player.h
blob: 2cb2c8c977b4cade65dfde501a3f1fc10fa52925 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
/**
 * @file
 * @brief Player related functions.
**/


#ifndef PLAYER_H
#define PLAYER_H

#include "actor.h"
#include "beam.h"
#include "bitary.h"
#include "quiver.h"
#include "place-info.h"
#include "religion-enum.h"
#include "species.h"

#include <list>
#include <vector>

#ifdef USE_TILE
#include "tiledoll.h"
#endif

#define CONDENSATION_SHIELD_KEY "condensation_shield_pow"
#define ICY_ARMOUR_KEY "ozocubu's_armour_pow"
#define STONESKIN_KEY "stoneskin_pow"
#define TRANSFORM_POW_KEY "transform_pow"
#define BARBS_MOVE_KEY "moved_with_barbs_status"

class targetter;

int check_stealth();

typedef FixedVector<int, NUM_DURATIONS> durations_t;
class player : public actor
{
public:
  // ---------------
  // Permanent data:
  // ---------------
  string your_name;
  species_type species;
  string species_name;
  job_type char_class;
  string class_name;

  // This field is here even in non-WIZARD compiles, since the
  // player might have been playing previously under wiz mode.
  bool          wizard;               // true if player has entered wiz mode.
  time_t        birth_time;           // start time of game


  // ----------------
  // Long-term state:
  // ----------------
  int elapsed_time;        // total amount of elapsed time in the game
  int elapsed_time_at_last_input; // used for elapsed_time delta display

  int hp;
  int hp_max;
  int hp_max_adj_temp;        // temporary max HP loss (rotting)
  int hp_max_adj_perm;        // base HPs from background (and permanent loss)

  int magic_points;
  int max_magic_points;
  int mp_max_adj;             // max MP loss (ability costs, tutorial bonus)

  FixedVector<int8_t, NUM_STATS> stat_loss;
  FixedVector<int8_t, NUM_STATS> base_stats;
  FixedVector<uint8_t, NUM_STATS> stat_zero;

  int hunger;
  int disease;
  hunger_state_t hunger_state;
  uint8_t max_level;
  uint8_t hit_points_regeneration;
  uint8_t magic_points_regeneration;
  unsigned int experience;
  unsigned int total_experience; // Unaffected by draining. Used for skill cost.
  int experience_level;
  int gold;
  int zigs_completed, zig_max;

  FixedVector<int8_t, NUM_EQUIP> equip;
  FixedBitVector<NUM_EQUIP> melded;
  FixedBitVector<NUM_EQUIP> unrand_reacts;

  FixedArray<int, NUM_OBJECT_CLASSES, MAX_SUBTYPES> force_autopickup;

  // PC's symbol (usually @) and colour.
  monster_type symbol;
  transformation_type form;

  FixedVector< item_def, ENDOFPACK > inv;
  FixedBitVector<NUM_RUNE_TYPES> runes;
  int obtainable_runes; // can be != 15 in Sprint

  FixedVector<spell_type, MAX_KNOWN_SPELLS> spells;
  set<spell_type> old_vehumet_gifts, vehumet_gifts;

  uint8_t spell_no;
  game_direction_type char_direction;
  bool opened_zot;
  bool royal_jelly_dead;
  bool transform_uncancellable;
  bool fishtail; // Merfolk fishtail transformation

  unsigned short pet_target;

  durations_t duration;
  int rotting;
  int berserk_penalty;                // penalty for moving while berserk

  FixedVector<int, NUM_ATTRIBUTES> attribute;
  FixedVector<uint8_t, NUM_AMMO> quiver; // default items for quiver
  FixedVector<int, NUM_TIMERS> last_timer_effect;
  FixedVector<int, NUM_TIMERS> next_timer_effect;

  undead_state_type is_undead;

  bool dead; // ... but pending revival
  int lives;
  int deaths;
#if TAG_MAJOR_VERSION == 34
  float temperature; // For lava orcs.
  float temperature_last;
#endif

  FixedVector<uint8_t, NUM_SKILLS> skills; ///< skill level
  FixedVector<int8_t, NUM_SKILLS>  train;  ///< 0: disabled, 1: normal, 2: focus
  FixedVector<int8_t, NUM_SKILLS>  train_alt;      ///< config of the other mode
  FixedVector<unsigned int, NUM_SKILLS>  training; ///< percentage of XP used
  FixedBitVector<NUM_SKILLS> can_train; ///< Is training this skill allowed?
  FixedVector<unsigned int, NUM_SKILLS> skill_points;
  FixedVector<unsigned int, NUM_SKILLS> ct_skill_points;///<track skill points
                                                    ///<gained by crosstraining
  FixedVector<uint8_t, NUM_SKILLS>  skill_order;

  bool auto_training;
  list<skill_type> exercises;     ///< recent practise events
  list<skill_type> exercises_all; ///< also include events for disabled skills
  set<skill_type> stop_train;     ///< need to check if we can still train
  set<skill_type> start_train;    ///< we can resume training

  // Skill menu states
  skill_menu_state skill_menu_do;
  skill_menu_state skill_menu_view;

  //Ashenzari transfer knowledge
  skill_type    transfer_from_skill;
  skill_type    transfer_to_skill;
  unsigned int  transfer_skill_points;
  unsigned int  transfer_total_skill_points;

  int  skill_cost_level;
  int  exp_available;
  int  zot_points; // ZotDef currency

  int exp_docked, exp_docked_total; // Ashenzari's wrath

  FixedArray<uint8_t, 6, MAX_SUBTYPES> item_description;
  FixedVector<unique_item_status_type, MAX_UNRANDARTS> unique_items;
  FixedBitVector<NUM_MONSTERS> unique_creatures;

  // NOTE: The kills member is a pointer to a KillMaster object,
  // rather than the object itself, so that we can get away with
  // just a forward declare of the KillMaster class, rather than
  // having to #include kills.h and thus make every single .cc file
  // dependent on kills.h.  Having a pointer means that we have
  // to do our own implementations of copying the player object,
  // since the default implementations will lead to the kills member
  // pointing to freed memory, or worse yet lead to the same piece of
  // memory being freed twice.
  KillMaster* kills;

  branch_type where_are_you;
  int depth;

  FixedVector<uint8_t, 30> branch_stairs;

  god_type religion;
  string god_name;
  string jiyva_second_name;       // Random second name of Jiyva
  uint8_t piety;
  uint8_t piety_hysteresis;       // amount of stored-up docking
  uint8_t gift_timeout;
  FixedVector<uint8_t, NUM_GODS>  penance;
  FixedVector<uint8_t, NUM_GODS>  worshipped;
  FixedVector<short,   NUM_GODS>  num_current_gifts;
  FixedVector<short,   NUM_GODS>  num_total_gifts;
  FixedBitVector<      NUM_GODS>  one_time_ability_used;
  FixedVector<uint8_t, NUM_GODS>  piety_max;

  FixedVector<uint8_t, NUM_MUTATIONS> mutation;
  FixedVector<uint8_t, NUM_MUTATIONS> innate_mutation;
  FixedVector<uint8_t, NUM_MUTATIONS> temp_mutation;

  struct demon_trait
  {
      int           level_gained;
      mutation_type mutation;
  };

  vector<demon_trait> demonic_traits;

  int magic_contamination;

  FixedBitVector<NUM_FIXED_BOOKS> had_book;
  FixedBitVector<NUM_SPELLS>      seen_spell;
  FixedVector<uint32_t, NUM_WEAPONS> seen_weapon;
  FixedVector<uint32_t, NUM_ARMOURS> seen_armour;
  FixedBitVector<NUM_MISCELLANY>     seen_misc;
  uint8_t                            octopus_king_rings;

  uint8_t normal_vision;        // how far the species gets to see
  uint8_t current_vision;       // current sight radius (cells)

  int           real_time;            // real time played (in seconds)
  int           num_turns;            // number of turns taken
  int           exploration;          // levels explored (16.16 bit real number)

  int           last_view_update;     // what turn was the view last updated?

  // Warning: these two are quite different.
  //
  // The spell table is an index to a specific spell slot (you.spells).
  // The ability table lists the ability (ABIL_*) which prefers that letter.
  //
  // In other words, the spell table contains hard links and the ability
  // table contains soft links.
  FixedVector<int, 52>           spell_letter_table;   // ref to spell by slot
  FixedVector<ability_type, 52>  ability_letter_table; // ref to abil by enum

  // Maps without allow_dup that have been already used.
  set<string> uniq_map_tags;
  set<string> uniq_map_names;
  // All maps, by level.
  map<level_id, vector<string> > vault_list;

  PlaceInfo global_info;
  player_quiver* m_quiver;

  // monsters mesmerising player; should be protected, but needs to be saved
  // and restored.
  vector<int> beholders;

  // monsters causing fear to the player; see above
  vector<int> fearmongers;

  // Delayed level actions.  This array is never trimmed, as usually D:1 won't
  // be loaded again until the very end.
  vector<daction_type> dactions;

  // Path back from portal levels.
  vector<level_pos> level_stack;

  // The player's knowledge about item types.
  id_arr type_ids;
  // Additional information, about tried unidentified items.
  // (e.g. name of item, for scrolls of RC, ID, EA)
  CrawlHashTable type_id_props;

  // The version the save was last played with.
  string prev_save_version;

  // The type of a zotdef wave, if any.
  string zotdef_wave_name;
  // The biggest assigned monster id so far.
  mid_t last_mid;

  // Count of various types of actions made.
  map<pair<caction_type, int>, FixedVector<int, 27> > action_count;

  // Which branches have been noted to have been left during this game.
  FixedBitVector<NUM_BRANCHES> branches_left;

  // For now, only control the speed of abyss morphing.
  int abyss_speed;

  // Prompts or actions the player must answer before continuing.
  // A stack -- back() is the first to go.
  vector<pair<uncancellable_type, int> > uncancel;

  // A list of allies awaiting an active recall
  vector<mid_t> recall_list;

  // Hash seeds for deterministic stuff.
  FixedVector<uint32_t, NUM_SEEDS> game_seeds;

  // -------------------
  // Non-saved UI state:
  // -------------------
  unsigned short prev_targ;
  coord_def      prev_grd_targ;
  coord_def      prev_move;

  // Coordinates of last travel target; note that this is never used by
  // travel itself, only by the level-map to remember the last travel target.
  short travel_x, travel_y;
  level_id travel_z;

  runrest running;                    // Nonzero if running/traveling.
  bool travel_ally_pace;

  bool received_weapon_warning;
  bool received_noskill_warning;
  bool wizmode_teleported_into_rock;

  delay_queue_type delay_queue;       // pending actions

  time_t last_keypress_time;
  bool xray_vision;
  int8_t bondage_level;  // how much an Ash worshipper is into bondage
  int8_t bondage[NUM_ET];
  map<skill_type, int8_t> skill_boost; // Skill bonuses.
  bool digging;

  // The last spell cast by the player.
  spell_type last_cast_spell;
  map<int,int> last_pickup;


  // ---------------------------
  // Volatile (same-turn) state:
  // ---------------------------
  bool turn_is_over; // flag signaling that player has performed a timed action

  // If true, player is headed to the Abyss.
  bool banished;
  string banished_by;

  bool wield_change;          // redraw weapon
  bool redraw_quiver;         // redraw quiver
  uint64_t redraw_status_flags;

  bool redraw_title;
  bool redraw_hit_points;
  bool redraw_magic_points;
#if TAG_MAJOR_VERSION == 34
  bool redraw_temperature;
#endif
  FixedVector<bool, NUM_STATS> redraw_stats;
  bool redraw_experience;
  bool redraw_armour_class;
  bool redraw_evasion;

  colour_t flash_colour;
  targetter *flash_where;

  int time_taken;

  int old_hunger;            // used for hunger delta-meter (see output.cc)

  // Set when the character is going to a new level, to guard against levgen
  // failures
  dungeon_feature_type transit_stair;
  bool entering_level;

  int    escaped_death_cause;
  string escaped_death_aux;

  int turn_damage;   // cumulative damage per turn
  int damage_source; // death source of last damage done to player
  int source_damage; // cumulative damage for you.damage_source

  // When other levels are loaded (e.g. viewing), is the player on this level?
  bool on_current_level;

  // Did you spent this turn walking (/flying)?
  // 0 = no, 1 = cardinal move, 2 = diagonal move
  int walking;

  // View code clears and needs new data in places where we can't announce the
  // portal right away; delay the announcements then.
  int seen_portals;
  // Same with invisible monsters, for ring auto-id.
  bool seen_invis;

  // Number of viewport refreshes.
  unsigned int frame_no;


  // ---------------------
  // The save file itself.
  // ---------------------
  package *save;

protected:
    FixedVector<PlaceInfo, NUM_BRANCHES> branch_info;

public:
    player();
    player(const player &other);
    ~player();

    void copy_from(const player &other);

    void init();
    void init_skills();

    // Set player position without updating view geometry.
    void set_position(const coord_def &c);
    // Low-level move the player. Use this instead of changing pos directly.
    void moveto(const coord_def &c, bool clear_net = true);
    bool move_to_pos(const coord_def &c, bool clear_net = true);
    // Move the player during an abyss shift.
    void shiftto(const coord_def &c);
    bool blink_to(const coord_def& c, bool quiet = false);

    void reset_prev_move();

    int stat(stat_type stat, bool nonneg = true) const;
    int strength(bool nonneg = true) const;
    int intel(bool nonneg = true) const;
    int dex(bool nonneg = true) const;
    int max_stat(stat_type stat) const;
    int max_strength() const;
    int max_intel() const;
    int max_dex() const;

    bool in_water() const;
    bool in_lava() const;
    bool in_liquid() const;
    bool can_swim(bool permanently = false) const;
    int visible_igrd(const coord_def&) const;
    bool can_cling_to_walls() const;
    bool is_banished() const;
    bool is_web_immune() const;
    bool cannot_speak() const;
    bool invisible() const;
    bool can_see_invisible() const;
    bool can_see_invisible(bool unid, bool items = true) const;
    bool visible_to(const actor *looker) const;
    bool can_see(const actor* a) const;
    bool nightvision() const;
    reach_type reach_range() const;
    bool see_cell(const coord_def& p) const;

    // Is c in view but behind a transparent wall?
    bool trans_wall_blocking(const coord_def &c) const;

    bool is_icy() const;
    bool is_fiery() const;
    bool is_skeletal() const;

    bool tengu_flight() const;

    int spell_hp_cost() const;
    bool spellcasting_unholy() const;

    // Dealing with beholders. Implemented in behold.cc.
    void add_beholder(const monster* mon, bool axe = false);
    bool beheld() const;
    bool beheld_by(const monster* mon) const;
    monster* get_beholder(const coord_def &pos) const;
    monster* get_any_beholder() const;
    void remove_beholder(const monster* mon);
    void clear_beholders();
    void beholders_check_noise(int loudness, bool axe = false);
    void update_beholders();
    void update_beholder(const monster* mon);
    bool possible_beholder(const monster* mon) const;

    // Dealing with fearmongers. Implemented in fearmonger.cc.
    bool add_fearmonger(const monster* mon);
    bool afraid() const;
    bool afraid_of(const monster* mon) const;
    monster* get_fearmonger(const coord_def &pos) const;
    monster* get_any_fearmonger() const;
    void remove_fearmonger(const monster* mon);
    void clear_fearmongers();
    void fearmongers_check_noise(int loudness, bool axe = false);
    void update_fearmongers();
    void update_fearmonger(const monster* mon);

    bool made_nervous_by(const coord_def &pos);

    kill_category kill_alignment() const;

    bool has_spell(spell_type spell) const;

    size_type transform_size(transformation_type tform,
                             int psize = PSIZE_TORSO) const;
    string shout_verb() const;
    int shout_volume() const;

    item_def *slot_item(equipment_type eq, bool include_melded=false) const;

    // actor
    int mindex() const;
    int get_hit_dice() const;
    int get_experience_level() const;
    actor_type atype() const { return ACT_PLAYER; }
    monster* as_monster() { return NULL; }
    player* as_player() { return this; }
    const monster* as_monster() const { return NULL; }
    const player* as_player() const { return this; }

    god_type  deity() const;
    bool      alive() const;
    bool      is_summoned(int* duration = NULL, int* summon_type = NULL) const;
    bool      is_perm_summoned() const { return false; };

    bool        swimming() const;
    bool        submerged() const;
    bool        floundering() const;
    bool        extra_balanced() const;
    bool        shove(const char* feat_name = "");
    bool        can_pass_through_feat(dungeon_feature_type grid) const;
    bool        is_habitable_feat(dungeon_feature_type actual_grid) const;
    size_type   body_size(size_part_type psize = PSIZE_TORSO, bool base = false) const;
    int         body_weight(bool base = false) const;
    brand_type  damage_brand(int which_attack = -1);
    int         damage_type(int which_attack = -1);
    random_var  attack_delay(const item_def *weapon, const
                             item_def *projectile = NULL,
                             bool random = true, bool scaled = true) const;
    int         constriction_damage() const;

    int       has_claws(bool allow_tran = true) const;
    bool      has_usable_claws(bool allow_tran = true) const;
    int       has_talons(bool allow_tran = true) const;
    bool      has_usable_talons(bool allow_tran = true) const;
    int       has_hooves(bool allow_tran = true) const;
    bool      has_usable_hooves(bool allow_tran = true) const;
    int       has_fangs(bool allow_tran = true) const;
    int       has_usable_fangs(bool allow_tran = true) const;
    int       has_tail(bool allow_tran = true) const;
    int       has_usable_tail(bool allow_tran = true) const;
    bool      has_usable_offhand() const;
    int       has_pseudopods(bool allow_tran = true) const;
    int       has_usable_pseudopods(bool allow_tran = true) const;
    int       has_tentacles(bool allow_tran = true) const;
    int       has_usable_tentacles(bool allow_tran = true) const;

    int wearing(equipment_type slot, int sub_type, bool calc_unid = true) const;
    int wearing_ego(equipment_type slot, int type, bool calc_unid = true) const;
    int scan_artefacts(artefact_prop_type which_property,
                       bool calc_unid = true) const;

    item_def *weapon(int which_attack = -1) const;
    item_def *shield() const;

    hands_reqd_type hands_reqd(const item_def &item) const;

    bool      can_wield(const item_def &item,
                        bool ignore_curse = false,
                        bool ignore_brand = false,
                        bool ignore_shield = false,
                        bool ignore_transform = false) const;
    bool      could_wield(const item_def &item,
                          bool ignore_brand = false,
                          bool ignore_transform = false,
                          bool quiet = true) const;

    string name(description_level_type type, bool force_visible = false,
                bool force_article = false) const;
    string pronoun(pronoun_type pro, bool force_visible = false) const;
    string conj_verb(const string &verb) const;
    string hand_name(bool plural, bool *can_plural = NULL) const;
    string foot_name(bool plural, bool *can_plural = NULL) const;
    string arm_name(bool plural, bool *can_plural = NULL) const;
    string unarmed_attack_name() const;

    bool fumbles_attack(bool verbose = true);
    bool cannot_fight() const;
    bool fights_well_unarmed(int heavy_armour_penalty);

    void attacking(actor *other, bool ranged = false);
    bool can_go_berserk() const;
    bool can_go_berserk(bool intentional, bool potion = false,
                        bool quiet = false) const;
    bool can_jump() const;
    bool can_jump(bool quiet) const;
    bool go_berserk(bool intentional, bool potion = false);
    bool berserk() const;
    bool has_lifeforce() const;
    bool can_mutate() const;
    bool can_safely_mutate() const;
    bool is_lifeless_undead() const;
    bool can_polymorph() const;
    bool can_bleed(bool allow_tran = true) const;
    bool is_stationary() const;
    bool malmutate(const string &reason);
    bool polymorph(int pow);
    void backlight();
    void banish(actor *agent, const string &who = "");
    void blink(bool allow_partial_control = true);
    void teleport(bool right_now = false,
                  bool wizard_tele = false);
    void drain_stat(stat_type stat, int amount, actor* attacker);

    void expose_to_element(beam_type element, int strength = 0,
                           bool slow_cold_blood = true);
    void god_conduct(conduct_type thing_done, int level);

    void make_hungry(int nutrition, bool silent = true);
    bool poison(actor *agent, int amount = 1, bool force = false);
    bool sicken(int amount, bool allow_hint = true, bool quiet = false);
    void paralyse(actor *, int str, string source = "");
    void petrify(actor *, bool force = false);
    bool fully_petrify(actor *foe, bool quiet = false);
    void slow_down(actor *, int str);
    void confuse(actor *, int strength);
    void weaken(actor *attacker, int pow);
    bool heal(int amount, bool max_too = false);
    bool drain_exp(actor *, bool quiet = false, int pow = 3);
    bool rot(actor *, int amount, int immediate = 0, bool quiet = false);
    void sentinel_mark(bool trap = false);
    int hurt(const actor *attacker, int amount,
             beam_type flavour = BEAM_MISSILE,
             bool cleanup_dead = true,
             bool attacker_effects = true);

    bool wont_attack() const { return true; };
    mon_attitude_type temp_attitude() const { return ATT_FRIENDLY; };

    monster_type mons_species(bool zombie_base = false) const;

    mon_holy_type holiness() const;
    bool undead_or_demonic() const;
    bool holy_wrath_susceptible() const;
    bool is_holy(bool spells = true) const;
    bool is_unholy(bool spells = true) const;
    bool is_evil(bool spells = true) const;
    int how_chaotic(bool check_spells_god) const;
    bool is_artificial() const;
    bool is_unbreathing() const;
    bool is_insubstantial() const;
    int res_acid(bool calc_unid = true) const;
    int res_fire() const;
    int res_steam() const;
    int res_cold() const;
    int res_elec() const;
    int res_poison(bool temp = true) const;
    int res_rotting(bool temp = true) const;
    int res_asphyx() const;
    int res_water_drowning() const;
    int res_sticky_flame() const;
    int res_holy_energy(const actor *) const;
    int res_negative_energy(bool intrinsic_only = false) const;
    int res_torment() const;
    int res_wind() const;
    int res_petrify(bool temp = true) const;
    int res_constrict() const;
    int res_magic() const;
    bool no_tele(bool calc_unid = true, bool permit_id = true,
                 bool blink = false) const;

    bool gourmand(bool calc_unid = true, bool items = true) const;
    bool res_corr(bool calc_unid = true, bool items = true) const;
    bool clarity(bool calc_unid = true, bool items = true) const;
    bool stasis(bool calc_unid = true, bool items = true) const;

    flight_type flight_mode() const;
    bool cancellable_flight() const;
    bool permanent_flight() const;
    bool racial_permanent_flight() const;

    bool paralysed() const;
    bool cannot_move() const;
    bool cannot_act() const;
    bool confused() const;
    bool caught() const;
    bool backlit(bool self_halo = true) const;
    bool umbra() const;
    int halo_radius2() const;
    int silence_radius2() const;
    int liquefying_radius2() const;
    int umbra_radius2() const;
#if TAG_MAJOR_VERSION == 34
    int heat_radius2() const;
#endif
    bool glows_naturally() const;
    bool petrifying() const;
    bool petrified() const;
    bool liquefied_ground() const;
    bool incapacitated() const
    {
        return actor::incapacitated() || stat_zero[STAT_DEX];
    }

    bool asleep() const;
    void put_to_sleep(actor *, int power = 0, bool hibernate = false);
    void awake();
    void check_awaken(int disturbance);
    int beam_resists(bolt &beam, int hurted, bool doEffects, string source);

    bool can_throw_large_rocks() const;
    bool can_smell() const;

    int armour_class() const;
    int gdr_perc() const;
    int melee_evasion(const actor *attacker,
                      ev_ignore_type evit = EV_IGNORE_NONE) const;

    int stat_hp() const     { return hp; }
    int stat_maxhp() const  { return hp_max; }
    int stealth() const     { return check_stealth(); }

    bool shielded() const;
    int shield_bonus() const;
    int shield_block_penalty() const;
    int shield_bypass_ability(int tohit) const;
    void shield_block_succeeded(actor *foe);
    int missile_deflection() const;
    void ablate_deflection();

    // Combat-related adjusted penalty calculation methods
    int unadjusted_body_armour_penalty() const;
    int adjusted_body_armour_penalty(int scale = 1,
                                     bool use_size = false) const;
    int adjusted_shield_penalty(int scale = 1) const;
    int armour_tohit_penalty(bool random_factor, int scale = 1) const;
    int shield_tohit_penalty(bool random_factor, int scale = 1) const;

    bool wearing_light_armour(bool with_skill = false) const;
    int  skill(skill_type skill, int scale =1,
               bool real = false, bool drained = true) const;

    bool do_shaft();

    bool can_do_shaft_ability(bool quiet = false) const;
    bool do_shaft_ability();

    bool can_device_heal();

    void apply_location_effects(const coord_def &oldpos,
                                killer_type killer = KILL_NONE,
                                int killernum = -1);

    ////////////////////////////////////////////////////////////////

    PlaceInfo& get_place_info() const ; // Current place info
    PlaceInfo& get_place_info(branch_type branch) const;
    void clear_place_info();

    void goto_place(const level_id &level);

    void set_place_info(PlaceInfo info);
    // Returns copies of the PlaceInfo; modifying the vector won't
    // modify the player object.
    vector<PlaceInfo> get_all_place_info(bool visited_only = false,
                                         bool dungeon_only = false) const;

    bool did_escape_death() const;
    void reset_escaped_death();

    void add_gold(int delta);
    void del_gold(int delta);
    void set_gold(int amount);

    void increase_duration(duration_type dur, int turns, int cap = 0,
                           const char* msg = NULL);
    void set_duration(duration_type dur, int turns, int cap = 0,
                      const char *msg = NULL);

    bool attempt_escape(int attempts = 1);
    int usable_tentacles() const;
    bool has_usable_tentacle() const;

    bool form_uses_xl() const;

    bool clear_far_engulf();

protected:
    void _removed_beholder(bool quiet = false);
    bool _possible_beholder(const monster* mon) const;

    void _removed_fearmonger(bool quiet = false);
    bool _possible_fearmonger(const monster* mon) const;
};

#ifdef DEBUG_GLOBALS
#define you (*real_you)
#endif
extern player you;

struct player_save_info
{
    string name;
    unsigned int experience;
    int experience_level;
    bool wizard;
    species_type species;
    string species_name;
    string class_name;
    god_type religion;
    string god_name;
    string jiyva_second_name;
    game_type saved_game_type;

#ifdef USE_TILE
    dolls_data doll;
#endif

    bool save_loadable;
    string filename;

    player_save_info& operator=(const player& rhs);
    bool operator<(const player_save_info& rhs) const;
    string short_desc() const;
};

class monster;
struct item_def;

// Helper. Use move_player_to_grid or player::apply_location_effects instead.
void moveto_location_effects(dungeon_feature_type old_feat,
                             bool stepped=false, const coord_def& old_pos=coord_def());

bool check_moveto(const coord_def& p, const string &move_verb = "step",
                  const string &msg = "");
bool check_moveto_terrain(const coord_def& p, const string &move_verb,
                          const string &msg = "", bool *prompted = nullptr);
bool check_moveto_cloud(const coord_def& p, const string &move_verb = "step",
                        bool *prompted = nullptr);
bool check_moveto_exclusion(const coord_def& p,
                            const string &move_verb = "step",
                            bool *prompted = nullptr);
bool check_moveto_trap(const coord_def& p, const string &move_verb = "step",
        bool *prompted = nullptr);

bool swap_check(monster* mons, coord_def &loc, bool quiet = false);

void move_player_to_grid(const coord_def& p, bool stepped);

bool is_map_persistent();
bool player_in_mappable_area();
bool player_in_connected_branch();
bool player_in_hell();

static inline bool player_in_branch(int branch)
{
    return you.where_are_you == branch;
};

bool berserk_check_wielded_weapon();
bool player_equip_unrand(int unrand_index);
bool player_can_hit_monster(const monster* mon);
bool player_can_hear(const coord_def& p, int hear_distance = 999);

bool player_is_shapechanged();

bool is_effectively_light_armour(const item_def *item);
bool player_effectively_in_light_armour();

static inline int player_under_penance(god_type god = you.religion)
{
    return you.penance[god];
}

int player_energy();

int player_raw_body_armour_evasion_penalty();
int player_adjusted_shield_evasion_penalty(int scale);
int player_armour_shield_spell_penalty();
int player_evasion(ev_ignore_type evit = EV_IGNORE_NONE);

int player_movement_speed();

int player_hunger_rate(bool temp = true);

int calc_hunger(int food_cost);

int player_icemail_armour_class();

bool player_stoneskin();

int player_wizardry();

int player_prot_life(bool calc_unid = true, bool temp = true,
                     bool items = true);

int player_regen();

int player_res_cold(bool calc_unid = true, bool temp = true,
                    bool items = true);
int player_res_acid(bool calc_unid = true, bool items = true);

int player_res_torment(bool calc_unid = true, bool temp = true);
int player_kiku_res_torment();

int player_likes_chunks(bool permanently = false);
bool player_likes_water(bool permanently = false);
bool player_likes_lava(bool permanently = false);

int player_mutation_level(mutation_type mut, bool temp = true);

int player_res_electricity(bool calc_unid = true, bool temp = true,
                           bool items = true);

int player_res_fire(bool calc_unid = true, bool temp = true,
                    bool items = true);
int player_res_sticky_flame(bool calc_unid = true, bool temp = true,
                            bool items = true);
int player_res_steam(bool calc_unid = true, bool temp = true,
                     bool items = true);

int player_res_poison(bool calc_unid = true, bool temp = true,
                      bool items = true);
int player_res_magic(bool calc_unid = true, bool temp = true);

bool player_control_teleport(bool temp = true);

int player_shield_class();
int player_displayed_shield_class();

int player_spec_air();
int player_spec_cold();
int player_spec_conj();
int player_spec_death();
int player_spec_earth();
int player_spec_fire();
int player_spec_hex();
int player_spec_charm();
int player_spec_poison();
int player_spec_summ();

int player_speed();

int player_spell_levels();

bool player_sust_abil(bool calc_unid = true);

int player_teleport(bool calc_unid = true);

int player_monster_detect_radius();

int slaying_bonus(bool ranged = false);

unsigned int exp_needed(int lev, int exp_apt = -99);
bool will_gain_life(int lev);

int get_expiration_threshold(duration_type dur);
bool dur_expiring(duration_type dur);
void display_char_status();

void forget_map(bool rot = false);

int get_exp_progress();
void gain_exp(unsigned int exp_gained, unsigned int* actual_gain = NULL);

bool player_can_open_doors();

void level_change(int source = NON_MONSTER, const char *aux = NULL,
                  bool skip_attribute_increase = false);
void adjust_level(int diff, bool just_xp = false);

bool player_genus(genus_type which_genus,
                   species_type species = SP_UNKNOWN);
bool is_player_same_genus(const monster_type mon, bool = false);
monster_type player_mons(bool transform = true);
void update_player_symbol();
void update_vision_range();

bool you_can_wear(int eq, bool special_armour = false);
bool player_has_feet(bool temp = true);
bool player_wearing_slot(int eq);
bool you_tran_can_wear(const item_def &item);
bool you_tran_can_wear(int eq, bool check_mutation = false);

bool enough_hp(int minimum, bool suppress_msg, bool abort_macros = true);
bool enough_mp(int minimum, bool suppress_msg, bool abort_macros = true);
bool enough_zp(int minimum, bool suppress_msg);

void calc_hp();
void calc_mp();

void dec_hp(int hp_loss, bool fatal, const char *aux = NULL);
void dec_mp(int mp_loss, bool silent = false);
void drain_mp(int mp_loss);

void inc_mp(int mp_gain, bool silent = false);
void inc_hp(int hp_gain);
void flush_mp();

void rot_hp(int hp_loss);
void unrot_hp(int hp_recovered);
int player_rotted();
void rot_mp(int mp_loss);

void inc_max_hp(int hp_gain);
void dec_max_hp(int hp_loss);

void deflate_hp(int new_level, bool floor);
void set_hp(int new_amount);

int get_real_hp(bool trans, bool rotted = false);
int get_real_mp(bool include_items);

int get_contamination_level();
string describe_contamination(int level);

void set_mp(int new_amount);

void contaminate_player(int change, bool controlled = false, bool msg = true);

bool confuse_player(int amount, bool quiet = false);

bool curare_hits_player(int death_source, int levels, string name,
                        string source_name);
bool poison_player(int amount, string source, string source_aux = "",
                   bool force = false);
void paralyse_player(string source, int amount = 0);
void handle_player_poison(int delay);
void reduce_player_poison(int amount);
int get_player_poisoning();
bool poison_is_lethal();
int poison_survival();

bool miasma_player(string source, string source_aux = "");

bool napalm_player(int amount, string source, string source_aux = "");
void dec_napalm_player(int delay);

bool slow_player(int turns);
void dec_slow_player(int delay);
void dec_exhaust_player(int delay);

bool haste_player(int turns, bool rageext = false);
void dec_haste_player(int delay);
void dec_elixir_player(int delay);
bool flight_allowed(bool quiet = false);
void fly_player(int pow, bool already_flying = false);
void float_player();
bool land_player(bool quiet = false);
void player_open_door(coord_def doorpos, bool check_confused);

void dec_disease_player(int delay);

void dec_color_smoke_trail();

void handle_player_drowning(int delay);

bool player_weapon_wielded();

// Determines if the given grid is dangerous for the player to enter.
bool is_feat_dangerous(dungeon_feature_type feat, bool permanently = false,
                       bool ignore_flight = false);

void run_macro(const char *macroname = NULL);

int count_worn_ego(int which_ego);
bool need_expiration_warning(duration_type dur, dungeon_feature_type feat);
bool need_expiration_warning(dungeon_feature_type feat);
bool need_expiration_warning(duration_type dur, coord_def p = you.pos());
bool need_expiration_warning(coord_def p = you.pos());

void count_action(caction_type type, int subtype = 0);
bool player_has_orb();

#if TAG_MAJOR_VERSION == 34
enum temperature_level
{
    TEMP_MIN = 1, // Minimum (and starting) temperature. Not any warmer than bare rock.
    TEMP_COLD = 3,
    TEMP_COOL = 5,
    TEMP_ROOM = 7,
    TEMP_WARM = 9, // Warmer than most creatures.
    TEMP_HOT = 11,
    TEMP_FIRE = 13, // Hot enough to ignite paper around you.
    TEMP_MAX = 15, // Maximum temperature. As hot as lava!
};

enum temperature_effect
{
    LORC_LAVA_BOOST,
    LORC_FIRE_BOOST,
    LORC_STONESKIN,
    LORC_COLD_VULN,
    LORC_PASSIVE_HEAT,
    LORC_HEAT_AURA,
    LORC_NO_SCROLLS,
    LORC_FIRE_RES_I,
    LORC_FIRE_RES_II,
    LORC_FIRE_RES_III,
};

int temperature();
int temperature_last();
void temperature_check();
void temperature_increment(float degree);
void temperature_decrement(float degree);
void temperature_changed(float change);
void temperature_decay();
bool temperature_tier(int which);
bool temperature_effect(int which);
int temperature_colour(int temp);
string temperature_string(int temp);
string temperature_text(int temp);
#endif

#endif