/* * File: mon-util.h * Summary: Misc monster related functions. * Written by: Linley Henzell */ #ifndef MONUTIL_H #define MONUTIL_H #include "externs.h" #include "enum.h" #include "player.h" #include "monster.h" enum corpse_effect_type { CE_NOCORPSE, // 0 CE_CLEAN, // 1 CE_CONTAMINATED, // 2 CE_POISONOUS, // 3 CE_HCL, // 4 CE_MUTAGEN_RANDOM, // 5 CE_MUTAGEN_GOOD, // 6 - may be worth implementing {dlb} CE_MUTAGEN_BAD, // 7 - may be worth implementing {dlb} CE_RANDOM, // 8 - not used, but may be worth implementing {dlb} CE_ROTTEN = 50 // 50 - must remain at 50 for now {dlb} }; enum gender_type { GENDER_NEUTER, GENDER_MALE, GENDER_FEMALE }; enum mon_attack_type { AT_NONE, AT_HIT, // Including weapon attacks. AT_BITE, AT_STING, AT_SPORE, AT_TOUCH, AT_ENGULF, AT_CLAW, AT_PECK, AT_HEADBUTT, AT_PUNCH, AT_KICK, AT_TENTACLE_SLAP, AT_TAIL_SLAP, AT_GORE, AT_CONSTRICT, AT_SHOOT, // Attack representing missile damage for M_ARCHER. AT_WEAP_ONLY, // Ranged weap: shoot point-blank like AT_SHOOT, melee weap: // use it, no weapon: stand there doing nothing. AT_RANDOM // Anything but AT_SHOOT and AT_WEAP_ONLY. }; enum mon_attack_flavour { AF_PLAIN, AF_ACID, AF_BLINK, AF_COLD, AF_CONFUSE, AF_DISEASE, AF_DRAIN_DEX, AF_DRAIN_STR, AF_DRAIN_XP, AF_ELEC, AF_FIRE, AF_HUNGER, AF_MUTATE, AF_PARALYSE, AF_POISON, AF_POISON_NASTY, AF_POISON_MEDIUM, AF_POISON_STRONG, AF_POISON_STR, AF_ROT, AF_VAMPIRIC, AF_KLOWN, AF_DISTORT, AF_RAGE, AF_NAPALM, AF_CHAOS, AF_STEAL, AF_STEAL_FOOD, AF_CRUSH, AF_REACH }; // Non-spell "summoning" types to give to monsters::mark_summoned(), or // as the fourth parameter of mgen_data's constructor. // // Negative values since spells are non-negative. enum mon_summon_type { MON_SUMM_CLONE = -10000, // Cloned from another monster MON_SUMM_ANIMATE, // Item/feature/substance which was animated MON_SUMM_CHAOS, // Was made from pure chaos MON_SUMM_MISCAST, // Spell miscast MON_SUMM_ZOT, // Zot trap MON_SUMM_WRATH, // Divine wrath MON_SUMM_AID // Divine aid }; // properties of the monster class (other than resists/vulnerabilities) enum mons_class_flags { M_NO_FLAGS = 0, M_SPELLCASTER = (1<< 0), // any non-physical-attack powers, M_ACTUAL_SPELLS = (1<< 1), // monster is a wizard, M_PRIEST = (1<< 2), // monster is a priest, M_FIGHTER = (1<< 3), // monster is skilled fighter M_NO_WAND = (1<< 4), // do not give (unique) a wand M_NO_HT_WAND = (1<< 5), // do not give a high tier wand M_INVIS = (1<< 6), // is created invis M_SEE_INVIS = (1<< 7), // can see invis M_SENSE_INVIS = (1<< 8), // can sense invisible things M_SPEAKS = (1<< 9), // uses talking code M_CONFUSED = (1<<10), // monster is perma-confused, M_BATTY = (1<<11), // monster is batty M_SPLITS = (1<<12), // monster can split M_GLOWS = (1<<13), // monster glows M_STATIONARY = (1<<14), // monster is stationary M_BLOOD_SCENT = (1<<15), // monster can smell blood M_COLD_BLOOD = (1<<16), // susceptible to cold, // drainable by vampires M_WARM_BLOOD = (1<<17), // no effect currently, // drainable by vampires M_REGEN = (1<<18), // regenerates quickly M_BURROWS = (1<<19), // monster digs through rock // XXX: unused (1<<20), M_UNIQUE = (1<<21), // monster is a unique M_ACID_SPLASH = (1<<22), // Passive acid splash when hit. M_ARCHER = (1<<23), // gets various archery boosts M_INSUBSTANTIAL = (1<<24), // is insubstantial M_TWOWEAPON = (1<<25), // wields two weapons at once M_SPECIAL_ABILITY = (1<<26), // XXX: eventually make these spells? M_NO_REGEN = (1<<27), // cannot regenerate M_SPELL_NO_SILENT = (1<<28), // cannot cast spells when silenced, // even though it's not a priest or // wizard M_NOISY_SPELLS = (1<<29), // can cast spells when silenced, but // casting makes noise when not // silenced M_NO_SKELETON = (1<<30), // boneless corpses M_NO_EXP_GAIN = (1<<31) // worth 0 xp }; enum mon_intel_type // Must be in increasing intelligence order { I_PLANT = 0, I_INSECT, I_ANIMAL, I_NORMAL, I_HIGH }; enum habitat_type { // Flying monsters will appear in all categories except rock walls HT_LAND = 0, // Land critters HT_AMPHIBIOUS_LAND, // Amphibious land-preferring critters HT_AMPHIBIOUS_WATER, // Amphibious water-preferring critters HT_WATER, // Water critters HT_LAVA, // Lava critters HT_ROCK, // Rock critters NUM_HABITATS }; // order of these is important: enum mon_itemuse_type { MONUSE_NOTHING, MONUSE_OPEN_DOORS, MONUSE_STARTING_EQUIPMENT, MONUSE_WEAPONS_ARMOUR, MONUSE_MAGIC_ITEMS, NUM_MONUSE }; enum mon_itemeat_type { MONEAT_NOTHING, MONEAT_ITEMS, MONEAT_CORPSES, MONEAT_FOOD, NUM_MONEAT }; // now saved in an unsigned long. enum mon_resist_flags { MR_NO_FLAGS = 0, // resistances // Notes: // - negative energy is mostly handled via monsters::res_negative_energy() MR_RES_ELEC = (1<< 0), MR_RES_POISON = (1<< 1), MR_RES_FIRE = (1<< 2), MR_RES_HELLFIRE = (1<< 3), MR_RES_COLD = (1<< 4), MR_RES_ASPHYX = (1<< 5), MR_RES_ACID = (1<< 6), // vulnerabilities MR_VUL_ELEC = (1<< 7), MR_VUL_POISON = (1<< 8), MR_VUL_FIRE = (1<< 9), MR_VUL_COLD = (1<<10), // Melee armour resists/vulnerabilities. // XXX: how to do combos (bludgeon/slice, bludgeon/pierce) MR_RES_PIERCE = (1<<11), MR_RES_SLICE = (1<<12), MR_RES_BLUDGEON = (1<<13), MR_VUL_PIERCE = (1<<14), MR_VUL_SLICE = (1<<15), MR_VUL_BLUDGEON = (1<<16), // Immune to stickiness of sticky flame. MR_RES_STICKY_FLAME = (1<<17), // Immune to rotting. MR_RES_ROTTING = (1<<18), MR_RES_STEAM = (1<<19) }; enum shout_type { S_SILENT, // silent S_SHOUT, // shout S_BARK, // bark S_SHOUT2, // shout twice (e.g. two-headed ogres) S_ROAR, // roar S_SCREAM, // scream S_BELLOW, // bellow (yaks) S_SCREECH, // screech S_BUZZ, // buzz S_MOAN, // moan S_GURGLE, // gurgle S_WHINE, // irritating whine (mosquitos) S_CROAK, // frog croak S_GROWL, // for bears S_HISS, // for snakes and lizards S_DEMON_TAUNT, // for pandemonium lords NUM_SHOUTS, // Loudness setting for shouts that are only defined in dat/shout.txt S_VERY_SOFT, S_SOFT, S_NORMAL, S_LOUD, S_VERY_LOUD, NUM_LOUDNESS, S_RANDOM }; enum zombie_size_type { Z_NOZOMBIE = 0, Z_SMALL, Z_BIG }; struct bolt; // ($pellbinder) (c) D.G.S.E. 1998 struct mon_attack_def { mon_attack_type type; mon_attack_flavour flavour; int damage; static mon_attack_def attk(int damage, mon_attack_type type = AT_HIT, mon_attack_flavour flav = AF_PLAIN) { mon_attack_def def = { type, flav, damage }; return (def); } }; // Amount of monster->speed_increment used by different actions; defaults // to 10. struct mon_energy_usage { public: char move; char swim; char attack; char missile; // Arrows/crossbows/etc char spell; char special; char item; // Using an item (i.e., drinking a potion) // Percent of monster->speed used when picking up an item; defaults // to 100% char pickup_percent; public: mon_energy_usage(int mv = 10, int sw = 10, int att = 10, int miss = 10, int spl = 10, int spc = 10, int itm = 10, int pick = 100) : move(mv), swim(sw), attack(att), missile(miss), spell(spl), special(spc), item(itm), pickup_percent(pick) { } static mon_energy_usage attack_cost(int cost) { mon_energy_usage me; me.attack = cost; return me; } static mon_energy_usage missile_cost(int cost) { mon_energy_usage me; me.missile = cost; return me; } static mon_energy_usage move_cost(int mv, int sw = 10) { const mon_energy_usage me(mv, sw); return me; } mon_energy_usage operator | (const mon_energy_usage &o) const { return mon_energy_usage( combine(move, o.move), combine(swim, o.swim), combine(attack, o.attack), combine(missile, o.missile), combine(spell, o.spell), combine(special, o.special), combine(item, o.item), combine(pickup_percent, o.pickup_percent, 100) ); } private: char combine(char a, char b, char def = 10) const { return (b != def? b : a); } }; struct mon_resist_def { // All values are actually saved as single-bytes, so practical // range is -128 - 127, and the game only distinguishes values in // the range -1 to 3. short elec; short poison; short fire; short steam; short cold; short hellfire; short acid; bool asphyx; bool sticky_flame; bool rotting; // Physical damage resists (currently unused) short pierce; short slice; short bludgeon; mon_resist_def(); mon_resist_def(int flags, short level = -100); mon_resist_def operator | (const mon_resist_def &other) const; const mon_resist_def &operator |= (const mon_resist_def &other); short get_resist_level(mon_resist_flags res_type) const; private: short get_default_res_level(int resist, short level) const; }; inline mon_resist_def operator | (int a, const mon_resist_def &b) { return (mon_resist_def(a) | b); } typedef mon_resist_def mrd; struct monsterentry { short mc; // monster number unsigned char showchar, colour; const char *name; unsigned long bitfields; mon_resist_def 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) char 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[4]; // 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]; char AC; // armour class char ev; // evasion mon_spellbook_type sec; corpse_effect_type corpse_thingy; zombie_size_type zombie_size; shout_type shouts; mon_intel_type intel; habitat_type habitat; flight_type fly; char 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; }; habitat_type grid2habitat(dungeon_feature_type grid); dungeon_feature_type habitat2grid(habitat_type ht); monsterentry *get_monster_data(int p_monsterid); const mon_resist_def &get_mons_class_resists(int mc); mon_resist_def get_mons_resists(const monsters *mon); void init_monsters(); void init_monster_symbols(); monsters *monster_at(const coord_def &pos); // this is the old moname() std::string mons_type_name(int type, description_level_type desc); bool give_monster_proper_name(monsters *mon, bool orcs_only = true); flight_type mons_class_flies(int mc); flight_type mons_flies(const monsters *mon, bool randarts = true); bool mons_class_amphibious(int mc); bool mons_amphibious(const monsters *mon); bool mons_class_wall_shielded(int mc); bool mons_wall_shielded(const monsters *mon); mon_itemuse_type mons_class_itemuse(int mc); mon_itemuse_type mons_itemuse(const monsters *mon); mon_itemeat_type mons_class_itemeat(int mc); mon_itemeat_type mons_itemeat(const monsters *mon); bool mons_sense_invis(const monsters *mon); int get_shout_noise_level(const shout_type shout); shout_type mons_shouts(int mclass, bool demon_shout = false); bool mons_is_ghost_demon(int mc); bool mons_is_unique(int mc); int mons_difficulty(int mtype); int exper_value(const monsters *monster); int hit_points(int hit_dice, int min_hp, int rand_hp); int mons_type_hit_dice( int type ); int mons_resist_turn_undead( const monsters *mon ); bool mons_immune_magic( const monsters *mon ); const char* mons_resist_string(const monsters *mon); int mons_damage(int mc, int rt); mon_attack_def mons_attack_spec(const monsters *mon, int attk_number); corpse_effect_type mons_corpse_effect(int mc); bool mons_class_flag(int mc, int bf); int mons_unusable_items(const monsters *mon); mon_holy_type mons_class_holiness(int mc); bool mons_is_mimic( int mc ); bool mons_is_statue( int mc, bool allow_disintegrate = false ); bool mons_is_demon( int mc ); bool mons_class_wields_two_weapons(int mc); bool mons_wields_two_weapons(const monsters *m); bool mons_self_destructs(const monsters *m); mon_intel_type mons_class_intel(int mc); mon_intel_type mons_intel(const monsters *mon); // Use mons_habitat() and mons_primary_habitat() wherever possible, // since the class variants do not handle zombies correctly. habitat_type mons_class_habitat(int mc); habitat_type mons_habitat(const monsters *mon); habitat_type mons_class_primary_habitat(int mc); habitat_type mons_primary_habitat(const monsters *mon); habitat_type mons_class_secondary_habitat(int mc); habitat_type mons_secondary_habitat(const monsters *mon); bool intelligent_ally(const monsters *mon); bool mons_skeleton(int mc); int mons_weight(int mc); int mons_class_base_speed(int mc); int mons_class_zombie_base_speed(int zombie_base_mc); int mons_base_speed(const monsters *mon); int mons_real_base_speed(int mc); bool mons_class_can_regenerate(int mc); bool mons_can_regenerate(const monsters *mon); int mons_zombie_size(int mc); monster_type mons_zombie_base(const monsters *mon); bool mons_class_is_zombified(int mc); monster_type mons_base_type(const monsters *mon); bool mons_is_zombified(const monsters *monster); bool mons_class_can_be_zombified(int mc); bool mons_can_be_zombified(const monsters *mon); bool mons_class_can_use_stairs(int mc); bool mons_can_use_stairs(const monsters *mon); bool mons_enslaved_body_and_soul(const monsters *mon); bool mons_enslaved_twisted_soul(const monsters *mon); bool mons_enslaved_intact_soul(const monsters *mon); bool mons_enslaved_soul(const monsters *mon); bool name_zombie(monsters *mon, int mc, const std::string mon_name); bool name_zombie(monsters *mon, const monsters* orig); int mons_power(int mclass); unsigned mons_char(int mc); int mons_class_colour(int mc); int mons_colour(const monsters *mon); void mons_load_spells(monsters *mon, mon_spellbook_type book); monster_type royal_jelly_ejectable_monster(); monster_type random_draconian_monster_species(); void define_monster(int midx); void define_monster(monsters &mons); void mons_pacify(monsters *mon, mon_attitude_type att = ATT_GOOD_NEUTRAL); bool mons_should_fire(struct bolt &beam); bool ms_direct_nasty(spell_type monspell); bool ms_useful_fleeing_out_of_sight(const monsters *mon, spell_type monspell); bool ms_quick_get_away(const monsters *mon, spell_type monspell); bool ms_waste_of_time(const monsters *mon, spell_type monspell); bool ms_low_hitpoint_cast(const monsters *mon, spell_type monspell); bool mons_has_los_ability(monster_type mon_type); bool mons_has_los_attack(const monsters *mon); bool mons_has_ranged_spell(const monsters *mon, bool attack_only = false, bool ench_too = true); bool mons_has_ranged_attack(const monsters *mon); bool mons_has_ranged_ability(const monsters *mon); const char *mons_pronoun(monster_type mon_type, pronoun_type variant, bool visible = true); bool mons_aligned(int m1, int 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 monsters *m); bool mons_foe_is_mons(const monsters *mons); bool mons_behaviour_perceptible(const monsters *mon); bool mons_is_native_in_branch(const monsters *monster, const branch_type branch = you.where_are_you); bool mons_is_poisoner(const monsters *mon); bool mons_is_confused(const monsters *m, bool class_too = false); bool mons_is_wandering(const monsters *m); bool mons_is_seeking(const monsters *m); bool mons_is_fleeing(const monsters *m); bool mons_is_panicking(const monsters *m); bool mons_is_cornered(const monsters *m); bool mons_is_lurking(const monsters *m); bool mons_is_batty(const monsters *m); bool mons_is_influenced_by_sanctuary(const monsters *m); bool mons_is_fleeing_sanctuary(const monsters *m); bool mons_was_seen(const monsters *m); bool mons_is_known_mimic(const monsters *m); bool mons_is_unknown_mimic(const monsters *m); bool mons_is_skeletal(int mc); bool mons_class_is_slime(int mc); bool mons_is_slime(const monsters *mon); bool mons_class_is_plant(int mc); bool mons_is_plant(const monsters *mon); bool mons_eats_items(const monsters *mon); bool mons_eats_corpses(const monsters *mon); bool mons_eats_food(const monsters *mon); bool mons_has_lifeforce(const monsters *mon); monster_type mons_genus(int mc); monster_type mons_detected_base(monster_type mt); monster_type mons_species(int mc); bool mons_looks_stabbable(const monsters *m); bool mons_looks_distracted(const monsters *m); void mons_start_fleeing_from_sanctuary(monsters *monster); void mons_stop_fleeing_from_sanctuary(monsters *monster); bool mons_has_smite_attack(const monsters *monster); bool mons_class_is_confusable(int mc); bool mons_class_is_slowable(int mc); bool mons_class_is_stationary(int mc); bool mons_is_stationary(const monsters *mon); bool mons_is_fast( const monsters *mon ); bool mons_is_projectile(int mc); bool mons_is_insubstantial(int mc); bool mons_has_blood(int mc); bool invalid_monster(const monsters *mon); bool invalid_monster_type(monster_type mt); bool invalid_monster_index(int i); bool monster_shover(const monsters *m); bool monster_senior(const monsters *first, const monsters *second, bool fleeing = false); monster_type draco_subspecies(const monsters *mon); unsigned char ugly_thing_random_colour(); int ugly_thing_colour_offset(const unsigned char colour); std::string draconian_colour_name(monster_type mon_type); monster_type draconian_colour_by_name(const std::string &colour); monster_type random_monster_at_grid(const coord_def& p); monster_type random_monster_at_grid(dungeon_feature_type grid); void init_mon_name_cache(); monster_type get_monster_by_name(std::string name, bool exact = false); std::string do_mon_str_replacements(const std::string &msg, const monsters* monster, int s_type = -1); enum mon_body_shape { MON_SHAPE_HUMANOID, MON_SHAPE_HUMANOID_WINGED, MON_SHAPE_HUMANOID_TAILED, MON_SHAPE_HUMANOID_WINGED_TAILED, MON_SHAPE_CENTAUR, MON_SHAPE_NAGA, MON_SHAPE_QUADRUPED, MON_SHAPE_QUADRUPED_TAILLESS, MON_SHAPE_QUADRUPED_WINGED, MON_SHAPE_BAT, MON_SHAPE_SNAKE, // Including eels and worms MON_SHAPE_FISH, MON_SHAPE_INSECT, MON_SHAPE_INSECT_WINGED, MON_SHAPE_ARACHNID, MON_SHAPE_CENTIPEDE, MON_SHAPE_SNAIL, MON_SHAPE_PLANT, MON_SHAPE_FUNGUS, MON_SHAPE_ORB, MON_SHAPE_BLOB, MON_SHAPE_MISC }; mon_body_shape get_mon_shape(const monsters *mon); mon_body_shape get_mon_shape(const int type); std::string get_mon_shape_str(const monsters *mon); std::string get_mon_shape_str(const int type); std::string get_mon_shape_str(const mon_body_shape shape); bool mons_class_can_pass(int mc, const dungeon_feature_type grid); bool mons_can_pass(const monsters *mon, dungeon_feature_type grid); mon_inv_type equip_slot_to_mslot(equipment_type eq); mon_inv_type item_to_mslot(const item_def &item); int scan_mon_inv_randarts(const monsters *mon, artefact_prop_type ra_prop); bool player_or_mon_in_sanct(const monsters* monster); #endif