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