3 * Summary: Zot Def specific functions
4 * Written by: Mark Mackey
11 #include "dungeon.h" // for Zotdef unique placement
15 #include "items.h" // // for find_floor_item
16 #include "itemname.h" // // for make_name
21 #include "mgen_data.h"
22 #include "mon-stuff.h"
23 #include "mon-place.h"
36 // Size of the mons_alloc array (or at least the bit of
38 #define NSLOTS (MAX_MONS_ALLOC - 1)
39 #define BOSS_SLOT NSLOTS
41 //#define DEBUG_WAVE 1
43 static monster_type
_pick_unique(int level
);
45 static int _fuzz_mons_level(int level
)
47 if (level
> 1 && one_chance_in(7))
49 const int fuzz
= random2avg(9, 2);
50 return (fuzz
> 4 ? level
+ fuzz
- 4 : level
);
55 // Choose a random branch. Which branches may be chosen is a function of
57 branch_type
zotdef_random_branch()
59 int wavenum
= you
.num_turns
/ CYCLE_LENGTH
;
63 branch_type pb
= static_cast<branch_type
>(random2(NUM_BRANCHES
));
67 case BRANCH_MAIN_DUNGEON
:
69 // reduce freq at high levels
74 case BRANCH_SNAKE_PIT
:
76 // reduce freq at high levels
77 if (wavenum
> 40 && !coinflip())
82 case BRANCH_ECUMENICAL_TEMPLE
:
84 case BRANCH_VESTIBULE_OF_HELL
:
86 break; // vaults/vestibule same as dungeon
88 case BRANCH_ORCISH_MINES
:
89 ok
= wavenum
< 30; // <6K turns only
91 case BRANCH_ELVEN_HALLS
:
92 ok
= wavenum
> 10 && wavenum
< 60; // 2.2-12K turns
95 ok
= wavenum
< 40; // <8K turns only
98 ok
= wavenum
> 12 && wavenum
< 40; // 2.6-8K turns
101 ok
= wavenum
> 12 && wavenum
< 60; // 2.6-12K turns
104 ok
= wavenum
> 13; // 2.8K-
106 case BRANCH_SLIME_PITS
:
107 ok
= wavenum
> 20 && coinflip(); // 4K-
108 break; // >4K turns only
110 ok
= wavenum
> 12 && wavenum
< 35; // 2.6-7.5K
112 case BRANCH_HALL_OF_BLADES
:
113 ok
= wavenum
> 30; // 6K-
116 ok
= wavenum
> 30 && coinflip(); // 6K-
118 case BRANCH_DIS
: // 8K-
120 case BRANCH_TARTARUS
:
122 ok
= wavenum
> 40 && one_chance_in(3);
124 case BRANCH_HALL_OF_ZOT
: // 10K-
129 return (one_chance_in(4) ? BRANCH_MAIN_DUNGEON
: pb
);
130 // strong bias to main dungeon
134 int mon_strength(monster_type mon_type
)
136 monsterentry
*mentry
= get_monster_data(mon_type
);
139 int strength
= (mentry
->hpdice
[0] * mentry
->exp_mod
) / 10;
140 // Fix for skeletons and zombies
143 case MONS_SKELETON_SMALL
:
144 case MONS_ZOMBIE_SMALL
:
147 case MONS_SKELETON_LARGE
:
148 case MONS_ZOMBIE_LARGE
:
151 case MONS_PANDEMONIUM_DEMON
: // base init has 4HD (!)
160 // Fill the wave list with selections from a supplied array.
161 // Each array contains a monster if random2(power)>chance. Power
162 // is also compared to the strength of each critter to allow later
163 // waves to be stronger than earlier ones.
165 // Note that this fills in the boss slot as well.
166 static void _zotdef_fill_from_list(monster_type mlist
[], int chance
, int power
)
168 for (int i
= 0; i
<= NSLOTS
; i
++)
170 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
171 if (i
< NSLOTS
&& random2(power
) < chance
)
172 continue; // no monster this entry
173 while (env
.mons_alloc
[i
] == MONS_PROGRAM_BUG
)
175 monster_type mon_type
= RANDOM_ELEMENT(mlist
);
176 if (random2((power
* 3) / 2) > mon_strength(mon_type
))
177 continue; // bias away from weaker critters
178 if (random2((power
* 3) / 2) > mon_strength(mon_type
))
179 env
.mons_alloc
[i
] = mon_type
;
180 if (one_chance_in(100))
181 env
.mons_alloc
[i
] = mon_type
; // occasional random pick
186 // Choose a boss from the supplied list. If a unique is chosen and has
187 // already been seen we try again. After a few tries we give up and
188 // leave the existing entry there.
189 static void _zotdef_choose_boss(monster_type mlist
[], int power
)
192 while (tries
++ < 100)
194 monster_type mon_type
= RANDOM_ELEMENT(mlist
);
195 if (mons_is_unique(mon_type
)
196 && you
.unique_creatures
[mon_type
])
200 if (random2avg(power
* 3, 2) < mon_strength(mon_type
))
204 env
.mons_alloc
[BOSS_SLOT
] = mon_type
;
209 static void _zotdef_danger_msg(const char *msg
)
211 mpr(msg
, MSGCH_DANGER
);
215 void hydra_wave(int power
)
220 monster_type hydras
[] = {MONS_HYDRA
};
221 monster_type boss
[] = {MONS_LERNAEAN_HYDRA
};
222 _zotdef_fill_from_list(hydras
, 4, power
); // 66% full at power 12
223 _zotdef_choose_boss(boss
, power
* 2);
224 _zotdef_danger_msg("You hear a distant many-voiced hissing!");
227 void fire_wave(int power
)
232 monster_type firemons
[] = {MONS_FIRE_ELEMENTAL
, MONS_FIRE_DRAKE
, MONS_IMP
,
233 MONS_DRAGON
, MONS_FIRE_VORTEX
,MONS_FIRE_GIANT
, MONS_HELLION
,
234 MONS_MOLTEN_GARGOYLE
, MONS_SALAMANDER
, MONS_SUN_DEMON
,
235 MONS_RED_DRACONIAN
, MONS_MOTTLED_DRACONIAN
, MONS_DRACONIAN_SCORCHER
,
236 MONS_FLAMING_CORPSE
, MONS_MOTTLED_DRAGON
, MONS_EFREET
,
237 MONS_HELL_KNIGHT
, MONS_FIEND
, MONS_BALRUG
, MONS_HELL_HOUND
,
239 monster_type boss
[] = {MONS_AZRAEL
, MONS_XTAHUA
, MONS_SERPENT_OF_HELL
,
240 MONS_MARGERY
, MONS_FIEND
, MONS_BALRUG
, MONS_FIRE_GIANT
};
241 _zotdef_fill_from_list(firemons
, 0, power
);
242 _zotdef_choose_boss(boss
, power
);
243 _zotdef_danger_msg("You hear roaring flames in the distance!");
246 void cold_wave(int power
)
251 monster_type coldmons
[] = {MONS_ICE_BEAST
, MONS_AZURE_JELLY
,
252 MONS_FREEZING_WRAITH
, MONS_WHITE_IMP
, MONS_ICE_DEVIL
, MONS_ICE_FIEND
,
253 MONS_WHITE_DRACONIAN
, MONS_SIMULACRUM_SMALL
, MONS_SIMULACRUM_LARGE
,
254 MONS_FROST_GIANT
, MONS_POLAR_BEAR
, MONS_BLUE_DEVIL
};
255 monster_type boss
[] = {MONS_ANTAEUS
, MONS_ICE_FIEND
, MONS_AZURE_JELLY
,
256 MONS_WHITE_DRACONIAN
};
257 _zotdef_fill_from_list(coldmons
, 4, power
);
258 _zotdef_choose_boss(boss
, power
);
259 _zotdef_danger_msg("A deadly chill settles over the dungeon!");
262 void gnoll_wave(int power
)
267 monster_type gnolls
[] = {MONS_GNOLL
, MONS_GNOLL
, MONS_GNOLL
,
268 MONS_GNOLL
, MONS_GNOLL
, MONS_GNOLL
, MONS_TROLL
};
269 monster_type boss
[] = {MONS_GRUM
, MONS_TROLL
};
270 _zotdef_fill_from_list(gnolls
, 0, power
); // full
271 _zotdef_choose_boss(boss
, power
);
272 _zotdef_danger_msg("Harsh voices can be heard, coming closer!");
275 void rat_wave(int power
)
280 monster_type rats
[] = {MONS_RAT
, MONS_GREEN_RAT
, MONS_GREY_RAT
,
282 monster_type boss
[] = {MONS_ORANGE_RAT
};
283 _zotdef_fill_from_list(rats
, 0, power
); // full power
284 _zotdef_choose_boss(boss
, power
);
285 _zotdef_danger_msg("You hear distant squeaking!");
288 void hound_wave(int power
)
293 monster_type hounds
[] = {MONS_JACKAL
, MONS_HOUND
, MONS_WARG
,
294 MONS_WOLF
, MONS_WAR_DOG
};
295 monster_type boss
[] = {MONS_HELL_HOUND
};
296 _zotdef_fill_from_list(hounds
, 0, power
); // full
297 _zotdef_choose_boss(boss
, power
);
298 _zotdef_danger_msg("Horrible howls echo around!");
301 void abomination_wave(int power
)
304 mpr("ABOMINATION WAVE");
306 monster_type aboms
[] = {MONS_ABOMINATION_SMALL
, MONS_ABOMINATION_LARGE
};
307 monster_type boss
[] = {MONS_TENTACLED_MONSTROSITY
};
308 _zotdef_fill_from_list(aboms
, 0, power
); // full
309 _zotdef_choose_boss(boss
, power
);
310 _zotdef_danger_msg("A dreadful chittering sound fills the air. It's coming closer...");
313 void ugly_wave(int power
)
318 monster_type ugly
[] = {MONS_UGLY_THING
, MONS_UGLY_THING
, MONS_UGLY_THING
,
319 MONS_VERY_UGLY_THING
};
320 monster_type boss
[] = {MONS_VERY_UGLY_THING
};
321 _zotdef_fill_from_list(ugly
, 6, power
); // reduced size
322 _zotdef_choose_boss(boss
, power
);
323 _zotdef_danger_msg("You feel uneasy.");
326 void golem_wave(int power
)
331 monster_type golems
[] = {MONS_CLAY_GOLEM
, MONS_WOOD_GOLEM
, MONS_STONE_GOLEM
,
332 MONS_IRON_GOLEM
, MONS_CRYSTAL_GOLEM
, MONS_TOENAIL_GOLEM
};
333 monster_type boss
[] = {MONS_ELECTRIC_GOLEM
};
334 _zotdef_fill_from_list(golems
, 6, power
* 2 / 3); // reduced size
335 _zotdef_choose_boss(boss
, power
);
336 _zotdef_danger_msg("Booming thuds herald the arrival of something large...");
339 void human_wave(int power
)
344 monster_type humans
[] = {MONS_HUMAN
, MONS_HELL_KNIGHT
, MONS_NECROMANCER
,
345 MONS_WIZARD
, MONS_VAULT_GUARD
, MONS_KILLER_KLOWN
};
346 monster_type boss
[] = {MONS_HELL_KNIGHT
, MONS_KILLER_KLOWN
,
347 MONS_VAULT_GUARD
, MONS_JOSEPH
, MONS_ERICA
, MONS_JOSEPHINE
,
348 MONS_HAROLD
, MONS_JOZEF
, MONS_AGNES
,
349 MONS_MAUD
, MONS_LOUISE
, MONS_FRANCES
,
350 MONS_RUPERT
, MONS_KIRKE
,
351 MONS_NORRIS
, MONS_FREDERICK
, MONS_MARGERY
, MONS_EUSTACHIO
,
353 _zotdef_fill_from_list(humans
, 4, power
); // reduced size due to banding
355 // Get too many hell knights with the defaults, due to their large band
357 for (int i
= 0; i
< NSLOTS
; i
++)
359 if (env
.mons_alloc
[i
] == MONS_HELL_KNIGHT
&& random2(power
) < 8)
360 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
363 _zotdef_choose_boss(boss
, power
);
364 _zotdef_danger_msg("War cries fill the air!");
367 void butterfly_wave(int power
)
370 mpr("BUTTERFLY WAVE");
372 monster_type bfs
[] = {MONS_BUTTERFLY
};
373 _zotdef_fill_from_list(bfs
, 0, power
); // full
374 _zotdef_danger_msg("You feel a sudden sense of peace!");
377 void beast_wave(int power
)
382 monster_type bst
[] = {MONS_BEAST
};
383 _zotdef_fill_from_list(bst
, 0, power
); // full
384 _zotdef_danger_msg("A hideous howling noise can be heard in the distance!");
387 void frog_wave(int power
)
392 monster_type frogs
[] = {MONS_GIANT_FROG
, MONS_GIANT_TOAD
,
393 MONS_SPINY_FROG
, MONS_BLINK_FROG
};
394 monster_type boss
[] = {MONS_PRINCE_RIBBIT
, MONS_SPINY_FROG
, MONS_BLINK_FROG
};
395 _zotdef_fill_from_list(frogs
, 0, power
); // full
396 _zotdef_choose_boss(boss
, power
);
397 _zotdef_danger_msg("Croaking noises echo off the walls!");
400 void bear_wave(int power
)
405 monster_type bears
[] = {MONS_BEAR
, MONS_GRIZZLY_BEAR
, MONS_POLAR_BEAR
,
407 monster_type boss
[] = {MONS_GRIZZLY_BEAR
, MONS_POLAR_BEAR
};
408 _zotdef_fill_from_list(bears
, 0, power
); // full
409 _zotdef_choose_boss(boss
, power
);
410 _zotdef_danger_msg("Gravelly voices can be heard calling for porridge!");
413 void wraith_wave(int power
)
418 monster_type wraiths
[] = {MONS_WRAITH
, MONS_SHADOW_WRAITH
, MONS_FREEZING_WRAITH
,
419 MONS_EIDOLON
, MONS_PHANTASMAL_WARRIOR
, MONS_SPECTRAL_THING
};
420 monster_type boss
[] = {MONS_EIDOLON
, MONS_PHANTASMAL_WARRIOR
, MONS_SPECTRAL_THING
};
421 _zotdef_fill_from_list(wraiths
, 0, power
); // full
422 _zotdef_choose_boss(boss
, power
);
423 _zotdef_danger_msg("The hair rises on the back of your neck!");
426 void giant_wave(int power
)
431 monster_type giants
[] = {MONS_ETTIN
, MONS_CYCLOPS
, MONS_TWO_HEADED_OGRE
,
432 MONS_OGRE
, MONS_TROLL
, MONS_MINOTAUR
, MONS_HILL_GIANT
,
433 MONS_STONE_GIANT
, MONS_FIRE_GIANT
, MONS_FROST_GIANT
, MONS_OGRE_MAGE
,
434 MONS_ROCK_TROLL
, MONS_IRON_TROLL
, MONS_DEEP_TROLL
, MONS_TITAN
};
435 monster_type boss
[] = {MONS_EROLCHA
, MONS_POLYPHEMUS
, MONS_ANTAEUS
,
436 MONS_SNORG
, MONS_PURGY
, MONS_STONE_GIANT
, MONS_FIRE_GIANT
,
437 MONS_FROST_GIANT
, MONS_TITAN
};
438 _zotdef_fill_from_list(giants
, 0, power
); // full
439 _zotdef_choose_boss(boss
, power
);
440 _zotdef_danger_msg("The stamp of enormous boots can be heard in the distance.");
443 void yak_wave(int power
)
448 monster_type yaks
[] = {MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
449 MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
450 MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
452 monster_type boss
[] = {MONS_POLYPHEMUS
, MONS_CYCLOPS
};
453 _zotdef_fill_from_list(yaks
, 0, power
); // full
454 _zotdef_choose_boss(boss
, power
);
455 _zotdef_danger_msg("Bleats and roars echo around!");
458 void insect_wave(int power
)
463 monster_type insects
[] = {MONS_GIANT_ANT
, MONS_KILLER_BEE
, MONS_YELLOW_WASP
,
464 MONS_GIANT_BEETLE
, MONS_QUEEN_BEE
, MONS_WOLF_SPIDER
, MONS_BUTTERFLY
,
465 MONS_BOULDER_BEETLE
, MONS_GIANT_MITE
, MONS_BUMBLEBEE
, MONS_REDBACK
,
466 MONS_GIANT_BLOWFLY
, MONS_RED_WASP
, MONS_SOLDIER_ANT
, MONS_QUEEN_ANT
,
467 MONS_GIANT_COCKROACH
, MONS_BORING_BEETLE
, MONS_TRAPDOOR_SPIDER
,
468 MONS_SCORPION
, MONS_GIANT_MOSQUITO
, MONS_GIANT_CENTIPEDE
};
469 monster_type boss
[] = {MONS_GIANT_BEETLE
, MONS_BOULDER_BEETLE
,
470 MONS_QUEEN_ANT
, MONS_BORING_BEETLE
, MONS_QUEEN_BEE
};
471 _zotdef_fill_from_list(insects
, 0, power
); // full
472 _zotdef_choose_boss(boss
, power
);
473 _zotdef_danger_msg("You hear an ominous buzzing.");
476 void pan_wave(int power
)
481 // The unique '&'s are a bit too strong at lower levels. Lom
482 // Lobon in particular is almost unkillable
483 monster_type boss
[] = {MONS_MNOLEG
, MONS_LOM_LOBON
, MONS_CEREBOV
,
484 MONS_GLOORX_VLOQ
, MONS_GERYON
, MONS_DISPATER
,
485 MONS_ASMODEUS
, MONS_ERESHKIGAL
, MONS_PANDEMONIUM_DEMON
};
486 monster_type weakboss
[] = {MONS_PANDEMONIUM_DEMON
, MONS_FIEND
,
487 MONS_PIT_FIEND
, MONS_ICE_FIEND
, MONS_BLUE_DEATH
};
489 for (int i
= 0; i
<= NSLOTS
; i
++)
491 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
492 while (env
.mons_alloc
[i
] == MONS_PROGRAM_BUG
)
494 monster_type mon_type
= static_cast<monster_type
>(random2(NUM_MONSTERS
));
495 monsterentry
*mentry
= get_monster_data(mon_type
);
496 int pow
= random2avg(power
, 2);
497 switch (mentry
->showchar
)
499 case '5': if (pow
> 4) continue; break;
500 case '4': if (pow
> 4) continue; break;
501 case '3': if (pow
> 6) continue; break;
502 case '2': if (pow
> 10) continue; break;
503 case '1': if (pow
> 12) continue; break;
506 env
.mons_alloc
[i
] = mon_type
;
509 // Weak bosses only at lower power
510 _zotdef_choose_boss((power
< 27 ? weakboss
: boss
), power
);
511 _zotdef_danger_msg("Hellish voices call for your blood. They are coming!");
514 void zotdef_set_special_wave(int power
)
516 void (*wave_fn
)(int) = NULL
;
519 while (wave_fn
== NULL
&& tries
++ < 10000)
524 case 0: wave_fn
= hydra_wave
; wpow
= 10; break;
525 case 1: wave_fn
= fire_wave
; wpow
= 12; break;
526 case 2: wave_fn
= cold_wave
; wpow
= 12; break;
527 case 3: wave_fn
= gnoll_wave
; wpow
= 4; break;
528 case 4: wave_fn
= rat_wave
; wpow
= 2; break;
529 case 5: wave_fn
= hound_wave
; wpow
= 2; break;
530 case 6: wave_fn
= abomination_wave
; wpow
= 12; break;
531 case 7: wave_fn
= ugly_wave
; wpow
= 14; break;
532 case 8: wave_fn
= golem_wave
; wpow
= 22; break;
533 case 9: wave_fn
= human_wave
; wpow
= 12; break;
534 case 10: wave_fn
= butterfly_wave
; wpow
= 1; break;
535 case 11: wave_fn
= beast_wave
; wpow
= 12; break;
536 case 12: wave_fn
= frog_wave
; wpow
= 4; break;
537 case 13: wave_fn
= bear_wave
; wpow
= 6; break;
538 case 14: wave_fn
= wraith_wave
; wpow
= 8; break;
539 case 15: wave_fn
= giant_wave
; wpow
= 16; break;
540 case 16: wave_fn
= yak_wave
; wpow
= 12; break; // lots of bands
541 case 17: wave_fn
= insect_wave
; wpow
= 4; break;
542 case 18: wave_fn
= pan_wave
; wpow
= 24; break;
543 // extra copies of fire and cold at higher power
544 case 19: wave_fn
= fire_wave
; wpow
= 20; break;
545 case 20: wave_fn
= cold_wave
; wpow
= 20; break;
547 // Algorithm: doesn't appear before 'wpow-5'. Max probability
548 // at 'wpow'. Doesn't appear after 'wpow*2+4'.
549 // OK: do we keep this one?
550 if (power
>= (wpow
- 5) && power
<= (wpow
* 2 + 4))
552 int diff
= power
- wpow
;
554 diff
/= 2; // weaker waves more common
555 if (one_chance_in(diff
* diff
))
556 break; // keep this one
567 for (int i
= 0; i
< 15 * FREQUENCY_OF_RUNES
; i
++)
569 you
.num_turns
+= CYCLE_LENGTH
;
574 monster_type
get_zotdef_monster(level_id
&place
, int power
)
576 monster_type mon_type
;
577 monster_type mon_type_ret
= MONS_PROGRAM_BUG
;
578 for (int i
= 0; i
<= 10000; ++i
)
585 mon_type
= static_cast<monster_type
>(random2(NUM_MONSTERS
));
587 rarity
= (place
.branch
== NUM_BRANCHES
) ? 30 : mons_rarity(mon_type
, place
);
589 while (rarity
== 0 && count
< 2000);
592 return (MONS_PROGRAM_BUG
);
594 // Calculate strength
595 monsterentry
*mentry
= get_monster_data(mon_type
);
598 if (mentry
== get_monster_data(MONS_PROGRAM_BUG
))
600 if (mons_is_unique(mon_type
))
601 continue; // No uniques here!
602 if (mons_class_is_stationary(mon_type
))
603 continue; // Must be able to move!
605 int strength
= mon_strength(mon_type
);
608 int lev_mons
= (place
.branch
== NUM_BRANCHES
)
609 ? ((strength
* 3) / 2)
610 : mons_level(mon_type
, place
);
612 // if >50, bail out - these are special flags
616 //int orig_lev_mons = lev_mons;
618 // adjust level based on strength, as weak monsters with high
619 // level pop up on some branches and we want to allow them
620 if (place
.branch
!= BRANCH_MAIN_DUNGEON
622 && lev_mons
> strength
* 3)
624 lev_mons
= (lev_mons
+ 2 * strength
) / 3;
627 // reduce power to 32 if that reduces diff
628 if (lev_mons
<= 32 && power
> 32)
630 int diff
= power
- lev_mons
;
632 diff
= diff
* 20 / power
; // reduce diff at high power
634 int chance
= rarity
- (diff
* diff
);
635 // Occasionally accept a weaker monster
636 if (diff
> 0 && chance
<= 0)
639 if (lev_mons
> 20) chance
= 3;
640 if (lev_mons
> 25) chance
= 5;
643 // Rarely accept monsters too far outside the power range
644 if ((diff
<- 5 || diff
> 5) && !one_chance_in(3))
647 // Less OOD allowed on early levels
648 if (diff
< std::min(-3,-power
))
651 const char *bn
= "RANDOM";
652 if (place
.branch
!= NUM_BRANCHES
)
653 bn
= branches
[place
.branch
].shortname
;
655 if (random2avg(100, 2) <= chance
)
657 dprf("ZOTDEF %d %s chose monster %s rarity %d power %d strength %d "
658 "level %d chance %d", i
, bn
,mentry
->name
, rarity
, power
,
659 strength
, lev_mons
, chance
);
660 mon_type_ret
= mon_type
;
665 return (MONS_PROGRAM_BUG
);
671 void zotdef_set_random_branch_wave(int power
)
673 //mprf("RANDOM WAVE");
674 for (int i
= 0; i
< NSLOTS
; i
++)
676 level_id
l(zotdef_random_branch(), -1);
677 env
.mons_alloc
[i
] = get_zotdef_monster(l
, _fuzz_mons_level(power
));
679 level_id
l(zotdef_random_branch(), -1);
680 env
.mons_alloc
[BOSS_SLOT
] = get_zotdef_monster(l
,
681 power
+ BOSS_MONSTER_EXTRA_POWER
);
684 void zotdef_set_branch_wave(branch_type b
, int power
)
687 dprf("BRANCH WAVE: BRANCH %s",
688 (b
== NUM_BRANCHES
) ? "RANDOM" : branches
[b
].shortname
);
689 for (int i
= 0; i
< NSLOTS
; i
++)
690 env
.mons_alloc
[i
] = get_zotdef_monster(l
, _fuzz_mons_level(power
));
691 env
.mons_alloc
[BOSS_SLOT
] = get_zotdef_monster(l
,
692 power
+ BOSS_MONSTER_EXTRA_POWER
);
695 void zotdef_set_boss_unique()
697 for (int tries
= 0; tries
< 100; tries
++)
699 int level
= random2avg(you
.num_turns
/ CYCLE_LENGTH
, 2) + 1;
700 monster_type which_unique
= _pick_unique(level
);
702 // Sometimes, we just quit if a unique is already placed.
703 if (which_unique
== MONS_PROGRAM_BUG
704 || you
.unique_creatures
[which_unique
] && one_chance_in(5))
709 env
.mons_alloc
[BOSS_SLOT
] = which_unique
;
714 // Set the env.mons_alloc data for this wave. Note that
715 // mons_alloc[BOSS_SLOT] is the boss.
717 // A game lasts for 15 runes, each rune 1400 turns apart
718 // (assuming FREQUENCY_OF_RUNES=7, CYCLE_LENGTH=200). That's
719 // a total of 105 waves. Set probabilities accordingly.
720 void zotdef_set_wave()
722 // power ramps up from 1 to 35 over the course of the game.
723 int power
= (you
.num_turns
+ CYCLE_LENGTH
* 2) / (CYCLE_LENGTH
* 3);
725 // Early waves are all DUNGEON
726 if (you
.num_turns
< CYCLE_LENGTH
* 4)
728 zotdef_set_branch_wave(BRANCH_MAIN_DUNGEON
, power
);
736 zotdef_set_branch_wave(BRANCH_MAIN_DUNGEON
, power
);
741 branch_type b
= zotdef_random_branch();
742 // HoB branch waves v. rare before 10K turns
743 if (b
== BRANCH_HALL_OF_BLADES
&& you
.num_turns
/ CYCLE_LENGTH
< 50)
744 b
= zotdef_random_branch();
745 zotdef_set_branch_wave(b
, power
);
748 // A random mixture of monsters from across the branches
750 zotdef_set_random_branch_wave(power
);
754 // special waves have their own boss choices. Note that flavour
755 // messages can be emitted by each individual wave type
756 if (one_chance_in(8))
757 zotdef_set_special_wave(power
);
760 // Truly random wave, (crappily) signalled by passing branch=NUM_BRANCHES
761 if (power
> 8 && one_chance_in(20))
763 _zotdef_danger_msg("The air ripples, and you hear distant laughter!");
764 zotdef_set_branch_wave(NUM_BRANCHES
, power
);
767 // overwrite the previously-set boss with a random unique?
768 if (one_chance_in(3))
769 zotdef_set_boss_unique();
773 for (int i = 0; i < 20; i++)
775 monsterentry *mentry = get_monster_data(env.mons_alloc[i]);
776 mprf("NEW WAVE: monster %d is %s",i,mentry->name);
781 int zotdef_spawn(bool boss
)
783 monster_type mt
= env
.mons_alloc
[random2(NSLOTS
)];
786 mt
= env
.mons_alloc
[BOSS_SLOT
];
788 if (mons_is_unique(mt
) && you
.unique_creatures
[mt
])
789 mt
= env
.mons_alloc
[0]; // grab slot 0 as crap alternative
791 if (mt
== MONS_PROGRAM_BUG
)
794 // Generate a monster of the appropriate branch and strength
795 mgen_data
mg(mt
, BEH_SEEK
, NULL
, 0, 0, coord_def(), MHITYOU
);
796 mg
.proximity
= PROX_NEAR_STAIRS
;
797 mg
.flags
|= MG_PERMIT_BANDS
;
799 int mid
= mons_place(mg
);
801 // Boss monsters which aren't uniques are named, and beefed a bit further
802 if (mid
!= -1 && boss
&& !mons_is_unique(mt
))
804 // Use the proper name function: if that fails, fall back
805 // to the randart name generator
806 if (!menv
[mid
].is_named()) // Don't rename uniques!
808 if (!give_monster_proper_name(&menv
[mid
], false))
809 menv
[mid
].mname
= make_name(random_int(), false);
812 menv
[mid
].hit_points
= (menv
[mid
].hit_points
* 3) / 2;
813 menv
[mid
].max_hit_points
= menv
[mid
].hit_points
;
819 rune_type
get_rune(int runenumber
)
830 return RUNE_TARTARUS
;
832 return RUNE_SLIME_PITS
;
836 return RUNE_SNAKE_PIT
;
848 return RUNE_LOM_LOBON
;
852 return RUNE_GLOORX_VLOQ
;
858 // Dowan is automatically placed together with Duvessa.
859 static monster_type
_choose_unique_by_depth(int step
)
864 case 0: // depth <= 3
865 ret
= random_choose(MONS_TERENCE
, MONS_JESSICA
, MONS_IJYB
,
868 case 1: // depth <= 7
869 ret
= random_choose(MONS_IJYB
, MONS_SIGMUND
, MONS_BLORK_THE_ORC
,
870 MONS_EDMUND
, MONS_PRINCE_RIBBIT
, MONS_PURGY
,
871 MONS_MENKAURE
, MONS_DUVESSA
, MONS_PIKEL
, -1);
873 case 2: // depth <= 9
874 ret
= random_choose(MONS_BLORK_THE_ORC
, MONS_EDMUND
, MONS_PSYCHE
, MONS_JOSEPH
,
875 MONS_EROLCHA
, MONS_PRINCE_RIBBIT
, MONS_GRUM
,
876 MONS_GASTRONOK
, MONS_GRINDER
, MONS_MAURICE
,
879 case 3: // depth <= 13
880 ret
= random_choose(MONS_PSYCHE
, MONS_EROLCHA
, MONS_DONALD
, MONS_URUG
,
881 MONS_EUSTACHIO
, MONS_SONJA
, MONS_GRUM
, MONS_NIKOLA
,
882 MONS_ERICA
, MONS_JOSEPHINE
, MONS_JOZEF
,
883 MONS_HAROLD
, MONS_GASTRONOK
, MONS_ILSUIW
,
886 case 4: // depth <= 16
887 ret
= random_choose(MONS_URUG
, MONS_EUSTACHIO
, MONS_SONJA
,
888 MONS_SNORG
, MONS_ERICA
, MONS_JOSEPHINE
, MONS_HAROLD
,
889 MONS_ROXANNE
, MONS_RUPERT
, MONS_JOZEF
, MONS_NIKOLA
,
890 MONS_AZRAEL
, MONS_NESSOS
, MONS_AGNES
, MONS_AIZUL
,
891 MONS_MAUD
, MONS_LOUISE
, MONS_NERGALLE
, MONS_KIRKE
, -1);
893 case 5: // depth <= 19
894 ret
= random_choose(MONS_SNORG
, MONS_LOUISE
, MONS_FRANCES
, MONS_KHUFU
,
895 MONS_RUPERT
, MONS_NORRIS
, MONS_AGNES
,
896 MONS_AZRAEL
, MONS_NESSOS
, MONS_NERGALLE
,
897 MONS_ROXANNE
, MONS_SAINT_ROKA
, MONS_KIRKE
,
900 case 6: // depth > 19
902 ret
= random_choose(MONS_FRANCES
, MONS_MARA
, MONS_WIGLAF
, MONS_MENNAS
,
903 MONS_XTAHUA
, MONS_NORRIS
, MONS_FREDERICK
, MONS_TIAMAT
,
904 MONS_MARGERY
, MONS_BORIS
, MONS_SAINT_ROKA
, -1);
907 return static_cast<monster_type
>(ret
);
910 static monster_type
_pick_unique(int level
)
912 // Pick generic unique depending on depth.
914 ((level
<= 3) ? _choose_unique_by_depth(0) :
915 (level
<= 7) ? _choose_unique_by_depth(1) :
916 (level
<= 9) ? _choose_unique_by_depth(2) :
917 (level
<= 13) ? _choose_unique_by_depth(3) :
918 (level
<= 16) ? _choose_unique_by_depth(4) :
919 (level
<= 19) ? _choose_unique_by_depth(5) :
920 _choose_unique_by_depth(6));
922 return static_cast<monster_type
>(which_unique
);
925 // Ask for a location and place a trap there. Returns true
927 bool create_trap(trap_type spec_type
)
930 direction_chooser_args args
;
931 args
.restricts
= DIR_TARGET
;
932 args
.needs_path
= false;
933 args
.may_target_monster
= false;
934 args
.top_prompt
= "Make ";
935 args
.top_prompt
+= trap_name(spec_type
);
936 args
.top_prompt
+= " trap where?";
937 direction(abild
, args
);
938 const dungeon_feature_type grid
= grd(abild
.target
);
945 // only try to create on floor squares
946 if (grid
>= DNGN_FLOOR_MIN
&& grid
<= DNGN_FLOOR_MAX
)
947 return place_specific_trap(abild
.target
, spec_type
);
950 mpr("You can't create a trap there!");
955 bool create_zotdef_ally(monster_type mtyp
, const char *successmsg
)
958 std::string msg
= "Make ";
959 msg
+= get_monster_data(mtyp
)->name
;
962 direction_chooser_args args
;
963 args
.restricts
= DIR_TARGET
;
964 args
.needs_path
= false;
965 args
.may_target_monster
= false;
966 args
.top_prompt
= msg
;
967 direction(abild
, args
);
975 if (mons_place(mgen_data(mtyp
, BEH_FRIENDLY
, &you
, 0, 0, abild
.target
,
976 you
.pet_target
)) == -1)
978 mpr("You can't create it there!");
985 void zotdef_bosses_check()
987 if ((you
.num_turns
+ 1) % CYCLE_LENGTH
== 0)
989 int mon
= zotdef_spawn(true); // boss monster=true
993 const char *msg
= "You sense that a powerful threat has arrived.";
994 if (!(((you
.num_turns
+ 1) / CYCLE_LENGTH
) % FREQUENCY_OF_RUNES
))
996 int which_rune
= get_rune(((you
.num_turns
+ 1) / CYCLE_LENGTH
)
997 / FREQUENCY_OF_RUNES
);
998 int ip
= items(1, OBJ_MISCELLANY
, MISC_RUNE_OF_ZOT
, true,
999 which_rune
, which_rune
);
1000 int *const item_made
= &ip
;
1001 if (*item_made
!= NON_ITEM
&& *item_made
!= -1)
1003 move_item_to_grid(item_made
, menv
[mon
].pos());
1004 msg
= "You feel a sense of great excitement!";
1007 _zotdef_danger_msg(msg
);
1011 if ((you
.num_turns
+ 1) % CYCLE_LENGTH
== CYCLE_INTERVAL
)
1013 // Set the next wave