1 /**
2  * @file
3  * @brief Functions used when placing monsters in the dungeon.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "mon-place.h"
9 #include "mgen-data.h"
10 
11 #include <algorithm>
12 #include <functional>
13 
14 #include "abyss.h"
15 #include "areas.h"
16 #include "arena.h"
17 #include "attitude-change.h"
18 #include "branch.h"
19 #include "cloud.h"
20 #include "colour.h"
21 #include "coordit.h"
22 #include "directn.h"
23 #include "dungeon.h"
24 #include "env.h"
25 #include "errors.h"
26 #include "fprop.h"
27 #include "gender-type.h"
28 #include "ghost.h"
29 #include "god-abil.h"
30 #include "god-passive.h" // passive_t::slow_abyss, slow_orb_run
31 #include "libutil.h"
32 #include "losglobal.h"
33 #include "message.h"
34 #include "mon-act.h"
35 #include "mon-behv.h"
36 #include "mon-death.h"
37 #include "mon-gear.h"
38 #include "mon-pick.h"
39 #include "mon-poly.h"
40 #include "mon-tentacle.h"
41 #include "random.h"
42 #include "religion.h"
43 #include "shopping.h"
44 #include "spl-clouds.h"
45 #include "spl-damage.h"
46 #include "spl-summoning.h"
47 #include "state.h"
48 #include "stringutil.h"
49 #include "tag-version.h"
50 #include "terrain.h"
51 #ifdef USE_TILE
52  #include "rltiles/tiledef-player.h"
53 #endif
54 #include "tilepick.h"
55 #include "traps.h"
56 #include "travel.h"
57 #include "unwind.h"
58 #include "view.h"
59 
60 band_type active_monster_band = BAND_NO_BAND;
61 
62 static vector<int> vault_mon_types;
63 static vector<int> vault_mon_bases;
64 static vector<level_id> vault_mon_places;
65 static vector<int> vault_mon_weights;
66 static vector<bool> vault_mon_bands;
67 
68 #if TAG_MAJOR_VERSION > 34
69 #define VAULT_MON_TYPES_KEY   "vault_mon_types"
70 #define VAULT_MON_BASES_KEY   "vault_mon_bases"
71 #define VAULT_MON_PLACES_KEY  "vault_mon_places"
72 #define VAULT_MON_WEIGHTS_KEY "vault_mon_weights"
73 #define VAULT_MON_BANDS_KEY   "vault_mon_bands"
74 #endif
75 
76 #define BIG_BAND        20
77 
78 static monster_type _band_member(band_type band, int which,
79                                  level_id parent_place, bool allow_ood);
80 static band_type _choose_band(monster_type mon_type, int *band_size_p = nullptr,
81                               bool *natural_leader_p = nullptr);
82 
83 static monster* _place_monster_aux(const mgen_data &mg, const monster *leader,
84                                    level_id place,
85                                    bool force_pos = false,
86                                    bool dont_place = false);
87 static monster* _place_pghost_aux(const mgen_data &mg, const monster *leader,
88                                    level_id place,
89                                    bool force_pos, bool dont_place);
90 
91 
92 /**
93  * Is this feature "close enough" to the one we want for monster generation?
94  *
95  * @param wanted_feat the preferred feature
96  * @param actual_feat the feature to be compared to it
97  * @returns Whether wanted_feat is considered to be similar enough to
98  *          actual_feat that being able to survive in the former means you can
99  *          survive in the latter.
100  */
_feat_compatible(dungeon_feature_type wanted_feat,dungeon_feature_type actual_feat)101 static bool _feat_compatible(dungeon_feature_type wanted_feat,
102                              dungeon_feature_type actual_feat)
103 {
104     return wanted_feat == actual_feat
105            || wanted_feat == DNGN_DEEP_WATER && feat_is_watery(actual_feat)
106            || wanted_feat == DNGN_FLOOR && feat_has_solid_floor(actual_feat);
107 }
108 
_hab_requires_mon_flight(dungeon_feature_type g)109 static bool _hab_requires_mon_flight(dungeon_feature_type g)
110 {
111     return g == DNGN_LAVA || g == DNGN_DEEP_WATER;
112 }
113 
114 /**
115  * Can this monster survive on actual_grid?
116  *
117  * @param mon         the monster to be checked.
118  * @param actual_grid the feature type that mon might not be able to survive.
119  * @returns whether the monster can survive being in/over the feature,
120  *          regardless of whether it may be dangerous or harmful.
121  */
monster_habitable_grid(const monster * mon,dungeon_feature_type actual_grid)122 bool monster_habitable_grid(const monster* mon,
123                             dungeon_feature_type actual_grid)
124 {
125     // Zombified monsters enjoy the same habitat as their original,
126     // except lava-based monsters.
127     const monster_type mt = mons_is_job(mon->type)
128         ? draco_or_demonspawn_subspecies(*mon)
129         : fixup_zombie_type(mon->type, mons_base_type(*mon));
130 
131     bool type_safe = monster_habitable_grid(mt, actual_grid, DNGN_UNSEEN);
132     return type_safe ||
133                     _hab_requires_mon_flight(actual_grid) && mon->airborne();
134 }
135 
136 /**
137  * Can monsters of this class survive on actual_grid?
138  *
139  * @param mt the monster class to check against
140  * @param actual_grid the terrain feature being checked
141  * @param wanted_grid if == DNGN_UNSEEN, or if the monster can't survive on it,
142  *                    ignored. Otherwise, return false even if actual_grid is
143  *                    survivable, if actual_grid isn't similar to wanted_grid.
144  * @param flies if true, treat the monster as flying even if the monster class
145  *              can't usually fly.
146  */
monster_habitable_grid(monster_type mt,dungeon_feature_type actual_grid,dungeon_feature_type wanted_grid)147 bool monster_habitable_grid(monster_type mt,
148                             dungeon_feature_type actual_grid,
149                             dungeon_feature_type wanted_grid)
150 {
151     // No monster may be placed in walls etc.
152     if (!mons_class_can_pass(mt, actual_grid))
153         return false;
154 
155 #if TAG_MAJOR_VERSION == 34
156     // Monsters can't use teleporters, and standing there would look just wrong.
157     if (actual_grid == DNGN_TELEPORTER)
158         return false;
159 #endif
160     // The kraken is so large it cannot enter shallow water.
161     // Its tentacles can, and will, though.
162     if (actual_grid == DNGN_SHALLOW_WATER && mt == MONS_KRAKEN)
163         return false;
164 
165     const dungeon_feature_type feat_preferred =
166         habitat2grid(mons_class_primary_habitat(mt));
167     const dungeon_feature_type feat_nonpreferred =
168         habitat2grid(mons_class_secondary_habitat(mt));
169 
170     // If the caller insists on a specific feature type, try to honour
171     // the request. This allows the builder to place amphibious
172     // creatures only on land, or flying creatures only on lava, etc.
173     if (wanted_grid != DNGN_UNSEEN
174         && monster_habitable_grid(mt, wanted_grid, DNGN_UNSEEN))
175     {
176         return _feat_compatible(wanted_grid, actual_grid);
177     }
178 
179     if (actual_grid == DNGN_MALIGN_GATEWAY)
180     {
181         if (mt == MONS_ELDRITCH_TENTACLE
182             || mt == MONS_ELDRITCH_TENTACLE_SEGMENT)
183         {
184             return true;
185         }
186         else
187             return false;
188     }
189 
190     if (_feat_compatible(feat_preferred, actual_grid)
191         || _feat_compatible(feat_nonpreferred, actual_grid))
192     {
193         return true;
194     }
195 
196     // [dshaligram] Flying creatures are all HT_LAND, so we
197     // only have to check for the additional valid grids of deep
198     // water and lava.
199     if (_hab_requires_mon_flight(actual_grid) && (mons_class_flag(mt, M_FLIES)))
200         return true;
201 
202     return false;
203 }
204 
205 // Returns true if the monster can submerge in the given grid.
monster_can_submerge(const monster * mon,dungeon_feature_type feat)206 bool monster_can_submerge(const monster* mon, dungeon_feature_type feat)
207 {
208     if (!mon->is_habitable_feat(feat))
209         return false;
210     if (mons_class_flag(mon->type, M_SUBMERGES))
211     {
212         switch (mons_habitat(*mon))
213         {
214         case HT_WATER:
215         case HT_AMPHIBIOUS:
216             return feat_is_watery(feat);
217         case HT_LAVA:
218         case HT_AMPHIBIOUS_LAVA:
219             return feat == DNGN_LAVA;
220         case HT_LAND:
221             return feat == DNGN_FLOOR;
222         default:
223             return false;
224         }
225     }
226     else
227         return false;
228 }
229 
_ood_fuzzspan(level_id & place)230 static int _ood_fuzzspan(level_id &place)
231 {
232     if (place.branch != BRANCH_DUNGEON || place.depth >= 5)
233         return 5;
234 
235     // Literally any OOD is too nasty for D:1.
236     if (place.depth == 1)
237         return 0;
238 
239     // In early D, since player and enemy strength scale so rapidly
240     // with depth, spawn OODs from much closer depths.
241     // Only up to D:4 on D:2, up to D:6 on D:3, and D:8 on D:4.
242     return place.depth;
243 }
244 
_apply_ood(level_id & place)245 static void _apply_ood(level_id &place)
246 {
247     // OODs do not apply to any portal vaults, any 1-level branches, Zot and
248     // hells. What with newnewabyss?
249     if (!is_connected_branch(place)
250         || place.branch == BRANCH_ZOT
251         || is_hell_subbranch(place.branch)
252         || brdepth[place.branch] <= 1)
253     {
254         return;
255     }
256 
257 #ifdef DEBUG_DIAGNOSTICS
258     level_id old_place = place;
259 #endif
260 
261     const int fuzzspan = _ood_fuzzspan(place);
262     if (fuzzspan && x_chance_in_y(14, 100))
263     {
264         // We want a left-weighted distribution; slight fuzzing should be much
265         // more common than the full depth fuzz. This does mean that OODs are closer
266         // to a 6% chance than the 14% implied above, which is a bit silly.
267         const int fuzz = random_range(-fuzzspan, fuzzspan);
268         if (fuzz > 0)
269         {
270             place.depth += fuzz;
271             dprf("Monster level fuzz: %d (old: %s, new: %s)",
272                  fuzz, old_place.describe().c_str(), place.describe().c_str());
273         }
274     }
275 }
276 
277 //#define DEBUG_MON_CREATION
278 
279 /**
280  * Spawn random monsters.
281 
282  * The spawn rate defaults to the current env.spawn_random_rate for the branch,
283  * but is modified by whether the player is in the abyss and on what level, as
284  * well as whether the player has the orb.
285  */
spawn_random_monsters()286 void spawn_random_monsters()
287 {
288     if (crawl_state.disables[DIS_SPAWNS])
289         return;
290 
291     if (crawl_state.game_is_arena()
292         || (crawl_state.game_is_sprint()
293             && player_in_connected_branch()
294             && you.chapter == CHAPTER_ORB_HUNTING)
295         // Spawns no longer occur outside the Orb run in connected branches.
296         || !player_on_orb_run() && player_in_connected_branch())
297     {
298         return;
299     }
300 
301 #ifdef DEBUG_MON_CREATION
302     mprf(MSGCH_DIAGNOSTICS, "in spawn_random_monsters()");
303 #endif
304     int rate = env.spawn_random_rate;
305     if (!rate)
306     {
307 #ifdef DEBUG_MON_CREATION
308         mprf(MSGCH_DIAGNOSTICS, "random monster gen turned off");
309 #endif
310         return;
311     }
312 
313     if (player_on_orb_run())
314         rate = have_passive(passive_t::slow_orb_run) ? 36 : 18;
315 
316     if (player_in_branch(BRANCH_ABYSS))
317     {
318         if (!player_in_starting_abyss())
319             rate = 5;
320         if (have_passive(passive_t::slow_abyss))
321             rate *= 2;
322     }
323 
324     if (!x_chance_in_y(5, rate))
325         return;
326 
327     // Orb spawns. Don't generate orb spawns in Abyss to show some mercy to
328     // players that get banished there on the orb run.
329     if (player_on_orb_run() && !player_in_branch(BRANCH_ABYSS))
330     {
331         dprf(DIAG_MONPLACE, "Placing monster, rate: %d, turns here: %d",
332              rate, env.turns_on_level);
333 
334         mgen_data mg(WANDERING_MONSTER);
335         mg.proximity = PROX_CLOSE_TO_PLAYER;
336         mg.foe = MHITYOU;
337         // Don't count orb run spawns in the xp_by_level dump
338         mg.xp_tracking = XP_UNTRACKED;
339         mons_place(mg);
340         viewwindow();
341         update_screen();
342         return;
343     }
344 
345     mgen_data mg(WANDERING_MONSTER);
346     if (player_in_branch(BRANCH_PANDEMONIUM)
347         && !env.properties.exists("vault_mon_weights")
348         && !one_chance_in(40))
349     {
350         mg.cls = env.mons_alloc[random2(PAN_MONS_ALLOC)];
351         mg.flags |= MG_PERMIT_BANDS;
352     }
353 
354     mons_place(mg);
355     viewwindow();
356     update_screen();
357 }
358 
_is_random_monster(monster_type mt)359 static bool _is_random_monster(monster_type mt)
360 {
361     return mt == RANDOM_MONSTER || mt == RANDOM_MOBILE_MONSTER
362            || mt == RANDOM_COMPATIBLE_MONSTER
363            || mt == RANDOM_BANDLESS_MONSTER
364            || mt == WANDERING_MONSTER;
365 }
366 
_has_big_aura(monster_type mt)367 static bool _has_big_aura(monster_type mt)
368 {
369     return mt == MONS_SILENT_SPECTRE;
370 }
371 
_is_incompatible_monster(monster_type mt)372 static bool _is_incompatible_monster(monster_type mt)
373 {
374     return mons_class_is_stationary(mt)
375         || god_hates_monster(mt);
376 }
377 
_is_banded_monster(monster_type mt)378 static bool _is_banded_monster(monster_type mt)
379 {
380     return _choose_band(mt) != BAND_NO_BAND;
381 }
382 
383 // Caller must use !invalid_monster_type to check if the return value
384 // is a real monster.
pick_random_monster(level_id place,monster_type kind,level_id * final_place,bool allow_ood)385 monster_type pick_random_monster(level_id place,
386                                  monster_type kind,
387                                  level_id *final_place,
388                                  bool allow_ood)
389 {
390     if (crawl_state.game_is_arena())
391     {
392         monster_type type = arena_pick_random_monster(place);
393         if (!_is_random_monster(type))
394             return type;
395     }
396 
397     if (allow_ood)
398         _apply_ood(place);
399 
400     place.depth = min(place.depth, branch_ood_cap(place.branch));
401 
402     if (final_place)
403         *final_place = place;
404 
405     if (crawl_state.game_is_arena())
406         return pick_monster(place, arena_veto_random_monster);
407 
408     ASSERT(_is_random_monster(kind) || kind == MONS_NO_MONSTER);
409 
410     if (kind == RANDOM_MOBILE_MONSTER)
411         return pick_monster(place, mons_class_is_stationary);
412     else if (kind == RANDOM_COMPATIBLE_MONSTER)
413         return pick_monster(place, _is_incompatible_monster);
414     else if (kind == RANDOM_BANDLESS_MONSTER)
415         return pick_monster(place, _is_banded_monster);
416     else if (crawl_state.game_is_sprint())
417         return pick_monster(place, _has_big_aura);
418     else
419         return pick_monster(place);
420 }
421 
drac_colour_incompatible(int drac,int colour)422 bool drac_colour_incompatible(int drac, int colour)
423 {
424     return drac == MONS_DRACONIAN_SCORCHER && colour == MONS_WHITE_DRACONIAN;
425 }
426 
needs_resolution(monster_type mon_type)427 bool needs_resolution(monster_type mon_type)
428 {
429     return mon_type == RANDOM_DRACONIAN || mon_type == RANDOM_BASE_DRACONIAN
430            || mon_type == RANDOM_NONBASE_DRACONIAN
431            || mon_type >= RANDOM_DEMON_LESSER && mon_type <= RANDOM_DEMON
432            || mon_type == RANDOM_DEMONSPAWN
433            || mon_type == RANDOM_BASE_DEMONSPAWN
434            || mon_type == RANDOM_NONBASE_DEMONSPAWN
435            || _is_random_monster(mon_type);
436 }
437 
resolve_monster_type(monster_type mon_type,monster_type & base_type,proximity_type proximity,coord_def * pos,unsigned mmask,level_id * place,bool * want_band,bool allow_ood)438 monster_type resolve_monster_type(monster_type mon_type,
439                                   monster_type &base_type,
440                                   proximity_type proximity,
441                                   coord_def *pos,
442                                   unsigned mmask,
443                                   level_id *place,
444                                   bool *want_band,
445                                   bool allow_ood)
446 {
447     if (want_band)
448         *want_band = false;
449 
450     if (mon_type == RANDOM_DRACONIAN)
451     {
452         // Pick any random drac, constrained by colour if requested.
453         do
454         {
455             if (coinflip())
456                 mon_type = random_draconian_monster_species();
457             else
458                 mon_type = random_draconian_job();
459         }
460         while (base_type != MONS_PROGRAM_BUG
461                && mon_type != base_type
462                && (mons_species(mon_type) == mon_type
463                    || drac_colour_incompatible(mon_type, base_type)));
464     }
465     else if (mon_type == RANDOM_BASE_DRACONIAN)
466         mon_type = random_draconian_monster_species();
467     else if (mon_type == RANDOM_NONBASE_DRACONIAN)
468         mon_type = random_draconian_job();
469     else if (mon_type >= RANDOM_DEMON_LESSER && mon_type <= RANDOM_DEMON)
470         mon_type = summon_any_demon(mon_type, true);
471     else if (mon_type == RANDOM_DEMONSPAWN)
472     {
473         do
474         {
475             mon_type =
476                 static_cast<monster_type>(
477                     random_range(MONS_FIRST_DEMONSPAWN,
478                                  MONS_LAST_DEMONSPAWN));
479         }
480         while (base_type != MONS_PROGRAM_BUG
481                && mon_type != base_type
482                && mons_species(mon_type) == mon_type);
483     }
484     else if (mon_type == RANDOM_BASE_DEMONSPAWN)
485         mon_type = random_demonspawn_monster_species();
486     else if (mon_type == RANDOM_NONBASE_DEMONSPAWN)
487         mon_type = random_demonspawn_job();
488 
489     // (2) Take care of non-draconian random monsters.
490     else if (_is_random_monster(mon_type))
491     {
492         // Only use the vault list if the monster comes from this level.
493         if (!vault_mon_types.empty() && *place == level_id::current())
494         {
495             int i = 0;
496             int tries = 0;
497             int type;
498             do
499             {
500                 i = choose_random_weighted(vault_mon_weights.begin(),
501                                            vault_mon_weights.end());
502                 type = vault_mon_types[i];
503 
504                 // Give up after enough attempts: for example, a Yred
505                 // worshipper casting Shadow Creatures in holy Pan.
506                 if (tries++ >= 300)
507                     type = MONS_NO_MONSTER;
508                 // If the monster list says not to place, or to place
509                 // by level, or to place a random monster, accept that.
510                 // If it's random, we'll be recursively calling ourselves
511                 // later on for the new monster type.
512                 if (type == MONS_NO_MONSTER || type == -1
513                     || needs_resolution((monster_type)type))
514                 {
515                     break;
516                 }
517             }
518             while (mon_type == RANDOM_MOBILE_MONSTER
519                       && mons_class_is_stationary((monster_type)type)
520                    || mon_type == RANDOM_COMPATIBLE_MONSTER
521                       && _is_incompatible_monster((monster_type)type)
522                    || mon_type == RANDOM_BANDLESS_MONSTER
523                       && _is_banded_monster((monster_type)type));
524 
525             int base = vault_mon_bases[i];
526             bool banded = vault_mon_bands[i];
527 
528             if (type == -1)
529                 *place = vault_mon_places[i];
530             else
531             {
532                 base_type = (monster_type) base;
533                 mon_type  = (monster_type) type;
534                 if (want_band)
535                     *want_band = banded;
536                 if (needs_resolution(mon_type))
537                 {
538                     mon_type =
539                         resolve_monster_type(mon_type, base_type,
540                                              proximity, pos, mmask,
541                                              place, want_band, allow_ood);
542                 }
543                 return mon_type;
544             }
545         }
546 
547         // Now pick a monster of the given branch and level.
548         mon_type = pick_random_monster(*place, mon_type, place, allow_ood);
549     }
550     return mon_type;
551 }
552 
553 // For generation purposes, don't treat simulacra of lava enemies as
554 // being able to place on lava.
fixup_zombie_type(const monster_type cls,const monster_type base_type)555 monster_type fixup_zombie_type(const monster_type cls,
556                                          const monster_type base_type)
557 {
558     return (mons_class_is_zombified(cls)
559             && mons_class_secondary_habitat(base_type) != HT_LAVA)
560             ? base_type
561             : cls;
562 }
563 
564 // Checks if the monster is ok to place at mg_pos. If force_location
565 // is true, then we'll be less rigorous in our checks, in particular
566 // allowing land monsters to be placed in shallow water and water
567 // creatures in fountains.
_valid_monster_generation_location(const mgen_data & mg,const coord_def & mg_pos)568 static bool _valid_monster_generation_location(const mgen_data &mg,
569                                                 const coord_def &mg_pos)
570 {
571     if (!in_bounds(mg_pos)
572         || monster_at(mg_pos)
573         || you.pos() == mg_pos && !fedhas_passthrough_class(mg.cls))
574     {
575         ASSERT(!crawl_state.generating_level
576                 || !in_bounds(mg_pos)
577                 || you.pos() != mg_pos
578                 || you.where_are_you == BRANCH_ABYSS);
579         return false;
580     }
581 
582     const monster_type montype = fixup_zombie_type(mg.cls, mg.base_type);
583     if (!monster_habitable_grid(montype, env.grid(mg_pos), mg.preferred_grid_feature)
584         || (mg.behaviour != BEH_FRIENDLY
585             && is_sanctuary(mg_pos)
586             && !mons_is_tentacle_segment(montype)))
587     {
588         return false;
589     }
590 
591     bool close_to_player = grid_distance(you.pos(), mg_pos) <= LOS_RADIUS;
592     if (mg.proximity == PROX_AWAY_FROM_PLAYER && close_to_player
593         || mg.proximity == PROX_CLOSE_TO_PLAYER && !close_to_player)
594     {
595         ASSERT(!crawl_state.generating_level || you.where_are_you == BRANCH_ABYSS);
596         return false;
597     }
598     // Check that the location is not proximal to level stairs.
599     else if (mg.proximity == PROX_AWAY_FROM_STAIRS)
600     {
601         for (distance_iterator di(mg_pos, false, false, LOS_RADIUS); di; ++di)
602             if (feat_is_stone_stair(env.grid(*di)))
603                 return false;
604     }
605     // Check that the location is not proximal to an area where the player
606     // begins the game.
607     else if (mg.proximity == PROX_AWAY_FROM_ENTRANCE)
608     {
609         for (distance_iterator di(mg_pos, false, false, LOS_RADIUS); di; ++di)
610         {
611             // for consistency, this should happen regardless of whether the
612             // player is starting on D:1
613             if (env.absdepth0 == 0)
614             {
615                 if (feat_is_branch_exit(env.grid(*di))
616                     // We may be checking before branch exit cleanup.
617                     || feat_is_stone_stair_up(env.grid(*di)))
618                 {
619                     return false;
620                 }
621             }
622             else if (env.absdepth0 == starting_absdepth())
623             {
624                 // Delvers start on a (specific) D:5 downstairs.
625                 if (env.grid(*di) == DNGN_STONE_STAIRS_DOWN_I)
626                     return false;
627             }
628         }
629     }
630 
631     return true;
632 }
633 
_valid_monster_generation_location(mgen_data & mg)634 static bool _valid_monster_generation_location(mgen_data &mg)
635 {
636     return _valid_monster_generation_location(mg, mg.pos);
637 }
638 
place_monster(mgen_data mg,bool force_pos,bool dont_place)639 monster* place_monster(mgen_data mg, bool force_pos, bool dont_place)
640 {
641     rng::subgenerator monster_rng;
642 
643 #ifdef DEBUG_MON_CREATION
644     mprf(MSGCH_DIAGNOSTICS, "in place_monster()");
645 #endif
646 
647     const int mon_count = count_if(begin(env.mons), end(env.mons),
648                                    [] (const monster &mons) -> bool
649                                    { return mons.type != MONS_NO_MONSTER; });
650     // All monsters have been assigned? {dlb}
651     if (mon_count >= MAX_MONSTERS - 1)
652         return nullptr;
653 
654     int tries = 0;
655 
656     // (1) Early out (summoned to occupied grid).
657     if (mg.use_position() && monster_at(mg.pos))
658         return 0;
659 
660     if (!mg.place.is_valid())
661         mg.place = level_id::current();
662 
663     const bool allow_ood = !(mg.flags & MG_NO_OOD);
664     bool want_band = false;
665     level_id place = mg.place;
666     mg.cls = resolve_monster_type(mg.cls, mg.base_type, mg.proximity,
667                                   &mg.pos, mg.map_mask,
668                                   &place, &want_band, allow_ood);
669     // TODO: it doesn't seem that this check can ever come out to be true??
670     bool chose_ood_monster = place.absdepth() > mg.place.absdepth() + 5;
671     if (want_band)
672         mg.flags |= MG_PERMIT_BANDS;
673 
674     if (mons_class_requires_band(mg.cls) && ! mg.flags & MG_PERMIT_BANDS)
675         return 0;
676 
677     if (mg.cls == MONS_NO_MONSTER || mg.cls == MONS_PROGRAM_BUG)
678         return 0;
679 
680     bool create_band = mg.permit_bands();
681     // If we drew an OOD monster and the level has less absdepth than D:13
682     // disable band generation. This applies only to randomly picked monsters
683     // -- chose_ood_monster will never be set true for explicitly specified
684     // monsters in vaults and other places.
685     if (chose_ood_monster && env.absdepth0 < 12)
686     {
687         dprf(DIAG_MONPLACE,
688              "Chose monster with OOD roll: %s, disabling band generation",
689              get_monster_data(mg.cls)->name);
690         create_band = false;
691     }
692 
693     if (mg.cls == MONS_PROGRAM_BUG)
694         return 0;
695 
696     // (3) Decide on banding (good lord!)
697     int band_size = 1;
698     bool leader = false;
699     monster_type band_monsters[BIG_BAND];        // band monster types
700     band_type band = BAND_NO_BAND;
701     band_monsters[0] = mg.cls;
702 
703     if (create_band)
704     {
705 #ifdef DEBUG_MON_CREATION
706         mprf(MSGCH_DIAGNOSTICS, "Choose band members...");
707 #endif
708         band = _choose_band(mg.cls, &band_size, &leader);
709         band_size++;
710         for (int i = 1; i < band_size; ++i)
711         {
712             band_monsters[i] = _band_member(band, i, place, allow_ood);
713             if (band_monsters[i] == NUM_MONSTERS)
714                 die("Unhandled band type %d", band);
715         }
716 
717         // Set the (very) ugly thing band colour.
718         ugly_thing_apply_uniform_band_colour(mg, band_monsters, band_size);
719     }
720 
721     // For first monster, choose location. This is pretty intensive.
722     if (!mg.use_position() && !force_pos)
723     {
724         tries = 0;
725 
726         // Try to pick a position that is
727         // a) not occupied
728         // b) compatible
729         // c) in the 'correct' proximity to the player
730 
731         while (true)
732         {
733             if (tries++ >= 45)
734                 return nullptr;
735 
736             mg.pos = random_in_bounds();
737 
738             if (!_valid_monster_generation_location(mg))
739                 continue;
740 
741             // Is the grid verboten?
742             if (map_masked(mg.pos, mg.map_mask))
743                 continue;
744 
745             break;
746         }
747     }
748     // Sanity check that the specified position is valid.
749     else if (!_valid_monster_generation_location(mg) && !dont_place)
750         return nullptr;
751 
752     monster* mon;
753     if (mg.cls == MONS_PLAYER_GHOST)
754         mon = _place_pghost_aux(mg, nullptr, place, force_pos, dont_place);
755     else
756         mon = _place_monster_aux(mg, nullptr, place, force_pos, dont_place);
757 
758     if (!mon)
759         return nullptr;
760 
761     if (mg.props.exists(MAP_KEY))
762         mon->set_originating_map(mg.props[MAP_KEY].get_string());
763 
764     if (chose_ood_monster)
765         mon->props[MON_OOD_KEY].get_bool() = true;
766 
767     if (mg.needs_patrol_point()
768         || (mon->type == MONS_ALLIGATOR
769             && !testbits(mon->flags, MF_BAND_MEMBER)))
770     {
771         mon->patrol_point = mon->pos();
772 #ifdef DEBUG_PATHFIND
773         mprf("Monster %s is patrolling around (%d, %d).",
774              mon->name(DESC_PLAIN).c_str(), mon->pos().x, mon->pos().y);
775 #endif
776     }
777 
778     if (player_in_branch(BRANCH_ABYSS) && !mg.summoner
779         && in_bounds(mon->pos())
780         && !(mg.extra_flags & MF_WAS_IN_VIEW)
781         && !cell_is_solid(mon->pos()))
782     {
783         big_cloud(CLOUD_TLOC_ENERGY, mon, mon->pos(), 3 + random2(3), 3, 3);
784     }
785 
786     if (player_in_branch(BRANCH_ABYSS) && you.can_see(*mon)
787              && !crawl_state.generating_level
788              && !mg.summoner
789              && !crawl_state.is_god_acting()
790              && !(mon->flags & MF_WAS_IN_VIEW)) // is this possible?
791     {
792         mon->seen_context = SC_ABYSS;
793     }
794 
795     // Now, forget about banding if the first placement failed, or there are
796     // too many monsters already.
797     if (mon->mindex() >= MAX_MONSTERS - 30)
798         return mon;
799 
800     if (band_size > 1)
801         mon->flags |= MF_BAND_MEMBER;
802 
803     const bool priest = mon->is_priest();
804 
805     mgen_data band_template = mg;
806 
807     if (leader && !mg.summoner)
808     {
809         band_template.summoner = mon;
810         band_template.flags |= MG_BAND_MINION;
811     }
812 
813     unwind_var<band_type> current_band(active_monster_band, band);
814     // (5) For each band monster, loop call to place_monster_aux().
815     for (int i = 1; i < band_size; i++)
816     {
817         if (band_monsters[i] == MONS_NO_MONSTER)
818             break;
819 
820         band_template.cls = band_monsters[i];
821 
822         // We don't want to place a unique that has already been
823         // generated.
824         if (mons_is_unique(band_template.cls)
825             && you.unique_creatures[band_template.cls])
826         {
827             continue;
828         }
829 
830         if (monster *member = _place_monster_aux(band_template, mon, place))
831         {
832             member->flags |= MF_BAND_MEMBER;
833             member->props["band_leader"].get_int() = mon->mid;
834             member->set_originating_map(mon->originating_map());
835 
836             // Priestly band leaders should have an entourage of the
837             // same religion, unless members of that entourage already
838             // have a different one.
839             if (priest && member->god == GOD_NO_GOD)
840                 member->god = mon->god;
841 
842             if (mon->type == MONS_PIKEL)
843             {
844                 // Don't give XP for the slaves to discourage hunting. Pikel
845                 // has an artificially large XP modifier to compensate for
846                 // this.
847                 member->flags |= MF_NO_REWARD;
848                 member->props["pikel_band"] = true;
849             }
850             else if (mon->type == MONS_KIRKE)
851                 member->props["kirke_band"] = true;
852         }
853     }
854     dprf(DIAG_DNGN, "Placing %s at %d,%d", mon->name(DESC_PLAIN, true).c_str(),
855                 mon->pos().x, mon->pos().y);
856 
857     // Placement of first monster, at least, was a success.
858     return mon;
859 }
860 
get_free_monster()861 monster* get_free_monster()
862 {
863     for (auto &mons : menv_real)
864         if (mons.type == MONS_NO_MONSTER)
865         {
866             mons.reset();
867             return &mons;
868         }
869 
870     return nullptr;
871 }
872 
mons_add_blame(monster * mon,const string & blame_string)873 void mons_add_blame(monster* mon, const string &blame_string)
874 {
875     const bool exists = mon->props.exists("blame");
876     CrawlStoreValue& blame = mon->props["blame"];
877     if (!exists)
878         blame.new_vector(SV_STR, SFLAG_CONST_TYPE);
879     blame.get_vector().push_back(blame_string);
880 }
881 
_place_twister_clouds(monster * mon)882 static void _place_twister_clouds(monster *mon)
883 {
884     // Yay for the abj_degree having a huge granularity.
885     if (mon->has_ench(ENCH_ABJ))
886     {
887         mon_enchant abj = mon->get_ench(ENCH_ABJ);
888         mon->lose_ench_duration(abj, abj.duration / 2);
889     }
890 
891     polar_vortex_damage(mon, -10);
892 }
893 
_place_monster_aux(const mgen_data & mg,const monster * leader,level_id place,bool force_pos,bool dont_place)894 static monster* _place_monster_aux(const mgen_data &mg, const monster *leader,
895                                    level_id place,
896                                    bool force_pos, bool dont_place)
897 {
898     coord_def fpos;
899 
900     // Some sanity checks.
901     if (mons_is_unique(mg.cls) && you.unique_creatures[mg.cls]
902             && !crawl_state.game_is_arena()
903         || mons_class_flag(mg.cls, M_CANT_SPAWN))
904     {
905         die("invalid monster to place: %s (%d)", mons_class_name(mg.cls), mg.cls);
906     }
907 
908     const monsterentry *m_ent = get_monster_data(mg.cls);
909 
910     monster* mon = get_free_monster();
911     if (!mon)
912         return 0;
913 
914     const monster_type montype = fixup_zombie_type(mg.cls, mg.base_type);
915 
916     // Setup habitat and placement.
917     // If the space is occupied, try some neighbouring square instead.
918     if (dont_place)
919         fpos.reset();
920     else if (!leader
921         && in_bounds(mg.pos)
922         && (mg.behaviour == BEH_FRIENDLY ||
923             (!is_sanctuary(mg.pos) || mons_is_tentacle_segment(montype)))
924         && !monster_at(mg.pos)
925         && (you.pos() != mg.pos || fedhas_passthrough_class(mg.cls))
926         && (force_pos || monster_habitable_grid(montype, env.grid(mg.pos))))
927     {
928         fpos = mg.pos;
929     }
930     else
931     {
932         int i;
933         // We'll try 1000 times for a good spot.
934         for (i = 0; i < 1000; ++i)
935         {
936             fpos = mg.pos;
937             fpos.x += random_range(-3, 3);
938             fpos.y += random_range(-3, 3);
939 
940             // Place members within LOS_SOLID of their leader.
941             // TODO nfm - allow placing around corners but not across walls.
942             if ((leader == 0 || cell_see_cell(fpos, leader->pos(), LOS_SOLID))
943                 && _valid_monster_generation_location(mg, fpos))
944             {
945                 break;
946             }
947         }
948 
949         // Did we really try 1000 times?
950         if (i == 1000)
951             return 0;
952     }
953 
954     ASSERT(!monster_at(fpos));
955 
956     if (crawl_state.game_is_arena()
957         && arena_veto_place_monster(mg, leader == 0, fpos))
958     {
959         return 0;
960     }
961 
962     // Now, actually create the monster. (Wheeee!)
963     mon->set_new_monster_id();
964     mon->type         = mg.cls;
965     mon->base_monster = mg.base_type;
966     mon->xp_tracking  = mg.xp_tracking;
967 
968     // Set pos and link monster into monster grid.
969     if (!dont_place && !mon->move_to_pos(fpos))
970     {
971         env.mid_cache.erase(mon->mid);
972         mon->reset();
973         return 0;
974     }
975 
976     // Pick the correct Serpent of Hell.
977     if (mon->type == MONS_SERPENT_OF_HELL)
978     {
979         switch (place.branch)
980         {
981         case BRANCH_COCYTUS:
982             mon->type = MONS_SERPENT_OF_HELL_COCYTUS;
983             break;
984         case BRANCH_DIS:
985             mon->type = MONS_SERPENT_OF_HELL_DIS;
986             break;
987         case BRANCH_TARTARUS:
988             mon->type = MONS_SERPENT_OF_HELL_TARTARUS;
989             break;
990         default: ; // if it spawns out of Hell (sprint, wizmode), use Gehenna
991         }
992     }
993 
994     // Generate a brand shiny new monster, or zombie.
995     if (mons_class_is_zombified(mg.cls))
996     {
997         monster_type ztype = mg.base_type;
998 
999         if (ztype == MONS_NO_MONSTER || ztype == RANDOM_MONSTER)
1000             ztype = pick_local_zombifiable_monster(place, mg.cls, fpos);
1001 
1002         define_zombie(mon, ztype, mg.cls);
1003     }
1004     else
1005         define_monster(*mon);
1006 
1007     if (mons_genus(mg.cls) == MONS_HYDRA)
1008     {
1009         // We're about to check m_ent->attack[1], so we may as well add a
1010         // compile-time check to ensure that the array is at least 2 elements
1011         // large, else we risk undefined behaviour (The array's size is known at
1012         // compile time even though its value is not). This CHECK would only
1013         // ever fail if we made it impossible for monsters to have two melee
1014         // attacks, in which case the ASSERT becomes silly.
1015         COMPILE_CHECK(ARRAYSZ(m_ent->attack) > 1);
1016 
1017         // Usually hydrae have exactly one attack (which is implicitly repeated
1018         // for each head), but a "hydra" may have zero if it is actually a
1019         // hydra-shaped block of ice. We verify here that nothing "hydra-shaped"
1020         // has more than one attack, because any that do will need cleaning up
1021         // to fit into the attack-per-head policy.
1022 
1023         ASSERT(m_ent->attack[1].type == AT_NONE);
1024     }
1025 
1026     if (mon->type == MONS_MUTANT_BEAST)
1027     {
1028         vector<int> gen_facets;
1029         if (mg.props.exists(MUTANT_BEAST_FACETS))
1030             for (auto facet : mg.props[MUTANT_BEAST_FACETS].get_vector())
1031                 gen_facets.push_back(facet.get_int());
1032 
1033         init_mutant_beast(*mon, mg.hd, gen_facets);
1034     }
1035 
1036     // Is it a god gift?
1037     if (mg.god != GOD_NO_GOD)
1038         mons_make_god_gift(*mon, mg.god);
1039     // Not a god gift, give priestly monsters a god.
1040     else if (mon->is_priest())
1041     {
1042         // Berserkers belong to Trog.
1043         if (mg.cls == MONS_SPRIGGAN_BERSERKER)
1044             mon->god = GOD_TROG;
1045         // Death knights belong to Yredelemnul.
1046         else if (mg.cls == MONS_DEATH_KNIGHT)
1047             mon->god = GOD_YREDELEMNUL;
1048         // Asterion belongs to Mahkleb.
1049         else if (mg.cls == MONS_ASTERION)
1050             mon->god = GOD_MAKHLEB;
1051         // Seraphim follow the Shining One.
1052         else if (mg.cls == MONS_SERAPH)
1053             mon->god = GOD_SHINING_ONE;
1054         // Draconian stormcallers worship Qazlal.
1055         else if (mg.cls == MONS_DRACONIAN_STORMCALLER)
1056             mon->god = GOD_QAZLAL;
1057         // Classed demonspawn.
1058         else if (mg.cls == MONS_BLOOD_SAINT)
1059             mon->god = GOD_MAKHLEB;
1060         else if (mg.cls == MONS_BLACK_SUN)
1061             mon->god = GOD_KIKUBAAQUDGHA;
1062         else if (mg.cls == MONS_CORRUPTER)
1063             mon->god = GOD_LUGONU;
1064         else
1065         {
1066             switch (mons_genus(mg.cls))
1067             {
1068             case MONS_ORC:
1069                 mon->god = GOD_BEOGH;
1070                 break;
1071             case MONS_JELLY:
1072                 mon->god = GOD_JIYVA;
1073                 break;
1074             case MONS_MUMMY:
1075             case MONS_DRACONIAN:
1076             case MONS_ELF:
1077                 // [ds] Vault defs can request priest monsters of unusual types.
1078             default:
1079                 mon->god = GOD_NAMELESS;
1080                 break;
1081             }
1082         }
1083     }
1084     // The Royal Jelly belongs to Jiyva.
1085     else if (mg.cls == MONS_ROYAL_JELLY)
1086         mon->god = GOD_JIYVA;
1087     // Mennas belongs to Zin.
1088     else if (mg.cls == MONS_MENNAS)
1089         mon->god = GOD_ZIN;
1090     // Yiuf is a faithful Xommite.
1091     else if (mg.cls == MONS_CRAZY_YIUF)
1092         mon->god = GOD_XOM;
1093     // Grinder and Ignacio belong to Makhleb.
1094     else if (mg.cls == MONS_GRINDER
1095              || mg.cls == MONS_IGNACIO)
1096     {
1097         mon->god = GOD_MAKHLEB;
1098     }
1099     // 1 out of 7 non-priestly orcs are unbelievers.
1100     else if (mons_genus(mg.cls) == MONS_ORC)
1101     {
1102         if (!one_chance_in(7))
1103             mon->god = GOD_BEOGH;
1104     }
1105     else if (mg.cls == MONS_APIS)
1106         mon->god = GOD_ELYVILON;
1107     else if (mg.cls == MONS_PROFANE_SERVITOR)
1108         mon->god = GOD_YREDELEMNUL;
1109     // Angels (other than Mennas) and daevas belong to TSO, but 1 out of
1110     // 7 in the Abyss are adopted by Xom.
1111     else if (mons_class_holiness(mg.cls) == MH_HOLY)
1112     {
1113         if (mg.place != BRANCH_ABYSS || !one_chance_in(7))
1114             mon->god = GOD_SHINING_ONE;
1115         else
1116             mon->god = GOD_XOM;
1117     }
1118 
1119     // Holy monsters need their halo!
1120     if (mon->holiness() & MH_HOLY)
1121         invalidate_agrid(true);
1122     if (mg.cls == MONS_SILENT_SPECTRE || mg.cls == MONS_PROFANE_SERVITOR)
1123         invalidate_agrid(true);
1124 
1125     // If the caller requested a specific colour for this monster, apply
1126     // it now.
1127     if ((mg.colour == COLOUR_INHERIT
1128          && mons_class_colour(mon->type) != COLOUR_UNDEF)
1129         || mg.colour > COLOUR_UNDEF)
1130     {
1131         mon->colour = mg.colour;
1132     }
1133 
1134     if (!mg.mname.empty())
1135         mon->mname = mg.mname;
1136 
1137     if (mg.props.exists(MGEN_NUM_HEADS))
1138         mon->num_heads = mg.props[MGEN_NUM_HEADS];
1139     if (mg.props.exists(MGEN_BLOB_SIZE))
1140         mon->blob_size = mg.props[MGEN_BLOB_SIZE];
1141     if (mg.props.exists(MGEN_TENTACLE_CONNECT))
1142         mon->tentacle_connect = mg.props[MGEN_TENTACLE_CONNECT].get_int();
1143 
1144     if (mg.hd != 0)
1145     {
1146         int bonus_hp = 0;
1147         if (mons_is_demonspawn(mg.cls)
1148             && mg.cls != MONS_DEMONSPAWN
1149             && mons_species(mg.cls) == MONS_DEMONSPAWN)
1150         {
1151             // Nonbase demonspawn get bonuses from their base type.
1152             const monsterentry *mbase =
1153                 get_monster_data(draco_or_demonspawn_subspecies(*mon));
1154             bonus_hp = mbase->avg_hp_10x;
1155         }
1156         mon->set_hit_dice(mg.hd);
1157         mon->props[VAULT_HD_KEY] = mg.hd;
1158         // Re-roll HP.
1159         const int base_avg_hp = m_ent->avg_hp_10x + bonus_hp;
1160         const int new_avg_hp = div_rand_round(base_avg_hp * mg.hd, m_ent->HD);
1161         const int hp = hit_points(new_avg_hp);
1162         // But only for monsters with random HP. (XXX: should be everything?)
1163         if (hp > 0)
1164         {
1165             mon->max_hit_points = hp;
1166             mon->hit_points = hp;
1167         }
1168     }
1169 
1170     if (mg.hp != 0)
1171     {
1172         mon->max_hit_points = mg.hp;
1173         mon->hit_points = mg.hp;
1174         mon->props[KNOWN_MAX_HP_KEY] = mg.hp;
1175     }
1176 
1177     if (!crawl_state.game_is_arena())
1178     {
1179         mon->max_hit_points = min(mon->max_hit_points, MAX_MONSTER_HP);
1180         mon->hit_points = min(mon->hit_points, MAX_MONSTER_HP);
1181     }
1182 
1183     // Store the extra flags here.
1184     mon->flags       |= mg.extra_flags;
1185 
1186     // "Prince Ribbit returns to his original shape as he dies."
1187     if (mg.cls == MONS_PRINCE_RIBBIT)
1188         mon->props[ORIGINAL_TYPE_KEY].get_int() = MONS_PRINCE_RIBBIT;
1189 
1190     // The return of Boris is now handled in monster_die(). Not setting
1191     // this for Boris here allows for multiple Borises in the dungeon at
1192     // the same time. - bwr
1193     if (mons_is_unique(mg.cls))
1194         you.unique_creatures.set(mg.cls);
1195 
1196     if (mons_class_flag(mg.cls, M_INVIS))
1197         mon->add_ench(ENCH_INVIS);
1198 
1199     if (mons_class_flag(mg.cls, M_CONFUSED))
1200         mon->add_ench(ENCH_CONFUSION);
1201 
1202     if (mg.cls == MONS_SHAPESHIFTER)
1203         mon->add_ench(ENCH_SHAPESHIFTER);
1204 
1205     if (mg.cls == MONS_GLOWING_SHAPESHIFTER)
1206         mon->add_ench(ENCH_GLOWING_SHAPESHIFTER);
1207 
1208     if ((mg.cls == MONS_TOADSTOOL
1209          || mg.cls == MONS_PILLAR_OF_SALT
1210          || mg.cls == MONS_BLOCK_OF_ICE)
1211         && !mg.props.exists(MGEN_NO_AUTO_CRUMBLE))
1212     {
1213         // This enchantment is a timer that counts down until death.
1214         // It should last longer than the lifespan of a corpse, to avoid
1215         // spawning mushrooms in the same place over and over. Aside
1216         // from that, the value is slightly randomised to avoid
1217         // simultaneous die-offs of mushroom rings.
1218         mon->add_ench(ENCH_SLOWLY_DYING);
1219     }
1220     else if (mons_is_demonspawn(mon->type)
1221              && draco_or_demonspawn_subspecies(*mon) == MONS_GELID_DEMONSPAWN)
1222     {
1223         mon->add_ench(ENCH_ICEMAIL);
1224     }
1225 
1226     if (mg.cls == MONS_TWISTER || mg.cls == MONS_DIAMOND_OBELISK)
1227     {
1228         mon->props["polar_vortex_since"].get_int() = you.elapsed_time;
1229         mon->add_ench(mon_enchant(ENCH_POLAR_VORTEX, 0, 0, INFINITE_DURATION));
1230     }
1231 
1232     // this MUST follow hd initialization!
1233     if (mons_is_hepliaklqana_ancestor(mon->type))
1234     {
1235         set_ancestor_spells(*mon);
1236         if (mg.props.exists(MON_GENDER_KEY)) // move this out?
1237             mon->props[MON_GENDER_KEY] = mg.props[MON_GENDER_KEY].get_int();
1238         mon->props["dbname"] = mons_class_name(mon->type);
1239     }
1240 
1241     if (mon->type == MONS_HELLBINDER || mon->type == MONS_CLOUD_MAGE)
1242     {
1243         mon->props[MON_GENDER_KEY] = random_choose(GENDER_FEMALE, GENDER_MALE,
1244                                                    GENDER_NEUTRAL);
1245     }
1246 
1247     if (mon->has_spell(SPELL_REPEL_MISSILES))
1248         mon->add_ench(ENCH_REPEL_MISSILES);
1249 
1250     if (mons_class_flag(mon->type, M_FIRE_RING))
1251         mon->add_ench(ENCH_RING_OF_FLAMES);
1252 
1253     if (mons_class_flag(mon->type, M_THUNDER_RING))
1254         mon->add_ench(ENCH_RING_OF_THUNDER);
1255 
1256     mon->flags |= MF_JUST_SUMMONED;
1257 
1258     // Don't leave shifters in their starting shape.
1259     if (mg.cls == MONS_SHAPESHIFTER || mg.cls == MONS_GLOWING_SHAPESHIFTER)
1260     {
1261         msg::suppress nm;
1262         monster_polymorph(mon, RANDOM_MONSTER);
1263 
1264         // It's not actually a known shapeshifter if it happened to be
1265         // placed in LOS of the player.
1266         mon->flags &= ~MF_KNOWN_SHIFTER;
1267     }
1268 
1269     // dur should always be 1-6 for monsters that can be abjured.
1270     const bool summoned = mg.abjuration_duration >= 1
1271                        && mg.abjuration_duration <= 6;
1272 
1273     if (mons_class_is_animated_weapon(mg.cls))
1274     {
1275         if (mg.props.exists(TUKIMA_WEAPON))
1276             give_specific_item(mon, mg.props[TUKIMA_WEAPON].get_item());
1277         else
1278             give_item(mon, place.absdepth(), summoned);
1279 
1280 
1281         // Dancing weapons *always* have a weapon. Fail to create them
1282         // otherwise.
1283         item_def* wpn = mon->mslot_item(MSLOT_WEAPON);
1284         if (!wpn)
1285         {
1286             // If they got created with an alt weapon, swap it in.
1287             item_def* alt_wpn = mon->mslot_item(MSLOT_ALT_WEAPON);
1288             if (alt_wpn != nullptr)
1289             {
1290                 swap(mon->inv[MSLOT_WEAPON], mon->inv[MSLOT_ALT_WEAPON]);
1291                 wpn = alt_wpn;
1292             } else {
1293                 mon->destroy_inventory();
1294                 env.mid_cache.erase(mon->mid);
1295                 mon->reset();
1296                 env.mgrid(fpos) = NON_MONSTER;
1297                 return 0;
1298             }
1299         }
1300 
1301         mon->colour = wpn->get_colour();
1302     }
1303     else if (mons_class_itemuse(mg.cls) >= MONUSE_STARTING_EQUIPMENT)
1304     {
1305         give_item(mon, place.absdepth(), summoned);
1306         // Give these monsters a second weapon. - bwr
1307         if (mons_class_wields_two_weapons(mg.cls))
1308             give_weapon(mon, place.absdepth());
1309 
1310         unwind_var<int> save_speedinc(mon->speed_increment);
1311         mon->wield_melee_weapon(MB_FALSE);
1312     }
1313 
1314     if (mon->type == MONS_SLIME_CREATURE && mon->blob_size > 1)
1315     {
1316         // Boost HP to what it would have been if it had grown this
1317         // big by merging.
1318         mon->hit_points     *= mon->blob_size;
1319         mon->max_hit_points *= mon->blob_size;
1320     }
1321 
1322     if (monster_can_submerge(mon, env.grid(fpos)) && !summoned)
1323         mon->add_ench(ENCH_SUBMERGED);
1324 
1325     // Set attitude, behaviour and target.
1326     mon->attitude  = ATT_HOSTILE;
1327     mon->behaviour = mg.behaviour;
1328 
1329     // Statues cannot sleep (nor wander but it means they are a bit
1330     // more aware of the player than they'd be otherwise).
1331     if (mons_is_statue(mg.cls))
1332         mon->behaviour = BEH_WANDER;
1333 
1334     mon->foe_memory = 0;
1335 
1336     // Setting attitude will always make the monster wander...
1337     // If you want sleeping hostiles, use BEH_SLEEP since the default
1338     // attitude is hostile.
1339     if (mg.behaviour > NUM_BEHAVIOURS)
1340     {
1341         if (mg.behaviour == BEH_FRIENDLY)
1342             mon->attitude = ATT_FRIENDLY;
1343 
1344         if (mg.behaviour == BEH_GOOD_NEUTRAL)
1345             mon->attitude = ATT_GOOD_NEUTRAL;
1346 
1347         if (mg.behaviour == BEH_NEUTRAL)
1348             mon->attitude = ATT_NEUTRAL;
1349 
1350         if (mg.behaviour == BEH_STRICT_NEUTRAL)
1351             mon->attitude = ATT_STRICT_NEUTRAL;
1352 
1353         mon->behaviour = BEH_WANDER;
1354     }
1355 
1356     if (summoned)
1357     {
1358         // Instead of looking for dancing weapons, look for Tukima's dance.
1359         // Dancing weapons can be created with shadow creatures. {due}
1360         mon->mark_summoned(mg.abjuration_duration,
1361                            mg.summon_type != SPELL_TUKIMAS_DANCE,
1362                            mg.summon_type);
1363 
1364         if (mg.summon_type > 0 && mg.summoner && !(mg.flags & MG_DONT_CAP))
1365         {
1366             // If this is a band member created by shadow creatures, link its
1367             // ID and don't count it against the summon cap
1368             if (mg.summon_type == SPELL_SHADOW_CREATURES && leader)
1369                 mon->props["summon_id"].get_int() = leader->mid;
1370             else
1371             {
1372                 summoned_monster(mon, mg.summoner,
1373                                 static_cast<spell_type>(mg.summon_type));
1374             }
1375         }
1376     }
1377 
1378     // Perm summons shouldn't leave gear either.
1379     if (mg.extra_flags & MF_HARD_RESET && mg.extra_flags & MF_NO_REWARD)
1380         mon->mark_summoned(0, true, 0, false);
1381 
1382     ASSERT(!invalid_monster_index(mg.foe)
1383            || mg.foe == MHITYOU || mg.foe == MHITNOT);
1384     mon->foe = mg.foe;
1385 
1386     string blame_prefix;
1387 
1388     if (mg.flags & MG_BAND_MINION)
1389         blame_prefix = "led by ";
1390     else if (mg.abjuration_duration > 0)
1391     {
1392         blame_prefix = "summoned by ";
1393 
1394         if (mg.summoner != nullptr && mg.summoner->alive()
1395             && mg.summoner->type == MONS_MARA)
1396         {
1397             blame_prefix = "woven by ";
1398         }
1399 
1400         if (mg.cls == MONS_DANCING_WEAPON)
1401             blame_prefix = "animated by ";
1402 
1403         if (mg.summon_type == SPELL_SPECTRAL_CLOUD)
1404             blame_prefix = "called from beyond by ";
1405     }
1406     else if (mons_class_is_zombified(mg.cls))
1407         blame_prefix = "animated by ";
1408     else if (mg.cls == MONS_ELDRITCH_TENTACLE
1409              || mg.cls == MONS_ELDRITCH_TENTACLE_SEGMENT)
1410     {
1411         blame_prefix = "called by ";
1412     }
1413     else if (mons_is_child_tentacle(mg.cls))
1414         blame_prefix = "attached to ";
1415     else
1416         blame_prefix = "created by ";
1417 
1418     if (!mg.non_actor_summoner.empty())
1419         mons_add_blame(mon, blame_prefix + mg.non_actor_summoner);
1420     // NOTE: The summoner might be dead if the summoned is placed by a
1421     // beam which killed the summoner first (like fire vortexes placed
1422     // by the Fire Storm spell); a deceased summoner's mindex might also
1423     // be reused to create its summon, so make sure the summon doesn't
1424     // think it has summoned itself.
1425     else if (mg.summoner != nullptr && mg.summoner->alive()
1426              && mg.summoner != mon)
1427     {
1428         ASSERT(mg.summoner->alive());
1429         mon->summoner = mg.summoner->mid;
1430         if (mg.summoner->is_player())
1431             mons_add_blame(mon, blame_prefix + "the player character");
1432         else
1433         {
1434             const monster* sum = mg.summoner->as_monster();
1435             mons_add_blame(mon, (blame_prefix
1436                                  + sum->full_name(DESC_A)));
1437             if (sum->props.exists("blame"))
1438             {
1439                 const CrawlVector& oldblame = sum->props["blame"].get_vector();
1440                 for (const auto &bl : oldblame)
1441                     mons_add_blame(mon, bl.get_string());
1442             }
1443         }
1444     }
1445 
1446     // Initialise (very) ugly things and pandemonium demons.
1447     if (mon->type == MONS_UGLY_THING
1448         || mon->type == MONS_VERY_UGLY_THING)
1449     {
1450         ghost_demon ghost;
1451         colour_t force_colour;
1452         if (mg.colour < COLOUR_UNDEF)
1453             force_colour = COLOUR_UNDEF;
1454         else
1455             force_colour = mg.colour;
1456         ghost.init_ugly_thing(mon->type == MONS_VERY_UGLY_THING, false,
1457                               force_colour);
1458         mon->set_ghost(ghost);
1459         mon->uglything_init();
1460     }
1461     else if (mons_class_is_animated_weapon(mon->type))
1462     {
1463         ghost_demon ghost;
1464         // We can't use monster::weapon here because it wants to look
1465         // at attack types, which are in the ghost structure we're
1466         // building.
1467         ASSERT(mon->mslot_item(MSLOT_WEAPON));
1468         if (mon->type == MONS_DANCING_WEAPON)
1469         {
1470             // Dancing weapons are placed at pretty high power. Remember, the
1471             // player is fighting them one-on-one, while he will often summon
1472             // several.
1473             ghost.init_dancing_weapon(*(mon->mslot_item(MSLOT_WEAPON)),
1474                                       mg.props.exists(TUKIMA_POWER) ?
1475                                           mg.props[TUKIMA_POWER].get_int() : 100);
1476         }
1477         else
1478             ghost.init_spectral_weapon(*(mon->mslot_item(MSLOT_WEAPON)));
1479         mon->set_ghost(ghost);
1480         mon->ghost_demon_init();
1481     }
1482 
1483     tile_init_props(mon);
1484 
1485     init_poly_set(mon);
1486 
1487 #ifndef DEBUG_DIAGNOSTICS
1488     // A rare case of a debug message NOT showing in the debug mode.
1489     if (mons_class_flag(mon->type, M_UNFINISHED))
1490     {
1491         mprf(MSGCH_WARN, "Warning: monster '%s' is not yet fully coded.",
1492              mon->name(DESC_PLAIN, true).c_str());
1493     }
1494 #endif
1495 
1496     if (crawl_state.game_is_arena())
1497         arena_placed_monster(mon);
1498     else if (!crawl_state.generating_level && !dont_place && you.can_see(*mon))
1499     {
1500         if (mg.flags & MG_DONT_COME)
1501             mons_set_just_seen(mon);
1502     }
1503 
1504     // Area effects can produce additional messages, and thus need to be
1505     // done after come in view ones.
1506     if (mon->type == MONS_TWISTER && !dont_place)
1507         _place_twister_clouds(mon);
1508 
1509     if (!(mg.flags & MG_FORCE_BEH)
1510         && !crawl_state.game_is_arena()
1511         && !crawl_state.generating_level)
1512     {
1513         gozag_set_bribe(mon);
1514     }
1515 
1516     return mon;
1517 }
1518 
_place_pghost_aux(const mgen_data & mg,const monster * leader,level_id place,bool force_pos,bool dont_place)1519 static monster* _place_pghost_aux(const mgen_data &mg, const monster *leader,
1520                                    level_id place,
1521                                    bool force_pos, bool dont_place)
1522 {
1523     // we need to isolate the generation of a pghost from the caller's RNG,
1524     // since depending on the ghost, the aux call can trigger variation in
1525     // things like whether an enchantment (with a random duration) is
1526     // triggered.
1527     rng::generator rng(rng::SYSTEM_SPECIFIC);
1528     return _place_monster_aux(mg, leader, place, force_pos, dont_place);
1529 }
1530 
1531 // Check base monster class against zombie type and position if set.
_good_zombie(monster_type base,monster_type cs,const coord_def & pos)1532 static bool _good_zombie(monster_type base, monster_type cs,
1533                          const coord_def& pos)
1534 {
1535     base = fixup_zombie_type(cs, base);
1536 
1537     // Actually pick a monster that is happy where we want to put it.
1538     // Fish zombies on land are helpless and uncool.
1539     if (in_bounds(pos) && !monster_habitable_grid(base, env.grid(pos)))
1540         return false;
1541 
1542     if (cs == MONS_NO_MONSTER)
1543         return true;
1544 
1545     // If skeleton, monster must have a skeleton.
1546     if (cs == MONS_SKELETON && !mons_skeleton(base))
1547         return false;
1548 
1549     // If zombie, monster must have a corpse.
1550     if (cs == MONS_ZOMBIE && !mons_zombifiable(base))
1551         return false;
1552 
1553     return true;
1554 }
1555 
1556 // Veto for the zombie picker class
veto(monster_type mt)1557 bool zombie_picker::veto(monster_type mt)
1558 {
1559     monster_type corpse_type = mons_species(mt);
1560 
1561     // XXX: nonbase draconian leave base draconian corpses.
1562     if (mt != MONS_DRACONIAN && corpse_type == MONS_DRACONIAN)
1563         corpse_type = random_draconian_monster_species();
1564 
1565     // Zombifiability in general.
1566     if (!mons_class_can_leave_corpse(corpse_type))
1567         return true;
1568     // Monsters that don't really exist
1569     if (mons_class_flag(mt, M_UNFINISHED))
1570         return true;
1571     // Monsters that can have derived undead, but never randomly generated.
1572     if (mons_class_flag(mt, M_NO_GEN_DERIVED))
1573         return true;
1574     if (!mons_zombie_size(corpse_type) || mons_is_unique(mt))
1575         return true;
1576     if (!(mons_class_holiness(corpse_type) & MH_NATURAL))
1577         return true;
1578     if (!_good_zombie(corpse_type, zombie_kind, pos))
1579         return true;
1580     return positioned_monster_picker::veto(mt);
1581 }
1582 
_mc_too_slow_for_zombies(monster_type mon)1583 static bool _mc_too_slow_for_zombies(monster_type mon)
1584 {
1585     // zombies slower than the player are boring!
1586     return mons_class_zombie_base_speed(mons_species(mon)) < BASELINE_DELAY;
1587 }
1588 
1589 /**
1590  * Pick a local monster type that's suitable for turning into a corpse.
1591  *
1592  * @param place     The branch/level that the monster type should come from,
1593  *                  if possible. (Not guaranteed for e.g. branches with no
1594  *                  corpses.)
1595  * @return          A monster type that can be used to fill out a corpse.
1596  */
pick_local_corpsey_monster(level_id place)1597 monster_type pick_local_corpsey_monster(level_id place)
1598 {
1599     return pick_local_zombifiable_monster(place, MONS_NO_MONSTER, coord_def(),
1600                                           true);
1601 }
1602 
pick_local_zombifiable_monster(level_id place,monster_type cs,const coord_def & pos,bool for_corpse)1603 monster_type pick_local_zombifiable_monster(level_id place,
1604                                             monster_type cs,
1605                                             const coord_def& pos,
1606                                             bool for_corpse)
1607 {
1608     const bool really_in_d = place.branch == BRANCH_DUNGEON;
1609 
1610     if (place.branch == BRANCH_ZIGGURAT)
1611     {
1612         // Get Zigs something reasonable to work with, if there's no place
1613         // explicitly defined.
1614         place = level_id(BRANCH_DEPTHS, 14 - (27 - place.depth) / 3);
1615     }
1616     else
1617     {
1618         // Zombies tend to be weaker than their normal counterparts;
1619         // thus, make them OOD proportional to the current dungeon depth.
1620         place.depth += 1 + div_rand_round(place.absdepth(), 5);
1621     }
1622 
1623     zombie_picker picker = zombie_picker(pos, cs);
1624 
1625     place.depth = max(1, min(place.depth, branch_ood_cap(place.branch)));
1626 
1627     const bool need_veto = really_in_d && !for_corpse;
1628     mon_pick_vetoer veto = need_veto ? _mc_too_slow_for_zombies : nullptr;
1629 
1630     // try to grab a proper zombifiable monster
1631     monster_type mt = picker.pick_with_veto(zombie_population(place.branch),
1632                                             place.depth, MONS_0, veto);
1633     // there might not be one in this branch - if we can't find one, try
1634     // elsewhere
1635     if (!mt)
1636         mt = pick_monster_all_branches(place.absdepth(), picker);
1637 
1638     ASSERT(mons_class_can_be_zombified(mons_species(mt)));
1639     return mt;
1640 }
1641 
roll_zombie_hp(monster * mon)1642 void roll_zombie_hp(monster* mon)
1643 {
1644     ASSERT(mon); // TODO: change to monster &mon
1645     ASSERT(mons_class_is_zombified(mon->type));
1646 
1647     const int avg_hp_10x = derived_undead_avg_hp(mon->type,
1648                                                  mon->get_hit_dice());
1649     const int hp = hit_points(avg_hp_10x);
1650     mon->max_hit_points = max(hp, 1);
1651     mon->hit_points     = mon->max_hit_points;
1652 }
1653 
define_zombie(monster * mon,monster_type ztype,monster_type cs)1654 void define_zombie(monster* mon, monster_type ztype, monster_type cs)
1655 {
1656 #if TAG_MAJOR_VERSION == 34
1657     // Upgrading monster enums is a losing battle, they sneak through too many
1658     // channels, like env props, etc. So convert them on placement, too.
1659     if (cs == MONS_ZOMBIE_SMALL || cs == MONS_ZOMBIE_LARGE)
1660         cs = MONS_ZOMBIE;
1661     if (cs == MONS_SKELETON_SMALL || cs == MONS_SKELETON_LARGE)
1662         cs = MONS_SKELETON;
1663     if (cs == MONS_SIMULACRUM_SMALL || cs == MONS_SIMULACRUM_LARGE)
1664         cs = MONS_SIMULACRUM;
1665 #endif
1666 
1667     ASSERT(ztype != MONS_NO_MONSTER);
1668     ASSERT(!invalid_monster_type(ztype));
1669     ASSERT(mons_class_is_zombified(cs));
1670 
1671     // Set type to the original type to calculate appropriate stats.
1672     mon->type         = ztype;
1673     mon->base_monster = MONS_PROGRAM_BUG;
1674     define_monster(*mon);
1675 
1676     // Zombies and such can't cast spells, except they should still be
1677     // able to make tentacles!
1678     monster_spells oldspells = mon->spells;
1679     mon->spells.clear();
1680     for (const mon_spell_slot &slot : oldspells)
1681         if (slot.spell == SPELL_CREATE_TENTACLES)
1682             mon->spells.push_back(slot);
1683 
1684     // handle zombies with jobs & ghostdemon zombies; they otherwise
1685     // wouldn't store enough information for us to recreate them right.
1686     if (mons_is_job(ztype) || mons_is_ghost_demon(ztype))
1687     {
1688         mon->props[ZOMBIE_BASE_AC_KEY] = mon->base_armour_class();
1689         mon->props[ZOMBIE_BASE_EV_KEY] = mon->base_evasion();
1690     }
1691 
1692     mon->type         = cs;
1693     mon->base_monster = ztype;
1694 
1695     mon->colour       = COLOUR_INHERIT;
1696     mon->speed        = (cs == MONS_SPECTRAL_THING
1697                             ? mons_class_base_speed(mon->base_monster)
1698                             : mons_class_zombie_base_speed(mon->base_monster));
1699 
1700     // Turn off all melee ability flags except dual-wielding.
1701     mon->flags       &= (~MF_MELEE_MASK | MF_TWO_WEAPONS);
1702 
1703     // Turn off regeneration if the base monster cannot regenerate.
1704     // This is needed for e.g. spectral things of non-regenerating
1705     // monsters.
1706     if (!mons_class_can_regenerate(mon->base_monster))
1707         mon->flags   |= MF_NO_REGEN;
1708 
1709     roll_zombie_hp(mon);
1710 }
1711 
downgrade_zombie_to_skeleton(monster * mon)1712 bool downgrade_zombie_to_skeleton(monster* mon)
1713 {
1714     if (mon->type != MONS_ZOMBIE || !mons_skeleton(mon->base_monster))
1715         return false;
1716 
1717     const int old_hp    = mon->hit_points;
1718     const int old_maxhp = mon->max_hit_points;
1719 
1720     mon->type           = MONS_SKELETON;
1721     mon->speed          = mons_class_zombie_base_speed(mon->base_monster);
1722     roll_zombie_hp(mon);
1723 
1724     // Scale the skeleton HP to the zombie HP.
1725     mon->hit_points     = old_hp * mon->max_hit_points / old_maxhp;
1726     mon->hit_points     = max(mon->hit_points, 1);
1727 
1728     return true;
1729 }
1730 
1731 /// Under what conditions should a band spawn with a monster?
1732 struct band_conditions
1733 {
1734     int chance_denom; ///< A 1/x chance for the band to appear.
1735     int min_depth; ///< The minimum absdepth for the band.
1736     function<bool()> custom_condition; ///< Additional conditions.
1737 
1738     /// Are the conditions met?
metband_conditions1739     bool met() const
1740     {
1741         return (!chance_denom || one_chance_in(chance_denom))
1742                && (!min_depth || env.absdepth0 >= min_depth)
1743                && (!custom_condition || custom_condition());
1744     }
1745 };
1746 
1747 /// Information about a band of followers that may spawn with some monster.
1748 struct band_info
1749 {
1750     /// The type of the band; used to determine the type of followers.
1751     band_type type;
1752     /// The min & max # of followers; doesn't count the leader.
1753     random_var range;
1754     /// Should the band followers try very hard to stick to the leader?
1755     bool natural_leader;
1756 };
1757 
1758 /// One or more band_infos, with conditions.
1759 struct band_set
1760 {
1761     /// When should the band actually be generated?
1762     band_conditions conditions;
1763     /// The bands to be selected between, with equal weight.
1764     vector<band_info> bands;
1765 };
1766 
1767 // We handle Vaults centaur warriors specially.
1768 static const band_conditions centaur_band_condition
__anon536559e20202() 1769     = { 3, 10, []() { return !player_in_branch(BRANCH_SHOALS)
1770                           && !player_in_branch(BRANCH_VAULTS); }};
1771 
1772 // warrior & mage spawn alone more frequently at shallow depths of Snake
1773 static const band_conditions naga_band_condition
__anon536559e20302() 1774     = { 0, 0, []() { return !player_in_branch(BRANCH_SNAKE)
1775                             || x_chance_in_y(you.depth, 5); }};
1776 
1777 /// can we spawn dracs in the current branch?
1778 static const function<bool()> drac_branch
__anon536559e20402() 1779     = []() { return player_in_connected_branch(); };
1780 
1781 /// non-classed draconian band description
1782 static const band_set basic_drac_set = { {3, 19, drac_branch},
1783                                          {{BAND_DRACONIAN, {2, 5} }}};
1784 
1785 /// classed draconian band description
1786 static const band_set classy_drac_set = { {0, 21, drac_branch},
1787                                           {{BAND_DRACONIAN, {3, 7} }}};
1788 
1789 // javelineer & impaler
__anon536559e20502() 1790 static const band_conditions mf_band_condition = { 0, 0, []() {
1791     return !player_in_branch(BRANCH_DEPTHS) &&
1792           (!player_in_branch(BRANCH_SHOALS) || x_chance_in_y(you.depth, 5));
1793 }};
1794 
1795 /// For each monster, what band or bands may follow them?
1796 static const map<monster_type, band_set> bands_by_leader = {
1797     { MONS_ORC,             { {2}, {{ BAND_ORCS, {2, 5} }}}},
1798     { MONS_ORC_WIZARD,      { {}, {{ BAND_ORCS, {2, 5} }}}},
1799     { MONS_ORC_PRIEST,      { {}, {{ BAND_ORC_WARRIOR, {2, 5} }}}},
1800     { MONS_ORC_WARRIOR,     { {}, {{ BAND_ORC_WARRIOR, {2, 5} }}}},
__anon536559e20602()1801     { MONS_ORC_WARLORD,     { {0, 0, [](){ return !player_in_branch(BRANCH_VAULTS); }},
1802                                          {{ BAND_ORC_KNIGHT, {8, 16}, true }}}},
1803     { MONS_SAINT_ROKA,      { {}, {{ BAND_ORC_KNIGHT, {8, 16}, true }}}},
1804     { MONS_ORC_KNIGHT,      { {}, {{ BAND_ORC_KNIGHT, {3, 7}, true }}}},
1805     { MONS_ORC_HIGH_PRIEST, { {}, {{ BAND_ORC_KNIGHT, {4, 8}, true }}}},
1806     { MONS_KOBOLD_BRIGAND,      { {0, 4}, {{ BAND_KOBOLDS, {2, 8} }}}},
1807     { MONS_KILLER_BEE,      { {}, {{ BAND_KILLER_BEES, {2, 6} }}}},
1808     { MONS_CAUSTIC_SHRIKE,  { {}, {{ BAND_CAUSTIC_SHRIKE, {2, 5} }}}},
1809     { MONS_SHARD_SHRIKE,    { {}, {{ BAND_SHARD_SHRIKE, {1, 4} }}}},
1810     { MONS_FLYING_SKULL,    { {}, {{ BAND_FLYING_SKULLS, {2, 6} }}}},
1811     { MONS_SLIME_CREATURE,  { {}, {{ BAND_SLIME_CREATURES, {2, 6} }}}},
1812     { MONS_YAK,             { {}, {{ BAND_YAKS, {2, 6} }}}},
1813     { MONS_VERY_UGLY_THING, { {0, 19}, {{ BAND_VERY_UGLY_THINGS, {2, 6} }}}},
1814     { MONS_UGLY_THING,      { {0, 13}, {{ BAND_UGLY_THINGS, {2, 6} }}}},
1815     { MONS_HELL_HOUND,      { {}, {{ BAND_HELL_HOUNDS, {2, 5} }}}},
1816     { MONS_JACKAL,          { {}, {{ BAND_JACKALS, {1, 4} }}}},
1817     { MONS_MARGERY,         { {}, {{ BAND_HELL_KNIGHTS, {4, 8}, true }}}},
1818     { MONS_HELL_KNIGHT,     { {}, {{ BAND_HELL_KNIGHTS, {4, 8} }}}},
1819     { MONS_JOSEPHINE,       { {}, {{ BAND_JOSEPHINE, {3, 6}, true }}}},
1820     { MONS_NECROMANCER,     { {}, {{ BAND_NECROMANCER, {3, 6}, true }}}},
1821     { MONS_VAMPIRE_MAGE,    { {3}, {{ BAND_JIANGSHI, {2, 4}, true }}}},
1822     { MONS_JIANGSHI,        { {}, {{ BAND_JIANGSHI, {0, 2} }}}},
1823     { MONS_GNOLL,           { {0, 1}, {{ BAND_GNOLLS, {2, 4} }}}},
1824     { MONS_GNOLL_SHAMAN,    { {}, {{ BAND_GNOLLS, {3, 6} }}}},
1825     { MONS_GNOLL_SERGEANT,  { {}, {{ BAND_GNOLLS, {3, 6} }}}},
__anon536559e20702() 1826     { MONS_DEATH_KNIGHT,    { {0, 0, []() { return x_chance_in_y(2, 3); }},
1827                                   {{ BAND_DEATH_KNIGHT, {3, 5}, true }}}},
1828     { MONS_GRUM,            { {}, {{ BAND_WOLVES, {2, 5}, true }}}},
1829     { MONS_WOLF,            { {}, {{ BAND_WOLVES, {2, 6} }}}},
1830     { MONS_CENTAUR_WARRIOR, { centaur_band_condition,
1831                                   {{ BAND_CENTAURS, {2, 6}, true }}}},
1832     { MONS_CENTAUR, { centaur_band_condition, {{ BAND_CENTAURS, {2, 6} }}}},
1833     { MONS_YAKTAUR_CAPTAIN, { {2}, {{ BAND_YAKTAURS, {2, 5}, true }}}},
1834     { MONS_YAKTAUR,         { {2}, {{ BAND_YAKTAURS, {2, 5} }}}},
1835     { MONS_DEATH_YAK,       { {}, {{ BAND_DEATH_YAKS, {2, 6} }}}},
1836     { MONS_OGRE_MAGE,       { {}, {{ BAND_OGRE_MAGE, {4, 8} }}}},
1837     { MONS_BALRUG,          { {}, {{ BAND_BALRUG, {2, 5}, true }}}},
1838     { MONS_CACODEMON,       { {}, {{ BAND_CACODEMON, {1, 4}, true }}}},
1839     { MONS_EXECUTIONER,     { {2}, {{ BAND_EXECUTIONER, {1, 4}, true }}}},
1840     { MONS_PANDEMONIUM_LORD, { {}, {{ BAND_PANDEMONIUM_LORD, {1, 4}, true }}}},
1841     { MONS_HELLWING,        { {2}, {{ BAND_HELLWING, {1, 5} }}}},
1842     { MONS_DEEP_ELF_KNIGHT, { {2}, {{ BAND_DEEP_ELF_KNIGHT, {3, 5} }}}},
1843     { MONS_DEEP_ELF_ARCHER, { {2}, {{ BAND_DEEP_ELF_KNIGHT, {3, 5} }}}},
1844     { MONS_DEEP_ELF_HIGH_PRIEST, { {2}, {{ BAND_DEEP_ELF_HIGH_PRIEST, {3, 7},
1845                                            true }}}},
1846     { MONS_KOBOLD_DEMONOLOGIST, { {2}, {{ BAND_KOBOLD_DEMONOLOGIST, {3, 9} }}}},
1847     { MONS_GUARDIAN_SERPENT, { {}, {{ BAND_GUARDIAN_SERPENT, {2, 6} }}}},
1848     { MONS_NAGA_MAGE,       { naga_band_condition, {{ BAND_NAGAS, {2, 5} }}}},
1849     { MONS_NAGA_WARRIOR,    { naga_band_condition, {{ BAND_NAGAS, {2, 5} }}}},
1850     { MONS_NAGA_SHARPSHOOTER, { {2}, {{ BAND_NAGA_SHARPSHOOTER, {1, 4} }}}},
1851     { MONS_NAGA_RITUALIST,  { {}, {{ BAND_NAGA_RITUALIST, {3, 6} }}}},
1852     { MONS_RIVER_RAT,       { {}, {{ BAND_GREEN_RATS, {4, 10} }}}},
1853     { MONS_HELL_RAT,        { {}, {{ BAND_HELL_RATS, {3, 7} }}}},
1854     { MONS_DREAM_SHEEP,     { {}, {{ BAND_DREAM_SHEEP, {3, 7} }}}},
1855     { MONS_GHOUL,           { {}, {{ BAND_GHOULS, {2, 5} }}}},
1856     { MONS_KIRKE,           { {}, {{ BAND_HOGS, {3, 8}, true }}}},
1857     { MONS_HOG,             { {}, {{ BAND_HOGS, {1, 4} }}}},
1858     { MONS_VAMPIRE_MOSQUITO, { {}, {{ BAND_VAMPIRE_MOSQUITOES, {1, 4} }}}},
1859     { MONS_FIRE_BAT,        { {}, {{ BAND_FIRE_BATS, {1, 4} }}}},
1860     { MONS_DEEP_TROLL_EARTH_MAGE, { {}, {{ BAND_DEEP_TROLL_SHAMAN, {3, 6} }}}},
1861     { MONS_DEEP_TROLL_SHAMAN, { {}, {{ BAND_DEEP_TROLL_SHAMAN, {3, 6} }}}},
1862     { MONS_HELL_HOG,        { {}, {{ BAND_HELL_HOGS, {2, 4} }}}},
1863     { MONS_BOGGART,         { {}, {{ BAND_BOGGARTS, {2, 5} }}}},
1864     { MONS_PRINCE_RIBBIT,   { {}, {{ BAND_BLINK_FROGS, {2, 5}, true }}}},
1865     { MONS_BLINK_FROG,      { {}, {{ BAND_BLINK_FROGS, {2, 5} }}}},
1866     { MONS_WIGHT,           { {}, {{ BAND_WIGHTS, {2, 5} }}}},
1867     { MONS_ANCIENT_CHAMPION, { {2}, {{ BAND_SKELETAL_WARRIORS, {2, 5}, true}}}},
1868     { MONS_SKELETAL_WARRIOR, { {}, {{ BAND_SKELETAL_WARRIORS, {2, 5}, true }}}},
__anon536559e20802() 1869     { MONS_CYCLOPS,         { { 0, 0, []() {
1870         return player_in_branch(BRANCH_SHOALS); }},
1871                                   {{ BAND_DREAM_SHEEP, {2, 5}, true }}}},
__anon536559e20902() 1872     { MONS_ALLIGATOR,       { { 5, 0, []() {
1873         return !player_in_branch(BRANCH_LAIR); }},
1874                                   {{ BAND_ALLIGATOR, {1, 2}, true }}}},
1875     { MONS_POLYPHEMUS,      { {}, {{ BAND_POLYPHEMUS, {3, 6}, true }}}},
1876     { MONS_HARPY,           { {}, {{ BAND_HARPIES, {2, 5} }}}},
1877     { MONS_SALTLING,        { {}, {{ BAND_SALTLINGS, {2, 4} }}}},
__anon536559e20a02() 1878     { MONS_PEACEKEEPER,     { { 0, 0, []() {
1879         return player_in_branch(BRANCH_VAULTS); }},
1880                                   {{ BAND_GOLEMS, {1, 3}, true }}}},
1881     // Journey -- Added Draconian Packs
1882     { MONS_WHITE_DRACONIAN, basic_drac_set },
1883     { MONS_RED_DRACONIAN,   basic_drac_set },
1884     { MONS_PURPLE_DRACONIAN, basic_drac_set },
1885     { MONS_YELLOW_DRACONIAN, basic_drac_set },
1886     { MONS_BLACK_DRACONIAN, basic_drac_set },
1887     { MONS_GREEN_DRACONIAN, basic_drac_set },
1888     { MONS_GREY_DRACONIAN, basic_drac_set },
1889     { MONS_PALE_DRACONIAN, basic_drac_set },
1890     { MONS_DRACONIAN_STORMCALLER, classy_drac_set },
1891     { MONS_DRACONIAN_MONK, classy_drac_set },
1892     { MONS_DRACONIAN_SCORCHER, classy_drac_set },
1893     { MONS_DRACONIAN_KNIGHT, classy_drac_set },
1894     { MONS_DRACONIAN_ANNIHILATOR, classy_drac_set },
1895     { MONS_DRACONIAN_SHIFTER, classy_drac_set },
1896     // yup, scary
1897     { MONS_TIAMAT,          { {}, {{ BAND_DRACONIAN, {8, 15}, true }}}},
1898     { MONS_ILSUIW,          { {}, {{ BAND_ILSUIW, {3, 6} }}}},
1899     { MONS_AZRAEL,          { {}, {{ BAND_AZRAEL, {4, 9}, true }}}},
1900     { MONS_DUVESSA,         { {}, {{ BAND_DUVESSA, {1, 2} }}}},
1901     { MONS_KHUFU,           { {}, {{ BAND_KHUFU, {3, 4}, true }}}},
1902     { MONS_GOLDEN_EYE,      { {}, {{ BAND_GOLDEN_EYE, {1, 6} }}}},
1903     { MONS_PIKEL,           { {}, {{ BAND_PIKEL, {4, 5}, true }}}},
1904     { MONS_MERFOLK_AQUAMANCER, { {}, {{ BAND_MERFOLK_AQUAMANCER, {3, 5} }}}},
1905     { MONS_MERFOLK_JAVELINEER, { mf_band_condition,
1906                                   {{ BAND_MERFOLK_JAVELINEER, {2, 5} }}}},
1907     { MONS_MERFOLK_IMPALER, { mf_band_condition,
1908                                   {{ BAND_MERFOLK_IMPALER, {2, 5} }}}},
1909     { MONS_ELEPHANT,        { {}, {{ BAND_ELEPHANT, {2, 6} }}}},
1910     { MONS_REDBACK,         { {}, {{ BAND_REDBACK, {1, 6} }}}},
1911     { MONS_ENTROPY_WEAVER,  { {}, {{ BAND_REDBACK, {1, 5} }}}},
1912     { MONS_JUMPING_SPIDER,  { {2}, {{ BAND_JUMPING_SPIDER, {1, 6} }}}},
1913     { MONS_TARANTELLA,      { {2}, {{ BAND_TARANTELLA, {1, 5} }}}},
1914     { MONS_VAULT_WARDEN,    { {}, {{ BAND_YAKTAURS, {2, 6}, true },
1915                                    { BAND_VAULT_WARDEN, {2, 5}, true }}}},
1916     { MONS_IRONBOUND_PRESERVER, { {}, {{ BAND_DEEP_TROLLS, {3, 6}, true }}}},
1917     { MONS_TENGU_CONJURER,  { {2}, {{ BAND_TENGU, {1, 2}, true }}}},
1918     { MONS_TENGU_WARRIOR,   { {2}, {{ BAND_TENGU, {1, 2}, true }}}},
1919     { MONS_SOJOBO,          { {}, {{ BAND_SOJOBO, {2, 3}, true }}}},
1920     { MONS_SPRIGGAN_RIDER,  { {3}, {{ BAND_SPRIGGAN_RIDERS, {1, 3} }}}},
1921     { MONS_SPRIGGAN_BERSERKER, { {2}, {{ BAND_SPRIGGANS, {2, 4} }}}},
1922     { MONS_SPRIGGAN_DEFENDER, { {}, {{ BAND_SPRIGGAN_ELITES, {2, 5}, true }}}},
1923     { MONS_THE_ENCHANTRESS, { {}, {{ BAND_ENCHANTRESS, {6, 11}, true }}}},
1924     { MONS_SHAMBLING_MANGROVE, { {4}, {{ BAND_SPRIGGAN_RIDERS, {1, 2} }}}},
1925     { MONS_VAMPIRE_KNIGHT,  { {4}, {{ BAND_PHANTASMAL_WARRIORS, {2, 3} }}}},
1926     { MONS_RAIJU,           { {}, {{ BAND_RAIJU, {2, 4} }}}},
1927     { MONS_SALAMANDER_MYSTIC, { {}, {{ BAND_SALAMANDERS, {2, 4} }}}},
1928     { MONS_SALAMANDER_TYRANT, { {}, {{ BAND_SALAMANDER_ELITES, {2, 5} }}}},
__anon536559e20b02() 1929     { MONS_MONSTROUS_DEMONSPAWN, { {2, 0, []() {
1930         return !player_in_branch(BRANCH_WIZLAB); // hack for wizlab_wucad_mu
1931     }},                             {{ BAND_MONSTROUS_DEMONSPAWN, {1, 3}}}}},
1932     { MONS_GELID_DEMONSPAWN, { {2}, {{ BAND_GELID_DEMONSPAWN, {1, 3} }}}},
1933     { MONS_INFERNAL_DEMONSPAWN, { {2}, {{ BAND_INFERNAL_DEMONSPAWN, {1, 3} }}}},
1934     { MONS_TORTUROUS_DEMONSPAWN, {{2}, {{ BAND_TORTUROUS_DEMONSPAWN, {1, 3}}}}},
1935     { MONS_BLOOD_SAINT,     { {}, {{ BAND_BLOOD_SAINT, {1, 4} }}}},
1936     { MONS_WARMONGER,       { {}, {{ BAND_WARMONGER, {2, 4} }}}},
1937     { MONS_CORRUPTER,       { {}, {{ BAND_CORRUPTER, {1, 4} }}}},
1938     { MONS_BLACK_SUN,       { {}, {{ BAND_BLACK_SUN, {2, 4} }}}},
1939     { MONS_VASHNIA,         { {}, {{ BAND_VASHNIA, {3, 6}, true }}}},
1940     { MONS_ROBIN,           { {}, {{ BAND_ROBIN, {10, 13}, true }}}},
__anon536559e20c02() 1941     { MONS_RAKSHASA,        { {2, 0, []() {
1942         return branch_has_monsters(you.where_are_you)
1943             || !vault_mon_types.empty();
1944     }},                           {{ BAND_RANDOM_SINGLE, {1, 2} }}}},
1945     { MONS_CEREBOV,         { {}, {{ BAND_CEREBOV, {5, 8}, true }}}},
1946     { MONS_GLOORX_VLOQ,     { {}, {{ BAND_GLOORX_VLOQ, {5, 8}, true }}}},
1947     { MONS_MNOLEG,          { {}, {{ BAND_MNOLEG, {5, 8}, true }}}},
1948     { MONS_LOM_LOBON,       { {}, {{ BAND_LOM_LOBON, {5, 8}, true }}}},
1949     { MONS_DEATH_SCARAB,    { {}, {{ BAND_DEATH_SCARABS, {3, 6} }}}},
1950     { MONS_SERAPH,          { {}, {{ BAND_HOLIES, {1, 4}, true }}}},
1951     { MONS_IRON_GIANT,      { {}, {{ BAND_ANCIENT_CHAMPIONS, {2, 3}, true }}}},
__anon536559e20d02() 1952     { MONS_SPARK_WASP,      { {0, 0, []() {
1953         return you.where_are_you == BRANCH_DEPTHS;
1954     }},                           {{ BAND_SPARK_WASPS, {1, 4} }}}},
1955     { MONS_HOWLER_MONKEY,   { {2, 6}, {{ BAND_HOWLER_MONKEY, {1, 3} }}}},
__anon536559e20e02() 1956     { MONS_FLOATING_EYE,   { {0, 0, []() {
1957         return branch_has_monsters(you.where_are_you)
1958             || !vault_mon_types.empty();
1959     }},                           {{ BAND_RANDOM_SINGLE, {1, 2} }}}},
1960     { MONS_MELIAI,          { {}, {{ BAND_MELIAI, {2, 3} }}}},
__anon536559e20f02() 1961     { MONS_DANCING_WEAPON,  { {0, 0, []() {
1962         return you.where_are_you == BRANCH_DESOLATION;
1963     }},                            {{ BAND_DANCING_WEAPONS, {2, 3} }}}},
__anon536559e21002() 1964     { MONS_MOLTEN_GARGOYLE,  { {0, 0, []() {
1965         return you.where_are_you == BRANCH_DESOLATION;
1966     }},                            {{ BAND_MOLTEN_GARGOYLES, {2, 3} }}}},
1967     { MONS_IRONBOUND_BEASTMASTER, { {}, {{ BAND_DIRE_ELEPHANTS, {1, 3}, true },
1968                                         { BAND_LINDWURMS, {1, 4}, true}}}},
__anon536559e21102() 1969     { MONS_WIZARD,  { {0, 0, []() {
1970         return player_in_branch(BRANCH_VAULTS);
1971     }},                            {{ BAND_UGLY_THINGS, {2, 4}, true }}}},
1972 
1973 
1974     // special-cased band-sizes
1975     { MONS_SPRIGGAN_DRUID,  { {3}, {{ BAND_SPRIGGAN_DRUID, {0, 1} }}}},
1976     { MONS_THRASHING_HORROR, { {}, {{ BAND_THRASHING_HORRORS, {0, 1} }}}},
1977 };
1978 
_choose_band(monster_type mon_type,int * band_size_p,bool * natural_leader_p)1979 static band_type _choose_band(monster_type mon_type, int *band_size_p,
1980                               bool *natural_leader_p)
1981 {
1982 #ifdef DEBUG_MON_CREATION
1983     mprf(MSGCH_DIAGNOSTICS, "in _choose_band()");
1984 #endif
1985     // Access outparameters by reference, or local dummies if they were null.
1986     int bs, &band_size = band_size_p ? *band_size_p : bs;
1987     bool nl, &natural_leader = natural_leader_p ? *natural_leader_p : nl;
1988 
1989     // Band size describes the number of monsters in addition to
1990     // the band leader.
1991     band_size = 0; // Single monster, no band.
1992     natural_leader = false;
1993     band_type band = BAND_NO_BAND;
1994 
1995     const band_set* bands = map_find(bands_by_leader, mon_type);
1996     if (bands && bands->conditions.met())
1997     {
1998         ASSERT(bands->bands.size() > 0);
1999         const band_info& band_desc = *random_iterator(bands->bands);
2000         band = band_desc.type;
2001         band_size = band_desc.range.roll();
2002         natural_leader = band_desc.natural_leader;
2003     }
2004 
2005     // special cases...
2006     switch (mon_type)
2007     {
2008     case MONS_TORPOR_SNAIL:
2009     {
2010         natural_leader = true; // snails are natural-born leaders. fact.
2011 
2012         struct band_choice { band_type band; int min; int max; };
2013         typedef vector<pair<band_choice, int>> band_weights;
2014         const static map<branch_type, band_weights> band_pick =
2015         {
2016             // branch              band             #min #max weight
2017             { BRANCH_LAIR,   { { { BAND_YAKS,          2, 5 },  3 },
2018                                { { BAND_DEATH_YAKS,    1, 2 },  1 },
2019                                { { BAND_DREAM_SHEEP,   2, 4 },  1 },
2020                              } },
2021             { BRANCH_SPIDER, { { { BAND_REDBACK,       2, 4 },  1 },
2022                                { { BAND_RANDOM_SINGLE, 1, 1 },  1 },
2023                              } },
2024             { BRANCH_DEPTHS, { { { BAND_RANDOM_SINGLE, 1, 1 },  1 },
2025                              } },
2026         };
2027 
2028         if (const auto *weights = map_find(band_pick, you.where_are_you))
2029         {
2030             if (const auto *chosen = random_choose_weighted(*weights))
2031             {
2032                 band = chosen->band;
2033                 band_size = random_range(chosen->min, chosen->max);
2034             }
2035         }
2036         break;
2037     }
2038 
2039     // Per-branch hacks. TODO: move this into the main branch structure
2040     // (probably moving conditionals inside band_info?)
2041     case MONS_CENTAUR_WARRIOR:
2042         if (player_in_branch(BRANCH_VAULTS))
2043         {
2044             band = BAND_CENTAUR_WARRIORS;
2045             band_size = random_range(2, 4);
2046         }
2047         break;
2048 
2049     case MONS_ORC_WARLORD:
2050         if (player_in_branch(BRANCH_VAULTS))
2051         {
2052             band = BAND_ORC_WARLORD;
2053             band_size = random_range(2, 4);
2054         }
2055         break;
2056 
2057     case MONS_SATYR:
2058         if (!one_chance_in(3))
2059         {
2060             natural_leader = true;
2061             band = one_chance_in(5) ? BAND_FAUN_PARTY : BAND_FAUNS;
2062             band_size = 3 + random2(2);
2063         }
2064         break;
2065 
2066     case MONS_FAUN:
2067         if (!one_chance_in(3))
2068         {
2069             band = random_choose(BAND_FAUNS, BAND_FAUN_PARTY);
2070             band_size = 2 + random2(2);
2071         }
2072         break;
2073 
2074     case MONS_SPRIGGAN_DRUID:
2075         if (band != BAND_NO_BAND)
2076             band_size = (one_chance_in(4) ? 3 : 2);
2077         break;
2078 
2079     case MONS_THRASHING_HORROR:
2080         // XXX: rewrite this - wrong & bad if horrors aren't in abyss
2081         band_size = random2(min(brdepth[BRANCH_ABYSS], you.depth));
2082         break;
2083 
2084     default: ;
2085     }
2086 
2087     if (band != BAND_NO_BAND && band_size == 0)
2088         band = BAND_NO_BAND;
2089 
2090     if (band_size >= BIG_BAND)
2091         band_size = BIG_BAND - 1;
2092 
2093     return band;
2094 }
2095 
2096 /// a weighted list of possible monsters for a given band slot.
2097 typedef vector<pair<monster_type, int>> member_possibilites;
2098 
2099 /**
2100  * For each band type, a list of weighted lists of monsters that can appear
2101  * in that band.
2102  *
2103  * Each element in the list, other than the last, is a list of candidates for
2104  * that slot in the band. The final element lists candidates for all further
2105  * slots.
2106  *
2107  * An example: Let's say we have {BAND_FOO,
2108  *                                  {{{MONS_A, 1}},
2109  *                                   {{MONS_B, 1}},
2110  *                                   {{MONS_C, 1}, {MONS_D, 1}}}}.
2111  * This indicates that the first member of these bands (not the leader, but
2112  * their first follower) will be a MONS_A, the second will be a MONS_B, and
2113  * the third, fourth, etc monsters will either be MONS_C or MONS_D with equal
2114  * likelihood.
2115  */
2116 static const map<band_type, vector<member_possibilites>> band_membership = {
2117     { BAND_HOGS,                {{{MONS_HOG, 1}}}},
2118     { BAND_YAKS,                {{{MONS_YAK, 1}}}},
2119     { BAND_FAUNS,               {{{MONS_FAUN, 1}}}},
2120     { BAND_WOLVES,              {{{MONS_WOLF, 1}}}},
2121     { BAND_DUVESSA,             {{{MONS_DOWAN, 1}}}},
2122     { BAND_GNOLLS,              {{{MONS_GNOLL, 1}}}},
2123     { BAND_HARPIES,             {{{MONS_HARPY, 1}}}},
2124     { BAND_RAIJU,               {{{MONS_RAIJU, 1}}}},
2125     { BAND_WIGHTS,              {{{MONS_WIGHT, 1}}}},
2126     { BAND_JACKALS,             {{{MONS_JACKAL, 1}}}},
2127     { BAND_KOBOLDS,             {{{MONS_KOBOLD, 1}}}},
2128     { BAND_PIKEL,               {{{MONS_LEMURE, 1}}}},
2129     { BAND_JOSEPHINE,           {{{MONS_WRAITH, 1}}}},
2130     { BAND_MELIAI,              {{{MONS_MELIAI, 1}}}},
2131     { BAND_BOGGARTS,            {{{MONS_BOGGART, 1}}}},
2132     { BAND_CENTAURS,            {{{MONS_CENTAUR, 1}}}},
2133     { BAND_YAKTAURS,            {{{MONS_YAKTAUR, 1}}}},
2134     { BAND_MERFOLK_IMPALER,     {{{MONS_MERFOLK, 1}}}},
2135     { BAND_MERFOLK_JAVELINEER,  {{{MONS_MERFOLK, 1}}}},
2136     { BAND_ELEPHANT,            {{{MONS_ELEPHANT, 1}}}},
2137     { BAND_FIRE_BATS,           {{{MONS_FIRE_BAT, 1}}}},
2138     { BAND_HELL_HOGS,           {{{MONS_HELL_HOG, 1}}}},
2139     { BAND_HELL_RATS,           {{{MONS_HELL_RAT, 1}}}},
2140     { BAND_JIANGSHI,            {{{MONS_JIANGSHI, 1}}}},
2141     { BAND_LINDWURMS,           {{{MONS_LINDWURM, 1}}}},
2142     { BAND_ALLIGATOR,           {{{MONS_ALLIGATOR, 1}}}},
2143     { BAND_DEATH_YAKS,          {{{MONS_DEATH_YAK, 1}}}},
2144     { BAND_GREEN_RATS,          {{{MONS_RIVER_RAT, 1}}}},
2145     { BAND_BLINK_FROGS,         {{{MONS_BLINK_FROG, 1}}}},
2146     { BAND_GOLDEN_EYE,          {{{MONS_GOLDEN_EYE, 1}}}},
2147     { BAND_HELL_HOUNDS,         {{{MONS_HELL_HOUND, 1}}}},
2148     { BAND_KILLER_BEES,         {{{MONS_KILLER_BEE, 1}}}},
2149     { BAND_ORC_WARLORD,         {{{MONS_ORC_KNIGHT, 1}}}},
2150     { BAND_SALAMANDERS,         {{{MONS_SALAMANDER, 1}}}},
2151     { BAND_SPARK_WASPS,         {{{MONS_SPARK_WASP, 1}}}},
2152     { BAND_UGLY_THINGS,         {{{MONS_UGLY_THING, 1}}}},
2153     { BAND_DREAM_SHEEP,         {{{MONS_DREAM_SHEEP, 1}}}},
2154     { BAND_DEATH_SCARABS,       {{{MONS_DEATH_SCARAB, 1}}}},
2155     { BAND_FLYING_SKULLS,       {{{MONS_FLYING_SKULL, 1}}}},
2156     { BAND_SHARD_SHRIKE,        {{{MONS_SHARD_SHRIKE, 1}}}},
2157     { BAND_SOJOBO,              {{{MONS_TENGU_REAVER, 1}}}},
2158     { BAND_DIRE_ELEPHANTS,      {{{MONS_DIRE_ELEPHANT, 1}}}},
2159     { BAND_HOWLER_MONKEY,       {{{MONS_HOWLER_MONKEY, 1}}}},
2160     { BAND_CAUSTIC_SHRIKE,      {{{MONS_CAUSTIC_SHRIKE, 1}}}},
2161     { BAND_DANCING_WEAPONS,     {{{MONS_DANCING_WEAPON, 1}}}},
2162     { BAND_SLIME_CREATURES,     {{{MONS_SLIME_CREATURE, 1}}}},
2163     { BAND_SPRIGGAN_RIDERS,     {{{MONS_SPRIGGAN_RIDER, 1}}}},
2164     { BAND_CENTAUR_WARRIORS,    {{{MONS_CENTAUR_WARRIOR, 1}}}},
2165     { BAND_MOLTEN_GARGOYLES,    {{{MONS_MOLTEN_GARGOYLE, 1}}}},
2166     { BAND_SKELETAL_WARRIORS,   {{{MONS_SKELETAL_WARRIOR, 1}}}},
2167     { BAND_THRASHING_HORRORS,   {{{MONS_THRASHING_HORROR, 1}}}},
2168     { BAND_VAMPIRE_MOSQUITOES,  {{{MONS_VAMPIRE_MOSQUITO, 1}}}},
2169     { BAND_ANCIENT_CHAMPIONS,   {{{MONS_ANCIENT_CHAMPION, 1}}}},
2170     { BAND_EXECUTIONER,         {{{MONS_ABOMINATION_LARGE, 1}}}},
2171     { BAND_VASHNIA,             {{{MONS_NAGA_SHARPSHOOTER, 1}}}},
2172     { BAND_PHANTASMAL_WARRIORS, {{{MONS_PHANTASMAL_WARRIOR, 1}}}},
2173     { BAND_DEEP_TROLLS,         {{{MONS_DEEP_TROLL, 1}}}},
2174     { BAND_DEEP_ELF_KNIGHT,     {{{MONS_DEEP_ELF_AIR_MAGE, 46},
2175                                   {MONS_DEEP_ELF_FIRE_MAGE, 46},
2176                                   {MONS_DEEP_ELF_KNIGHT, 24},
2177                                   {MONS_DEEP_ELF_ARCHER, 24},
2178                                   {MONS_DEEP_ELF_DEATH_MAGE, 3},
2179                                   {MONS_DEEP_ELF_DEMONOLOGIST, 2},
2180                                   {MONS_DEEP_ELF_ANNIHILATOR, 2},
2181                                   {MONS_DEEP_ELF_SORCERER, 2}}}},
2182     { BAND_DEEP_ELF_HIGH_PRIEST, {{{MONS_DEEP_ELF_AIR_MAGE, 3},
2183                                    {MONS_DEEP_ELF_FIRE_MAGE, 3},
2184                                    {MONS_DEEP_ELF_KNIGHT, 2},
2185                                    {MONS_DEEP_ELF_ARCHER, 2},
2186                                    {MONS_DEEP_ELF_DEMONOLOGIST, 1},
2187                                    {MONS_DEEP_ELF_ANNIHILATOR, 1},
2188                                    {MONS_DEEP_ELF_SORCERER, 1},
2189                                    {MONS_DEEP_ELF_DEATH_MAGE, 1}}}},
2190     { BAND_BALRUG,              {{{MONS_SUN_DEMON, 1},
2191                                   {MONS_RED_DEVIL, 1}}}},
2192     { BAND_HELLWING,            {{{MONS_HELLWING, 1},
2193                                   {MONS_SMOKE_DEMON, 1}}}},
2194     { BAND_CACODEMON,           {{{MONS_SIXFIRHY, 1},
2195                                   {MONS_ORANGE_DEMON, 1}}}},
2196     { BAND_NECROMANCER,         {{{MONS_ZOMBIE, 2},
2197                                   {MONS_SKELETON, 2},
2198                                   {MONS_SIMULACRUM, 1}}}},
2199     { BAND_HELL_KNIGHTS,        {{{MONS_HELL_KNIGHT, 3},
2200                                   {MONS_NECROMANCER, 1}}}},
2201     { BAND_POLYPHEMUS,          {{{MONS_CATOBLEPAS, 1}},
2202 
2203                                  {{MONS_DEATH_YAK, 1}}}},
2204     { BAND_VERY_UGLY_THINGS,    {{{MONS_UGLY_THING, 3},
2205                                   {MONS_VERY_UGLY_THING, 4}}}},
2206     { BAND_GOLEMS,              {{{MONS_WAR_GARGOYLE, 1},
2207                                   {MONS_CRYSTAL_GUARDIAN, 1}}}},
2208     { BAND_ORCS,                {{{MONS_ORC_PRIEST, 6},
2209                                   {MONS_ORC_WIZARD, 7},
2210                                   {MONS_ORC, 35}}}},
2211     { BAND_ORC_WARRIOR,         {{{MONS_ORC_PRIEST, 5},
2212                                   {MONS_ORC_WIZARD, 7},
2213                                   {MONS_ORC,       22}}}},
2214     // XXX: For Beogh punishment, ogres and trolls look out of place...
2215     // (For normal generation, they're okay, of course.)
2216     { BAND_ORC_KNIGHT,          {{{MONS_ORC, 12},
2217                                   {MONS_ORC_WARRIOR, 9},
2218                                   {MONS_WARG, 2},
2219                                   {MONS_ORC_WIZARD, 2},
2220                                   {MONS_ORC_PRIEST, 2},
2221                                   {MONS_OGRE, 1},
2222                                   {MONS_TROLL, 1},
2223                                   {MONS_ORC_SORCERER, 1}}}},
2224     { BAND_OGRE_MAGE,           {{{MONS_TWO_HEADED_OGRE, 2},
2225                                   {MONS_OGRE, 1}}}},
2226     { BAND_OGRE_MAGE_EXTERN,    {{{MONS_OGRE_MAGE, 1}},
2227                                  {{MONS_TWO_HEADED_OGRE, 1},
2228                                   {MONS_OGRE, 2}}}},
2229     { BAND_KOBOLD_DEMONOLOGIST, {{{MONS_KOBOLD, 4},
2230                                   {MONS_KOBOLD_BRIGAND, 2},
2231                                   {MONS_KOBOLD_DEMONOLOGIST, 1}}}},
2232     // Favour tougher naga suited to melee, compared to normal naga bands
2233     { BAND_GUARDIAN_SERPENT,    {{{MONS_NAGA_MAGE, 5}, {MONS_NAGA_WARRIOR, 10}},
2234 
2235                                  {{MONS_NAGA_MAGE, 5}, {MONS_NAGA_WARRIOR, 10},
2236                                   {MONS_SALAMANDER, 3}, {MONS_NAGA, 12}},
2237 
2238                                  {{MONS_SALAMANDER, 3}, {MONS_NAGA, 12}}}},
2239     { BAND_NAGA_RITUALIST,      {{{MONS_BLACK_MAMBA, 15},
2240                                   {MONS_MANA_VIPER, 7},
2241                                   {MONS_ANACONDA, 4}}}},
2242     { BAND_NAGA_SHARPSHOOTER,   {{{MONS_NAGA_SHARPSHOOTER, 1},
2243                                   {MONS_NAGA, 2}}}},
2244     { BAND_GHOULS,              {{{MONS_GHOUL, 4},
2245                                   {MONS_NECROPHAGE, 3},
2246                                   {MONS_BOG_BODY, 2}}}},
2247     { BAND_ILSUIW,              {{{MONS_MERFOLK_SIREN, 6},
2248                                   {MONS_MERFOLK, 3},
2249                                   {MONS_MERFOLK_JAVELINEER, 2},
2250                                   {MONS_MERFOLK_IMPALER, 2}}}},
2251     { BAND_AZRAEL,              {{{MONS_FIRE_ELEMENTAL, 1},
2252                                   {MONS_HELL_HOUND, 1}}}},
2253     { BAND_KHUFU,               {{{MONS_ROYAL_MUMMY, 1},
2254                                   {MONS_MUMMY, 1}}}},
2255     { BAND_MERFOLK_AQUAMANCER,  {{{MONS_MERFOLK, 4},
2256                                   {MONS_WATER_ELEMENTAL, 11}}}},
2257     { BAND_DEEP_TROLL_SHAMAN,   {{{MONS_DEEP_TROLL, 18},
2258                                   {MONS_IRON_TROLL, 8},
2259                                   {MONS_DEEP_TROLL_EARTH_MAGE, 3},
2260                                   {MONS_DEEP_TROLL_SHAMAN, 3}}}},
2261     { BAND_REDBACK,             {{{MONS_REDBACK, 6},
2262                                   {MONS_TARANTELLA, 1},
2263                                   {MONS_JUMPING_SPIDER, 1}}}},
2264     { BAND_JUMPING_SPIDER,      {{{MONS_JUMPING_SPIDER, 12},
2265                                   {MONS_WOLF_SPIDER, 8},
2266                                   {MONS_ORB_SPIDER, 7},
2267                                   {MONS_REDBACK, 5},
2268                                   {MONS_DEMONIC_CRAWLER, 2}}}},
2269     { BAND_TARANTELLA,          {{{MONS_TARANTELLA, 10},
2270                                   {MONS_REDBACK, 8},
2271                                   {MONS_WOLF_SPIDER, 7},
2272                                   {MONS_ORB_SPIDER, 3},
2273                                   {MONS_DEMONIC_CRAWLER, 2}}}},
2274 
2275     { BAND_VAULT_WARDEN,        {{{MONS_VAULT_SENTINEL, 4},
2276                                   {MONS_IRONBOUND_CONVOKER, 6},
2277                                   {MONS_IRONBOUND_PRESERVER, 5},
2278                                   {MONS_IRONBOUND_FROSTHEART, 3},
2279                                   {MONS_IRONBOUND_THUNDERHULK, 2}},
2280         // one fancy pal, and a 50% chance of another
2281                                 {{MONS_VAULT_SENTINEL, 4},
2282                                  {MONS_IRONBOUND_CONVOKER, 6},
2283                                  {MONS_IRONBOUND_PRESERVER, 5},
2284                                  {MONS_IRONBOUND_FROSTHEART, 3},
2285                                  {MONS_IRONBOUND_THUNDERHULK, 2},
2286                                  {MONS_VAULT_GUARD, 20}},
2287 
2288                                 {{MONS_VAULT_GUARD, 1}}}},
2289 
2290     { BAND_FAUN_PARTY,          {{{MONS_MERFOLK_SIREN, 1}},
2291 
2292                                  {{MONS_FAUN, 1}}}},
2293 
2294     { BAND_TENGU,               {{{MONS_TENGU_WARRIOR, 1},
2295                                   {MONS_TENGU_CONJURER, 1}}}},
2296 
2297     { BAND_SPRIGGANS,           {{{MONS_SPRIGGAN_RIDER, 11},
2298                                   {MONS_SPRIGGAN_AIR_MAGE, 4},
2299                                   {MONS_SPRIGGAN_BERSERKER, 3}}}},
2300 
2301     { BAND_SPRIGGAN_ELITES,     {{{MONS_SPRIGGAN_DEFENDER, 18},
2302                                   {MONS_SPRIGGAN_RIDER, 11},
2303                                   {MONS_SPRIGGAN_AIR_MAGE, 4},
2304                                   {MONS_SPRIGGAN_BERSERKER, 3}},
2305 
2306                                  {{MONS_SPRIGGAN_RIDER, 11},
2307                                   {MONS_SPRIGGAN_AIR_MAGE, 4},
2308                                   {MONS_SPRIGGAN_BERSERKER, 3}}}},
2309 
2310     { BAND_ENCHANTRESS,         {{{MONS_SPRIGGAN_DEFENDER, 1}},
2311 
2312                                  {{MONS_SPRIGGAN_DEFENDER, 1}},
2313 
2314                                  {{MONS_SPRIGGAN_DEFENDER, 1}},
2315 
2316                                  {{MONS_SPRIGGAN_AIR_MAGE, 1}},
2317 
2318                                  {{MONS_SPRIGGAN_AIR_MAGE, 1},
2319                                   {MONS_SPRIGGAN_BERSERKER, 1},
2320                                   {MONS_SPRIGGAN_RIDER, 1},
2321                                   {MONS_SPRIGGAN, 3}}}},
2322 
2323     { BAND_SPRIGGAN_DRUID,      {{{MONS_SPRIGGAN, 2},
2324                                   {MONS_SPRIGGAN_RIDER, 1}}}},
2325 
2326     { BAND_SALAMANDER_ELITES,   {{{MONS_SALAMANDER_MYSTIC, 1},
2327                                   {MONS_SALAMANDER, 1}},
2328 
2329                                  {{MONS_SALAMANDER, 1}}}},
2330     { BAND_ROBIN,               {{{MONS_GOBLIN, 3},
2331                                   {MONS_HOBGOBLIN, 1}}}},
2332 
2333     { BAND_CEREBOV,             {{{MONS_BRIMSTONE_FIEND, 1}},
2334 
2335                                  {{MONS_BALRUG, 1},
2336                                   {MONS_SUN_DEMON, 3},
2337                                   {MONS_EFREET, 3}}}},
2338 
2339     { BAND_GLOORX_VLOQ,         {{{MONS_CURSE_SKULL, 1}},
2340 
2341                                  {{MONS_EXECUTIONER, 1}},
2342 
2343                                  {{MONS_SHADOW_DEMON, 1},
2344                                   {MONS_DEMONIC_CRAWLER, 3},
2345                                   {MONS_SHADOW_WRAITH, 3}}}},
2346 
2347     { BAND_MNOLEG,              {{{MONS_TENTACLED_MONSTROSITY, 1}},
2348 
2349                                  {{MONS_TENTACLED_MONSTROSITY, 1},
2350                                   {MONS_CACODEMON, 2},
2351                                   {MONS_ABOMINATION_LARGE, 3},
2352                                   {MONS_VERY_UGLY_THING, 3},
2353                                   {MONS_NEQOXEC, 3}}}},
2354 
2355     { BAND_LOM_LOBON,           {{{MONS_SPRIGGAN_AIR_MAGE, 1},
2356                                   {MONS_TITAN, 1},
2357                                   {MONS_LICH, 1},
2358                                   {MONS_DRACONIAN_ANNIHILATOR, 2},
2359                                   {MONS_DEEP_ELF_ANNIHILATOR, 2},
2360                                   {MONS_GLOWING_ORANGE_BRAIN, 2},
2361                                   {MONS_BLIZZARD_DEMON, 2},
2362                                   {MONS_GREEN_DEATH, 2},
2363                                   {MONS_RAKSHASA, 4},
2364                                   {MONS_WIZARD, 4}}}},
2365 
2366     { BAND_HOLIES,              {{{MONS_ANGEL, 100},
2367                                   {MONS_CHERUB, 80},
2368                                   {MONS_DAEVA, 50},
2369                                   {MONS_OPHAN, 1}}}}, // !?
2370 
2371     // one supporter, and maybe more
2372     { BAND_SALTLINGS,           {{{MONS_GUARDIAN_SERPENT, 1},
2373                                   {MONS_IRONBOUND_CONVOKER, 1},
2374                                   {MONS_RAGGED_HIEROPHANT, 2},
2375                                   {MONS_SERVANT_OF_WHISPERS, 2},
2376                                   {MONS_PEACEKEEPER, 2}},
2377 
2378                                  {{MONS_SALTLING, 150},
2379                                   {MONS_RAGGED_HIEROPHANT, 5},
2380                                   {MONS_SERVANT_OF_WHISPERS, 5},
2381                                   {MONS_PEACEKEEPER, 5},
2382                                   {MONS_MOLTEN_GARGOYLE, 5},
2383                                   {MONS_IRONBOUND_CONVOKER, 2},
2384                                   {MONS_GUARDIAN_SERPENT, 2},
2385                                   {MONS_IMPERIAL_MYRMIDON, 2}}}},
2386 };
2387 
2388 /**
2389  * Return the type of the nth monster in a band.
2390  *
2391  * @param band      The type of band
2392  * @param which     The index of the monster (starting from 1)
2393  * @return          The type of monster to create
2394  */
_band_member(band_type band,int which,level_id parent_place,bool allow_ood)2395 static monster_type _band_member(band_type band, int which,
2396                                  level_id parent_place, bool allow_ood)
2397 {
2398     if (band == BAND_NO_BAND)
2399         return MONS_PROGRAM_BUG;
2400     ASSERT(which > 0);
2401 
2402     if (const auto *membership = map_find(band_membership, band))
2403     {
2404         ASSERT(membership->size() > 0);
2405         const size_t idx = min<size_t>(which, membership->size()) - 1;
2406         const auto *choice = random_choose_weighted((*membership)[idx]);
2407         ASSERT(choice); /* empty weights vector */
2408         return *choice;
2409     }
2410 
2411     switch (band)
2412     {
2413 
2414     case BAND_PANDEMONIUM_LORD:
2415         if (one_chance_in(7))
2416         {
2417             return random_choose_weighted(50, MONS_LICH,
2418                                           10, MONS_ANCIENT_LICH);
2419         }
2420         else if (one_chance_in(6))
2421         {
2422             return random_choose_weighted(50, MONS_ABOMINATION_SMALL,
2423                                           40, MONS_ABOMINATION_LARGE,
2424                                           10, MONS_TENTACLED_MONSTROSITY);
2425         }
2426         else
2427         {
2428             return summon_any_demon(random_choose_weighted(
2429                                           50, RANDOM_DEMON_COMMON,
2430                                           20, RANDOM_DEMON_GREATER,
2431                                           10, RANDOM_DEMON),
2432                                     true);
2433         }
2434         break;
2435 
2436     case BAND_NAGAS:
2437         if (which == 1 && coinflip() || which == 2 && one_chance_in(4))
2438         {
2439             return random_choose_weighted( 8, MONS_NAGA_WARRIOR,
2440                                           11, MONS_NAGA_MAGE,
2441                                            6, MONS_NAGA_RITUALIST,
2442                                            8, MONS_NAGA_SHARPSHOOTER,
2443                                            6, MONS_SALAMANDER_MYSTIC);
2444         }
2445         else
2446             return one_chance_in(7) ? MONS_SALAMANDER : MONS_NAGA;
2447 
2448 
2449     case BAND_DRACONIAN:
2450         if (env.absdepth0 >= 24 && x_chance_in_y(13, 40))
2451         {
2452             // Hack: race is rolled elsewhere.
2453             return random_choose_weighted(
2454                 1, MONS_DRACONIAN_STORMCALLER,
2455                 2, MONS_DRACONIAN_KNIGHT,
2456                 2, MONS_DRACONIAN_MONK,
2457                 2, MONS_DRACONIAN_SHIFTER,
2458                 2, MONS_DRACONIAN_ANNIHILATOR,
2459                 2, MONS_DRACONIAN_SCORCHER);
2460         }
2461 
2462         return random_draconian_monster_species();
2463 
2464     case BAND_DEATH_KNIGHT:
2465         if (!player_in_branch(BRANCH_DUNGEON)
2466             && which == 1 && x_chance_in_y(2, 3))
2467         {
2468             return one_chance_in(3) ? MONS_GHOUL : MONS_FLAYED_GHOST;
2469         }
2470         else
2471             return random_choose_weighted(5, MONS_WRAITH,
2472                                           6, MONS_FREEZING_WRAITH,
2473                                           3, MONS_PHANTASMAL_WARRIOR,
2474                                           3, MONS_SKELETAL_WARRIOR);
2475 
2476     case BAND_MONSTROUS_DEMONSPAWN:
2477         if (which == 1 || x_chance_in_y(2, 3))
2478         {
2479             return random_choose_weighted( 2, MONS_DEMONIC_CRAWLER,
2480                                            2, MONS_SIXFIRHY,
2481                                            3, MONS_MONSTROUS_DEMONSPAWN);
2482         }
2483         return random_demonspawn_monster_species();
2484 
2485     case BAND_GELID_DEMONSPAWN:
2486         if (which == 1 || x_chance_in_y(2, 3))
2487         {
2488             return random_choose_weighted( 4, MONS_ICE_DEVIL,
2489                                            3, MONS_GELID_DEMONSPAWN);
2490         }
2491         return random_demonspawn_monster_species();
2492 
2493     case BAND_INFERNAL_DEMONSPAWN:
2494         if (which == 1 || x_chance_in_y(2, 3))
2495         {
2496             return random_choose_weighted( 2, MONS_RED_DEVIL,
2497                                            2, MONS_SUN_DEMON,
2498                                            3, MONS_INFERNAL_DEMONSPAWN);
2499         }
2500         return random_demonspawn_monster_species();
2501 
2502     case BAND_TORTUROUS_DEMONSPAWN:
2503         if (which == 1 || x_chance_in_y(2, 3))
2504         {
2505             return random_choose_weighted( 2, MONS_ORANGE_DEMON,
2506                                            2, MONS_SIXFIRHY,
2507                                            3, MONS_TORTUROUS_DEMONSPAWN);
2508         }
2509         return random_demonspawn_monster_species();
2510 
2511     case BAND_BLOOD_SAINT:
2512         if (which == 1 || which == 2 && one_chance_in(3))
2513         {
2514             if (x_chance_in_y(2, 3))
2515                 return random_choose(MONS_BALRUG, MONS_BLIZZARD_DEMON);
2516             else
2517                 return random_demonspawn_job();
2518         }
2519         return random_demonspawn_monster_species();
2520 
2521     case BAND_WARMONGER:
2522         if (which == 1 || which == 2 && one_chance_in(3))
2523         {
2524             if (x_chance_in_y(2, 3))
2525                 return one_chance_in(4) ? MONS_EXECUTIONER : MONS_REAPER;
2526             else
2527                 return random_demonspawn_job();
2528         }
2529         return random_demonspawn_monster_species();
2530 
2531     case BAND_CORRUPTER:
2532         if (which == 1 || which == 2 && one_chance_in(3))
2533         {
2534             if (x_chance_in_y(2, 3))
2535                 return one_chance_in(4) ? MONS_CACODEMON : MONS_SHADOW_DEMON;
2536             else
2537                 return random_demonspawn_job();
2538         }
2539         return random_demonspawn_monster_species();
2540 
2541     case BAND_BLACK_SUN:
2542         if (which == 1 || which == 2 && one_chance_in(3))
2543         {
2544             if (x_chance_in_y(2, 3))
2545                 return one_chance_in(3) ? MONS_LOROCYPROCA : MONS_SOUL_EATER;
2546             else
2547                 return random_demonspawn_job();
2548         }
2549         return random_demonspawn_monster_species();
2550 
2551     case BAND_RANDOM_SINGLE:
2552     {
2553         monster_type tmptype = MONS_PROGRAM_BUG;
2554         coord_def tmppos;
2555         return resolve_monster_type(RANDOM_BANDLESS_MONSTER, tmptype,
2556                                     PROX_ANYWHERE, &tmppos, 0,
2557                                     &parent_place, nullptr, allow_ood);
2558     }
2559 
2560     default:
2561         return NUM_MONSTERS;
2562     }
2563 }
2564 
2565 /// Check to make sure that all band types are handled.
debug_bands()2566 void debug_bands()
2567 {
2568     vector<int> unhandled_bands;
2569     for (int i = 0; i < NUM_BANDS; ++i)
2570         if (_band_member((band_type)i, 1, BRANCH_DUNGEON, true) == NUM_MONSTERS)
2571             unhandled_bands.push_back(i);
2572 
2573     if (!unhandled_bands.empty())
2574     {
2575         const string fails = "Unhandled bands: "
2576            + comma_separated_fn(unhandled_bands.begin(), unhandled_bands.end(),
2577                                 [](int i){ return make_stringf("%d", i); });
2578 
2579         dump_test_fails(fails, "mon-bands");
2580     }
2581 }
2582 
2583 // PUBLIC FUNCTION -- mons_place().
2584 
_pick_zot_exit_defender()2585 static monster_type _pick_zot_exit_defender()
2586 {
2587     // 10% Pan lord or Boris
2588     //  - ~1% named pan lord / seraph / Boris
2589     //  - ~9% random pan lord
2590     // 15% Orb Guardian
2591     // 40% Demon
2592     //  - 25% greater demon
2593     //  - 10% common demon
2594     // 40% Pan spawn (can also include pan lords and demons)
2595     if (one_chance_in(10))
2596     {
2597         for (int i = 0; i < 4; i++)
2598         {
2599             // Sometimes pick an unique lord whose rune you've stolen.
2600             if (you.runes[RUNE_MNOLEG + i]
2601                 && !you.unique_creatures[MONS_MNOLEG + i]
2602                 && one_chance_in(10))
2603             {
2604                 return static_cast<monster_type>(MONS_MNOLEG + i);
2605             }
2606         }
2607 
2608         // If Boris has spawned once and is not
2609         // currently alive he has a chance of coming for you on
2610         // the orb run
2611         if (you.props["killed_boris_once"]
2612             && !you.unique_creatures[MONS_BORIS] && one_chance_in(10))
2613         {
2614             return MONS_BORIS;
2615         }
2616 
2617         if (one_chance_in(10))
2618             return MONS_SERAPH;
2619 
2620         return MONS_PANDEMONIUM_LORD;
2621     }
2622 
2623     return random_choose_weighted(
2624         15, MONS_ORB_GUARDIAN,
2625         25, RANDOM_DEMON_GREATER,
2626         10, RANDOM_DEMON_COMMON,
2627         40, pick_monster_no_rarity(BRANCH_PANDEMONIUM));
2628 }
2629 
mons_place(mgen_data mg)2630 monster* mons_place(mgen_data mg)
2631 {
2632 #ifdef DEBUG_MON_CREATION
2633     mprf(MSGCH_DIAGNOSTICS, "in mons_place()");
2634 #endif
2635 
2636     if (mg.cls == WANDERING_MONSTER)
2637     {
2638 #ifdef DEBUG_MON_CREATION
2639         mprf(MSGCH_DIAGNOSTICS, "Set class RANDOM_MONSTER");
2640 #endif
2641         mg.cls = RANDOM_MONSTER;
2642     }
2643 
2644     // This gives a slight challenge to the player as they ascend the
2645     // dungeon with the Orb.
2646     if (_is_random_monster(mg.cls) && player_on_orb_run()
2647         && !player_in_branch(BRANCH_ABYSS) && !mg.summoned())
2648     {
2649 #ifdef DEBUG_MON_CREATION
2650         mprf(MSGCH_DIAGNOSTICS, "Call _pick_zot_exit_defender()");
2651 #endif
2652         mg.cls    = _pick_zot_exit_defender();
2653         mg.flags |= MG_PERMIT_BANDS;
2654     }
2655     else if (_is_random_monster(mg.cls))
2656         mg.flags |= MG_PERMIT_BANDS;
2657 
2658     if (mg.behaviour == BEH_COPY)
2659     {
2660         mg.behaviour = (mg.summoner && mg.summoner->is_player())
2661                         ? BEH_FRIENDLY
2662                         : SAME_ATTITUDE(mg.summoner->as_monster());
2663     }
2664 
2665     monster* creation = place_monster(mg);
2666     if (!creation)
2667         return 0;
2668 
2669     dprf(DIAG_MONPLACE, "Created %s.", creation->base_name(DESC_A, true).c_str());
2670 
2671     // Look at special cases: CHARMED, FRIENDLY, NEUTRAL, GOOD_NEUTRAL,
2672     // HOSTILE.
2673     if (mg.behaviour > NUM_BEHAVIOURS)
2674     {
2675         if (mg.behaviour == BEH_FRIENDLY)
2676             creation->flags |= MF_NO_REWARD;
2677 
2678         if (mg.behaviour == BEH_NEUTRAL || mg.behaviour == BEH_GOOD_NEUTRAL
2679             || mg.behaviour == BEH_STRICT_NEUTRAL)
2680         {
2681             creation->flags |= MF_WAS_NEUTRAL;
2682         }
2683 
2684         if (mg.behaviour == BEH_CHARMED)
2685         {
2686             creation->attitude = ATT_HOSTILE;
2687             creation->add_ench(ENCH_CHARM);
2688         }
2689 
2690         if (!(mg.flags & MG_FORCE_BEH) && !crawl_state.game_is_arena())
2691             check_lovelessness(*creation);
2692 
2693         behaviour_event(creation, ME_EVAL);
2694     }
2695 
2696     if (mg.flags & MG_AUTOFOE && (creation->attitude == ATT_FRIENDLY
2697                                   || mg.behaviour == BEH_CHARMED))
2698     {
2699         set_nearest_monster_foe(creation, true);
2700     }
2701 
2702     return creation;
2703 }
2704 
_monster_primary_habitat_feature(monster_type mc)2705 static dungeon_feature_type _monster_primary_habitat_feature(monster_type mc)
2706 {
2707     if (_is_random_monster(mc))
2708         return DNGN_FLOOR;
2709     return habitat2grid(mons_class_primary_habitat(mc));
2710 }
2711 
_monster_secondary_habitat_feature(monster_type mc)2712 static dungeon_feature_type _monster_secondary_habitat_feature(monster_type mc)
2713 {
2714     if (_is_random_monster(mc))
2715         return DNGN_FLOOR;
2716     return habitat2grid(mons_class_secondary_habitat(mc));
2717 }
2718 
_valid_spot(coord_def pos)2719 static bool _valid_spot(coord_def pos)
2720 {
2721     if (actor_at(pos))
2722         return false;
2723     if (env.level_map_mask(pos) & MMT_NO_MONS)
2724         return false;
2725     return true;
2726 }
2727 
2728 class newmons_square_find : public travel_pathfind
2729 {
2730 private:
2731     dungeon_feature_type feat_wanted;
2732     int maxdistance;
2733 
2734     int best_distance;
2735     int nfound;
2736 public:
2737     // Terrain that we can't spawn on, but that we can skip through.
2738     set<dungeon_feature_type> passable;
2739 public:
newmons_square_find(dungeon_feature_type grdw,const coord_def & pos,int maxdist=0)2740     newmons_square_find(dungeon_feature_type grdw,
2741                         const coord_def &pos,
2742                         int maxdist = 0)
2743         :  feat_wanted(grdw), maxdistance(maxdist),
2744            best_distance(0), nfound(0)
2745     {
2746         start = pos;
2747     }
2748 
2749     // This is an overload, not an override!
pathfind()2750     coord_def pathfind()
2751     {
2752         set_floodseed(start);
2753         return travel_pathfind::pathfind(RMODE_CONNECTIVITY);
2754     }
2755 
path_flood(const coord_def &,const coord_def & dc)2756     bool path_flood(const coord_def &/*c*/, const coord_def &dc) override
2757     {
2758         if (best_distance && traveled_distance > best_distance)
2759             return true;
2760 
2761         if (!in_bounds(dc)
2762             || (maxdistance > 0 && traveled_distance > maxdistance))
2763         {
2764             return false;
2765         }
2766         if (!_feat_compatible(feat_wanted, env.grid(dc)))
2767         {
2768             if (passable.count(env.grid(dc)))
2769                 good_square(dc);
2770             return false;
2771         }
2772         if (_valid_spot(dc) && one_chance_in(++nfound))
2773         {
2774             greedy_dist = traveled_distance;
2775             greedy_place = dc;
2776             best_distance = traveled_distance;
2777         }
2778         else
2779             good_square(dc);
2780         return false;
2781     }
2782 };
2783 
2784 // Finds a square for a monster of the given class, pathfinding
2785 // through only contiguous squares of habitable terrain.
find_newmons_square_contiguous(monster_type mons_class,const coord_def & start,int distance)2786 coord_def find_newmons_square_contiguous(monster_type mons_class,
2787                                          const coord_def &start,
2788                                          int distance)
2789 {
2790     coord_def p;
2791 
2792     const dungeon_feature_type feat_preferred =
2793         _monster_primary_habitat_feature(mons_class);
2794     const dungeon_feature_type feat_nonpreferred =
2795         _monster_secondary_habitat_feature(mons_class);
2796 
2797     newmons_square_find nmpfind(feat_preferred, start, distance);
2798     const coord_def pp = nmpfind.pathfind();
2799     p = pp;
2800 
2801     if (feat_nonpreferred != feat_preferred && !in_bounds(pp))
2802     {
2803         newmons_square_find nmsfind(feat_nonpreferred, start, distance);
2804         const coord_def ps = nmsfind.pathfind();
2805         p = ps;
2806     }
2807 
2808     return in_bounds(p) ? p : coord_def(-1, -1);
2809 }
2810 
find_newmons_square(monster_type mons_class,const coord_def & p,const monster * viable_mon)2811 coord_def find_newmons_square(monster_type mons_class, const coord_def &p,
2812                               const monster* viable_mon)
2813 {
2814     coord_def empty;
2815     coord_def pos(-1, -1);
2816 
2817     if (mons_class == WANDERING_MONSTER)
2818         mons_class = RANDOM_MONSTER;
2819 
2820     // Might be better if we chose a space and tried to match the monster
2821     // to it in the case of RANDOM_MONSTER, that way if the target square
2822     // is surrounded by water or lava this function would work.  -- bwr
2823 
2824     if (find_habitable_spot_near(p, mons_class, 2, true, empty, viable_mon))
2825         pos = empty;
2826 
2827     return pos;
2828 }
2829 
can_spawn_mushrooms(coord_def where)2830 bool can_spawn_mushrooms(coord_def where)
2831 {
2832     cloud_struct *cloud = cloud_at(where);
2833     if (!cloud)
2834         return true;
2835     if (you_worship(GOD_FEDHAS)
2836         && (cloud->whose == KC_YOU || cloud->whose == KC_FRIENDLY))
2837     {
2838         return true;
2839     }
2840 
2841     monster dummy;
2842     dummy.type = MONS_TOADSTOOL;
2843     define_monster(dummy);
2844 
2845     return actor_cloud_immune(dummy, *cloud);
2846 }
2847 
god_hates_monster(monster_type type)2848 conduct_type god_hates_monster(monster_type type)
2849 {
2850     monster dummy;
2851     dummy.type = type;
2852 
2853     // no spellcasting/etc zombies currently; pick something that always works
2854     if (mons_class_is_zombified(type))
2855         define_zombie(&dummy, MONS_GOBLIN, type);
2856     else
2857         define_monster(dummy);
2858 
2859     return god_hates_monster(dummy);
2860 }
2861 
2862 /**
2863  * Is the player hated by all? If so, does this monster care?
2864  */
mons_can_hate(monster_type type)2865 bool mons_can_hate(monster_type type)
2866 {
2867     return you.get_mutation_level(MUT_NO_LOVE)
2868         // don't turn foxfire, guardian golem, etc hostile
2869         && !mons_is_conjured(type)
2870         // ignore things like tentacles, butterflies, plants, etc
2871         && mons_class_gives_xp(type);
2872 }
2873 
check_lovelessness(monster & mons)2874 void check_lovelessness(monster &mons)
2875 {
2876     if (!mons_can_hate(mons.type) || !mons.wont_attack())
2877         return;
2878 
2879     mons.attitude = ATT_HOSTILE;
2880     mons.del_ench(ENCH_CHARM);
2881     behaviour_event(&mons, ME_ALERT, &you);
2882     mprf("%s feels only hate for you!", mons.name(DESC_THE).c_str());
2883 }
2884 
2885 /**
2886  * Does the player's current religion conflict with the given monster? If so,
2887  * why?
2888  *
2889  * XXX: this should ideally return a list of conducts that can be filtered by
2890  *      callers by god; we're duplicating god-conduct.cc right now.
2891  *
2892  * @param mon   The monster in question.
2893  * @return      The reason the player's religion conflicts with the monster
2894  *              (e.g. DID_EVIL for evil monsters), or DID_NOTHING.
2895  */
god_hates_monster(const monster & mon)2896 conduct_type god_hates_monster(const monster &mon)
2897 {
2898     // Player angers all real monsters
2899     if (mons_can_hate(mon.type))
2900         return DID_SACRIFICE_LOVE;
2901 
2902     if (is_good_god(you.religion) && mon.evil())
2903         return DID_EVIL;
2904 
2905     if (is_evil_god(you.religion) && mon.is_holy())
2906         return DID_HOLY;
2907 
2908     if (you_worship(GOD_ZIN))
2909     {
2910         if (mon.how_unclean())
2911             return DID_UNCLEAN;
2912         if (mon.how_chaotic())
2913             return DID_CHAOS;
2914     }
2915     if (god_hates_spellcasting(you.religion) && mon.is_actual_spellcaster())
2916         return DID_SPELL_CASTING;
2917 
2918     return DID_NOTHING;
2919 }
2920 
create_monster(mgen_data mg,bool fail_msg)2921 monster* create_monster(mgen_data mg, bool fail_msg)
2922 {
2923     ASSERT(in_bounds(mg.pos)); // otherwise it's a guaranteed fail
2924 
2925     const monster_type montype = fixup_zombie_type(mg.cls, mg.base_type);
2926 
2927     monster *summd = 0;
2928 
2929     if (!mg.force_place()
2930         || monster_at(mg.pos)
2931         || you.pos() == mg.pos && !fedhas_passthrough_class(mg.cls)
2932         || !mons_class_can_pass(montype, env.grid(mg.pos)))
2933     {
2934         // Gods other than Xom will try to avoid placing their monsters
2935         // directly in harm's way.
2936         if (mg.god != GOD_NO_GOD && mg.god != GOD_XOM)
2937         {
2938             monster dummy;
2939             const monster_type resistless_mon = MONS_HUMAN;
2940             // If the type isn't known yet assume no resists or anything.
2941             dummy.type         = needs_resolution(mg.cls) ? resistless_mon
2942                                                           : mg.cls;
2943             dummy.base_monster = mg.base_type;
2944             dummy.god          = mg.god;
2945             dummy.behaviour    = mg.behaviour;
2946 
2947             // Monsters that have resistance info in the ghost
2948             // structure cannot be handled as dummies, so treat them
2949             // as a known no-resist monster. mons_avoids_cloud() will
2950             // crash for dummy monsters which should have a
2951             // ghost_demon setup.
2952             if (mons_is_ghost_demon(dummy.type))
2953                 dummy.type = resistless_mon;
2954             mg.pos = find_newmons_square(montype, mg.pos, &dummy);
2955         }
2956         else
2957             mg.pos = find_newmons_square(montype, mg.pos);
2958     }
2959 
2960     if (in_bounds(mg.pos))
2961     {
2962         summd = mons_place(mg);
2963         // If the arena vetoed the placement then give no fail message.
2964         if (crawl_state.game_is_arena())
2965             fail_msg = false;
2966 
2967         if (!summd && fail_msg && you.see_cell(mg.pos))
2968             mpr("You see a puff of smoke.");
2969     }
2970 
2971     return summd;
2972 }
2973 
find_habitable_spot_near(const coord_def & where,monster_type mon_type,int radius,bool allow_centre,coord_def & empty,const monster * viable_mon)2974 bool find_habitable_spot_near(const coord_def& where, monster_type mon_type,
2975                               int radius, bool allow_centre, coord_def& empty,
2976                               const monster* viable_mon)
2977 {
2978     // XXX: A lot of hacks that could be avoided by passing the
2979     //      monster generation data through.
2980 
2981     int good_count = 0;
2982 
2983     for (radius_iterator ri(where, radius, C_SQUARE, !allow_centre);
2984          ri; ++ri)
2985     {
2986         bool success = false;
2987 
2988         if (actor_at(*ri))
2989             continue;
2990 
2991         if (!cell_see_cell(where, *ri, LOS_NO_TRANS))
2992             continue;
2993 
2994         success = monster_habitable_grid(mon_type, env.grid(*ri));
2995         if (success && viable_mon)
2996             success = !mons_avoids_cloud(viable_mon, *ri, true);
2997 
2998         if (success && one_chance_in(++good_count))
2999             empty = *ri;
3000     }
3001 
3002     return good_count > 0;
3003 }
3004 
3005 static void _get_vault_mon_list(vector<mons_spec> &list);
3006 
random_demon_by_tier(int tier)3007 monster_type random_demon_by_tier(int tier)
3008 {
3009     switch (tier)
3010     {
3011     case 5:
3012         return random_choose(MONS_CRIMSON_IMP,
3013                              MONS_QUASIT,
3014                              MONS_WHITE_IMP,
3015                              MONS_UFETUBUS,
3016                              MONS_IRON_IMP,
3017                              MONS_SHADOW_IMP);
3018     case 4:
3019         return random_choose(MONS_ICE_DEVIL,
3020                              MONS_RUST_DEVIL,
3021                              MONS_ORANGE_DEMON,
3022                              MONS_RED_DEVIL,
3023                              MONS_CHAOS_SPAWN,
3024                              MONS_HELLWING);
3025     case 3:
3026         return random_choose(MONS_SUN_DEMON,
3027                              MONS_SOUL_EATER,
3028                              MONS_SMOKE_DEMON,
3029                              MONS_NEQOXEC,
3030                              MONS_YNOXINUL,
3031                              MONS_SIXFIRHY);
3032     case 2:
3033         return random_choose(MONS_GREEN_DEATH,
3034                              MONS_BLIZZARD_DEMON,
3035                              MONS_BALRUG,
3036                              MONS_CACODEMON,
3037                              MONS_HELL_BEAST,
3038                              MONS_HELLION,
3039                              MONS_REAPER,
3040                              MONS_LOROCYPROCA,
3041                              MONS_TORMENTOR,
3042                              MONS_SHADOW_DEMON);
3043     case 1:
3044         return random_choose(MONS_BRIMSTONE_FIEND,
3045                              MONS_ICE_FIEND,
3046                              MONS_TZITZIMITL,
3047                              MONS_HELL_SENTINEL,
3048                              MONS_EXECUTIONER);
3049     default:
3050         die("invalid demon tier");
3051     }
3052 }
3053 
summon_any_demon(monster_type dct,bool use_local_demons)3054 monster_type summon_any_demon(monster_type dct, bool use_local_demons)
3055 {
3056     // Draw random demon types in Pan from the local pools first.
3057     if (use_local_demons
3058         && player_in_branch(BRANCH_PANDEMONIUM)
3059         && !one_chance_in(40))
3060     {
3061         monster_type typ = MONS_0;
3062         int count = 0;
3063         vector<mons_spec> list;
3064         _get_vault_mon_list(list);
3065         const bool list_set = !list.empty();
3066         const int max = list_set ? list.size() : PAN_MONS_ALLOC;
3067         for (int i = 0; i < max; i++)
3068         {
3069             const monster_type cur = list_set ? list[i].monbase
3070                                               : env.mons_alloc[i];
3071             if (invalid_monster_type(cur))
3072                 continue;
3073             if (dct == RANDOM_DEMON && !mons_is_demon(cur)
3074                 || dct == RANDOM_DEMON_LESSER && mons_demon_tier(cur) != 5
3075                 || dct == RANDOM_DEMON_COMMON
3076                    && mons_demon_tier(cur) != 4
3077                    && mons_demon_tier(cur) != 3
3078                 || dct == RANDOM_DEMON_GREATER
3079                    && mons_demon_tier(cur) != 2
3080                    && mons_demon_tier(cur) != 1)
3081             {
3082                 continue;
3083             }
3084             const int weight = list_set ? list[i].genweight : 1;
3085             count += weight;
3086             if (x_chance_in_y(weight, count))
3087                 typ = cur;
3088         }
3089         if (count)
3090             return typ;
3091     }
3092 
3093     if (dct == RANDOM_DEMON)
3094     {
3095         dct = random_choose(RANDOM_DEMON_LESSER, RANDOM_DEMON_COMMON,
3096                             RANDOM_DEMON_GREATER);
3097     }
3098 
3099     switch (dct)
3100     {
3101     case RANDOM_DEMON_LESSER:
3102         return random_demon_by_tier(5);
3103 
3104     case RANDOM_DEMON_COMMON:
3105         if (x_chance_in_y(6, 10))
3106             return random_demon_by_tier(4);
3107         else
3108             return random_demon_by_tier(3);
3109 
3110     case RANDOM_DEMON_GREATER:
3111         if (x_chance_in_y(6, 10))
3112             return random_demon_by_tier(2);
3113         else
3114             return random_demon_by_tier(1);
3115 
3116     default:
3117         return dct;
3118     }
3119 }
3120 
replace_boris()3121 void replace_boris()
3122 {
3123     // Initial generation is governed by the vault uniq_boris. Once he is killed
3124     // a first time, as long as he isn't alive somewhere, he can regenerate when
3125     // a new level is entered.
3126     if (!you.props["killed_boris_once"]
3127         || you.unique_creatures[MONS_BORIS]
3128         || !one_chance_in(6))
3129     {
3130         return;
3131     }
3132 
3133     // TODO: kind of ad hoc, maybe read from uniq_boris vault?
3134     switch (you.where_are_you)
3135     {
3136     case BRANCH_DEPTHS:
3137     case BRANCH_VAULTS:
3138     case BRANCH_TOMB:
3139     case BRANCH_CRYPT:
3140         break;
3141     default:
3142         return;
3143     }
3144 
3145     mgen_data boris = mgen_data(MONS_BORIS);
3146     mons_place(boris);
3147 }
3148 
3149 /////////////////////////////////////////////////////////////////////////////
3150 //
3151 // Random monsters for portal vaults. Used for e.g. shadow creatures.
3152 //
3153 /////////////////////////////////////////////////////////////////////////////
3154 
set_vault_mon_list(const vector<mons_spec> & list)3155 void set_vault_mon_list(const vector<mons_spec> &list)
3156 {
3157     CrawlHashTable &props = env.properties;
3158 
3159     props.erase(VAULT_MON_TYPES_KEY);
3160     props.erase(VAULT_MON_BASES_KEY);
3161     props.erase(VAULT_MON_PLACES_KEY);
3162     props.erase(VAULT_MON_WEIGHTS_KEY);
3163     props.erase(VAULT_MON_BANDS_KEY);
3164 
3165     size_t size = list.size();
3166     if (size == 0)
3167     {
3168         setup_vault_mon_list();
3169         return;
3170     }
3171 
3172     props[VAULT_MON_TYPES_KEY].new_vector(SV_INT).resize(size);
3173     props[VAULT_MON_BASES_KEY].new_vector(SV_INT).resize(size);
3174     props[VAULT_MON_PLACES_KEY].new_vector(SV_LEV_ID).resize(size);
3175     props[VAULT_MON_WEIGHTS_KEY].new_vector(SV_INT).resize(size);
3176     props[VAULT_MON_BANDS_KEY].new_vector(SV_BOOL).resize(size);
3177 
3178     CrawlVector &type_vec   = props[VAULT_MON_TYPES_KEY].get_vector();
3179     CrawlVector &base_vec   = props[VAULT_MON_BASES_KEY].get_vector();
3180     CrawlVector &place_vec  = props[VAULT_MON_PLACES_KEY].get_vector();
3181     CrawlVector &weight_vec = props[VAULT_MON_WEIGHTS_KEY].get_vector();
3182     CrawlVector &band_vec   = props[VAULT_MON_BANDS_KEY].get_vector();
3183 
3184     for (size_t i = 0; i < size; i++)
3185     {
3186         const mons_spec &spec = list[i];
3187 
3188         if (spec.place.is_valid())
3189         {
3190             ASSERT(branch_has_monsters(spec.place.branch));
3191             type_vec[i] = -1;
3192             base_vec[i] = -1;
3193             place_vec[i] = spec.place;
3194         }
3195         else
3196         {
3197             ASSERT(!_is_random_monster(spec.type)
3198                    && !_is_random_monster(spec.monbase));
3199             type_vec[i] = spec.type;
3200             base_vec[i] = spec.monbase;
3201             band_vec[i] = spec.band;
3202             place_vec[i] = level_id();
3203         }
3204         weight_vec[i] = spec.genweight;
3205     }
3206 
3207     setup_vault_mon_list();
3208 }
3209 
_get_vault_mon_list(vector<mons_spec> & list)3210 static void _get_vault_mon_list(vector<mons_spec> &list)
3211 {
3212     list.clear();
3213 
3214     CrawlHashTable &props = env.properties;
3215 
3216     if (!props.exists(VAULT_MON_TYPES_KEY))
3217         return;
3218 
3219     ASSERT(props.exists(VAULT_MON_BASES_KEY));
3220     ASSERT(props.exists(VAULT_MON_WEIGHTS_KEY));
3221     ASSERT(props.exists(VAULT_MON_BANDS_KEY));
3222     ASSERT(props.exists(VAULT_MON_PLACES_KEY));
3223 
3224     CrawlVector &type_vec   = props[VAULT_MON_TYPES_KEY].get_vector();
3225     CrawlVector &base_vec   = props[VAULT_MON_BASES_KEY].get_vector();
3226     CrawlVector &place_vec  = props[VAULT_MON_PLACES_KEY].get_vector();
3227     CrawlVector &weight_vec = props[VAULT_MON_WEIGHTS_KEY].get_vector();
3228     CrawlVector &band_vec   = props[VAULT_MON_BANDS_KEY].get_vector();
3229 
3230     size_t size = type_vec.size();
3231     ASSERT(size == base_vec.size());
3232     ASSERT(size == place_vec.size());
3233     ASSERT(size == weight_vec.size());
3234     ASSERT(size == band_vec.size());
3235 
3236     for (size_t i = 0; i < size; i++)
3237     {
3238         monster_type type = static_cast<monster_type>(type_vec[i].get_int());
3239         monster_type base = static_cast<monster_type>(base_vec[i].get_int());
3240         level_id    place = place_vec[i];
3241 
3242         mons_spec spec;
3243 
3244         if (place.is_valid())
3245         {
3246             ASSERT(branch_has_monsters(place.branch));
3247             spec.place = place;
3248         }
3249         else
3250         {
3251             spec.type    = type;
3252             spec.monbase = base;
3253             ASSERT(!_is_random_monster(spec.type)
3254                    && !_is_random_monster(spec.monbase));
3255         }
3256         spec.genweight = weight_vec[i];
3257         spec.band = band_vec[i];
3258 
3259         list.push_back(spec);
3260     }
3261 }
3262 
setup_vault_mon_list()3263 void setup_vault_mon_list()
3264 {
3265     vault_mon_types.clear();
3266     vault_mon_bases.clear();
3267     vault_mon_places.clear();
3268     vault_mon_weights.clear();
3269     vault_mon_bands.clear();
3270 
3271     vector<mons_spec> list;
3272     _get_vault_mon_list(list);
3273 
3274     unsigned int size = list.size();
3275 
3276     vault_mon_types.resize(size);
3277     vault_mon_bases.resize(size);
3278     vault_mon_places.resize(size);
3279     vault_mon_weights.resize(size);
3280     vault_mon_bands.resize(size);
3281 
3282     for (size_t i = 0; i < size; i++)
3283     {
3284         if (list[i].place.is_valid())
3285         {
3286             vault_mon_types[i] = -1;
3287             vault_mon_bases[i] = -1;
3288             vault_mon_places[i] = list[i].place;
3289         }
3290         else
3291         {
3292             vault_mon_types[i] = list[i].type;
3293             vault_mon_bases[i] = list[i].monbase;
3294             vault_mon_places[i] = level_id();
3295         }
3296         vault_mon_bands[i] = list[i].band;
3297         vault_mon_weights[i] = list[i].genweight;
3298     }
3299     if (size)
3300         dprf(DIAG_MONPLACE, "Level has a custom monster set.");
3301 }
3302