avoid "the Serpent of Hell the spectral Serpent of Hell"
[crawl.git] / crawl-ref / source / mon-util.cc
1 /**
2  * @file
3  * @brief Misc monster related functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "mon-util.h"
9
10 #include <algorithm>
11 #include <cmath>
12 #include <sstream>
13
14 #include "act-iter.h"
15 #include "areas.h"
16 #include "artefact.h"
17 #include "attitude-change.h"
18 #include "beam.h"
19 #include "cloud.h"
20 #include "colour.h"
21 #include "coordit.h"
22 #include "database.h"
23 #include "delay.h"
24 #include "dgn-overview.h"
25 #include "directn.h"
26 #include "dungeon.h"
27 #include "english.h"
28 #include "env.h"
29 #include "errors.h"
30 #include "fight.h"
31 #include "food.h"
32 #include "fprop.h"
33 #include "ghost.h"
34 #include "goditem.h"
35 #include "itemname.h"
36 #include "itemprop.h"
37 #include "items.h"
38 #include "libutil.h"
39 #include "mapmark.h"
40 #include "message.h"
41 #include "mgen_data.h"
42 #include "misc.h"
43 #include "mon-abil.h"
44 #include "mon-behv.h"
45 #include "mon-book.h"
46 #include "mon-death.h"
47 #include "mon-place.h"
48 #include "mon-poly.h"
49 #include "mon-tentacle.h"
50 #include "mutant-beast.h"
51 #include "notes.h"
52 #include "options.h"
53 #include "random.h"
54 #include "religion.h"
55 #include "showsymb.h"
56 #include "species.h"
57 #include "spl-summoning.h"
58 #include "spl-util.h"
59 #include "state.h"
60 #include "stringutil.h"
61 #include "terrain.h"
62 #include "tiledef-player.h"
63 #include "tilepick.h"
64 #include "tileview.h"
65 #include "timed_effects.h"
66 #include "traps.h"
67 #include "unicode.h"
68 #include "unwind.h"
69 #include "view.h"
70
71 static FixedVector < int, NUM_MONSTERS > mon_entry;
72
73 struct mon_display
74 {
75     ucs_t        glyph;
76     colour_t     colour;
77
78     mon_display(unsigned gly = 0, unsigned col = 0)
79        : glyph(gly), colour(col) { }
80 };
81
82 static mon_display monster_symbols[NUM_MONSTERS];
83
84 static bool initialised_randmons = false;
85 static vector<monster_type> monsters_by_habitat[NUM_HABITATS];
86 static vector<monster_type> species_by_habitat[NUM_HABITATS];
87
88 #include "mon-spell.h"
89 #include "mon-data.h"
90
91 #define MONDATASIZE ARRAYSZ(mondata)
92
93 static int _mons_exp_mod(monster_type mclass);
94
95 // Macro that saves some typing, nothing more.
96 #define smc get_monster_data(mc)
97 // ASSERT(smc) was getting really old
98 #define ASSERT_smc()                                                    \
99     do {                                                                \
100         if (!get_monster_data(mc))                                      \
101             die("bogus mc (no monster data): %s (%d)",                  \
102                 mons_type_name(mc, DESC_PLAIN).c_str(), mc);            \
103     } while (false)
104
105 /* ******************** BEGIN PUBLIC FUNCTIONS ******************** */
106
107 static habitat_type _grid2habitat(dungeon_feature_type grid)
108 {
109     if (feat_is_watery(grid))
110         return HT_WATER;
111
112     switch (grid)
113     {
114     case DNGN_LAVA:
115         return HT_LAVA;
116     case DNGN_FLOOR:
117     default:
118         return HT_LAND;
119     }
120 }
121
122 dungeon_feature_type habitat2grid(habitat_type ht)
123 {
124     switch (ht)
125     {
126     case HT_WATER:
127         return DNGN_DEEP_WATER;
128     case HT_LAVA:
129         return DNGN_LAVA;
130     case HT_LAND:
131     case HT_AMPHIBIOUS:
132     case HT_AMPHIBIOUS_LAVA:
133     default:
134         return DNGN_FLOOR;
135     }
136 }
137
138 static void _initialise_randmons()
139 {
140     for (int i = 0; i < NUM_HABITATS; ++i)
141     {
142         set<monster_type> tmp_species;
143         const dungeon_feature_type grid = habitat2grid(habitat_type(i));
144
145         for (monster_type mt = MONS_0; mt < NUM_MONSTERS; ++mt)
146         {
147             if (invalid_monster_type(mt))
148                 continue;
149
150             if (monster_habitable_grid(mt, grid))
151                 monsters_by_habitat[i].push_back(mt);
152
153             const monster_type species = mons_species(mt);
154             if (monster_habitable_grid(species, grid))
155                 tmp_species.insert(species);
156
157         }
158
159         for (auto type : tmp_species)
160             species_by_habitat[i].push_back(type);
161     }
162     initialised_randmons = true;
163 }
164
165 monster_type random_monster_at_grid(const coord_def& p, bool species)
166 {
167     if (!initialised_randmons)
168         _initialise_randmons();
169
170     const habitat_type ht = _grid2habitat(grd(p));
171     const vector<monster_type> &valid_mons = species ? species_by_habitat[ht]
172                                                      : monsters_by_habitat[ht];
173
174     ASSERT(!valid_mons.empty());
175     return valid_mons.empty() ? MONS_PROGRAM_BUG
176                               : valid_mons[ random2(valid_mons.size()) ];
177 }
178
179 typedef map<string, monster_type> mon_name_map;
180 static mon_name_map Mon_Name_Cache;
181
182 void init_mon_name_cache()
183 {
184     if (!Mon_Name_Cache.empty())
185         return;
186
187     for (const monsterentry &me : mondata)
188     {
189         string name = me.name;
190         lowercase(name);
191
192         const int          mtype = me.mc;
193         const monster_type mon   = monster_type(mtype);
194
195         // Deal sensibly with duplicate entries; refuse or allow the
196         // insert, depending on which should take precedence. Mostly we
197         // don't care, except looking up "rakshasa" and getting _FAKE
198         // breaks ?/M rakshasa.
199         if (Mon_Name_Cache.count(name))
200         {
201             if (mon == MONS_PLAYER_SHADOW
202                 || mon != MONS_SERPENT_OF_HELL
203                    && mons_species(mon) == MONS_SERPENT_OF_HELL)
204             {
205                 // Keep previous entry.
206                 continue;
207             }
208             else
209                 die("Un-handled duplicate monster name: %s", name.c_str());
210         }
211
212         Mon_Name_Cache[name] = mon;
213     }
214 }
215
216 static const char *_mon_entry_name(size_t idx)
217 {
218     return mondata[idx].name;
219 }
220
221 monster_type get_monster_by_name(string name, bool substring)
222 {
223     if (name.empty())
224         return MONS_PROGRAM_BUG;
225
226     lowercase(name);
227
228     if (!substring)
229     {
230         if (monster_type *mc = map_find(Mon_Name_Cache, name))
231             return *mc;
232         return MONS_PROGRAM_BUG;
233     }
234
235     size_t idx = find_earliest_match(name, (size_t) 0, ARRAYSZ(mondata),
236                                      always_true<size_t>, _mon_entry_name);
237     return idx == ARRAYSZ(mondata) ? MONS_PROGRAM_BUG
238                                    : (monster_type) mondata[idx].mc;
239 }
240
241 void init_monsters()
242 {
243     // First, fill static array with dummy values. {dlb}
244     mon_entry.init(-1);
245
246     // Next, fill static array with location of entry in mondata[]. {dlb}:
247     for (unsigned int i = 0; i < MONDATASIZE; ++i)
248         mon_entry[mondata[i].mc] = i;
249
250     // Finally, monsters yet with dummy entries point to TTTSNB(tm). {dlb}:
251     for (int &entry : mon_entry)
252         if (entry == -1)
253             entry = mon_entry[MONS_PROGRAM_BUG];
254
255     init_monster_symbols();
256 }
257
258 void init_monster_symbols()
259 {
260     map<unsigned, monster_type> base_mons;
261     for (monster_type mc = MONS_0; mc < NUM_MONSTERS; ++mc)
262     {
263         mon_display &md = monster_symbols[mc];
264         if (const monsterentry *me = get_monster_data(mc))
265         {
266             md.glyph  = me->basechar;
267             md.colour = me->colour;
268             auto it = base_mons.find(md.glyph);
269             if (it == base_mons.end() || it->first == MONS_PROGRAM_BUG)
270                 base_mons[md.glyph] = mc;
271         }
272     }
273
274     // Let those follow the feature settings, unless specifically overridden.
275     monster_symbols[MONS_ANIMATED_TREE].glyph = get_feat_symbol(DNGN_TREE);
276     for (monster_type mc = MONS_0; mc < NUM_MONSTERS; ++mc)
277         if (mons_genus(mc) == MONS_STATUE)
278             monster_symbols[mc].glyph = get_feat_symbol(DNGN_GRANITE_STATUE);
279
280     // Validate all glyphs, even those which didn't come from an override.
281     for (monster_type i = MONS_PROGRAM_BUG; i < NUM_MONSTERS; ++i)
282         if (wcwidth(monster_symbols[i].glyph) != 1)
283             monster_symbols[i].glyph = mons_base_char(i);
284 }
285
286 void set_resist(resists_t &all, mon_resist_flags res, int lev)
287 {
288     if (res > MR_LAST_MULTI)
289     {
290         ASSERT_RANGE(lev, 0, 2);
291         if (lev)
292             all |= res;
293         else
294             all &= ~res;
295         return;
296     }
297
298     ASSERT_RANGE(lev, -3, 5);
299     all = (all & ~(res * 7)) | (res * (lev & 7));
300 }
301
302 int get_mons_class_ac(monster_type mc)
303 {
304     const monsterentry *me = get_monster_data(mc);
305     return me ? me->AC : get_monster_data(MONS_PROGRAM_BUG)->AC;
306 }
307
308 int get_mons_class_ev(monster_type mc)
309 {
310     const monsterentry *me = get_monster_data(mc);
311     return me ? me->ev : get_monster_data(MONS_PROGRAM_BUG)->ev;
312 }
313
314 static resists_t _apply_holiness_resists(resists_t resists, mon_holy_type mh)
315 {
316     // Undead and non-living beings get full poison resistance.
317     if (mh & (MH_UNDEAD | MH_NONLIVING))
318         resists = (resists & ~(MR_RES_POISON * 7)) | (MR_RES_POISON * 3);
319
320     // Everything but natural creatures have full rNeg. Set here for the
321     // benefit of the monster_info constructor. If you change this, also
322     // change monster::res_negative_energy.
323     if (!(mh & MH_NATURAL))
324         resists = (resists & ~(MR_RES_NEG * 7)) | (MR_RES_NEG * 3);
325
326     return resists;
327 }
328
329 /**
330  * What special resistances does the given mutant beast facet provide?
331  *
332  * @param facet     The beast_facet in question, e.g. BF_FIRE.
333  * @return          A bitfield of resists corresponding to the given facet;
334  *                  e.g. MR_RES_FIRE for BF_FIRE.
335  */
336 static resists_t _beast_facet_resists(beast_facet facet)
337 {
338     static const map<beast_facet, resists_t> resists = {
339         { BF_STING, MR_RES_POISON },
340         { BF_FIRE,  MR_RES_FIRE },
341         { BF_SHOCK, MR_RES_ELEC },
342         { BF_OX,    MR_RES_COLD },
343     };
344
345     return lookup(resists, facet, 0);
346 }
347
348 resists_t get_mons_class_resists(monster_type mc)
349 {
350     const monsterentry *me = get_monster_data(mc);
351     const resists_t resists = me ? me->resists
352                                  : get_monster_data(MONS_PROGRAM_BUG)->resists;
353     // Don't apply fake holiness resists.
354     if (mons_is_sensed(mc))
355         return resists;
356
357     // Assumes that, when a monster's holiness differs from other monsters
358     // of the same type, that only adds resistances, never removes them.
359     // Currently the only such case is MF_FAKE_UNDEAD.
360     return _apply_holiness_resists(resists, mons_class_holiness(mc));
361 }
362
363 resists_t get_mons_resists(const monster* mon)
364 {
365     get_tentacle_head(mon);
366
367     resists_t resists = get_mons_class_resists(mon->type);
368
369     if (mons_is_ghost_demon(mon->type))
370         resists |= mon->ghost->resists;
371
372     if (mons_genus(mon->type) == MONS_DRACONIAN
373             && mon->type != MONS_DRACONIAN
374         || mon->type == MONS_TIAMAT
375         || mons_genus(mon->type) == MONS_DEMONSPAWN
376             && mon->type != MONS_DEMONSPAWN)
377     {
378         monster_type subspecies = draco_or_demonspawn_subspecies(mon);
379         if (subspecies != mon->type)
380             resists |= get_mons_class_resists(subspecies);
381     }
382
383     if (mon->props.exists(MUTANT_BEAST_FACETS))
384         for (auto facet : mon->props[MUTANT_BEAST_FACETS].get_vector())
385             resists |= _beast_facet_resists((beast_facet)facet.get_int());
386
387     // This is set from here in case they're undead due to the
388     // MF_FAKE_UNDEAD flag. See the comment in get_mons_class_resists.
389     return _apply_holiness_resists(resists, mon->holiness());
390 }
391
392 int get_mons_resist(const monster* mon, mon_resist_flags res)
393 {
394     return get_resist(get_mons_resists(mon), res);
395 }
396
397 // Returns true if the monster successfully resists this attempt to poison it.
398 const bool monster_resists_this_poison(const monster* mons, bool force)
399 {
400     const int res = mons->res_poison();
401     if (res >= 3)
402         return true;
403     if (!force && res >= 1 && x_chance_in_y(2, 3))
404         return true;
405     return false;
406 }
407
408 monster* monster_at(const coord_def &pos)
409 {
410     if (!in_bounds(pos))
411         return nullptr;
412
413     const int mindex = mgrd(pos);
414     if (mindex == NON_MONSTER)
415         return nullptr;
416
417     ASSERT(mindex <= MAX_MONSTERS);
418     return &menv[mindex];
419 }
420
421 /// Are any of the bits set?
422 bool mons_class_flag(monster_type mc, monclass_flags_t bits)
423 {
424     const monsterentry * const me = get_monster_data(mc);
425     return me && (me->bitfields & bits);
426 }
427
428 int monster::wearing(equipment_type slot, int sub_type, bool calc_unid) const
429 {
430     int ret = 0;
431     const item_def *item = 0;
432
433     switch (slot)
434     {
435     case EQ_WEAPON:
436     case EQ_STAFF:
437         {
438             const mon_inv_type end = mons_wields_two_weapons(this)
439                                      ? MSLOT_ALT_WEAPON : MSLOT_WEAPON;
440
441             for (int i = MSLOT_WEAPON; i <= end; i = i + 1)
442             {
443                 item = mslot_item((mon_inv_type) i);
444                 if (item && item->base_type == (slot == EQ_WEAPON ? OBJ_WEAPONS
445                                                                   : OBJ_STAVES)
446                     && item->sub_type == sub_type
447                     // Weapon subtypes are always known, staves not.
448                     && (slot == EQ_WEAPON || calc_unid
449                         || item_type_known(*item)))
450                 {
451                     ret++;
452                 }
453             }
454         }
455         break;
456
457     case EQ_ALL_ARMOUR:
458     case EQ_CLOAK:
459     case EQ_HELMET:
460     case EQ_GLOVES:
461     case EQ_BOOTS:
462     case EQ_SHIELD:
463         item = mslot_item(MSLOT_SHIELD);
464         if (item && item->is_type(OBJ_ARMOUR, sub_type))
465             ret++;
466         // Don't check MSLOT_ARMOUR for EQ_SHIELD
467         if (slot == EQ_SHIELD)
468             break;
469         // intentional fall-through
470     case EQ_BODY_ARMOUR:
471         item = mslot_item(MSLOT_ARMOUR);
472         if (item && item->is_type(OBJ_ARMOUR, sub_type))
473             ret++;
474         break;
475
476     case EQ_AMULET:
477     case EQ_AMULET_PLUS:
478     case EQ_RINGS:
479     case EQ_RINGS_PLUS:
480         item = mslot_item(MSLOT_JEWELLERY);
481         if (item && item->is_type(OBJ_JEWELLERY, sub_type)
482             && (calc_unid || item_type_known(*item)))
483         {
484             if (slot == EQ_RINGS_PLUS || slot == EQ_AMULET_PLUS)
485                 ret += item->plus;
486             else
487                 ret++;
488         }
489         break;
490     default:
491         die("invalid slot %d for monster::wearing()", slot);
492     }
493     return ret;
494 }
495
496 int monster::wearing_ego(equipment_type slot, int special, bool calc_unid) const
497 {
498     int ret = 0;
499     const item_def *item = 0;
500
501     switch (slot)
502     {
503     case EQ_WEAPON:
504         {
505             const mon_inv_type end = mons_wields_two_weapons(this)
506                                      ? MSLOT_ALT_WEAPON : MSLOT_WEAPON;
507
508             for (int i = MSLOT_WEAPON; i <= end; i++)
509             {
510                 item = mslot_item((mon_inv_type) i);
511                 if (item && item->base_type == OBJ_WEAPONS
512                     && get_weapon_brand(*item) == special
513                     && (calc_unid || item_type_known(*item)))
514                 {
515                     ret++;
516                 }
517             }
518         }
519         break;
520
521     case EQ_ALL_ARMOUR:
522     case EQ_CLOAK:
523     case EQ_HELMET:
524     case EQ_GLOVES:
525     case EQ_BOOTS:
526     case EQ_SHIELD:
527         item = mslot_item(MSLOT_SHIELD);
528         if (item && item->base_type == OBJ_ARMOUR
529             && get_armour_ego_type(*item) == special
530             && (calc_unid || item_type_known(*item)))
531         {
532             ret++;
533         }
534         // Don't check MSLOT_ARMOUR for EQ_SHIELD
535         if (slot == EQ_SHIELD)
536             break;
537         // intentional fall-through
538     case EQ_BODY_ARMOUR:
539         item = mslot_item(MSLOT_ARMOUR);
540         if (item && item->base_type == OBJ_ARMOUR
541             && get_armour_ego_type(*item) == special
542             && (calc_unid || item_type_known(*item)))
543         {
544             ret++;
545         }
546         break;
547
548     case EQ_AMULET:
549     case EQ_STAFF:
550     case EQ_RINGS:
551     case EQ_RINGS_PLUS:
552         // No egos.
553         break;
554
555     default:
556         die("invalid slot %d for monster::wearing_ego()", slot);
557     }
558     return ret;
559 }
560
561 int monster::scan_artefacts(artefact_prop_type ra_prop, bool calc_unid,
562                             vector<item_def> *matches) const
563 {
564     UNUSED(matches); //TODO: implement this when it will be required somewhere
565     int ret = 0;
566
567     // TODO: do we really want to prevent randarts from working for zombies?
568     if (mons_itemuse(this) >= MONUSE_STARTING_EQUIPMENT)
569     {
570         const int weap      = inv[MSLOT_WEAPON];
571         const int second    = inv[MSLOT_ALT_WEAPON]; // Two-headed ogres, etc.
572         const int armour    = inv[MSLOT_ARMOUR];
573         const int shld      = inv[MSLOT_SHIELD];
574         const int jewellery = inv[MSLOT_JEWELLERY];
575
576         if (weap != NON_ITEM && mitm[weap].base_type == OBJ_WEAPONS
577             && is_artefact(mitm[weap]))
578         {
579             ret += artefact_property(mitm[weap], ra_prop);
580         }
581
582         if (second != NON_ITEM && mitm[second].base_type == OBJ_WEAPONS
583             && is_artefact(mitm[second]) && mons_wields_two_weapons(this))
584         {
585             ret += artefact_property(mitm[second], ra_prop);
586         }
587
588         if (armour != NON_ITEM && mitm[armour].base_type == OBJ_ARMOUR
589             && is_artefact(mitm[armour]))
590         {
591             ret += artefact_property(mitm[armour], ra_prop);
592         }
593
594         if (shld != NON_ITEM && mitm[shld].base_type == OBJ_ARMOUR
595             && is_artefact(mitm[shld]))
596         {
597             ret += artefact_property(mitm[shld], ra_prop);
598         }
599
600         if (jewellery != NON_ITEM && mitm[jewellery].base_type == OBJ_JEWELLERY
601             && is_artefact(mitm[jewellery]))
602         {
603             ret += artefact_property(mitm[jewellery], ra_prop);
604         }
605     }
606
607     return ret;
608 }
609
610 mon_holy_type holiness_by_name(string name)
611 {
612     lowercase(name);
613     for (const auto bit : mon_holy_type::range())
614     {
615         if (name == holiness_name(mon_holy_type::exponent(bit)))
616             return mon_holy_type::exponent(bit);
617     }
618     return MH_NONE;
619 }
620
621 const char * holiness_name(mon_holy_type_flags which_holiness)
622 {
623     switch (which_holiness)
624     {
625     case MH_HOLY:
626         return "holy";
627     case MH_NATURAL:
628         return "natural";
629     case MH_UNDEAD:
630         return "undead";
631     case MH_DEMONIC:
632         return "demonic";
633     case MH_NONLIVING:
634         return "nonliving";
635     case MH_PLANT:
636         return "plant";
637     case MH_EVIL:
638         return "evil";
639     case MH_UNHOLY:
640         return "unholy";
641     default:
642         return "bug";
643     }
644 }
645
646 string holiness_description(mon_holy_type holiness)
647 {
648     string description = "";
649     for (const auto bit : mon_holy_type::range())
650     {
651         if (holiness & bit)
652         {
653             if (!description.empty())
654                 description += ",";
655             description += holiness_name(bit);
656         }
657     }
658     return description;
659 }
660
661 mon_holy_type mons_class_holiness(monster_type mc)
662 {
663     ASSERT_smc();
664     return smc->holiness;
665 }
666
667 bool mons_class_is_stationary(monster_type mc)
668 {
669     return mons_class_flag(mc, M_STATIONARY);
670 }
671
672 /**
673  * Can killing this class of monster ever reward xp?
674  *
675  * This answers whether any agent could receive XP for killing a monster of
676  * this class. Monsters that fail this have M_NO_EXP_GAIN set.
677  * @param mc       The monster type
678  * @param indirect If true this will count monsters that are parts of a parent
679  *                 monster as xp rewarding even if the parts themselves don't
680  *                 reward xp (e.g. tentacles).
681  * @returns True if killing a monster of this class could reward xp, false
682  * otherwise.
683  */
684 bool mons_class_gives_xp(monster_type mc, bool indirect)
685 {
686     return !mons_class_flag(mc, M_NO_EXP_GAIN)
687         || (indirect && mons_is_tentacle_or_tentacle_segment(mc));
688 }
689
690 /**
691  * Can killing this monster reward xp to the given actor?
692  *
693  * This answers whether the player or a monster could ever receive XP for
694  * killing the monster, assuming an appropriate kill_type.
695  * @param mon      The monster.
696  * @param agent    The actor who would be responsible for the kill.
697  * @returns True if killing the monster will reward the agent with xp, false
698  * otherwise.
699  */
700 bool mons_gives_xp(const monster* victim, const actor* agent)
701 {
702     ASSERT(victim && agent);
703
704     // Either the player killed a monster that's no reward (created friendly or
705     // the Royal Jelly spawns), or a monster killed an aligned monster, or a
706     // friendly monster killed a no-reward monster.
707     bool killed_friend;
708     if (agent->is_player())
709         killed_friend = testbits(victim->flags, MF_NO_REWARD);
710     else
711     {
712         killed_friend = mons_aligned(victim, agent)
713             || testbits(victim->flags, MF_NO_REWARD)
714             && mons_aligned(&you, agent);
715     }
716     return !victim->is_summoned()                   // no summons
717         && !victim->has_ench(ENCH_ABJ)              // not-really-summons
718         && !victim->has_ench(ENCH_FAKE_ABJURATION)  // no animated remains
719         && mons_class_gives_xp(victim->type)        // class must reward xp
720         && !testbits(victim->flags, MF_WAS_NEUTRAL) // no neutral monsters
721         && !killed_friend;
722 }
723
724 bool mons_class_is_threatening(monster_type mo)
725 {
726     return !mons_class_flag(mo, M_NO_THREAT);
727 }
728
729 bool mons_is_threatening(const monster *mons)
730 {
731     return mons_class_is_threatening(mons->type) || mons_is_active_ballisto(mons);
732 }
733
734 /**
735  * Is this an active ballistomycete?
736  *
737  * @param mon             The monster
738  * @returns True if the monster is an active ballistomycete, false otherwise.
739  */
740 bool mons_is_active_ballisto(const monster* mon)
741 {
742     return mon->type == MONS_BALLISTOMYCETE && mon->ballisto_activity;
743 }
744
745 /**
746  * Is this monster class firewood?
747  *
748  * Firewood monsters are harmless stationary monsters than don't give xp. These
749  * are worthless obstacles: not to be attacked by default, but may be cut down
750  * to get to target even if coaligned.
751  * @param mc The monster type
752  * @returns True if the monster class is firewood, false otherwise.
753  */
754 bool mons_class_is_firewood(monster_type mc)
755 {
756     return mons_class_is_stationary(mc)
757            && mons_class_flag(mc, M_NO_THREAT)
758            && !mons_is_tentacle_or_tentacle_segment(mc);
759 }
760
761 /**
762  * Is this monster firewood?
763  *
764  * Firewood monsters are stationary monsters than don't give xp.
765  * @param mon             The monster
766  * @returns True if the monster is firewood, false otherwise.
767  */
768 bool mons_is_firewood(const monster* mon)
769 {
770     return mons_class_is_firewood(mon->type);
771 }
772
773 // "body" in a purely grammatical sense.
774 bool mons_has_body(const monster* mon)
775 {
776     if (mon->type == MONS_FLYING_SKULL
777         || mon->type == MONS_CURSE_SKULL
778         || mon->type == MONS_CURSE_TOE
779         || mons_class_is_animated_weapon(mon->type))
780     {
781         return false;
782     }
783
784     switch (mons_base_char(mon->type))
785     {
786     case 'P':
787     case 'v':
788     case 'G':
789     case '*':
790     case '%':
791     case 'J':
792         return false;
793     }
794
795     return true;
796 }
797
798 bool mons_has_flesh(const monster* mon)
799 {
800     if (mon->is_skeletal() || mon->is_insubstantial())
801         return false;
802
803     // Dictionary says:
804     // 1. (12) flesh -- (the soft tissue of the body of a vertebrate:
805     //    mainly muscle tissue and fat)
806     // 3. pulp, flesh -- (a soft moist part of a fruit)
807     // yet I exclude sense 3 anyway but include arthropods and molluscs.
808     return !(mon->holiness() & (MH_PLANT | MH_NONLIVING))
809            && mons_genus(mon->type) != MONS_GIANT_EYEBALL
810            && mons_genus(mon->type) != MONS_GIANT_ORANGE_BRAIN
811            && mons_genus(mon->type) != MONS_JELLY
812            && mon->type != MONS_DEATH_COB; // plant!
813 }
814
815 // Difference in speed between monster and the player for Cheibriados'
816 // purposes. This is the speed difference disregarding the player's
817 // slow status.
818 int cheibriados_monster_player_speed_delta(const monster* mon)
819 {
820     // Ignore the Slow effect.
821     unwind_var<int> ignore_slow(you.duration[DUR_SLOW], 0);
822     const int pspeed = 1000 / (player_movement_speed() * player_speed());
823     dprf("Your delay: %d, your speed: %d, mon speed: %d",
824         player_movement_speed(), pspeed, mon->speed);
825     return mon->speed - pspeed;
826 }
827
828 bool cheibriados_thinks_mons_is_fast(const monster* mon)
829 {
830     return cheibriados_monster_player_speed_delta(mon) > 0;
831 }
832
833 // Dithmenos also hates fire users and generally fiery beings.
834 bool mons_is_fiery(const monster* mon)
835 {
836     if (mons_genus(mon->type) == MONS_DRACONIAN
837         && draco_or_demonspawn_subspecies(mon) == MONS_RED_DRACONIAN)
838     {
839         return true;
840     }
841     return mon->has_attack_flavour(AF_FIRE)
842            || mon->has_attack_flavour(AF_PURE_FIRE)
843            || mon->has_attack_flavour(AF_STICKY_FLAME)
844            || mon->has_spell_of_type(SPTYP_FIRE);
845 }
846
847 bool mons_is_projectile(monster_type mc)
848 {
849     return mons_class_flag(mc, M_PROJECTILE);
850 }
851
852 bool mons_is_projectile(const monster* mon)
853 {
854     return mons_is_projectile(mon->type);
855 }
856
857 bool mons_is_boulder(const monster* mon)
858 {
859     return mon->type == MONS_BOULDER_BEETLE && mon->rolling();
860 }
861
862 static bool _mons_class_is_clingy(monster_type type)
863 {
864     return mons_genus(type) == MONS_SPIDER || type == MONS_GIANT_GECKO
865         || type == MONS_GIANT_COCKROACH || type == MONS_DEMONIC_CRAWLER
866         || type == MONS_DART_SLUG;
867 }
868
869 bool mons_can_cling_to_walls(const monster* mon)
870 {
871     return _mons_class_is_clingy(mon->type);
872 }
873
874 // Conjuration or Hexes. Summoning and Necromancy make the monster a creature
875 // at least in some degree, golems have a chem granting them that.
876 bool mons_is_object(monster_type mc)
877 {
878     return mons_is_conjured(mc)
879            || mc == MONS_TWISTER
880            // unloading seeds helps the species
881            || mc == MONS_GIANT_SPORE
882            || mc == MONS_LURKING_HORROR
883            || mc == MONS_DANCING_WEAPON
884            || mc == MONS_LIGHTNING_SPIRE;
885 }
886
887 bool mons_has_blood(monster_type mc)
888 {
889     return mons_class_flag(mc, M_COLD_BLOOD)
890            || mons_class_flag(mc, M_WARM_BLOOD);
891 }
892
893 bool mons_is_sensed(monster_type mc)
894 {
895     return mc == MONS_SENSED
896            || mc == MONS_SENSED_FRIENDLY
897            || mc == MONS_SENSED_TRIVIAL
898            || mc == MONS_SENSED_EASY
899            || mc == MONS_SENSED_TOUGH
900            || mc == MONS_SENSED_NASTY;
901 }
902
903 bool mons_allows_beogh(const monster* mon)
904 {
905     if (!species_is_orcish(you.species) || you_worship(GOD_BEOGH))
906         return false; // no one else gives a damn
907
908     return mons_genus(mon->type) == MONS_ORC
909            && mon->is_priest() && mon->god == GOD_BEOGH;
910 }
911
912 bool mons_allows_beogh_now(const monster* mon)
913 {
914     // Do the expensive LOS check last.
915     return mon && mons_allows_beogh(mon)
916                && !mon->is_summoned() && !mon->friendly()
917                && !silenced(mon->pos()) && !mon->has_ench(ENCH_MUTE)
918                && !mons_is_confused(mon) && mons_is_seeking(mon)
919                && mon->foe == MHITYOU && !mons_is_immotile(mon)
920                && you.visible_to(mon) && you.can_see(*mon);
921 }
922
923 // Returns true for monsters that obviously (to the player) feel
924 // "thematically at home" in a branch. Currently used for native
925 // monsters recognising traps and patrolling branch entrances.
926 bool mons_is_native_in_branch(const monster* mons,
927                               const branch_type branch)
928 {
929     switch (branch)
930     {
931     case BRANCH_ELF:
932         return mons_genus(mons->type) == MONS_ELF;
933
934     case BRANCH_ORC:
935         return mons_genus(mons->type) == MONS_ORC;
936
937     case BRANCH_SHOALS:
938         return mons_species(mons->type) == MONS_CYCLOPS
939                || mons_species(mons->type) == MONS_MERFOLK
940                || mons->type == MONS_HARPY;
941
942     case BRANCH_SLIME:
943         return mons_is_slime(mons);
944
945     case BRANCH_SNAKE:
946         return mons_genus(mons->type) == MONS_NAGA
947                || mons_genus(mons->type) == MONS_SALAMANDER
948                || mons_genus(mons->type) == MONS_SNAKE;
949
950     case BRANCH_ZOT:
951         return mons_genus(mons->type) == MONS_DRACONIAN
952                || mons->type == MONS_ORB_GUARDIAN
953                || mons->type == MONS_ORB_OF_FIRE
954                || mons->type == MONS_DEATH_COB
955                || mons->type == MONS_KILLER_KLOWN;
956
957     case BRANCH_VAULTS:
958         return mons_genus(mons->type) == MONS_HUMAN;
959
960     case BRANCH_CRYPT:
961         return mons->holiness() == MH_UNDEAD;
962
963     case BRANCH_TOMB:
964         return mons_genus(mons->type) == MONS_MUMMY
965               || mons->type == MONS_ANUBIS_GUARD
966               || mons->type == MONS_USHABTI
967               || mons->type == MONS_DEATH_SCARAB;
968
969     case BRANCH_SPIDER:
970         return mons_genus(mons->type) == MONS_SPIDER;
971
972     case BRANCH_ABYSS:
973         return mons_is_abyssal_only(mons->type)
974                || mons->type == MONS_ABOMINATION_LARGE
975                || mons->type == MONS_ABOMINATION_SMALL
976                || mons->type == MONS_TENTACLED_MONSTROSITY
977                || mons->type == MONS_TENTACLED_STARSPAWN
978                || mons->type == MONS_THRASHING_HORROR
979                || mons->type == MONS_UNSEEN_HORROR
980                || mons->type == MONS_WORLDBINDER;
981
982     default:
983         return false;
984     }
985 }
986
987 bool mons_is_abyssal_only(monster_type mc)
988 {
989     switch (mc)
990     {
991     case MONS_ANCIENT_ZYME:
992     case MONS_ELDRITCH_TENTACLE:
993     case MONS_ELDRITCH_TENTACLE_SEGMENT:
994     case MONS_LURKING_HORROR:
995     case MONS_WRETCHED_STAR:
996         return true;
997     default:
998         return false;
999     }
1000 }
1001
1002 // Monsters considered as "slime" for Jiyva.
1003 bool mons_class_is_slime(monster_type mc)
1004 {
1005     return mons_genus(mc) == MONS_JELLY
1006            || mons_genus(mc) == MONS_GIANT_EYEBALL
1007            || mons_genus(mc) == MONS_GIANT_ORANGE_BRAIN;
1008 }
1009
1010 bool mons_is_slime(const monster* mon)
1011 {
1012     return mons_class_is_slime(mon->type);
1013 }
1014
1015 bool herd_monster(const monster* mon)
1016 {
1017     return mons_class_flag(mon->type, M_HERD);
1018 }
1019
1020 // Plant or fungus or really anything with
1021 // permanent plant holiness
1022 bool mons_class_is_plant(monster_type mc)
1023 {
1024     return bool(mons_class_holiness(mc) & MH_PLANT);
1025 }
1026
1027 bool mons_is_plant(const monster* mon)
1028 {
1029     return mons_class_is_plant(mon->type);
1030 }
1031
1032 bool mons_eats_items(const monster* mon)
1033 {
1034     return mons_class_flag(mon->type, M_EAT_ITEMS)
1035            || mon->has_ench(ENCH_EAT_ITEMS);
1036 }
1037
1038 bool invalid_monster(const monster* mon)
1039 {
1040     return !mon || invalid_monster_type(mon->type);
1041 }
1042
1043 bool invalid_monster_type(monster_type mt)
1044 {
1045     return mt < 0 || mt >= NUM_MONSTERS
1046            || mon_entry[mt] == mon_entry[MONS_PROGRAM_BUG];
1047 }
1048
1049 bool invalid_monster_index(int i)
1050 {
1051     return i < 0 || i >= MAX_MONSTERS;
1052 }
1053
1054 bool mons_is_statue(monster_type mc)
1055 {
1056     return mc == MONS_ORANGE_STATUE
1057            || mc == MONS_OBSIDIAN_STATUE
1058            || mc == MONS_ICE_STATUE
1059            || mc == MONS_ROXANNE;
1060 }
1061
1062 /**
1063  * The mimic [(cackles|chortles...) and ]vanishes in[ a puff of smoke]!
1064  *
1065  * @param pos       The mimic's location.
1066  * @param name      The mimic's name.
1067  */
1068 static void _mimic_vanish(const coord_def& pos, const string& name)
1069 {
1070     const bool can_place_smoke = !cloud_at(pos);
1071     if (can_place_smoke)
1072         place_cloud(CLOUD_BLACK_SMOKE, pos, 2 + random2(2), nullptr);
1073     if (!you.see_cell(pos))
1074         return;
1075
1076     const char* const smoke_str = can_place_smoke ? " in a puff of smoke" : "";
1077
1078     const bool can_cackle = !silenced(pos) && !silenced(you.pos());
1079     const string db_cackle = getSpeakString("_laughs_");
1080     const string cackle = db_cackle != "" ? db_cackle : "cackles";
1081     const string cackle_str = can_cackle ? cackle + " and " : "";
1082
1083     mprf("The %s mimic %svanishes%s!",
1084          name.c_str(), cackle_str.c_str(), smoke_str);
1085     interrupt_activity(AI_MIMIC);
1086 }
1087
1088 /**
1089  * Clean up a "feature" that a mimic was pretending to be.
1090  *
1091  * @param pos   The location of the 'feature'.
1092  */
1093 static void _destroy_mimic_feature(const coord_def &pos)
1094 {
1095 #if TAG_MAJOR_VERSION == 34
1096     const dungeon_feature_type feat = grd(pos);
1097 #endif
1098
1099     unnotice_feature(level_pos(level_id::current(), pos));
1100     grd(pos) = DNGN_FLOOR;
1101     env.level_map_mask(pos) &= ~MMT_MIMIC;
1102     set_terrain_changed(pos);
1103     remove_markers_and_listeners_at(pos);
1104
1105 #if TAG_MAJOR_VERSION == 34
1106     if (feat_is_door(feat))
1107         env.level_map_mask(pos) |= MMT_WAS_DOOR_MIMIC;
1108 #endif
1109 }
1110
1111 void discover_mimic(const coord_def& pos)
1112 {
1113     item_def* item = item_mimic_at(pos);
1114     const bool feature_mimic = !item && feature_mimic_at(pos);
1115     // Is there really a mimic here?
1116     if (!item && !feature_mimic)
1117         return;
1118
1119     const dungeon_feature_type feat = grd(pos);
1120
1121     // If the feature has been destroyed, don't create a floor mimic.
1122     if (feature_mimic && !feat_is_mimicable(feat, false))
1123     {
1124         env.level_map_mask(pos) &= ~MMT_MIMIC;
1125         return;
1126     }
1127
1128     const string name = feature_mimic ? "the " + string(feat_type_name(feat))
1129                                       : item->name(DESC_THE, false, false,
1130                                                              false, true);
1131     const bool plural = feature_mimic ? false : item->quantity > 1;
1132
1133 #ifdef USE_TILE
1134     tileidx_t tile = tileidx_feature(pos);
1135     apply_variations(env.tile_flv(pos), &tile, pos);
1136 #endif
1137
1138     if (you.see_cell(pos))
1139         mprf("%s %s a mimic!", name.c_str(), plural ? "are" : "is");
1140
1141     const string shortname = feature_mimic ? feat_type_name(feat)
1142                                            : item->name(DESC_BASENAME);
1143     if (item)
1144         destroy_item(item->index(), true);
1145     else
1146         _destroy_mimic_feature(pos);
1147     _mimic_vanish(pos, shortname);
1148
1149     // Just in case there's another one.
1150     if (mimic_at(pos))
1151         discover_mimic(pos);
1152 }
1153
1154 void discover_shifter(monster* shifter)
1155 {
1156     shifter->flags |= MF_KNOWN_SHIFTER;
1157 }
1158
1159 bool mons_is_demon(monster_type mc)
1160 {
1161     return mons_class_holiness(mc) & MH_DEMONIC
1162              && (mons_demon_tier(mc) != 0 && mc != MONS_ANTAEUS
1163                  || mons_species(mc) == MONS_RAKSHASA);
1164 }
1165
1166 int mons_demon_tier(monster_type mc)
1167 {
1168     switch (mons_base_char(mc))
1169     {
1170     case 'C':
1171         if (mc != MONS_ANTAEUS)
1172             return 0;
1173         // intentional fall-through for Antaeus
1174     case '&':
1175         return -1;
1176     case '1':
1177         return 1;
1178     case '2':
1179         return 2;
1180     case '3':
1181         return 3;
1182     case '4':
1183         return 4;
1184     case '5':
1185         return 5;
1186     default:
1187         return 0;
1188     }
1189 }
1190
1191 // Beware; returns false for Tiamat!
1192 bool mons_is_draconian(monster_type mc)
1193 {
1194     return mc >= MONS_FIRST_DRACONIAN && mc <= MONS_LAST_DRACONIAN;
1195 }
1196
1197 bool mons_is_base_draconian(monster_type mc)
1198 {
1199     return mc >= MONS_FIRST_DRACONIAN && mc <= MONS_LAST_BASE_DRACONIAN;
1200 }
1201
1202 bool mons_is_demonspawn(monster_type mc)
1203 {
1204     return
1205 #if TAG_MAJOR_VERSION == 34
1206         mc == MONS_DEMONSPAWN ||
1207 #endif
1208         mc >= MONS_FIRST_DEMONSPAWN && mc <= MONS_LAST_DEMONSPAWN;
1209 }
1210
1211 // Conjured (as opposed to summoned) monsters are actually here, even
1212 // though they're typically volatile (like, made of real fire). As such,
1213 // they should be immune to Abjuration or Recall. Also, they count as
1214 // things rather than beings.
1215 bool mons_is_conjured(monster_type mc)
1216 {
1217     return mons_is_projectile(mc)
1218            || mons_is_avatar(mc)
1219            || mons_class_flag(mc, M_CONJURED);
1220 }
1221
1222 size_type mons_class_body_size(monster_type mc)
1223 {
1224     // Should pass base_type to get the right size for zombies, skeletons &c.
1225     // For normal monsters, base_type is set to type in the constructor.
1226     const monsterentry *e = get_monster_data(mc);
1227     return e ? e->size : SIZE_MEDIUM;
1228 }
1229
1230 int max_corpse_chunks(monster_type mc)
1231 {
1232     switch (mons_class_body_size(mc))
1233     {
1234     case SIZE_TINY:
1235         return 1;
1236     case SIZE_LITTLE:
1237         return 2;
1238     case SIZE_SMALL:
1239         return 3;
1240     case SIZE_MEDIUM:
1241         return 4;
1242     case SIZE_LARGE:
1243         return 9;
1244     case SIZE_BIG:
1245         return 10;
1246     case SIZE_GIANT:
1247         return 12;
1248     default:
1249         return 0;
1250     }
1251 }
1252
1253 corpse_effect_type mons_corpse_effect(monster_type mc)
1254 {
1255     ASSERT_smc();
1256     return smc->corpse_thingy;
1257 }
1258
1259 monster_type mons_genus(monster_type mc)
1260 {
1261     if (mc == RANDOM_DRACONIAN || mc == RANDOM_BASE_DRACONIAN
1262         || mc == RANDOM_NONBASE_DRACONIAN
1263         || (mc == MONS_PLAYER_ILLUSION && species_is_draconian(you.species)))
1264     {
1265         return MONS_DRACONIAN;
1266     }
1267
1268     if (mc == RANDOM_DEMONSPAWN || mc == RANDOM_BASE_DEMONSPAWN
1269         || mc == RANDOM_NONBASE_DEMONSPAWN)
1270     {
1271         return MONS_DEMONSPAWN;
1272     }
1273
1274     if (mc == MONS_NO_MONSTER)
1275         return MONS_NO_MONSTER;
1276
1277     ASSERT_smc();
1278     return smc->genus;
1279 }
1280
1281 monster_type mons_species(monster_type mc)
1282 {
1283     const monsterentry *me = get_monster_data(mc);
1284     return me ? me->species : MONS_PROGRAM_BUG;
1285 }
1286
1287 monster_type draco_or_demonspawn_subspecies(monster_type type,
1288                                             monster_type base)
1289 {
1290     const monster_type species = mons_species(type);
1291
1292     if ((species == MONS_DRACONIAN || species == MONS_DEMONSPAWN)
1293         && type != species)
1294     {
1295         return base;
1296     }
1297
1298     return species;
1299 }
1300
1301 monster_type draco_or_demonspawn_subspecies(const monster* mon)
1302 {
1303     ASSERT(mons_genus(mon->type) == MONS_DRACONIAN
1304            || mons_genus(mon->type) == MONS_DEMONSPAWN);
1305
1306     if (mon->type == MONS_PLAYER_ILLUSION
1307         && mons_genus(mon->type) == MONS_DRACONIAN)
1308     {
1309         return player_species_to_mons_species(mon->ghost->species);
1310     }
1311
1312     return draco_or_demonspawn_subspecies(mon->type, mon->base_monster);
1313 }
1314
1315 monster_type mons_detected_base(monster_type mc)
1316 {
1317     return mons_genus(mc);
1318 }
1319
1320 /** Does a monster of this type behold opponents like a siren?
1321  */
1322 bool mons_is_siren_beholder(monster_type mc)
1323 {
1324     return mc == MONS_SIREN || mc == MONS_MERFOLK_AVATAR;
1325 }
1326
1327 /** Does this monster behold opponents like a siren?
1328  *  Ignores any disabilities, checking only the monster's type.
1329  */
1330 bool mons_is_siren_beholder(const monster* mons)
1331 {
1332     return mons_is_siren_beholder(mons->type);
1333 }
1334
1335 int get_shout_noise_level(const shout_type shout)
1336 {
1337     switch (shout)
1338     {
1339     case S_SILENT:
1340         return 0;
1341     case S_HISS:
1342     case S_VERY_SOFT:
1343         return 4;
1344     case S_SOFT:
1345         return 6;
1346     case S_GURGLE:
1347     case S_LOUD:
1348         return 10;
1349     case S_SHOUT2:
1350     case S_ROAR:
1351     case S_VERY_LOUD:
1352         return 12;
1353     case S_RUMBLE:
1354         return 16;
1355
1356     default:
1357         return 8;
1358     }
1359 }
1360
1361 // Only beasts and chaos spawns use S_RANDOM for noise type.
1362 // Pandemonium lords can also get here, but this is mostly used for the
1363 // "says" verb used for insults.
1364 static bool _shout_fits_monster(monster_type mc, int shout)
1365 {
1366     if (shout == NUM_SHOUTS || shout >= NUM_LOUDNESS || shout == S_SILENT)
1367         return false;
1368
1369     // Chaos spawns can do anything but demon taunts, since they're
1370     // not coherent enough to actually say words.
1371     if (mc == MONS_CHAOS_SPAWN)
1372         return shout != S_DEMON_TAUNT;
1373
1374     // For Pandemonium lords, almost everything is fair game. It's only
1375     // used for the shouting verb ("say", "bellow", "roar", etc.) anyway.
1376     if (mc != MONS_HELL_BEAST && mc != MONS_MUTANT_BEAST)
1377         return true;
1378
1379     switch (shout)
1380     {
1381     // Bees, cherubs and two-headed ogres never fit.
1382     case S_SHOUT2:
1383     case S_BUZZ:
1384     case S_CHERUB:
1385     // The beast cannot speak.
1386     case S_DEMON_TAUNT:
1387         return false;
1388     default:
1389         return true;
1390     }
1391 }
1392
1393 // If demon_shout is true, we're trying to find a random verb and
1394 // loudness for a Pandemonium lord trying to shout.
1395 shout_type mons_shouts(monster_type mc, bool demon_shout)
1396 {
1397     ASSERT_smc();
1398     shout_type u = smc->shouts;
1399
1400     // Pandemonium lords use this to get the noises.
1401     if (u == S_RANDOM || demon_shout && u == S_DEMON_TAUNT)
1402     {
1403         const int max_shout = (u == S_RANDOM ? NUM_SHOUTS : NUM_LOUDNESS);
1404         do
1405         {
1406             u = static_cast<shout_type>(random2(max_shout));
1407         }
1408         while (!_shout_fits_monster(mc, u));
1409     }
1410
1411     return u;
1412 }
1413
1414 bool mons_is_ghost_demon(monster_type mc)
1415 {
1416     return mons_class_flag(mc, M_GHOST_DEMON)
1417 #if TAG_MAJOR_VERSION == 34
1418            || mc == MONS_CHIMERA;
1419 #endif
1420            ;
1421 }
1422
1423 bool mons_is_pghost(monster_type mc)
1424 {
1425     return mc == MONS_PLAYER_GHOST || mc == MONS_PLAYER_ILLUSION;
1426 }
1427
1428 /**
1429  * What mutant beast tier does the given XL (base HD) correspond to?
1430  *
1431  * If the given value is between tiers, choose the higher possibility.
1432  *
1433  * @param xl    The XL (HD) of the mutant beast in question.
1434  * @return      The corresponding mutant beast tier (e.g. BT_MATURE).
1435  */
1436 int mutant_beast_tier(int xl)
1437 {
1438     for (int bt = BT_FIRST; bt < NUM_BEAST_TIERS; ++bt)
1439         if (xl <= beast_tiers[bt])
1440             return bt;
1441     return BT_NONE; // buggy
1442 }
1443
1444 /**
1445  * Is the provided monster_type a demonspawn job type? (Not just any
1446  * demonspawn, but specifically one with a job! Or the job itself, depending
1447  * how you think about it.)
1448  *
1449  * @param mc    The monster type in question.
1450  * @return      Whether that monster type is a demonspawn job.
1451  **/
1452 bool mons_is_demonspawn_job(monster_type mc)
1453 {
1454     return mc >= MONS_FIRST_NONBASE_DEMONSPAWN
1455            && mc <= MONS_LAST_NONBASE_DEMONSPAWN;
1456 }
1457
1458 /**
1459  * Is the provided monster_type a draconian job type? (Not just any draconian,
1460  * but specifically one with a job! Or the job itself, depending how you think
1461  * about it.)
1462  *
1463  * @param mc    The monster type in question.
1464  * @return      Whether that monster type is a draconian job.
1465  **/
1466 bool mons_is_draconian_job(monster_type mc)
1467 {
1468     return mc >= MONS_FIRST_NONBASE_DRACONIAN
1469            && mc <= MONS_LAST_NONBASE_DRACONIAN;
1470 }
1471
1472 /**
1473  * Is the provided monster_type a job? (E.g. black sun, draconian knight)
1474  *
1475  * @param mc    The monster type in question.
1476  * @return      Whether that monster type is a job.
1477  **/
1478 bool mons_is_job(monster_type mc)
1479 {
1480     return mons_is_draconian_job(mc) || mons_is_demonspawn_job(mc);
1481 }
1482
1483 bool mons_is_unique(monster_type mc)
1484 {
1485     return mons_class_flag(mc, M_UNIQUE);
1486 }
1487
1488 bool mons_is_or_was_unique(const monster& mon)
1489 {
1490     return mons_is_unique(mon.type)
1491            || mon.props.exists(ORIGINAL_TYPE_KEY)
1492               && mons_is_unique((monster_type) mon.props[ORIGINAL_TYPE_KEY].get_int());
1493 }
1494
1495 /**
1496  * Can this type of monster be blinded?
1497  *
1498  * Certain monsters, e.g. those with a powerful sense of smell, echolocation,
1499  * or no eyes, are completely immune to blinding.
1500  *
1501  * Note that 'dazzling' (from dazzling spray) has additional restrictions above
1502  * this.
1503  *
1504  * @param mc    The class of monster in question.
1505  * @return      Whether monsters of this type can get ENCH_BLIND.
1506  */
1507 bool mons_can_be_blinded(monster_type mc)
1508 {
1509     return !mons_class_flag(mc, M_UNBLINDABLE);
1510 }
1511
1512
1513 /**
1514  * Can this kind of monster be dazzled?
1515  *
1516  * The undead, nonliving, vegetative, or unblindable cannot be dazzled.
1517  *
1518  * @param mc    The class of monster in question.
1519  * @return      Whether monsters of this type can get ENCH_BLIND from Dazzling
1520  *              Spray.
1521  */
1522 bool mons_can_be_dazzled(monster_type mc)
1523 {
1524     // This was implemented by checking type so that we could use it in
1525     // monster descriptions (which only have mon_info structs); not sure if
1526     // that's useful
1527
1528     const mon_holy_type holiness = mons_class_holiness(mc);
1529     return !(holiness & (MH_UNDEAD | MH_NONLIVING | MH_PLANT))
1530         && mons_can_be_blinded(mc);
1531 }
1532
1533 ucs_t mons_char(monster_type mc)
1534 {
1535     if (Options.mon_glyph_overrides.count(mc)
1536         && Options.mon_glyph_overrides[mc].ch)
1537     {
1538         return Options.mon_glyph_overrides[mc].ch;
1539     }
1540     else
1541         return monster_symbols[mc].glyph;
1542 }
1543
1544 char mons_base_char(monster_type mc)
1545 {
1546     const monsterentry *me = get_monster_data(mc);
1547     return me ? me->basechar : 0;
1548 }
1549
1550 mon_itemuse_type mons_class_itemuse(monster_type mc)
1551 {
1552     ASSERT_smc();
1553     return smc->gmon_use;
1554 }
1555
1556 mon_itemuse_type mons_itemuse(const monster* mon)
1557 {
1558     if (mons_enslaved_soul(mon))
1559         return mons_class_itemuse(mons_zombie_base(mon));
1560
1561     return mons_class_itemuse(mon->type);
1562 }
1563
1564 int mons_class_colour(monster_type mc)
1565 {
1566     ASSERT_smc();
1567     // Player monster is a dummy monster used only for display purposes, so
1568     // it's ok to override it here.
1569     if (mc == MONS_PLAYER
1570         && Options.mon_glyph_overrides.count(MONS_PLAYER)
1571         && Options.mon_glyph_overrides[MONS_PLAYER].col)
1572     {
1573         return Options.mon_glyph_overrides[MONS_PLAYER].col;
1574     }
1575     else
1576         return monster_symbols[mc].colour;
1577 }
1578
1579 bool mons_class_can_regenerate(monster_type mc)
1580 {
1581     return !mons_class_flag(mc, M_NO_REGEN);
1582 }
1583
1584 bool mons_can_regenerate(const monster* mon)
1585 {
1586     get_tentacle_head(mon);
1587
1588     if (testbits(mon->flags, MF_NO_REGEN))
1589         return false;
1590
1591     return mons_class_can_regenerate(mon->type);
1592 }
1593
1594 bool mons_class_fast_regen(monster_type mc)
1595 {
1596     return mons_class_flag(mc, M_FAST_REGEN);
1597 }
1598
1599 /**
1600  * Do monsters of the given type ever leave a hide?
1601  *
1602  * @param mc      The class of monster in question.
1603  * @return        Whether the monster has a chance of dropping a hide when
1604  *                butchered.
1605  */
1606 bool mons_class_leaves_hide(monster_type mc)
1607 {
1608     return hide_for_monster(mc) != NUM_ARMOURS;
1609 }
1610
1611 int mons_zombie_size(monster_type mc)
1612 {
1613     mc = mons_species(mc);
1614     if (!mons_class_can_be_zombified(mc))
1615         return Z_NOZOMBIE;
1616
1617     ASSERT_smc();
1618     return smc->size > SIZE_MEDIUM ? Z_BIG : Z_SMALL;
1619 }
1620
1621 monster_type mons_zombie_base(const monster* mon)
1622 {
1623     return mons_species(mon->base_monster);
1624 }
1625
1626 bool mons_class_is_zombified(monster_type mc)
1627 {
1628 #if TAG_MAJOR_VERSION == 34
1629     switch (mc)
1630     {
1631         case MONS_ZOMBIE_SMALL:     case MONS_ZOMBIE_LARGE:
1632         case MONS_SKELETON_SMALL:   case MONS_SKELETON_LARGE:
1633         case MONS_SIMULACRUM_SMALL: case MONS_SIMULACRUM_LARGE:
1634             return true;
1635         default:
1636             break;
1637     }
1638 #endif
1639
1640     return mc == MONS_ZOMBIE
1641         || mc == MONS_SKELETON
1642         || mc == MONS_SIMULACRUM
1643         || mc == MONS_SPECTRAL_THING;
1644 }
1645
1646 bool mons_class_is_hybrid(monster_type mc)
1647 {
1648     return mons_class_flag(mc, M_HYBRID);
1649 }
1650
1651 bool mons_class_is_animated_weapon(monster_type type)
1652 {
1653     return type == MONS_DANCING_WEAPON || type == MONS_SPECTRAL_WEAPON;
1654 }
1655
1656 bool mons_is_zombified(const monster* mon)
1657 {
1658     return mons_class_is_zombified(mon->type);
1659 }
1660
1661 monster_type mons_base_type(const monster* mon)
1662 {
1663     if (mons_class_is_zombified(mon->type))
1664         return mons_species(mon->base_monster);
1665     return mon->type;
1666 }
1667
1668 bool mons_class_can_leave_corpse(monster_type mc)
1669 {
1670     return mons_corpse_effect(mc) != CE_NOCORPSE;
1671 }
1672
1673 bool mons_class_can_be_zombified(monster_type mc)
1674 {
1675     monster_type ms = mons_species(mc);
1676     return !invalid_monster_type(ms)
1677            && mons_class_can_leave_corpse(ms);
1678 }
1679
1680 bool mons_can_be_zombified(const monster* mon)
1681 {
1682     return mons_class_can_be_zombified(mon->type)
1683            && !mon->is_summoned()
1684            && !mons_enslaved_body_and_soul(mon);
1685 }
1686
1687 bool mons_class_can_use_stairs(monster_type mc)
1688 {
1689     return (!mons_class_is_zombified(mc) || mc == MONS_SPECTRAL_THING)
1690            && !mons_is_tentacle_or_tentacle_segment(mc)
1691            && mc != MONS_SILENT_SPECTRE
1692            && mc != MONS_PLAYER_GHOST
1693            && mc != MONS_GERYON
1694            && mc != MONS_ROYAL_JELLY;
1695 }
1696
1697 bool mons_can_use_stairs(const monster* mon, dungeon_feature_type stair)
1698 {
1699     if (!mons_class_can_use_stairs(mon->type))
1700         return false;
1701
1702     // Summons can't use stairs.
1703     if (mon->has_ench(ENCH_ABJ) || mon->has_ench(ENCH_FAKE_ABJURATION))
1704         return false;
1705
1706     if (mon->has_ench(ENCH_FRIENDLY_BRIBED)
1707         && (feat_is_branch_entrance(stair) || feat_is_branch_exit(stair)
1708             || stair == DNGN_ENTER_HELL || stair == DNGN_EXIT_HELL))
1709     {
1710         return false;
1711     }
1712
1713     // Everything else is fine
1714     return true;
1715 }
1716
1717 bool mons_enslaved_body_and_soul(const monster* mon)
1718 {
1719     return mon->has_ench(ENCH_SOUL_RIPE);
1720 }
1721
1722 bool mons_enslaved_soul(const monster* mon)
1723 {
1724     return testbits(mon->flags, MF_ENSLAVED_SOUL);
1725 }
1726
1727 void name_zombie(monster* mon, monster_type mc, const string &mon_name)
1728 {
1729     mon->mname = mon_name;
1730
1731     // Special case for Blork the orc: shorten his name to "Blork" to
1732     // avoid mentions of "Blork the orc the orc zombie".
1733     if (mc == MONS_BLORK_THE_ORC)
1734         mon->mname = "Blork";
1735     // Also for the Lernaean hydra: treat Lernaean as an adjective to
1736     // avoid mentions of "the Lernaean hydra the X-headed hydra zombie".
1737     else if (mc == MONS_LERNAEAN_HYDRA)
1738     {
1739         mon->mname = "Lernaean";
1740         mon->flags |= MF_NAME_ADJECTIVE;
1741     }
1742     // Also for the Enchantress: treat Enchantress as an adjective to
1743     // avoid mentions of "the Enchantress the spriggan zombie".
1744     else if (mc == MONS_THE_ENCHANTRESS)
1745     {
1746         mon->mname = "Enchantress";
1747         mon->flags |= MF_NAME_ADJECTIVE;
1748     }
1749     else if (mons_species(mc) == MONS_SERPENT_OF_HELL)
1750     {
1751         mon->mname = "";
1752     }
1753
1754     if (starts_with(mon->mname, "shaped "))
1755         mon->flags |= MF_NAME_SUFFIX;
1756
1757     // It's unlikely there's a desc for "Duvessa the elf skeleton", but
1758     // we still want to allow it if overridden.
1759     if (!mon->props.exists("dbname"))
1760         mon->props["dbname"] = mons_class_name(mon->type);
1761 }
1762
1763 void name_zombie(monster* mon, const monster* orig)
1764 {
1765     if (!mons_is_unique(orig->type) && orig->mname.empty())
1766         return;
1767
1768     string name;
1769
1770     if (!orig->mname.empty())
1771         name = orig->mname;
1772     else
1773         name = mons_type_name(orig->type, DESC_PLAIN);
1774
1775     name_zombie(mon, orig->type, name);
1776     mon->flags |= orig->flags & (MF_NAME_SUFFIX
1777                                  | MF_NAME_ADJECTIVE
1778                                  | MF_NAME_DESCRIPTOR);
1779 }
1780
1781 // Derived undead deal 80% of the damage of the base form.
1782 static int _downscale_zombie_damage(int damage)
1783 {
1784     return max(1, 4 * damage / 5);
1785 }
1786
1787 static mon_attack_def _downscale_zombie_attack(const monster* mons,
1788                                                mon_attack_def attk)
1789 {
1790     switch (attk.type)
1791     {
1792     case AT_STING: case AT_SPORE:
1793     case AT_TOUCH: case AT_ENGULF:
1794         attk.type = AT_HIT;
1795         break;
1796     default:
1797         break;
1798     }
1799
1800     if (mons->type == MONS_SIMULACRUM)
1801         attk.flavour = AF_COLD;
1802     else if (mons->type == MONS_SPECTRAL_THING && coinflip())
1803         attk.flavour = AF_DRAIN_XP;
1804     else if (attk.flavour != AF_REACH && attk.flavour != AF_CRUSH)
1805         attk.flavour = AF_PLAIN;
1806
1807     attk.damage = _downscale_zombie_damage(attk.damage);
1808
1809     return attk;
1810 }
1811
1812 /**
1813  * What attack does the given mutant beast facet provide?
1814  *
1815  * @param facet     The facet in question; e.g. BF_STING.
1816  * @param tier      The tier of the mutant beast; e.g.
1817  * @return          The attack corresponding to the given facet; e.g. BT_LARVAL
1818  *                  { AT_STING, AF_REACH_STING, 10 }. Scales with HD.
1819  *                  For facets that don't provide an attack, is { }.
1820  */
1821 static mon_attack_def _mutant_beast_facet_attack(int facet, int tier)
1822 {
1823     const int dam = tier * 5;
1824     switch (facet)
1825     {
1826         case BF_STING:
1827             return { AT_STING, AF_REACH_STING, dam };
1828         case BF_OX:
1829             return { AT_TRAMPLE, AF_TRAMPLE, dam };
1830         case BF_WEIRD:
1831             return { AT_CONSTRICT, AF_CRUSH, dam };
1832         default:
1833             return { };
1834     }
1835 }
1836
1837 /**
1838  * Get the attack type, attack flavour and damage for the given attack of a
1839  * mutant beast.
1840  *
1841  * @param mon           The monster in question.
1842  * @param attk_number   Which attack number to get.
1843  * @return              A mon_attack_def for the specified attack.
1844  */
1845 static mon_attack_def _mutant_beast_attack(const monster &mon, int attk_number)
1846 {
1847     const int tier = mutant_beast_tier(mon.get_experience_level());
1848     if (attk_number == 0)
1849         return { AT_HIT, AF_PLAIN, tier * 7 + 5 };
1850
1851     if (!mon.props.exists(MUTANT_BEAST_FACETS))
1852         return { };
1853
1854     int cur_attk = 1;
1855     for (auto facet : mon.props[MUTANT_BEAST_FACETS].get_vector())
1856     {
1857         const mon_attack_def atk = _mutant_beast_facet_attack(facet.get_int(),
1858                                                               tier);
1859         if (atk.type == AT_NONE)
1860             continue;
1861
1862         if (cur_attk == attk_number)
1863             return atk;
1864
1865         ++cur_attk;
1866     }
1867
1868     return { };
1869 }
1870
1871 /** Get the attack type, attack flavour and damage for a monster attack.
1872  *
1873  * @param mon The monster to look at.
1874  * @param attk_number Which attack number to get.
1875  * @param base_flavour If true, attack flavours that are randomised on every attack
1876  *                     will have their base flavour returned instead of one of the
1877  *                     random flavours.
1878  * @return  A mon_attack_def for the specified attack.
1879  */
1880 mon_attack_def mons_attack_spec(const monster* mon, int attk_number, bool base_flavour)
1881 {
1882     monster_type mc = mon->type;
1883
1884     get_tentacle_head(mon);
1885
1886     const bool zombified = mons_is_zombified(mon);
1887
1888     if (mon->has_hydra_multi_attack())
1889         attk_number -= mon->heads() - 1;
1890
1891     if (attk_number < 0 || attk_number >= MAX_NUM_ATTACKS)
1892         attk_number = 0;
1893
1894     if (mons_is_ghost_demon(mc))
1895     {
1896         if (attk_number == 0)
1897         {
1898             return mon_attack_def::attk(mon->ghost->damage,
1899                                         mon->ghost->att_type,
1900                                         mon->ghost->att_flav);
1901         }
1902
1903         return mon_attack_def::attk(0, AT_NONE);
1904     }
1905     else if (mc == MONS_MUTANT_BEAST)
1906         return _mutant_beast_attack(*mon, attk_number);
1907     else if (mons_is_demonspawn(mc) && attk_number != 0)
1908         mc = draco_or_demonspawn_subspecies(mon);
1909
1910     if (zombified && mc != MONS_KRAKEN_TENTACLE)
1911         mc = mons_zombie_base(mon);
1912
1913     ASSERT_smc();
1914     mon_attack_def attk = smc->attack[attk_number];
1915
1916     if (mons_is_demonspawn(mon->type) && attk_number == 0)
1917     {
1918         const monsterentry* mbase =
1919             get_monster_data (draco_or_demonspawn_subspecies(mon));
1920         ASSERT(mbase);
1921         attk.flavour = mbase->attack[0].flavour;
1922         return attk;
1923     }
1924
1925     // Nonbase draconians inherit aux attacks from their base type.
1926     // Implicit assumption: base draconian types only get one aux
1927     // attack, and it's in their second attack slot.
1928     // If that changes this code will need to be changed.
1929     if (mons_species(mon->type) == MONS_DRACONIAN
1930         && mon->type != MONS_DRACONIAN
1931         && attk.type == AT_NONE
1932         && attk_number > 0
1933         && smc->attack[attk_number - 1].type != AT_NONE)
1934     {
1935         const monsterentry* mbase =
1936             get_monster_data (draco_or_demonspawn_subspecies(mon));
1937         ASSERT(mbase);
1938         return mbase->attack[1];
1939     }
1940
1941     if (mon->type == MONS_PLAYER_SHADOW && attk_number == 0)
1942     {
1943         if (!you.weapon())
1944             attk.damage = max(1, you.skill_rdiv(SK_UNARMED_COMBAT, 10, 20));
1945     }
1946
1947     if (attk.type == AT_RANDOM)
1948         attk.type = random_choose(AT_HIT, AT_GORE);
1949
1950     if (attk.type == AT_CHERUB)
1951         attk.type = random_choose(AT_HIT, AT_BITE, AT_PECK, AT_GORE);
1952
1953     if (!base_flavour)
1954     {
1955         if (attk.flavour == AF_KLOWN)
1956         {
1957             attack_flavour flavours[] =
1958                 {AF_POISON_STRONG, AF_PAIN, AF_DRAIN_SPEED, AF_FIRE,
1959                  AF_COLD, AF_ELEC, AF_ANTIMAGIC, AF_ACID};
1960
1961             attk.flavour = RANDOM_ELEMENT(flavours);
1962         }
1963
1964         if (attk.flavour == AF_DRAIN_STAT)
1965         {
1966             attack_flavour flavours[] =
1967                 {AF_DRAIN_STR, AF_DRAIN_INT, AF_DRAIN_DEX};
1968
1969             attk.flavour = RANDOM_ELEMENT(flavours);
1970         }
1971     }
1972
1973     // Slime creature attacks are multiplied by the number merged.
1974     if (mon->type == MONS_SLIME_CREATURE && mon->blob_size > 1)
1975         attk.damage *= mon->blob_size;
1976
1977     return zombified ? _downscale_zombie_attack(mon, attk) : attk;
1978 }
1979
1980 static int _mons_damage(monster_type mc, int rt)
1981 {
1982     if (rt < 0 || rt > 3)
1983         rt = 0;
1984     ASSERT_smc();
1985     return smc->attack[rt].damage;
1986 }
1987
1988 bool mons_immune_magic(const monster* mon)
1989 {
1990     return get_monster_data(mon->type)->resist_magic == MAG_IMMUNE;
1991 }
1992
1993 bool mons_skeleton(monster_type mc)
1994 {
1995     return !mons_class_flag(mc, M_NO_SKELETON);
1996 }
1997
1998 bool mons_zombifiable(monster_type mc)
1999 {
2000     return !mons_class_flag(mc, M_NO_ZOMBIE) && mons_zombie_size(mc);
2001 }
2002
2003 bool mons_flattens_trees(const monster* mon)
2004 {
2005     return mons_base_type(mon) == MONS_LERNAEAN_HYDRA;
2006 }
2007
2008 bool mons_class_res_wind(monster_type mc)
2009 {
2010     return get_resist(get_mons_class_resists(mc), MR_RES_WIND);
2011 }
2012
2013 /**
2014  * Given an average max HP value for a given monster type, what should a given
2015  * monster have?
2016  *
2017  * @param avg_hp    The mean hp.
2018  * @param scale     A scale that the input avg_hp are multiplied by.
2019  * @return          A max HP value; no more than +-33% from the given average,
2020  *                  and within about +-10% of the average 95% of the time.
2021  *                  This value is not multiplied by the scale - it's an actual
2022  *                  hp value, regardless of the scale on the input.
2023  *                  If avg_hp is nonzero, always returns at least 1.
2024  */
2025 int hit_points(int avg_hp, int scale)
2026 {
2027     if (!avg_hp)
2028         return 0;
2029
2030     const int min_perc = 33;
2031     const int hp_variance = div_rand_round(avg_hp * min_perc, 100);
2032     const int min_hp = avg_hp - hp_variance;
2033     const int hp = min_hp + random2avg(hp_variance * 2, 8);
2034     return max(1, div_rand_round(hp, scale));
2035 }
2036
2037 // This function returns the standard number of hit dice for a type of
2038 // monster, not a particular monster's current hit dice. - bwr
2039 int mons_class_hit_dice(monster_type mc)
2040 {
2041     const monsterentry *me = get_monster_data(mc);
2042     return me ? me->HD : 0;
2043 }
2044
2045 /**
2046  * What base MR does a monster of the given type have?
2047  *
2048  * @param type    The monster type in question.
2049  * @param base    The base type of the monster. (For e.g. draconians.)
2050  * @return        The MR of a normal monster of that type.
2051  */
2052 int mons_class_res_magic(monster_type type, monster_type base)
2053 {
2054     const monster_type base_type =
2055         base != MONS_NO_MONSTER &&
2056         (mons_is_draconian(type) || mons_is_demonspawn(type))
2057             ? draco_or_demonspawn_subspecies(type, base)
2058             : type;
2059
2060     const int type_mr = (get_monster_data(base_type))->resist_magic;
2061
2062     // Negative values get multiplied with monster hit dice.
2063     if (type_mr >= 0)
2064         return type_mr;
2065     return mons_class_hit_dice(base_type) * -type_mr * 4 / 3;
2066 }
2067
2068 /**
2069  * Can a monster of the given type see invisible creatures?
2070  *
2071  * @param type    The monster type in question.
2072  * @param base    The base type of the monster. (For e.g. draconians.)
2073  * @return        Whether a normal monster of that type can see invisible
2074  *                things.
2075  */
2076 bool mons_class_sees_invis(monster_type type, monster_type base)
2077 {
2078     if (mons_class_flag(type, M_SEE_INVIS))
2079         return true;
2080
2081     if (base != MONS_NO_MONSTER && mons_is_demonspawn(type) // XXX: add dracs here? latent bug otherwise
2082         && mons_class_flag(draco_or_demonspawn_subspecies(type, base),
2083                            M_SEE_INVIS))
2084     {
2085         return true;
2086     }
2087
2088     return false;
2089 }
2090
2091 /**
2092  * What's the average hp for a given type of monster?
2093  *
2094  * @param mc        The type of monster in question.
2095  * @return          The average hp for that monster; rounds down.
2096  */
2097 int mons_avg_hp(monster_type mc)
2098 {
2099     const monsterentry* me = get_monster_data(mc);
2100
2101     if (!me)
2102         return 0;
2103
2104     // Hack for nonbase demonspawn: pretend it's a basic demonspawn with
2105     // a job.
2106     if (mons_is_demonspawn(mc)
2107         && mc != MONS_DEMONSPAWN
2108         && mons_species(mc) == MONS_DEMONSPAWN)
2109     {
2110         const monsterentry* mbase = get_monster_data(MONS_DEMONSPAWN);
2111         return (mbase->avg_hp_10x + me->avg_hp_10x) / 10;
2112     }
2113
2114     return me->avg_hp_10x / 10;
2115 }
2116
2117 /**
2118  * What's the maximum hp for a given type of monster?
2119  *
2120  * @param mc        The type of monster in question.
2121  * @param mbase     The type of the base monster, if applicable (for classed
2122  *                  monsters).
2123  * @return          The maximum hp for that monster; rounds down.
2124  */
2125 int mons_max_hp(monster_type mc, monster_type mbase_type)
2126 {
2127     const monsterentry* me = get_monster_data(mc);
2128
2129     if (!me)
2130         return 0;
2131
2132     // TODO: merge the 133% with their use in hit_points()
2133
2134     // Hack for nonbase demonspawn: pretend it's a basic demonspawn with
2135     // a job.
2136     if (mons_is_demonspawn(mc)
2137         && mc != MONS_DEMONSPAWN
2138         && mons_species(mc) == MONS_DEMONSPAWN)
2139     {
2140         const monsterentry* mbase =
2141             get_monster_data(mbase_type != MONS_NO_MONSTER ? mbase_type
2142                                                            : MONS_DEMONSPAWN);
2143         return (mbase->avg_hp_10x + me->avg_hp_10x) * 133 / 1000;
2144     }
2145
2146     return me->avg_hp_10x * 133 / 1000;
2147 }
2148
2149 int exper_value(const monster* mon, bool real)
2150 {
2151     int x_val = 0;
2152
2153     // These four are the original arguments.
2154     const monster_type mc = mon->type;
2155     int hd                = mon->get_experience_level();
2156     int maxhp             = mon->max_hit_points;
2157
2158     // pghosts and pillusions have no reasonable base values, and you can look
2159     // up the exact value anyway. Especially for pillusions.
2160     if (real || mon->type == MONS_PLAYER_GHOST || mon->type == MONS_PLAYER_ILLUSION)
2161     {
2162         // A berserking monster is much harder, but the xp value shouldn't
2163         // depend on whether it was berserk at the moment of death.
2164         if (mon->has_ench(ENCH_BERSERK))
2165             maxhp = (maxhp * 2 + 1) / 3;
2166     }
2167     else
2168     {
2169         const monsterentry *m = get_monster_data(mons_base_type(mon));
2170         ASSERT(m);
2171
2172         // Use real hd, zombies would use the basic species and lose
2173         // information known to the player ("orc warrior zombie"). Monsters
2174         // levelling up is visible (although it may happen off-screen), so
2175         // this is hardly ever a leak. Only Pan lords are unknown in the
2176         // general.
2177         if (m->mc == MONS_PANDEMONIUM_LORD)
2178             hd = m->HD;
2179         maxhp = mons_max_hp(mc);
2180     }
2181
2182     // Hacks to make merged slime creatures not worth so much exp. We
2183     // will calculate the experience we would get for 1 blob, and then
2184     // just multiply it so that exp is linear with blobs merged. -cao
2185     if (mon->type == MONS_SLIME_CREATURE && mon->blob_size > 1)
2186         maxhp /= mon->blob_size;
2187
2188     // These are some values we care about.
2189     const int speed       = mons_base_speed(mon);
2190     const int modifier    = _mons_exp_mod(mc);
2191     const int item_usage  = mons_itemuse(mon);
2192
2193     // XXX: Shapeshifters can qualify here, even though they can't cast.
2194     const bool spellcaster = mon->has_spells();
2195
2196     // Early out for no XP monsters.
2197     if (!mons_class_gives_xp(mc))
2198         return 0;
2199
2200     x_val = (16 + maxhp) * hd * hd / 10;
2201
2202     // Let's calculate a simple difficulty modifier. - bwr
2203     int diff = 0;
2204
2205     // Let's look for big spells.
2206     if (spellcaster)
2207     {
2208         for (const mon_spell_slot &slot : mon->spells)
2209         {
2210             switch (slot.spell)
2211             {
2212             case SPELL_PARALYSE:
2213             case SPELL_SMITING:
2214             case SPELL_SUMMON_EYEBALLS:
2215             case SPELL_CALL_DOWN_DAMNATION:
2216             case SPELL_HURL_DAMNATION:
2217             case SPELL_SYMBOL_OF_TORMENT:
2218             case SPELL_GLACIATE:
2219             case SPELL_FIRE_STORM:
2220             case SPELL_SHATTER:
2221             case SPELL_CHAIN_LIGHTNING:
2222             case SPELL_TORNADO:
2223             case SPELL_LEGENDARY_DESTRUCTION:
2224             case SPELL_SUMMON_ILLUSION:
2225             case SPELL_SPELLFORGED_SERVITOR:
2226                 diff += 25;
2227                 break;
2228
2229             case SPELL_SUMMON_GREATER_DEMON:
2230             case SPELL_HASTE:
2231             case SPELL_BLINK_RANGE:
2232             case SPELL_PETRIFY:
2233                 diff += 20;
2234                 break;
2235
2236             case SPELL_LIGHTNING_BOLT:
2237             case SPELL_STICKY_FLAME_RANGE:
2238             case SPELL_DISINTEGRATE:
2239             case SPELL_BANISHMENT:
2240             case SPELL_LEHUDIBS_CRYSTAL_SPEAR:
2241             case SPELL_IRON_SHOT:
2242             case SPELL_IOOD:
2243             case SPELL_FIREBALL:
2244             case SPELL_AGONY:
2245             case SPELL_LRD:
2246             case SPELL_DIG:
2247             case SPELL_CHAIN_OF_CHAOS:
2248             case SPELL_FAKE_MARA_SUMMON:
2249                 diff += 10;
2250                 break;
2251
2252             case SPELL_HAUNT:
2253             case SPELL_SUMMON_DRAGON:
2254             case SPELL_SUMMON_HORRIBLE_THINGS:
2255             case SPELL_PLANEREND:
2256             case SPELL_SUMMON_EMPEROR_SCORPIONS:
2257                 diff += 7;
2258                 break;
2259
2260             default:
2261                 break;
2262             }
2263         }
2264     }
2265
2266     // Let's look at regeneration.
2267     if (mons_class_fast_regen(mc))
2268         diff += 15;
2269
2270     // Monsters at normal or fast speed with big melee damage.
2271     if (speed >= 10)
2272     {
2273         int max_melee = 0;
2274         for (int i = 0; i < 4; ++i)
2275             max_melee += _mons_damage(mc, i);
2276
2277         if (max_melee > 30)
2278             diff += (max_melee / ((speed == 10) ? 2 : 1));
2279     }
2280
2281     // Monsters who can use equipment (even if only the equipment
2282     // they are given) can be considerably enhanced because of
2283     // the way weapons work for monsters. - bwr
2284     if (item_usage >= MONUSE_STARTING_EQUIPMENT)
2285         diff += 30;
2286
2287     // Set a reasonable range on the difficulty modifier...
2288     // Currently 70% - 200%. - bwr
2289     if (diff > 100)
2290         diff = 100;
2291     else if (diff < -30)
2292         diff = -30;
2293
2294     // Apply difficulty.
2295     x_val *= (100 + diff);
2296     x_val /= 100;
2297
2298     // Basic speed modification.
2299     if (speed > 0)
2300     {
2301         x_val *= speed;
2302         x_val /= 10;
2303     }
2304
2305     // Slow monsters without spells and items often have big HD which
2306     // cause the experience value to be overly large... this tries
2307     // to reduce the inappropriate amount of XP that results. - bwr
2308     if (speed < 10 && !spellcaster && item_usage < MONUSE_STARTING_EQUIPMENT)
2309         x_val /= 2;
2310
2311     // Apply the modifier in the monster's definition.
2312     if (modifier > 0)
2313     {
2314         x_val *= modifier;
2315         x_val /= 10;
2316     }
2317
2318     // Scale starcursed mass exp by what percentage of the whole it represents
2319     if (mon->type == MONS_STARCURSED_MASS)
2320         x_val = (x_val * mon->blob_size) / 12;
2321
2322     // Further reduce xp from zombies
2323     if (mons_is_zombified(mon))
2324         x_val /= 2;
2325
2326     // Reductions for big values. - bwr
2327     if (x_val > 100)
2328         x_val = 100 + ((x_val - 100) * 3) / 4;
2329     if (x_val > 750)
2330         x_val = 750 + (x_val - 750) / 3;
2331
2332     // Slime creature exp hack part 2: Scale exp back up by the number
2333     // of blobs merged. -cao
2334     // Has to be after the stepdown to prevent issues with 4-5 merged slime
2335     // creatures. -pf
2336     if (mon->type == MONS_SLIME_CREATURE && mon->blob_size > 1)
2337         x_val *= mon->blob_size;
2338
2339     // Guarantee the value is within limits.
2340     if (x_val <= 0)
2341         x_val = 1;
2342
2343     return x_val;
2344 }
2345
2346 monster_type random_draconian_monster_species()
2347 {
2348     const int num_drac = MONS_LAST_SPAWNED_DRACONIAN - MONS_FIRST_BASE_DRACONIAN + 1;
2349     return static_cast<monster_type>(MONS_FIRST_BASE_DRACONIAN + random2(num_drac));
2350 }
2351
2352 monster_type random_demonspawn_monster_species()
2353 {
2354     const int num_demons = MONS_LAST_BASE_DEMONSPAWN
2355                             - MONS_FIRST_BASE_DEMONSPAWN + 1;
2356     return static_cast<monster_type>(MONS_FIRST_BASE_DEMONSPAWN
2357                                      + random2(num_demons));
2358 }
2359
2360 // Note: For consistent behavior in player_will_anger_monster(), all
2361 // spellbooks a given monster can get here should produce the same
2362 // return values in the following:
2363 //
2364 //     (is_unholy_spell() || is_evil_spell())
2365 //
2366 //     (is_unclean_spell() || is_chaotic_spell())
2367 //
2368 // FIXME: This is not true for one set of spellbooks; MST_WIZARD_IV
2369 // contains the unholy and chaotic Banishment spell, but the other
2370 // MST_WIZARD-type spellbooks contain no unholy, evil, unclean or
2371 // chaotic spells.
2372 //
2373 // If a monster has only one spellbook, it is specified in mon-data.h.
2374 // If it has multiple books, mon-data.h sets the book to MST_NO_SPELLS,
2375 // and the books are accounted for here.
2376 static vector<mon_spellbook_type> _mons_spellbook_list(monster_type mon_type)
2377 {
2378     switch (mon_type)
2379     {
2380     case MONS_HELL_KNIGHT:
2381         return { MST_HELL_KNIGHT_I, MST_HELL_KNIGHT_II };
2382
2383     case MONS_NECROMANCER:
2384         return { MST_NECROMANCER_I, MST_NECROMANCER_II };
2385
2386     case MONS_ORC_WIZARD:
2387         return { MST_ORC_WIZARD_I, MST_ORC_WIZARD_II, MST_ORC_WIZARD_III };
2388
2389     case MONS_WIZARD:
2390     case MONS_EROLCHA:
2391         return { MST_WIZARD_I, MST_WIZARD_II, MST_WIZARD_III, MST_WIZARD_IV,
2392                  MST_WIZARD_V };
2393
2394     case MONS_OGRE_MAGE:
2395         return { MST_OGRE_MAGE_I, MST_OGRE_MAGE_II, MST_OGRE_MAGE_III,
2396                  MST_OGRE_MAGE_IV, MST_OGRE_MAGE_V };
2397
2398     case MONS_ANCIENT_CHAMPION:
2399         return { MST_ANCIENT_CHAMPION_I, MST_ANCIENT_CHAMPION_II,
2400                  MST_ANCIENT_CHAMPION_III };
2401
2402     case MONS_TENGU_CONJURER:
2403         return { MST_TENGU_CONJURER_I, MST_TENGU_CONJURER_II,
2404                  MST_TENGU_CONJURER_III, MST_TENGU_CONJURER_IV };
2405
2406     case MONS_TENGU_REAVER:
2407         return { MST_TENGU_REAVER_I, MST_TENGU_REAVER_II,
2408                  MST_TENGU_REAVER_III };
2409
2410     case MONS_DEEP_ELF_MAGE:
2411         return { MST_DEEP_ELF_MAGE_I, MST_DEEP_ELF_MAGE_II,
2412                  MST_DEEP_ELF_MAGE_III, MST_DEEP_ELF_MAGE_IV,
2413                  MST_DEEP_ELF_MAGE_V, MST_DEEP_ELF_MAGE_VI };
2414
2415     case MONS_FAUN:
2416         return { MST_FAUN_I, MST_FAUN_II };
2417
2418     case MONS_GREATER_MUMMY:
2419         return { MST_GREATER_MUMMY_I, MST_GREATER_MUMMY_II,
2420                  MST_GREATER_MUMMY_III, MST_GREATER_MUMMY_IV };
2421
2422     case MONS_DEEP_ELF_KNIGHT:
2423         return { MST_DEEP_ELF_KNIGHT_I, MST_DEEP_ELF_KNIGHT_II };
2424
2425     case MONS_LICH:
2426     case MONS_ANCIENT_LICH:
2427         return { MST_LICH_I, MST_LICH_II, MST_LICH_III,
2428                  MST_LICH_IV, MST_LICH_V, };
2429
2430     default:
2431         return { static_cast<mon_spellbook_type>(
2432                      get_monster_data(mon_type)->sec) };
2433     }
2434 }
2435
2436 vector<mon_spellbook_type> get_spellbooks(const monster_info &mon)
2437 {
2438     // special case for vault monsters: if they have a custom book,
2439     // treat it as MST_GHOST
2440     if (mon.props.exists(CUSTOM_SPELLS_KEY))
2441         return { MST_GHOST };
2442     else
2443         return _mons_spellbook_list(mon.type);
2444 }
2445
2446 // Get a list of unique spells from a monster's preset spellbooks
2447 // or in the case of ghosts their actual spells.
2448 // If flags is non-zero, it returns only spells that match those flags.
2449 unique_books get_unique_spells(const monster_info &mi,
2450                                mon_spell_slot_flags flags)
2451 {
2452     // No entry for MST_GHOST
2453     COMPILE_CHECK(ARRAYSZ(mspell_list) == NUM_MSTYPES - 1);
2454
2455     const vector<mon_spellbook_type> books = get_spellbooks(mi);
2456     const size_t num_books = books.size();
2457
2458     unique_books result;
2459     for (size_t i = 0; i < num_books; ++i)
2460     {
2461         const mon_spellbook_type book = books[i];
2462         // TODO: should we build an index to speed this reverse lookup?
2463         unsigned int msidx;
2464         for (msidx = 0; msidx < ARRAYSZ(mspell_list); ++msidx)
2465             if (mspell_list[msidx].type == book)
2466                 break;
2467
2468         vector<spell_type> spells;
2469
2470         // Only prepend the first time; might be misleading if a draconian
2471         // ever gets multiple sets of natural abilities.
2472         if (mons_genus(mi.type) == MONS_DRACONIAN && i == 0)
2473         {
2474             const mon_spell_slot breath =
2475                 drac_breath(mi.draco_or_demonspawn_subspecies());
2476             if (breath.flags & flags && breath.spell != SPELL_NO_SPELL)
2477                 spells.push_back(breath.spell);
2478             // No other spells; quit right away.
2479             if (book == MST_NO_SPELLS)
2480             {
2481                 if (spells.size())
2482                     result.push_back(spells);
2483                 return result;
2484             }
2485         }
2486
2487         if (book != MST_GHOST)
2488             ASSERT(msidx < ARRAYSZ(mspell_list));
2489         for (const mon_spell_slot &slot : (book == MST_GHOST
2490                                            ? mi.spells
2491                                            : mspell_list[msidx].spells))
2492         {
2493             if (flags != MON_SPELL_NO_FLAGS && !(slot.flags & flags))
2494                 continue;
2495
2496             if (find(spells.begin(), spells.end(), slot.spell) == spells.end())
2497                 spells.push_back(slot.spell);
2498         }
2499
2500         if (spells.size() == 0)
2501             continue;
2502
2503         result.push_back(spells);
2504     }
2505
2506     return result;
2507 }
2508
2509 mon_spell_slot drac_breath(monster_type drac_type)
2510 {
2511     spell_type sp;
2512     switch (drac_type)
2513     {
2514     case MONS_BLACK_DRACONIAN:   sp = SPELL_LIGHTNING_BOLT; break;
2515     case MONS_MOTTLED_DRACONIAN: sp = SPELL_STICKY_FLAME_SPLASH; break;
2516     case MONS_YELLOW_DRACONIAN:  sp = SPELL_SPIT_ACID; break;
2517     case MONS_GREEN_DRACONIAN:   sp = SPELL_POISONOUS_CLOUD; break;
2518     case MONS_PURPLE_DRACONIAN:  sp = SPELL_QUICKSILVER_BOLT; break;
2519     case MONS_RED_DRACONIAN:     sp = SPELL_SEARING_BREATH; break;
2520     case MONS_WHITE_DRACONIAN:   sp = SPELL_CHILLING_BREATH; break;
2521     case MONS_DRACONIAN:
2522     case MONS_GREY_DRACONIAN:    sp = SPELL_NO_SPELL; break;
2523     case MONS_PALE_DRACONIAN:    sp = SPELL_STEAM_BALL; break;
2524
2525     default:
2526         die("Invalid draconian subrace: %d", drac_type);
2527     }
2528
2529     mon_spell_slot slot;
2530     slot.spell = sp;
2531     slot.freq = 62;
2532     slot.flags = MON_SPELL_NATURAL | MON_SPELL_BREATH;
2533     return slot;
2534 }
2535
2536 void mons_load_spells(monster* mon)
2537 {
2538     vector<mon_spellbook_type> books = _mons_spellbook_list(mon->type);
2539     const mon_spellbook_type book = books[random2(books.size())];
2540
2541     if (book == MST_GHOST)
2542         return mon->load_ghost_spells();
2543
2544     mon->spells.clear();
2545     if (mons_genus(mon->type) == MONS_DRACONIAN)
2546     {
2547         mon_spell_slot breath = drac_breath(draco_or_demonspawn_subspecies(mon));
2548         if (breath.spell != SPELL_NO_SPELL)
2549             mon->spells.push_back(breath);
2550     }
2551
2552     if (book == MST_NO_SPELLS)
2553         return;
2554
2555     dprf(DIAG_MONPLACE, "%s: loading spellbook #%d",
2556          mon->name(DESC_PLAIN, true).c_str(), static_cast<int>(book));
2557
2558     for (const mon_spellbook &spbook : mspell_list)
2559         if (spbook.type == book)
2560         {
2561             mon->spells = spbook.spells;
2562             break;
2563         }
2564 }
2565
2566 // Never hand out DARKGREY as a monster colour, even if it is randomly
2567 // chosen.
2568 colour_t random_monster_colour()
2569 {
2570     colour_t col = DARKGREY;
2571     while (col == DARKGREY)
2572         col = random_colour();
2573
2574     return col;
2575 }
2576
2577 bool init_abomination(monster* mon, int hd)
2578 {
2579     if (mon->type == MONS_CRAWLING_CORPSE
2580         || mon->type == MONS_MACABRE_MASS)
2581     {
2582         mon->set_hit_dice(mon->hit_points = mon->max_hit_points = hd);
2583         return true;
2584     }
2585     else if (mon->type != MONS_ABOMINATION_LARGE
2586              && mon->type != MONS_ABOMINATION_SMALL)
2587     {
2588         return false;
2589     }
2590
2591     const int max_hd = mon->type == MONS_ABOMINATION_LARGE ? 30 : 15;
2592
2593     mon->set_hit_dice(min(max_hd, hd));
2594
2595     const monsterentry *m = get_monster_data(mon->type);
2596     const int hp = hit_points(div_rand_round(hd * m->avg_hp_10x, m->HD));
2597
2598     mon->max_hit_points = hp;
2599     mon->hit_points     = hp;
2600
2601     return true;
2602 }
2603
2604 // Generate a shiny, new and unscarred monster.
2605 void define_monster(monster* mons)
2606 {
2607     monster_type mcls         = mons->type;
2608     ASSERT(!mons_class_is_zombified(mcls)); // should have called define_zombie
2609
2610     monster_type monbase      = mons->base_monster;
2611     const monsterentry *m     = get_monster_data(mcls);
2612     int col                   = mons_class_colour(mcls);
2613     int hd                    = mons_class_hit_dice(mcls);
2614     int hp = 0;
2615
2616     mons->mname.clear();
2617
2618     // misc
2619     mons->god = GOD_NO_GOD;
2620
2621     switch (mcls)
2622     {
2623     case MONS_ABOMINATION_SMALL:
2624         hd = 4 + random2(4);
2625         mons->props[MON_SPEED_KEY] = 7 + random2avg(9, 2);
2626         init_abomination(mons, hd);
2627         break;
2628
2629     case MONS_ABOMINATION_LARGE:
2630         hd = 8 + random2(4);
2631         mons->props[MON_SPEED_KEY] = 6 + random2avg(7, 2);
2632         init_abomination(mons, hd);
2633         break;
2634
2635     case MONS_SLIME_CREATURE:
2636         // Slime creatures start off as only single un-merged blobs.
2637         mons->blob_size = 1;
2638         break;
2639
2640     case MONS_HYDRA:
2641         // Hydras start off with 4 to 8 heads.
2642         mons->num_heads = random_range(4, 8);
2643         break;
2644
2645     case MONS_LERNAEAN_HYDRA:
2646         // The Lernaean hydra starts off with 27 heads.
2647         mons->num_heads = 27;
2648         break;
2649
2650     case MONS_TIAMAT:
2651         // Initialise to a random draconian type.
2652         draconian_change_colour(mons);
2653         monbase = mons->base_monster;
2654         col = mons->colour;
2655         break;
2656
2657     case MONS_STARCURSED_MASS:
2658         mons->blob_size = 12;
2659         break;
2660
2661     // Randomize starting speed burst clock
2662     case MONS_SIXFIRHY:
2663     case MONS_JIANGSHI:
2664         mons->move_spurt = random2(360);
2665         break;
2666
2667     case MONS_SHAMBLING_MANGROVE:
2668         mons->mangrove_pests = x_chance_in_y(3, 5) ? random_range(2, 3) : 0;
2669         break;
2670
2671     case MONS_SERPENT_OF_HELL:
2672     case MONS_SERPENT_OF_HELL_COCYTUS:
2673     case MONS_SERPENT_OF_HELL_DIS:
2674     case MONS_SERPENT_OF_HELL_TARTARUS:
2675         mons->num_heads = 3;
2676         break;
2677
2678     default:
2679         break;
2680     }
2681
2682     if (mons_is_draconian_job(mcls))
2683     {
2684         // Professional draconians still have a base draconian type.
2685         // White draconians will never be draconian scorchers, but
2686         // apart from that, anything goes.
2687         do
2688         {
2689             monbase = random_draconian_monster_species();
2690         }
2691         while (drac_colour_incompatible(mcls, monbase));
2692     }
2693
2694     if (mons_is_demonspawn_job(mcls))
2695     {
2696         // Some base demonspawn have more or less HP, AC, EV than their
2697         // brethren; those should be based on the base monster,
2698         // with modifiers taken from the job.
2699
2700         monbase = (mons->base_monster == MONS_NO_MONSTER
2701                    || mons->base_monster == MONS_PROGRAM_BUG) // zombie gen
2702                   ? random_demonspawn_monster_species()
2703                   : mons->base_monster;
2704
2705         const monsterentry* mbase = get_monster_data(monbase);
2706         hp = hit_points(mbase->avg_hp_10x + m->avg_hp_10x);
2707     }
2708
2709     if (col == COLOUR_UNDEF) // but never give out darkgrey to monsters
2710         col = random_monster_colour();
2711
2712     // Some calculations.
2713     if (hp == 0)
2714         hp = hit_points(m->avg_hp_10x);
2715     const int hp_max = hp;
2716
2717     // So let it be written, so let it be done.
2718     mons->set_hit_dice(hd);
2719     mons->hit_points      = hp;
2720     mons->max_hit_points  = hp_max;
2721     mons->speed_increment = 70;
2722
2723     if (mons->base_monster == MONS_NO_MONSTER
2724         || mons->base_monster == MONS_PROGRAM_BUG) // latter is zombie gen
2725     {
2726         mons->base_monster = monbase;
2727     }
2728
2729     mons->flags      = MF_NO_FLAGS;
2730     mons->experience = 0;
2731     mons->colour     = col;
2732
2733     mons->bind_melee_flags();
2734
2735     mons_load_spells(mons);
2736     mons->bind_spell_flags();
2737
2738     // Reset monster enchantments.
2739     mons->enchantments.clear();
2740     mons->ench_cache.reset();
2741     mons->ench_countdown = 0;
2742
2743     switch (mcls)
2744     {
2745     case MONS_PANDEMONIUM_LORD:
2746     {
2747         ghost_demon ghost;
2748         ghost.init_pandemonium_lord();
2749         mons->set_ghost(ghost);
2750         mons->ghost_demon_init();
2751         mons->bind_melee_flags();
2752         mons->bind_spell_flags();
2753         break;
2754     }
2755
2756     case MONS_PLAYER_GHOST:
2757     case MONS_PLAYER_ILLUSION:
2758     {
2759         ghost_demon ghost;
2760         ghost.init_player_ghost(mcls == MONS_PLAYER_GHOST);
2761         mons->set_ghost(ghost);
2762         mons->ghost_init(!mons->props.exists("fake"));
2763         mons->bind_melee_flags();
2764         mons->bind_spell_flags();
2765         break;
2766     }
2767
2768     case MONS_UGLY_THING:
2769     case MONS_VERY_UGLY_THING:
2770     {
2771         ghost_demon ghost;
2772         ghost.init_ugly_thing(mcls == MONS_VERY_UGLY_THING);
2773         mons->set_ghost(ghost);
2774         mons->uglything_init();
2775         break;
2776     }
2777
2778     // Load with dummy values so certain monster properties can be queried
2779     // before placement without crashing (proper setup is done later here)
2780     case MONS_DANCING_WEAPON:
2781     case MONS_SPECTRAL_WEAPON:
2782     {
2783         ghost_demon ghost;
2784         mons->set_ghost(ghost);
2785         break;
2786     }
2787
2788     default:
2789         break;
2790     }
2791
2792     mons->calc_speed();
2793
2794     // When all is said and done, this monster had better have some hit
2795     // points, or it will be dead on arrival
2796     ASSERT(mons->hit_points > 0);
2797     ASSERT(mons->max_hit_points > 0);
2798 }
2799
2800 static const char *ugly_colour_names[] =
2801 {
2802     "red", "brown", "green", "cyan", "purple", "white"
2803 };
2804
2805 string ugly_thing_colour_name(colour_t colour)
2806 {
2807     int colour_offset = ugly_thing_colour_offset(colour);
2808
2809     if (colour_offset == -1)
2810         return "buggy";
2811
2812     return ugly_colour_names[colour_offset];
2813 }
2814
2815 static const colour_t ugly_colour_values[] =
2816 {
2817     RED, BROWN, GREEN, CYAN, MAGENTA, LIGHTGREY
2818 };
2819
2820 colour_t ugly_thing_random_colour()
2821 {
2822     return RANDOM_ELEMENT(ugly_colour_values);
2823 }
2824
2825 int str_to_ugly_thing_colour(const string &s)
2826 {
2827     COMPILE_CHECK(ARRAYSZ(ugly_colour_values) == ARRAYSZ(ugly_colour_names));
2828     for (int i = 0, size = ARRAYSZ(ugly_colour_values); i < size; ++i)
2829         if (s == ugly_colour_names[i])
2830             return ugly_colour_values[i];
2831     return BLACK;
2832 }
2833
2834 int ugly_thing_colour_offset(colour_t colour)
2835 {
2836     for (unsigned i = 0; i < ARRAYSZ(ugly_colour_values); ++i)
2837     {
2838         if (make_low_colour(colour) == ugly_colour_values[i])
2839             return i;
2840     }
2841
2842     return -1;
2843 }
2844
2845 static const char *drac_colour_names[] =
2846 {
2847     "black", "mottled", "yellow", "green", "purple", "red", "white", "grey", "pale"
2848 };
2849
2850 string draconian_colour_name(monster_type mon_type)
2851 {
2852     COMPILE_CHECK(ARRAYSZ(drac_colour_names) ==
2853                   MONS_LAST_BASE_DRACONIAN - MONS_DRACONIAN);
2854
2855     if (!mons_is_base_draconian(mon_type) || mon_type == MONS_DRACONIAN)
2856         return "buggy";
2857
2858     return drac_colour_names[mon_type - MONS_FIRST_BASE_DRACONIAN];
2859 }
2860
2861 monster_type draconian_colour_by_name(const string &name)
2862 {
2863     COMPILE_CHECK(ARRAYSZ(drac_colour_names)
2864                   == (MONS_LAST_BASE_DRACONIAN - MONS_DRACONIAN));
2865
2866     for (unsigned i = 0; i < ARRAYSZ(drac_colour_names); ++i)
2867     {
2868         if (name == drac_colour_names[i])
2869             return static_cast<monster_type>(i + MONS_FIRST_BASE_DRACONIAN);
2870     }
2871
2872     return MONS_PROGRAM_BUG;
2873 }
2874
2875 static const char *demonspawn_base_names[] =
2876 {
2877     "monstrous", "gelid", "infernal", "putrid", "torturous",
2878 };
2879
2880 string demonspawn_base_name(monster_type mon_type)
2881 {
2882     COMPILE_CHECK(ARRAYSZ(demonspawn_base_names) ==
2883                   MONS_LAST_BASE_DEMONSPAWN - MONS_FIRST_BASE_DEMONSPAWN + 1);
2884
2885     if (mon_type < MONS_FIRST_BASE_DEMONSPAWN
2886         || mon_type > MONS_LAST_BASE_DEMONSPAWN)
2887     {
2888         return "buggy";
2889     }
2890
2891     return demonspawn_base_names[mon_type - MONS_FIRST_BASE_DEMONSPAWN];
2892 }
2893
2894 monster_type demonspawn_base_by_name(const string &name)
2895 {
2896     COMPILE_CHECK(ARRAYSZ(demonspawn_base_names) ==
2897                   MONS_LAST_BASE_DEMONSPAWN - MONS_FIRST_BASE_DEMONSPAWN + 1);
2898
2899     for (unsigned i = 0; i < ARRAYSZ(demonspawn_base_names); ++i)
2900     {
2901         if (name == demonspawn_base_names[i])
2902             return static_cast<monster_type>(i + MONS_FIRST_BASE_DEMONSPAWN);
2903     }
2904
2905     return MONS_PROGRAM_BUG;
2906 }
2907
2908 string mons_type_name(monster_type mc, description_level_type desc)
2909 {
2910     string result;
2911
2912     if (!mons_is_unique(mc))
2913     {
2914         switch (desc)
2915         {
2916         case DESC_THE:       result = "the "; break;
2917         case DESC_A:         result = "a ";   break;
2918         case DESC_PLAIN: default:             break;
2919         }
2920     }
2921
2922     switch (mc)
2923     {
2924     case RANDOM_MONSTER:
2925         result += "random monster";
2926         return result;
2927     case RANDOM_DRACONIAN:
2928         result += "random draconian";
2929         return result;
2930     case RANDOM_BASE_DRACONIAN:
2931         result += "random base draconian";
2932         return result;
2933     case RANDOM_NONBASE_DRACONIAN:
2934         result += "random nonbase draconian";
2935         return result;
2936     case RANDOM_DEMONSPAWN:
2937         result += "random demonspawn";
2938         return result;
2939     case RANDOM_BASE_DEMONSPAWN:
2940         result += "random base demonspawn";
2941         return result;
2942     case RANDOM_NONBASE_DEMONSPAWN:
2943         result += "random nonbase demonspawn";
2944         return result;
2945     case WANDERING_MONSTER:
2946         result += "wandering monster";
2947         return result;
2948     default: ;
2949     }
2950
2951     const monsterentry *me = get_monster_data(mc);
2952     if (me == nullptr)
2953     {
2954         result += make_stringf("invalid monster_type %d", mc);
2955         return result;
2956     }
2957
2958     result += me->name;
2959
2960     // Vowel fix: Change 'a orc' to 'an orc'..
2961     if (result.length() >= 3
2962         && (result[0] == 'a' || result[0] == 'A')
2963         && result[1] == ' '
2964         && is_vowel(result[2])
2965         // XXX: Hack
2966         && !starts_with(&result[2], "one-"))
2967     {
2968         result.insert(1, "n");
2969     }
2970
2971     return result;
2972 }
2973
2974 static string _get_proper_monster_name(const monster* mon)
2975 {
2976     const monsterentry *me = mon->find_monsterentry();
2977     if (!me)
2978         return "";
2979
2980     string name = getRandNameString(me->name, " name");
2981     if (!name.empty())
2982         return name;
2983
2984     return getRandNameString(get_monster_data(mons_genus(mon->type))->name,
2985                              " name");
2986 }
2987
2988 // Names a previously unnamed monster.
2989 bool give_monster_proper_name(monster* mon, bool orcs_only)
2990 {
2991     // Already has a unique name.
2992     if (mon->is_named())
2993         return false;
2994
2995     // Since this is called from the various divine blessing routines,
2996     // don't bless non-orcs, and normally don't bless plain orcs, either.
2997     if (orcs_only)
2998     {
2999         if (mons_genus(mon->type) != MONS_ORC
3000             || mon->type == MONS_ORC && !one_chance_in(8))
3001         {
3002             return false;
3003         }
3004     }
3005
3006     mon->mname = _get_proper_monster_name(mon);
3007     if (!mon->props.exists("dbname"))
3008         mon->props["dbname"] = mons_class_name(mon->type);
3009
3010     if (mon->friendly())
3011         take_note(Note(NOTE_NAMED_ALLY, 0, 0, mon->mname));
3012
3013     return mon->is_named();
3014 }
3015
3016 // See mons_init for initialization of mon_entry array.
3017 monsterentry *get_monster_data(monster_type mc)
3018 {
3019     if (mc >= 0 && mc < NUM_MONSTERS)
3020         return &mondata[mon_entry[mc]];
3021     else
3022         return nullptr;
3023 }
3024
3025 static int _mons_exp_mod(monster_type mc)
3026 {
3027     ASSERT_smc();
3028     return smc->exp_mod;
3029 }
3030
3031 int mons_class_base_speed(monster_type mc)
3032 {
3033     ASSERT_smc();
3034     return smc->speed;
3035 }
3036
3037 mon_energy_usage mons_class_energy(monster_type mc)
3038 {
3039     ASSERT_smc();
3040     return smc->energy_usage;
3041 }
3042
3043 mon_energy_usage mons_energy(const monster* mon)
3044 {
3045     mon_energy_usage meu = mons_class_energy(mons_base_type(mon));
3046     if (mon->ghost.get())
3047         meu.move = meu.swim = mon->ghost->move_energy;
3048     return meu;
3049 }
3050
3051 int mons_class_zombie_base_speed(monster_type zombie_base_mc)
3052 {
3053     return max(3, mons_class_base_speed(zombie_base_mc) - 2);
3054 }
3055
3056 /**
3057  * What's this monster's base speed, before temporary effects are applied?
3058  *
3059  * @param mon       The monster in question.
3060  * @param known     Whether to include only information the player knows about,
3061  *                  i.e. not the speed of certain monsters with varying speeds
3062  *                  (abominations, hell beasts)
3063  * @return          The speed of the monster.
3064  */
3065 int mons_base_speed(const monster* mon, bool known)
3066 {
3067     if (mon->ghost.get())
3068         return mon->ghost->speed;
3069
3070     if (mon->props.exists(MON_SPEED_KEY)
3071         && (!known || mon->type == MONS_MUTANT_BEAST))
3072     {
3073         return mon->props[MON_SPEED_KEY];
3074     }
3075
3076     if (mon->type == MONS_SPECTRAL_THING)
3077         return mons_class_base_speed(mons_zombie_base(mon));
3078
3079     return mons_is_zombified(mon) ? mons_class_zombie_base_speed(mons_zombie_base(mon))
3080                                   : mons_class_base_speed(mon->type);
3081 }
3082
3083 mon_intel_type mons_class_intel(monster_type mc)
3084 {
3085     ASSERT_smc();
3086     return smc->intel;
3087 }
3088
3089 mon_intel_type mons_intel(const monster* mon)
3090 {
3091     get_tentacle_head(mon);
3092
3093     if (mons_enslaved_soul(mon))
3094         return mons_class_intel(mons_zombie_base(mon));
3095
3096     return mons_class_intel(mon->type);
3097 }
3098
3099 static habitat_type _mons_class_habitat(monster_type mc,
3100                                         bool real_amphibious = false)
3101 {
3102     const monsterentry *me = get_monster_data(mc);
3103     habitat_type ht = (me ? me->habitat
3104                           : get_monster_data(MONS_PROGRAM_BUG)->habitat);
3105     if (!real_amphibious)
3106     {
3107         // XXX: No class equivalent of monster::body_size(PSIZE_BODY)!
3108         size_type st = (me ? me->size
3109                            : get_monster_data(MONS_PROGRAM_BUG)->size);
3110         if (ht == HT_LAND && st >= SIZE_GIANT || mc == MONS_GREY_DRACONIAN)
3111             ht = HT_AMPHIBIOUS;
3112     }
3113     return ht;
3114 }
3115
3116 habitat_type mons_habitat(const monster* mon, bool real_amphibious)
3117 {
3118     return _mons_class_habitat(fixup_zombie_type(mon->type,
3119                                                  mons_base_type(mon)),
3120                                real_amphibious);
3121 }
3122
3123 habitat_type mons_class_primary_habitat(monster_type mc)
3124 {
3125     habitat_type ht = _mons_class_habitat(mc);
3126     if (ht == HT_AMPHIBIOUS || ht == HT_AMPHIBIOUS_LAVA)
3127         ht = HT_LAND;
3128     return ht;
3129 }
3130
3131 habitat_type mons_primary_habitat(const monster* mon)
3132 {
3133     return mons_class_primary_habitat(mons_base_type(mon));
3134 }
3135
3136 habitat_type mons_class_secondary_habitat(monster_type mc)
3137 {
3138     habitat_type ht = _mons_class_habitat(mc);
3139     if (ht == HT_AMPHIBIOUS)
3140         ht = HT_WATER;
3141     if (ht == HT_AMPHIBIOUS_LAVA)
3142         ht = HT_LAVA;
3143     return ht;
3144 }
3145
3146 habitat_type mons_secondary_habitat(const monster* mon)
3147 {
3148     return mons_class_secondary_habitat(mons_base_type(mon));
3149 }
3150
3151 bool intelligent_ally(const monster* mon)
3152 {
3153     return mon->attitude == ATT_FRIENDLY && mons_intel(mon) >= I_HUMAN;
3154 }
3155
3156 int mons_power(monster_type mc)
3157 {
3158     // For now, just return monster hit dice.
3159     ASSERT_smc();
3160     return mons_class_hit_dice(mc);
3161 }
3162
3163 bool mons_aligned(const actor *m1, const actor *m2)
3164 {
3165     mon_attitude_type fr1, fr2;
3166     const monster* mon1, *mon2;
3167
3168     if (!m1 || !m2)
3169         return true;
3170
3171     if (m1->is_player())
3172         fr1 = ATT_FRIENDLY;
3173     else
3174     {
3175         mon1 = static_cast<const monster* >(m1);
3176         if (mons_is_projectile(mon1->type))
3177             return true;
3178         fr1 = mons_attitude(mon1);
3179     }
3180
3181     if (m2->is_player())
3182         fr2 = ATT_FRIENDLY;
3183     else
3184     {
3185         mon2 = static_cast<const monster* >(m2);
3186         if (mons_is_projectile(mon2->type))
3187             return true;
3188         fr2 = mons_attitude(mon2);
3189     }
3190
3191     return mons_atts_aligned(fr1, fr2);
3192 }
3193
3194 bool mons_atts_aligned(mon_attitude_type fr1, mon_attitude_type fr2)
3195 {
3196     if (mons_att_wont_attack(fr1) && mons_att_wont_attack(fr2))
3197         return true;
3198
3199     return fr1 == fr2;
3200 }
3201
3202 bool mons_class_wields_two_weapons(monster_type mc)
3203 {
3204     return mons_class_flag(mc, M_TWO_WEAPONS);
3205 }
3206
3207 bool mons_wields_two_weapons(const monster* mon)
3208 {
3209     if (testbits(mon->flags, MF_TWO_WEAPONS))
3210         return true;
3211
3212     return mons_class_wields_two_weapons(mons_base_type(mon));
3213 }
3214
3215 bool mons_self_destructs(const monster* m)
3216 {
3217     return m->type == MONS_GIANT_SPORE
3218         || m->type == MONS_BALL_LIGHTNING
3219         || m->type == MONS_LURKING_HORROR
3220         || m->type == MONS_ORB_OF_DESTRUCTION
3221         || m->type == MONS_FULMINANT_PRISM;
3222 }
3223
3224 bool mons_att_wont_attack(mon_attitude_type fr)
3225 {
3226     return fr == ATT_FRIENDLY || fr == ATT_GOOD_NEUTRAL
3227            || fr == ATT_STRICT_NEUTRAL;
3228 }
3229
3230 mon_attitude_type mons_attitude(const monster* m)
3231 {
3232     if (m->friendly())
3233         return ATT_FRIENDLY;
3234     else if (m->good_neutral())
3235         return ATT_GOOD_NEUTRAL;
3236     else if (m->strict_neutral())
3237         return ATT_STRICT_NEUTRAL;
3238     else if (m->neutral())
3239         return ATT_NEUTRAL;
3240     else
3241         return ATT_HOSTILE;
3242 }
3243
3244 bool mons_is_confused(const monster* m, bool class_too)
3245 {
3246     return (m->has_ench(ENCH_CONFUSION) || m->has_ench(ENCH_MAD))
3247            && (class_too || !mons_class_flag(m->type, M_CONFUSED));
3248 }
3249
3250 bool mons_is_wandering(const monster* m)
3251 {
3252     return m->behaviour == BEH_WANDER;
3253 }
3254
3255 bool mons_is_seeking(const monster* m)
3256 {
3257     return m->behaviour == BEH_SEEK;
3258 }
3259
3260 // Either running in fear, or trapped and unable to do so (but still wishing to)
3261 bool mons_is_fleeing(const monster* m)
3262 {
3263     return m->behaviour == BEH_FLEE || mons_is_cornered(m);
3264 }
3265
3266 // Can be either an orderly withdrawal (from which the monster can stop at will)
3267 // or running in fear (from which they cannot)
3268 bool mons_is_retreating(const monster* m)
3269 {
3270     return m->behaviour == BEH_RETREAT || mons_is_fleeing(m);
3271 }
3272
3273 bool mons_is_cornered(const monster* m)
3274 {
3275     return m->behaviour == BEH_CORNERED;
3276 }
3277
3278 bool mons_is_influenced_by_sanctuary(const monster* m)
3279 {
3280     return !m->wont_attack() && !m->is_stationary();
3281 }
3282
3283 bool mons_is_fleeing_sanctuary(const monster* m)
3284 {
3285     return mons_is_influenced_by_sanctuary(m)
3286            && in_bounds(env.sanctuary_pos)
3287            && (m->flags & MF_FLEEING_FROM_SANCTUARY);
3288 }
3289
3290 bool mons_just_slept(const monster* m)
3291 {
3292     return bool(m->flags & MF_JUST_SLEPT);
3293 }
3294
3295 // Moving body parts, turning oklob flowers and so on counts as motile here.
3296 // So does preparing resurrect, struggling against a net, etc.
3297 bool mons_is_immotile(const monster* mons)
3298 {
3299     return mons_is_firewood(mons)
3300         || mons->petrified()
3301         || mons->asleep()
3302         || mons->paralysed();
3303 }
3304
3305 bool mons_is_batty(const monster* m)
3306 {
3307     return mons_class_flag(m->type, M_BATTY) || m->has_facet(BF_BAT);
3308 }
3309
3310 bool mons_looks_stabbable(const monster* m)
3311 {
3312     const stab_type st = find_stab_type(&you, m);
3313     return !m->friendly()
3314            && (st == STAB_PARALYSED || st == STAB_SLEEPING);
3315 }
3316
3317 bool mons_looks_distracted(const monster* m)
3318 {
3319     const stab_type st = find_stab_type(&you, m);
3320     return !m->friendly()
3321            && st != STAB_NO_STAB
3322            && st != STAB_PARALYSED
3323            && st != STAB_SLEEPING;
3324 }
3325
3326 void mons_start_fleeing_from_sanctuary(monster* mons)
3327 {
3328     mons->flags |= MF_FLEEING_FROM_SANCTUARY;
3329     mons->target = env.sanctuary_pos;
3330     behaviour_event(mons, ME_SCARE, 0, env.sanctuary_pos);
3331 }
3332
3333 void mons_stop_fleeing_from_sanctuary(monster* mons)
3334 {
3335     const bool had_flag {mons->flags & MF_FLEEING_FROM_SANCTUARY};
3336     mons->flags &= (~MF_FLEEING_FROM_SANCTUARY);
3337     if (had_flag)
3338         behaviour_event(mons, ME_EVAL, &you);
3339 }
3340
3341 void mons_pacify(monster* mon, mon_attitude_type att, bool no_xp)
3342 {
3343     // If the _real_ (non-charmed) attitude is already that or better,
3344     // don't degrade it. This can happen, for example, with a high-power
3345     // Crusade card on Pikel's slaves who would then go down from friendly
3346     // to good_neutral when you kill Pikel.
3347     if (mon->attitude >= att)
3348         return;
3349
3350     // Must be done before attitude change, so that proper targets are affected
3351     if (mon->type == MONS_FLAYED_GHOST)
3352         end_flayed_effect(mon);
3353
3354     // Make the monster permanently neutral.
3355     mon->attitude = att;
3356     mon->flags |= MF_WAS_NEUTRAL;
3357
3358     if (!testbits(mon->flags, MF_PACIFIED) // Don't allow repeatedly pacifying.
3359         && !no_xp
3360         && !mon->is_summoned()
3361         && !testbits(mon->flags, MF_NO_REWARD))
3362     {
3363         // Give the player half of the monster's XP.
3364         gain_exp((exper_value(mon) + 1) / 2);
3365     }
3366     mon->flags |= MF_PACIFIED;
3367
3368     if (mon->type == MONS_GERYON)
3369     {
3370         simple_monster_message(mon,
3371             make_stringf(" discards %s horn.",
3372                          mon->pronoun(PRONOUN_POSSESSIVE).c_str()).c_str());
3373         monster_drop_things(mon, false, item_is_horn_of_geryon);
3374     }
3375
3376     // End constriction.
3377     mon->stop_constricting_all(false);
3378     mon->stop_being_constricted();
3379
3380     // Cancel fleeing and such.
3381     mon->behaviour = BEH_WANDER;
3382
3383     // Remove haunting, which would otherwise cause monster to continue attacking
3384     mon->del_ench(ENCH_HAUNTING, true, true);
3385
3386     // Remove level annotation.
3387     mon->props["no_annotate"] = true;
3388     remove_unique_annotation(mon);
3389
3390     // Make the monster begin leaving the level.
3391     behaviour_event(mon, ME_EVAL);
3392
3393     if (mons_is_mons_class(mon, MONS_PIKEL))
3394         pikel_band_neutralise();
3395     if (mons_is_elven_twin(mon))
3396         elven_twins_pacify(mon);
3397     if (mons_is_mons_class(mon, MONS_KIRKE))
3398         hogs_to_humans();
3399     if (mon->type == MONS_VAULT_WARDEN)
3400         timeout_terrain_changes(0, true);
3401
3402     mons_att_changed(mon);
3403 }
3404
3405 static bool _mons_should_fire_beneficial(bolt &beam)
3406 {
3407     // Should monster heal other, haste other or might other be able to
3408     // target the player? Saying no for now. -cao
3409     if (beam.target == you.pos())
3410         return false;
3411
3412     // Assuming all beneficial beams are enchantments if a foe is in
3413     // the path the beam will definitely hit them so we shouldn't fire
3414     // in that case.
3415     if (beam.friend_info.count == 0
3416         || beam.foe_info.count != 0)
3417     {
3418         return false;
3419     }
3420
3421     // Should beneficial monster enchantment beams be allowed in a
3422     // sanctuary? -cao
3423     if (is_sanctuary(you.pos()) || is_sanctuary(beam.source))
3424         return false;
3425
3426     return true;
3427 }
3428
3429 static bool _beneficial_beam_flavour(beam_type flavour)
3430 {
3431     switch (flavour)
3432     {
3433     case BEAM_HASTE:
3434     case BEAM_HEALING:
3435     case BEAM_INVISIBILITY:
3436     case BEAM_MIGHT:
3437     case BEAM_AGILITY:
3438     case BEAM_RESISTANCE:
3439         return true;
3440
3441     default:
3442         return false;
3443     }
3444 }
3445
3446 bool mons_should_fire(bolt &beam, bool ignore_good_idea)
3447 {
3448     dprf("tracer: foes %d (pow: %d), friends %d (pow: %d), "
3449          "foe_ratio: %d",
3450          beam.foe_info.count, beam.foe_info.power,
3451          beam.friend_info.count, beam.friend_info.power,
3452          beam.foe_ratio);
3453
3454     // Use different evaluation criteria if the beam is a beneficial
3455     // enchantment (haste other).
3456     if (_beneficial_beam_flavour(beam.flavour))
3457         return _mons_should_fire_beneficial(beam);
3458
3459     if (is_sanctuary(you.pos()) || is_sanctuary(beam.source))
3460         return false;
3461
3462     if (ignore_good_idea)
3463         return true;
3464     // After this point, safety/self-interest checks only.
3465
3466
3467     // Friendly monsters shouldn't be targeting you: this will happen
3468     // often because the default behaviour for charmed monsters is to
3469     // have you as a target. While foe_ratio will handle this, we
3470     // don't want a situation where a friendly dragon breathes through
3471     // you to hit other creatures... it should target the other
3472     // creatures, and coincidentally hit you.
3473     //
3474     // FIXME: this can cause problems with reflection, bounces, etc.
3475     // It would be better to have the monster fire logic never reach
3476     // this point for friendlies.
3477     if (monster_by_mid(beam.source_id))
3478     {
3479         monster* m = monster_by_mid(beam.source_id);
3480         if (m->alive() && m->friendly() && beam.target == you.pos())
3481             return false;
3482     }
3483
3484     // Use of foeRatio:
3485     // The higher this number, the more monsters will _avoid_ collateral
3486     // damage to their friends.
3487     // Setting this to zero will in fact have all monsters ignore their
3488     // friends when considering collateral damage.
3489
3490     // Quick check - did we in fact get any foes?
3491     if (beam.foe_info.count == 0)
3492         return false;
3493
3494     // If we hit no friends, fire away.
3495     if (beam.friend_info.count == 0)
3496         return true;
3497
3498     // Only fire if they do acceptably low collateral damage.
3499     return beam.foe_info.power >=
3500            div_round_up(beam.foe_ratio *
3501                         (beam.foe_info.power + beam.friend_info.power),
3502                         100);
3503 }
3504
3505 /**
3506  * Can monsters use the given spell effectively from range? (If a monster has
3507  * the given spell, should it try to keep its distance from its enemies?)
3508  *
3509  * @param monspell      The spell in question.
3510  * @param attack_only   Whether to only count spells which directly harm
3511  *                      enemies (damage or stat drain). Overrides ench_too.
3512  * @param ench_too      Whether to count temporary debilitating effects (Slow,
3513  *                      etc).
3514  * @return              Whether the given spell should be considered 'ranged'.
3515  */
3516 static bool _ms_ranged_spell(spell_type monspell, bool attack_only = false,
3517                              bool ench_too = true)
3518 {
3519     // summoning spells are usable from ranged, but not direct attacks.
3520     if (spell_typematch(monspell, SPTYP_SUMMONING)
3521         || monspell == SPELL_CONJURE_BALL_LIGHTNING)
3522     {
3523         return !attack_only;
3524     }
3525
3526     const unsigned int flags = get_spell_flags(monspell);
3527
3528     // buffs & escape spells aren't considered 'ranged'.
3529     if (testbits(flags, SPFLAG_SELFENCH)
3530         || spell_typematch(monspell, SPTYP_CHARMS)
3531         || testbits(flags, SPFLAG_ESCAPE)
3532         || monspell == SPELL_BLINK_OTHER_CLOSE)
3533     {
3534         return false;
3535     }
3536
3537     // conjurations are attacks.
3538     if (spell_typematch(monspell, SPTYP_CONJURATION))
3539         return true;
3540
3541     // hexes that aren't conjurations or summons are enchantments.
3542     if (spell_typematch(monspell, SPTYP_HEXES))
3543         return !attack_only && ench_too;
3544
3545     switch (monspell)
3546     {
3547     case SPELL_NO_SPELL:
3548     case SPELL_CANTRIP:
3549     case SPELL_BLINK_CLOSE:
3550         return false;
3551
3552     default:
3553         // Everything else is probably some kind of attack, hopefully.
3554         return true;
3555     }
3556 }
3557
3558 // Returns true if the monster has an ability that can affect the target
3559 // anywhere in LOS_DEFAULT; i.e., even through glass.
3560 bool mons_has_los_ability(monster_type mon_type)
3561 {
3562     return mons_is_siren_beholder(mon_type)
3563            || mon_type == MONS_STARCURSED_MASS;
3564 }
3565
3566 bool mons_has_ranged_spell(const monster* mon, bool attack_only,
3567                            bool ench_too)
3568 {
3569     // Monsters may have spell-like abilities.
3570     if (mons_has_los_ability(mon->type))
3571         return true;
3572
3573     for (const mon_spell_slot &slot : mon->spells)
3574         if (_ms_ranged_spell(slot.spell, attack_only, ench_too))
3575             return true;
3576
3577     return false;
3578 }
3579
3580 // Returns whether the monster has a spell which is theoretically capable of
3581 // causing an incapacitation state in the target foe (ie: it can cast sleep
3582 // and the foe is not immune to being put to sleep)
3583 //
3584 // Note that this only current checks for inherent obvious immunity (ie: sleep
3585 // immunity from being undead) and not immunity that might be granted by gear
3586 // (such as clarity or stasis)
3587 bool mons_has_incapacitating_spell(const monster* mon, const actor* foe)
3588 {
3589     for (const mon_spell_slot &slot : mon->spells)
3590     {
3591         switch (slot.spell)
3592         {
3593         case SPELL_SLEEP:
3594             if (foe->can_sleep())
3595                 return true;
3596             break;
3597
3598         case SPELL_HIBERNATION:
3599             if (foe->can_hibernate(false, true))
3600                 return true;
3601             break;
3602
3603         case SPELL_CONFUSE:
3604         case SPELL_MASS_CONFUSION:
3605         case SPELL_PARALYSE:
3606             return true;
3607
3608         case SPELL_PETRIFY:
3609             if (foe->res_petrify())
3610                 return true;
3611             break;
3612
3613         default:
3614             break;
3615         }
3616     }
3617
3618     return false;
3619 }
3620
3621 static bool _mons_has_usable_ranged_weapon(const monster* mon)
3622 {
3623     // Ugh.
3624     const item_def *weapon  = mon->launcher();
3625     const item_def *primary = mon->mslot_item(MSLOT_WEAPON);
3626     const item_def *missile = mon->missiles();
3627
3628     // We don't have a usable ranged weapon if a different cursed weapon
3629     // is presently equipped.
3630     if (weapon != primary && primary && primary->cursed())
3631         return false;
3632
3633     if (!missile)
3634         return false;
3635
3636     return is_launched(mon, weapon, *missile);
3637 }
3638
3639 bool mons_has_ranged_attack(const monster* mon)
3640 {
3641     return mons_has_ranged_spell(mon, true)
3642            || _mons_has_usable_ranged_weapon(mon);
3643 }
3644
3645 bool mons_has_incapacitating_ranged_attack(const monster* mon, const actor* foe)
3646 {
3647     if (!_mons_has_usable_ranged_weapon(mon))
3648         return false;
3649
3650     const item_def *missile = mon->missiles();
3651
3652     if (missile && missile->sub_type == MI_THROWING_NET)
3653         return true;
3654     else if (missile && missile->sub_type == MI_NEEDLE)
3655     {
3656         switch (get_ammo_brand(*missile))
3657         {
3658         // Not actually incapacitating, but marked as such so that
3659         // assassins will prefer using it while ammo remains
3660         case SPMSL_CURARE:
3661             if (foe->res_poison() <= 0)
3662                 return true;
3663             break;
3664
3665         case SPMSL_SLEEP:
3666             if (foe->can_sleep())
3667                 return true;
3668             break;
3669
3670         case SPMSL_CONFUSION:
3671         case SPMSL_PARALYSIS:
3672             return true;
3673
3674         default:
3675             break;
3676         }
3677</