summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monster.h
blob: 1da2bd21b3fb8c80111034e089833fe77ce18e5d (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
#ifndef MONSTER_H
#define MONSTER_H

#include "actor.h"

const int KRAKEN_TENTACLE_RANGE = 3;
#define TIDE_CALL_TURN "tide-call-turn"

class mon_enchant
{
public:
    enchant_type  ench;
    int           degree;
    int           duration, maxduration;
    kill_category who;      // Who set this enchantment?

public:
    mon_enchant(enchant_type e = ENCH_NONE, int deg = 0,
                kill_category whose = KC_OTHER,
                int dur = 0);

    killer_type killer() const;
    int kill_agent() const;

    operator std::string () const;
    const char *kill_category_desc(kill_category) const;
    void merge_killer(kill_category who);
    void cap_degree();

    void set_duration(const monsters *mons, const mon_enchant *exist);

    bool operator < (const mon_enchant &other) const
    {
        return (ench < other.ench);
    }

    bool operator == (const mon_enchant &other) const
    {
        // NOTE: This does *not* check who/degree.
        return (ench == other.ench);
    }

    mon_enchant &operator += (const mon_enchant &other);
    mon_enchant operator + (const mon_enchant &other) const;

private:
    int modded_speed(const monsters *mons, int hdplus) const;
    int calc_duration(const monsters *mons, const mon_enchant *added) const;
};

typedef std::map<enchant_type, mon_enchant> mon_enchant_list;

struct monsterentry;

class monsters : public actor
{
public:
    monsters();
    monsters(const monsters &other);
    ~monsters();

    monsters &operator = (const monsters &other);
    void reset();

public:
    // Possibly some of these should be moved into the hash table
    std::string mname;

    monster_type type;
    int hit_points;
    int max_hit_points;
    int hit_dice;
    int ac;
    int ev;
    int speed;
    int speed_increment;

    coord_def target;
    coord_def patrol_point;
    mutable montravel_target_type travel_target;
    std::vector<coord_def> travel_path;
    FixedVector<short, NUM_MONSTER_SLOTS> inv;
    monster_spells spells;
    mon_attitude_type attitude;
    beh_type behaviour;
    unsigned short foe;
    char ench_countdown;
    mon_enchant_list enchantments;
    unsigned long flags;               // bitfield of boolean flags

    unsigned long experience;
    monster_type  base_monster;        // zombie base monster, draconian colour
    unsigned int  number;              // #heads (hydra), etc.
    int           colour;

    int foe_memory;                    // how long to 'remember' foe x,y
                                       // once they go out of sight.

    int shield_blocks;                 // Count of shield blocks this round.

    god_type god;                      // What god the monster worships, if
                                       // any.

    std::auto_ptr<ghost_demon> ghost;  // Ghost information.

    std::string seen_context;          // Non-standard context for
                                       // AI_SEE_MONSTER

    CrawlHashTable props;

public:
    mon_attitude_type temp_attitude() const;

    // Returns true if the monster is named with a proper name, or is
    // a player ghost.
    bool is_named() const;

    // Does this monster have a base name, i.e. is base_name() != name().
    // See base_name() for details.
    bool has_base_name() const;

    const monsterentry *find_monsterentry() const;
    monster_type get_mislead_type() const;

    void init_experience();

    void mark_summoned(int longevity, bool mark_items_summoned,
                       int summon_type = 0);
    bool is_summoned(int* duration = NULL, int* summon_type = NULL) const;
    bool has_action_energy() const;
    void check_redraw(const coord_def &oldpos) const;
    void apply_location_effects(const coord_def &oldpos,
                                killer_type killer = KILL_NONE,
                                int killernum = -1);

    void moveto(const coord_def& c);
    bool move_to_pos(const coord_def &newpos);
    bool blink_to(const coord_def& c, bool quiet = false);

    kill_category kill_alignment() const;

    int  foe_distance() const;
    bool needs_berserk(bool check_spells = true) const;

    // Has a hydra-like variable number of attacks based on mons->number.
    bool has_hydra_multi_attack() const;
    bool has_multitargeting() const;

    // Has the 'spellcaster' flag (may not actually have any spells).
    bool can_use_spells() const;

    // Has the 'priest' flag.
    bool is_priest() const;

    // Is an actual wizard-type spellcaster (it can be silenced, Trog
    // will dislike it, etc.).
    bool is_actual_spellcaster() const;

    // Has ENCH_SHAPESHIFTER or ENCH_GLOWING_SHAPESHIFTER.
    bool is_shapeshifter() const;

    bool has_ench(enchant_type ench) const;
    bool has_ench(enchant_type ench, enchant_type ench2) const;
    mon_enchant get_ench(enchant_type ench,
                         enchant_type ench2 = ENCH_NONE) const;
    bool add_ench(const mon_enchant &);
    void update_ench(const mon_enchant &);
    bool del_ench(enchant_type ench, bool quiet = false, bool effect = true);
    bool lose_ench_duration(const mon_enchant &e, int levels);
    bool lose_ench_levels(const mon_enchant &e, int lev);
    void lose_energy(energy_use_type et, int div = 1, int mult = 1);

    void scale_hp(int num, int den);
    bool gain_exp(int exp);

    void react_to_damage(int damage, beam_type flavour, kill_category whose);

    void forget_random_spell();

    void add_enchantment_effect(const mon_enchant &me, bool quiet = false);
    void remove_enchantment_effect(const mon_enchant &me, bool quiet = false);
    void apply_enchantments();
    void apply_enchantment(const mon_enchant &me);

    bool can_drink_potion(potion_type ptype) const;
    bool should_drink_potion(potion_type ptype) const;
    item_type_id_state_type drink_potion_effect(potion_type ptype);

    void timeout_enchantments(int levels);

    bool is_travelling() const;
    bool is_patrolling() const;
    bool needs_transit() const;
    void set_transit(const level_id &destination);
    bool find_place_to_live(bool near_player = false);
    bool find_home_near_place(const coord_def &c);
    bool find_home_near_player();
    bool find_home_around(const coord_def &c, int radius);
    bool find_home_anywhere();

    void set_ghost(const ghost_demon &ghost, bool has_name = true);
    void ghost_init();
    void pandemon_init();
    void dancing_weapon_init();
    void uglything_init(bool only_mutate = false);
    void uglything_mutate(unsigned char force_colour = BLACK);
    void uglything_upgrade();
    void destroy_inventory();
    void load_spells(mon_spellbook_type spellbook);

    actor *get_foe() const;

    // actor interface
    monster_type id() const;
    int mindex() const;
    int       get_experience_level() const;
    god_type  deity() const;
    bool      alive() const;
    bool      swimming() const;
    bool      wants_submerge() const;

    bool      submerged() const;
    bool      can_drown() const;
    bool      floundering() const;
    bool      extra_balanced() const;
    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;
    int       total_weight() const;
    int       damage_brand(int which_attack = -1);
    int       damage_type(int which_attack = -1);

    item_def *slot_item(equipment_type eq);
    item_def *mslot_item(mon_inv_type sl) const;
    item_def *weapon(int which_attack = -1);
    item_def *launcher();
    item_def *missiles();
    item_def *shield();

    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) const;

    int       missile_count();
    void      wield_melee_weapon(int near = -1);
    void      swap_weapons(int near = -1);

    bool      pickup_item(item_def &item, int near = -1, bool force = false);
    void      pickup_message(const item_def &item, int near);
    bool      pickup_wand(item_def &item, int near);
    bool      pickup_scroll(item_def &item, int near);
    bool      pickup_potion(item_def &item, int near);
    bool      pickup_gold(item_def &item, int near);
    bool      pickup_launcher(item_def &launcher, int near);
    bool      pickup_melee_weapon(item_def &item, int near);
    bool      pickup_throwable_weapon(item_def &item, int near);
    bool      pickup_weapon(item_def &item, int near, bool force);
    bool      pickup_armour(item_def &item, int near, bool force);
    bool      pickup_misc(item_def &item, int near);
    bool      pickup_missile(item_def &item, int near, bool force);
    void      equip(item_def &item, int slot, int near = -1);
    bool      unequip(item_def &item, int slot, int near = -1,
                      bool force = false);

    bool      can_use_missile(const item_def &item) const;

    std::string name(description_level_type type,
                     bool force_visible = false) const;

    // Base name of the monster, bypassing any mname setting. For an orc priest
    // named Arbolt, name() will return "Arbolt", but base_name() will return
    // "orc priest".
    std::string base_name(description_level_type type,
                          bool force_visible = false) const;
    // Full name of the monster.  For an orc priest named Arbolt, full_name()
    // will return "Arbolt the orc priest".
    std::string full_name(description_level_type type,
                          bool use_comma = false) const;
    std::string pronoun(pronoun_type pro, bool force_visible = false) const;
    std::string conj_verb(const std::string &verb) const;
    std::string hand_name(bool plural, bool *can_plural = NULL) const;
    std::string foot_name(bool plural, bool *can_plural = NULL) const;
    std::string arm_name(bool plural, bool *can_plural = NULL) const;

    bool fumbles_attack(bool verbose = true);
    bool cannot_fight() const;

    int  skill(skill_type skill, bool skill_bump = false) const;

    void attacking(actor *other);
    bool can_go_berserk() const;
    void go_berserk(bool intentional, bool potion = false);
    void go_frenzy();
    bool berserk() const;
    bool frenzied() const;
    bool can_mutate() const;
    bool can_safely_mutate() const;
    bool can_bleed() const;
    bool mutate();
    void banish(const std::string &who = "");
    void expose_to_element(beam_type element, int strength = 0);

    int mons_species() const;

    mon_holy_type holiness() const;
    bool undead_or_demonic() const;
    bool is_holy() const;
    bool is_unholy() const;
    bool is_evil() const;
    bool is_unclean() const;
    bool is_chaotic() const;
    int res_fire() const;
    int res_steam() const;
    int res_cold() const;
    int res_elec() const;
    int res_poison() const;
    int res_rotting() 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() const;
    int res_torment() const;
    int res_acid() const;
    int res_magic() const;

    flight_type flight_mode() const;
    bool is_levitating() const;
    bool invisible() const;
    bool can_see_invisible() const;
    bool visible_to(const actor *looker) const;
    bool mon_see_cell(const coord_def& pos, bool reach = false) const;
    bool near_foe() const;

    const los_def& get_los_no_trans();

    bool is_icy() const;
    bool is_fiery() const;
    bool paralysed() const;
    bool cannot_move() const;
    bool cannot_act() const;
    bool confused() const;
    bool confused_by_you() const;
    bool caught() const;
    bool asleep() const;
    bool backlit(bool check_haloed = true) const;
    int halo_radius() const;
    bool petrified() const;
    bool petrifying() const;

    bool friendly() const;
    bool neutral() const;
    bool good_neutral() const;
    bool strict_neutral() const;
    bool wont_attack() const;
    bool pacified() const;

    bool has_spells() const;
    bool has_spell(spell_type spell) const;
    bool has_holy_spell() const;
    bool has_unholy_spell() const;
    bool has_evil_spell() const;
    bool has_unclean_spell() const;
    bool has_chaotic_spell() const;

    bool has_attack_flavour(int flavour) const;
    bool has_damage_type(int dam_type);

    bool can_throw_large_rocks() const;
    bool can_speak();

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

    void poison(actor *agent, int amount = 1);
    bool sicken(int strength);
    void paralyse(actor *, int str);
    void petrify(actor *, int str);
    void slow_down(actor *, int str);
    void confuse(actor *, int strength);
    bool drain_exp(actor *, bool quiet = false, int pow = 3);
    bool rot(actor *, int amount, int immediate = 0, bool quiet = false);
    int hurt(const actor *attacker, int amount,
             beam_type flavour = BEAM_MISSILE,
             bool cleanup_dead = true);
    bool heal(int amount, bool max_too = false);
    void blink(bool allow_partial_control = true);
    void teleport(bool right_now = false,
                  bool abyss_shift = false,
                  bool wizard_tele = false);

    void hibernate(int power = 0);
    void put_to_sleep(actor *attacker, int power = 0);
    void check_awaken(int disturbance);

    int stat_hp() const    { return hit_points; }
    int stat_maxhp() const { return max_hit_points; }

    int shield_bonus() const;
    int shield_block_penalty() const;
    void shield_block_succeeded(actor *foe);
    int shield_bypass_ability(int tohit) const;

    actor_type atype() const { return ACT_MONSTER; }

    // Hacks, with a capital H.
    void fix_speed();
    void check_speed();
    void upgrade_type(monster_type after, bool adjust_hd, bool adjust_hp);

    std::string describe_enchantments() const;

    int action_energy(energy_use_type et) const;

    bool do_shaft();
    bool has_spell_of_type(unsigned) const;

    void bind_spell_flags();

private:
    void init_with(const monsters &mons);
    void swap_slots(mon_inv_type a, mon_inv_type b);
    bool need_message(int &near) const;
    bool level_up();
    bool level_up_change();
    bool pickup(item_def &item, int slot, int near, bool force_merge = false);
    void equip_weapon(item_def &item, int near, bool msg = true);
    void equip_armour(item_def &item, int near);
    void unequip_weapon(item_def &item, int near, bool msg = true);
    void unequip_armour(item_def &item, int near);

    bool decay_enchantment(const mon_enchant &me, bool decay_degree = true);

    bool drop_item(int eslot, int near);
    bool wants_weapon(const item_def &item) const;
    bool wants_armour(const item_def &item) const;
    void lose_pickup_energy();
    bool check_set_valid_home(const coord_def &place,
                              coord_def &chosen,
                              int &nvalid) const;
};

#endif