/** * @file * @brief Misc monster related functions. **/ #ifndef MONUTIL_H #define MONUTIL_H #include "externs.h" #include "enum.h" #include "mon-enum.h" #include "player.h" struct bolt; struct mon_attack_def { attack_type type; attack_flavour flavour; int damage; static mon_attack_def attk(int dam, attack_type typ = AT_HIT, attack_flavour flav = AF_PLAIN) { mon_attack_def def = { typ, flav, dam }; return def; } }; // Amount of mons->speed_increment used by different actions; defaults // to 10. #define DEFAULT_ENERGY {10, 10, 10, 10, 10, 10, 10, 100} struct mon_energy_usage { uint8_t move; uint8_t swim; uint8_t attack; uint8_t missile; // Arrows/crossbows/etc uint8_t spell; uint8_t special; uint8_t item; // Using an item (i.e., drinking a potion) // Percent of mons->speed used when picking up an item; defaults // to 100% uint8_t pickup_percent; static mon_energy_usage attack_cost(int cost, int sw = 10) { mon_energy_usage me = DEFAULT_ENERGY; me.attack = cost; me.swim = sw; return me; } static mon_energy_usage missile_cost(int cost) { mon_energy_usage me = DEFAULT_ENERGY; me.missile = cost; return me; } static mon_energy_usage swim_cost (int cost) { mon_energy_usage me = DEFAULT_ENERGY; me.swim = cost; return me; } static mon_energy_usage move_cost(int mv, int sw = 10) { mon_energy_usage me = DEFAULT_ENERGY; me.move = mv; me.swim = sw; return me; } mon_energy_usage operator | (const mon_energy_usage &o) const { mon_energy_usage me; me.move = combine(move, o.move); me.swim = combine(swim, o.swim); me.attack = combine(attack, o.attack); me.missile = combine(missile, o.missile); me.spell = combine(spell, o.spell); me.special = combine(special, o.special); me.item = combine(item, o.item); me.pickup_percent = combine(pickup_percent, o.pickup_percent, 100); return me; } bool operator == (const mon_energy_usage &rvalue) const { return move == rvalue.move && swim == rvalue.swim && attack == rvalue.attack && missile == rvalue.missile && spell == rvalue.spell && special == rvalue.special && item == rvalue.item && pickup_percent == rvalue.pickup_percent; } private: static uint8_t combine(uint8_t a, uint8_t b, uint8_t def = 10) { return b != def? b : a; } }; struct monsterentry { short mc; // monster number char basechar; colour_t colour; const char *name; uint64_t bitfields; resists_t resists; short weight; // [Obsolete] Experience used to be calculated like this: // ((((max_hp / 7) + 1) * (mHD * mHD) + 1) * exp_mod) / 10 // ^^^^^^ see below at hpdice // Note that this may make draining attacks less attractive (LRH) int8_t exp_mod; monster_type genus, // "team" the monster plays for species; // corpse type of the monster mon_holy_type holiness; short resist_magic; // (positive is ??) // max damage in a turn is total of these four? mon_attack_def attack[MAX_NUM_ATTACKS]; // hpdice[4]: [0]=HD [1]=min_hp [2]=rand_hp [3]=add_hp // min hp = [0]*[1]+[3] & max hp = [0]*([1]+[2])+[3]) // example: the Iron Golem, hpdice={15,7,4,0} // 15*7 < hp < 15*(7+4), // 105 < hp < 165 // hp will be around 135 each time. unsigned hpdice[4]; int8_t AC; // armour class int8_t ev; // evasion int sec; // actually mon_spellbook_type corpse_effect_type corpse_thingy; zombie_size_type zombie_size; shout_type shouts; mon_intel_type intel; habitat_type habitat; flight_type fly; int8_t speed; // How quickly speed_increment increases mon_energy_usage energy_usage; // And how quickly it decreases mon_itemuse_type gmon_use; mon_itemeat_type gmon_eat; size_type size; mon_body_shape shape; }; enum mon_threat_level_type { MTHRT_TRIVIAL, MTHRT_EASY, MTHRT_TOUGH, MTHRT_NASTY, MTHRT_UNDEF, }; void set_resist(resists_t &all, mon_resist_flags res, int lev); // In all cases this will be simplified to a bit field access, so let's let // the compiler inline it. static inline int get_resist(resists_t all, mon_resist_flags res) { if (res > MR_LAST_MULTI) return all & res ? 1 : 0; int v = (all / res) & 7; if (v > 4) return v - 8; return v; } dungeon_feature_type habitat2grid(habitat_type ht); monsterentry *get_monster_data(monster_type mc) IMMUTABLE; resists_t get_mons_class_resists(monster_type mc) IMMUTABLE; resists_t get_mons_resists(const monster* mon); int get_mons_resist(const monster* mon, mon_resist_flags res); void init_monsters(); void init_monster_symbols(); monster *monster_at(const coord_def &pos); // this is the old moname() string mons_type_name(monster_type type, description_level_type desc); bool give_monster_proper_name(monster* mon, bool orcs_only = true); flight_type mons_class_flies(monster_type mc); flight_type mons_flies(const monster* mon, bool temp = true); bool mons_flattens_trees(const monster* mon); int mons_class_res_wind(monster_type mc); mon_itemuse_type mons_class_itemuse(monster_type mc); mon_itemuse_type mons_itemuse(const monster* mon); mon_itemeat_type mons_itemeat(const monster* mon); bool mons_sense_invis(const monster* mon); int get_shout_noise_level(const shout_type shout); shout_type mons_shouts(monster_type mclass, bool demon_shout = false); bool mons_is_ghost_demon(monster_type mc); bool mons_is_unique(monster_type mc); bool mons_is_pghost(monster_type mc); int mons_avg_hp(monster_type mc); int exper_value(const monster* mon, bool real = true); int hit_points(int hit_dice, int min_hp, int rand_hp); int mons_class_hit_dice(monster_type mc); bool mons_immune_magic(const monster* mon); const char* mons_resist_string(const monster* mon, int res_margin); const char* resist_margin_phrase(int margin); mon_attack_def mons_attack_spec(const monster* mon, int attk_number, bool base_flavour = false); corpse_effect_type mons_corpse_effect(monster_type mc); bool mons_class_flag(monster_type mc, uint64_t bf); mon_holy_type mons_class_holiness(monster_type mc); bool mons_is_mimic(monster_type mc); bool mons_is_item_mimic(monster_type mc); bool mons_is_feat_mimic(monster_type mc); void discover_mimic(const coord_def& pos, bool wake = true); void discover_shifter(monster* shifter); bool mons_is_statue(monster_type mc); bool mons_is_demon(monster_type mc); bool mons_is_draconian(monster_type mc); bool mons_is_base_draconian(monster_type mc); bool mons_is_demonspawn(monster_type mc); bool mons_is_conjured(monster_type mc); bool mons_is_beast(monster_type mc); bool mons_is_avatar(monster_type mc); int mons_demon_tier(monster_type mc); bool mons_class_wields_two_weapons(monster_type mc); bool mons_wields_two_weapons(const monster* m); bool mons_self_destructs(const monster* m); mon_intel_type mons_class_intel(monster_type mc); mon_intel_type mons_intel(const monster* mon); // Use mons_habitat() and mons_primary_habitat() wherever possible, // since the class variants do not handle zombies correctly. habitat_type mons_habitat(const monster* mon, bool real_amphibious = false); habitat_type mons_class_primary_habitat(monster_type mc); habitat_type mons_primary_habitat(const monster* mon); habitat_type mons_class_secondary_habitat(monster_type mc); habitat_type mons_secondary_habitat(const monster* mon); bool intelligent_ally(const monster* mon); bool mons_skeleton(monster_type mc); bool mons_zombifiable(monster_type mc); int mons_weight(monster_type mc); int mons_class_base_speed(monster_type mc); mon_energy_usage mons_class_energy(monster_type mc); int mons_class_zombie_base_speed(monster_type zombie_base_mc); int mons_base_speed(const monster* mon); bool get_tentacle_head(const monster*& mon); bool mons_class_can_regenerate(monster_type mc); bool mons_can_regenerate(const monster* mon); bool mons_class_fast_regen(monster_type mc); int mons_zombie_size(monster_type mc); monster_type mons_zombie_base(const monster* mon); bool mons_class_is_zombified(monster_type mc); bool mons_class_is_hybrid(monster_type mc); bool mons_class_is_chimeric(monster_type mc); bool mons_class_is_animated_weapon(monster_type type); monster_type mons_base_type(const monster* mon); bool mons_class_can_leave_corpse(monster_type mc); bool mons_class_leaves_hide(monster_type mc); bool mons_is_zombified(const monster* mons); bool mons_class_can_be_zombified(monster_type mc); bool mons_can_be_zombified(const monster* mon); bool mons_class_can_use_stairs(monster_type mc); bool mons_can_use_stairs(const monster* mon); bool mons_enslaved_body_and_soul(const monster* mon); bool mons_enslaved_soul(const monster* mon); bool name_zombie(monster* mon, monster_type mc, const string &mon_name); bool name_zombie(monster* mon, const monster* orig); int mons_power(monster_type mc); ucs_t mons_char(monster_type mc); char mons_base_char(monster_type mc); int mons_class_colour(monster_type mc); monster_type royal_jelly_ejectable_monster(); monster_type random_draconian_monster_species(); monster_type random_demonspawn_monster_species(); bool init_abomination(monster* mon, int hd); void define_monster(monster* mons); void mons_pacify(monster* mon, mon_attitude_type att = ATT_GOOD_NEUTRAL, bool no_xp = false); bool mons_should_fire(bolt &beam); bool mons_has_los_ability(monster_type mon_type); bool mons_has_ranged_spell(const monster* mon, bool attack_only = false, bool ench_too = true); bool mons_has_ranged_attack(const monster* mon); bool mons_has_known_ranged_attack(const monster* mon); bool mons_can_attack(const monster* mon); bool mons_has_incapacitating_spell(const monster* mon, const actor* foe); bool mons_has_incapacitating_ranged_attack(const monster* mon, const actor* foe); // FIXME: move decline_pronoun somewhere more generic. const char *decline_pronoun(gender_type gender, pronoun_type variant); const char *mons_pronoun(monster_type mon_type, pronoun_type variant, bool visible = true); bool mons_aligned(const actor *m1, const actor *m2); bool mons_atts_aligned(mon_attitude_type fr1, mon_attitude_type fr2); bool mons_att_wont_attack(mon_attitude_type fr); mon_attitude_type mons_attitude(const monster* m); bool mons_foe_is_mons(const monster* mons); bool mons_is_native_in_branch(const monster* mons, const branch_type branch = you.where_are_you); bool mons_is_poisoner(const monster* mon); // Whether the monster is temporarily confused (class_too = false) // or confused at all (class_too = true; temporarily or by class). bool mons_is_confused(const monster* m, bool class_too = false); bool mons_is_wandering(const monster* m); bool mons_is_seeking(const monster* m); bool mons_is_fleeing(const monster* m); bool mons_is_retreating(const monster* m); bool mons_is_cornered(const monster* m); bool mons_is_lurking(const monster* m); bool mons_is_batty(const monster* m); bool mons_is_influenced_by_sanctuary(const monster* m); bool mons_is_fleeing_sanctuary(const monster* m); bool mons_just_slept(const monster* m); bool mons_class_is_slime(monster_type mc); bool mons_is_slime(const monster* mon); bool mons_class_is_plant(monster_type mc); bool mons_is_plant(const monster* mon); bool mons_eats_items(const monster* mon); bool mons_eats_corpses(const monster* mon); monster_type mons_genus(monster_type mc); monster_type mons_species(monster_type mc); monster_type draco_or_demonspawn_subspecies(const monster* mon); monster_type mons_detected_base(monster_type mt); bool mons_looks_stabbable(const monster* m); bool mons_looks_distracted(const monster* m); void mons_start_fleeing_from_sanctuary(monster* mons); void mons_stop_fleeing_from_sanctuary(monster* mons); bool mons_landlubbers_in_reach(const monster* mons); bool mons_class_is_confusable(monster_type mc); bool mons_class_is_stationary(monster_type mc); bool mons_class_is_firewood(monster_type mc); bool mons_is_firewood(const monster* mon); bool mons_has_body(const monster* mon); bool mons_has_flesh(const monster* mon); bool mons_is_abyssal_only(monster_type mc); bool herd_monster(const monster* mon); int cheibriados_monster_player_speed_delta(const monster* mon); bool cheibriados_thinks_mons_is_fast(const monster* mon); bool mons_is_illuminating(const monster* mon); bool mons_is_fiery(const monster* mon); bool mons_is_projectile(monster_type mc); bool mons_is_projectile(const monster* mon); bool mons_is_boulder(const monster* mon); bool mons_can_cling_to_walls(const monster* mon); bool mons_is_object(monster_type mc); bool mons_has_blood(monster_type mc); bool mons_is_sensed(monster_type mc); bool mons_allows_beogh(const monster* mon); bool mons_allows_beogh_now(const monster* mon); bool invalid_monster(const monster* mon); bool invalid_monster_type(monster_type mt); bool invalid_monster_index(int i); void mons_remove_from_grid(const monster* mon); bool monster_shover(const monster* m); bool monster_senior(const monster* first, const monster* second, bool fleeing = false); string ugly_thing_colour_name(colour_t colour); colour_t ugly_thing_random_colour(); int str_to_ugly_thing_colour(const string &s); colour_t random_monster_colour(); int ugly_thing_colour_offset(colour_t colour); string draconian_colour_name(monster_type mon_type); monster_type draconian_colour_by_name(const string &colour); string demonspawn_base_name(monster_type mon_type); monster_type demonspawn_base_by_name(const string &colour); monster_type random_monster_at_grid(const coord_def& p, bool species = false); void init_mon_name_cache(); monster_type get_monster_by_name(string name, bool substring = false); string do_mon_str_replacements(const string &msg, const monster* mons, int s_type = -1); mon_body_shape get_mon_shape(const monster* mon); mon_body_shape get_mon_shape(const monster_type mc); string get_mon_shape_str(const mon_body_shape shape); bool mons_class_can_pass(monster_type mc, const dungeon_feature_type grid); bool mons_can_open_door(const monster* mon, const coord_def& pos); bool mons_can_eat_door(const monster* mon, const coord_def& pos); bool mons_can_traverse(const monster* mon, const coord_def& pos, bool only_in_sight = false, bool checktraps = true); mon_inv_type equip_slot_to_mslot(equipment_type eq); mon_inv_type item_to_mslot(const item_def &item); bool player_or_mon_in_sanct(const monster* mons); bool mons_is_immotile(const monster* mons); int get_dist_to_nearest_monster(); bool monster_nearby(); actor *actor_by_mid(mid_t m); monster *monster_by_mid(mid_t m); bool mons_is_tentacle_head(monster_type mc); bool mons_is_child_tentacle(monster_type mc); bool mons_is_child_tentacle_segment(monster_type mc); bool mons_is_tentacle(monster_type mc); bool mons_is_tentacle_segment(monster_type mc); bool mons_is_tentacle_or_tentacle_segment(monster_type mc); bool mons_is_recallable(actor* caller, monster* targ); monster* mons_get_parent_monster(monster* mons); void init_anon(); actor *find_agent(mid_t m, kill_category kc); const char* mons_class_name(monster_type mc); void check_clinging(); monster_type mons_tentacle_parent_type(const monster* mons); monster_type mons_tentacle_child_type(const monster* mons); bool mons_tentacle_adjacent(const monster* parent, const monster* child); mon_threat_level_type mons_threat_level(const monster *mon, bool real = false); int count_monsters(monster_type mtyp, bool friendly_only); int count_allies(); bool mons_foe_is_marked(const monster* mons); vector get_on_level_followers(); bool mons_stores_tracking_data(const monster* mons); bool mons_is_player_shadow(const monster* mon); bool mons_antimagic_affected(const monster* mons); void reset_all_monsters(); void debug_mondata(); bool choose_any_monster(const monster* mon); monster *choose_random_nearby_monster( int weight, bool (*suitable)(const monster* mon) = choose_any_monster, bool prefer_named_or_priest = false); monster *choose_random_monster_on_level( int weight, bool (*suitable)(const monster* mon) = choose_any_monster); #endif