3 * Summary: Zot Def specific functions
4 * Written by: Mark Mackey
11 #include "dungeon.h" // for Zotdef unique placement
16 #include "items.h" // // for find_floor_item
17 #include "itemname.h" // // for make_name
20 #include "mgen_data.h"
21 #include "mon-stuff.h"
22 #include "mon-place.h"
34 // Size of the mons_alloc array (or at least the bit of
36 #define NSLOTS (MAX_MONS_ALLOC - 1)
37 #define BOSS_SLOT NSLOTS
38 #define END static_cast<monster_type>(-1)
40 static monster_type
_pick_unique(int level
);
42 static int _fuzz_mons_level(int level
)
44 if (level
> 1 && one_chance_in(7))
46 const int fuzz
= random2avg(9, 2);
47 return (fuzz
> 4 ? level
+ fuzz
- 4 : level
);
52 // Choose a random branch. Which branches may be chosen is a function of
54 static branch_type
_zotdef_random_branch()
56 int wavenum
= you
.num_turns
/ CYCLE_LENGTH
;
60 branch_type pb
= static_cast<branch_type
>(random2(NUM_BRANCHES
));
64 case BRANCH_MAIN_DUNGEON
:
66 // reduce freq at high levels
71 case BRANCH_SNAKE_PIT
:
73 // reduce freq at high levels
74 if (wavenum
> 40 && !coinflip())
79 case BRANCH_ECUMENICAL_TEMPLE
:
81 case BRANCH_VESTIBULE_OF_HELL
:
83 break; // vaults/vestibule same as dungeon
85 case BRANCH_ORCISH_MINES
:
86 ok
= wavenum
< 30; // <6K turns only
88 case BRANCH_ELVEN_HALLS
:
89 ok
= wavenum
> 10 && wavenum
< 60; // 2.2-12K turns
92 ok
= wavenum
< 40; // <8K turns only
95 ok
= wavenum
> 12 && wavenum
< 40; // 2.6-8K turns
98 ok
= wavenum
> 12 && wavenum
< 60; // 2.6-12K turns
101 ok
= wavenum
> 13; // 2.8K-
103 case BRANCH_SLIME_PITS
:
104 ok
= wavenum
> 20 && coinflip(); // 4K-
105 break; // >4K turns only
107 ok
= wavenum
> 12 && wavenum
< 35; // 2.6-7.5K
109 case BRANCH_HALL_OF_BLADES
:
110 ok
= wavenum
> 30; // 6K-
113 ok
= wavenum
> 30 && coinflip(); // 6K-
115 case BRANCH_DIS
: // 8K-
117 case BRANCH_TARTARUS
:
119 ok
= wavenum
> 40 && one_chance_in(3);
121 case BRANCH_HALL_OF_ZOT
: // 10K-
126 return (one_chance_in(4) ? BRANCH_MAIN_DUNGEON
: pb
);
127 // strong bias to main dungeon
131 static int _mon_strength(monster_type mon_type
)
133 monsterentry
*mentry
= get_monster_data(mon_type
);
136 int strength
= (mentry
->hpdice
[0] * mentry
->exp_mod
) / 10;
137 // Fix for skeletons and zombies
140 case MONS_SKELETON_SMALL
:
141 case MONS_ZOMBIE_SMALL
:
144 case MONS_SKELETON_LARGE
:
145 case MONS_ZOMBIE_LARGE
:
148 case MONS_PANDEMONIUM_DEMON
: // base init has 4HD (!)
157 // Fill the wave list with selections from a supplied array.
158 // Each array contains a monster if random2(power)>chance. Power
159 // is also compared to the strength of each critter to allow later
160 // waves to be stronger than earlier ones.
162 // Note that this fills in the boss slot as well.
163 static void _zotdef_fill_from_list(monster_type mlist
[], int chance
, int power
)
166 while (mlist
[ls
] != END
)
170 for (int i
= 0; i
<= NSLOTS
; i
++)
172 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
173 if (i
< NSLOTS
&& random2(power
) < chance
)
174 continue; // no monster this entry
175 while (env
.mons_alloc
[i
] == MONS_PROGRAM_BUG
)
177 monster_type mon_type
= mlist
[random2(ls
)];
178 if (random2((power
* 3) / 2) > _mon_strength(mon_type
))
179 continue; // bias away from weaker critters
180 if (random2((power
* 3) / 2) > _mon_strength(mon_type
))
181 env
.mons_alloc
[i
] = mon_type
;
182 if (one_chance_in(100))
183 env
.mons_alloc
[i
] = mon_type
; // occasional random pick
188 // Choose a boss from the supplied list. If a unique is chosen and has
189 // already been seen we try again. After a few tries we give up and
190 // leave the existing entry there.
191 static void _zotdef_choose_boss(monster_type mlist
[], int power
)
194 while (mlist
[ls
] != END
)
199 while (tries
++ < 100)
201 monster_type mon_type
= mlist
[random2(ls
)];
202 if (mons_is_unique(mon_type
)
203 && you
.unique_creatures
[mon_type
])
207 if (random2avg(power
* 3, 2) < _mon_strength(mon_type
))
211 env
.mons_alloc
[BOSS_SLOT
] = mon_type
;
216 static void _zotdef_danger_msg(const char *msg
)
218 mpr(msg
, MSGCH_DANGER
);
222 static void wave_name(const char *n
)
224 you
.zotdef_wave_name
= n
;
228 static void _hydra_wave(int power
)
230 wave_name("HYDRA WAVE");
231 monster_type hydras
[] = {MONS_HYDRA
, END
};
232 monster_type boss
[] = {MONS_LERNAEAN_HYDRA
, END
};
233 _zotdef_fill_from_list(hydras
, 4, power
); // 66% full at power 12
234 _zotdef_choose_boss(boss
, power
* 2);
235 _zotdef_danger_msg("You hear a distant many-voiced hissing!");
238 static void _fire_wave(int power
)
240 wave_name("FIRE WAVE");
241 monster_type firemons
[] = {MONS_FIRE_ELEMENTAL
, MONS_FIRE_DRAKE
, MONS_IMP
,
242 MONS_DRAGON
, MONS_FIRE_VORTEX
,MONS_FIRE_GIANT
, MONS_HELLION
,
243 MONS_MOLTEN_GARGOYLE
, MONS_SALAMANDER
, MONS_SUN_DEMON
,
244 MONS_RED_DRACONIAN
, MONS_MOTTLED_DRACONIAN
, MONS_DRACONIAN_SCORCHER
,
245 MONS_FLAMING_CORPSE
, MONS_MOTTLED_DRAGON
, MONS_EFREET
,
246 MONS_HELL_KNIGHT
, MONS_FIEND
, MONS_BALRUG
, MONS_HELL_HOUND
,
248 monster_type boss
[] = {MONS_AZRAEL
, MONS_XTAHUA
, MONS_SERPENT_OF_HELL
,
249 MONS_MARGERY
, MONS_FIEND
, MONS_BALRUG
, MONS_FIRE_GIANT
, END
};
250 _zotdef_fill_from_list(firemons
, 0, power
);
251 _zotdef_choose_boss(boss
, power
);
252 _zotdef_danger_msg("You hear roaring flames in the distance!");
255 static void _cold_wave(int power
)
257 wave_name("COLD WAVE");
258 monster_type coldmons
[] = {MONS_ICE_BEAST
, MONS_AZURE_JELLY
,
259 MONS_FREEZING_WRAITH
, MONS_WHITE_IMP
, MONS_ICE_DEVIL
, MONS_ICE_FIEND
,
260 MONS_WHITE_DRACONIAN
, MONS_SIMULACRUM_SMALL
, MONS_SIMULACRUM_LARGE
,
261 MONS_FROST_GIANT
, MONS_POLAR_BEAR
, MONS_BLUE_DEVIL
, END
};
262 monster_type boss
[] = {MONS_ANTAEUS
, MONS_ICE_FIEND
, MONS_AZURE_JELLY
,
263 MONS_WHITE_DRACONIAN
, END
};
264 _zotdef_fill_from_list(coldmons
, 4, power
);
265 _zotdef_choose_boss(boss
, power
);
266 _zotdef_danger_msg("A deadly chill settles over the dungeon!");
269 static void _gnoll_wave(int power
)
271 wave_name("GNOLL WAVE");
272 monster_type gnolls
[] = {MONS_GNOLL
, MONS_GNOLL
, MONS_GNOLL
,
273 MONS_GNOLL
, MONS_GNOLL
, MONS_GNOLL
, MONS_TROLL
, END
};
274 monster_type boss
[] = {MONS_GRUM
, MONS_TROLL
, END
};
275 _zotdef_fill_from_list(gnolls
, 0, power
); // full
276 _zotdef_choose_boss(boss
, power
);
277 _zotdef_danger_msg("Harsh voices can be heard, coming closer!");
280 static void _rat_wave(int power
)
282 wave_name("RAT WAVE");
283 monster_type rats
[] = {MONS_RAT
, MONS_GREEN_RAT
, MONS_GREY_RAT
,
284 MONS_ORANGE_RAT
, END
};
285 monster_type boss
[] = {MONS_ORANGE_RAT
, END
};
286 _zotdef_fill_from_list(rats
, 0, power
); // full power
287 _zotdef_choose_boss(boss
, power
);
288 _zotdef_danger_msg("You hear distant squeaking!");
291 static void _hound_wave(int power
)
293 wave_name("HOUND WAVE");
294 monster_type hounds
[] = {MONS_JACKAL
, MONS_HOUND
, MONS_WARG
,
295 MONS_WOLF
, MONS_WAR_DOG
, END
};
296 monster_type boss
[] = {MONS_HELL_HOUND
, END
};
297 _zotdef_fill_from_list(hounds
, 0, power
); // full
298 _zotdef_choose_boss(boss
, power
);
299 _zotdef_danger_msg("Horrible howls echo around!");
302 static void _abomination_wave(int power
)
304 wave_name("ABOMINATION WAVE");
305 monster_type aboms
[] = {MONS_ABOMINATION_SMALL
, MONS_ABOMINATION_LARGE
, END
};
306 monster_type boss
[] = {MONS_TENTACLED_MONSTROSITY
, END
};
307 _zotdef_fill_from_list(aboms
, 0, power
); // full
308 _zotdef_choose_boss(boss
, power
);
309 _zotdef_danger_msg("A dreadful chittering sound fills the air. It's coming closer...");
312 static void _ugly_wave(int power
)
314 wave_name("UGLY WAVE");
315 monster_type ugly
[] = {MONS_UGLY_THING
, MONS_UGLY_THING
, MONS_UGLY_THING
,
316 MONS_VERY_UGLY_THING
, END
};
317 monster_type boss
[] = {MONS_VERY_UGLY_THING
, END
};
318 _zotdef_fill_from_list(ugly
, 6, power
); // reduced size
319 _zotdef_choose_boss(boss
, power
);
320 _zotdef_danger_msg("You feel uneasy.");
323 static void _golem_wave(int power
)
325 wave_name("GOLEM WAVE");
326 monster_type golems
[] = {MONS_CLAY_GOLEM
, MONS_WOOD_GOLEM
, MONS_STONE_GOLEM
,
327 MONS_IRON_GOLEM
, MONS_CRYSTAL_GOLEM
, MONS_TOENAIL_GOLEM
, END
};
328 monster_type boss
[] = {MONS_ELECTRIC_GOLEM
, END
};
329 _zotdef_fill_from_list(golems
, 6, power
* 2 / 3); // reduced size
330 _zotdef_choose_boss(boss
, power
);
331 _zotdef_danger_msg("Booming thuds herald the arrival of something large...");
334 static void _human_wave(int power
)
336 wave_name("HUMAN WAVE");
337 monster_type humans
[] = {MONS_HUMAN
, MONS_HELL_KNIGHT
, MONS_NECROMANCER
,
338 MONS_WIZARD
, MONS_VAULT_GUARD
, MONS_KILLER_KLOWN
, END
};
339 monster_type boss
[] = {MONS_HELL_KNIGHT
, MONS_KILLER_KLOWN
,
340 MONS_VAULT_GUARD
, MONS_JOSEPH
, MONS_ERICA
, MONS_JOSEPHINE
,
341 MONS_HAROLD
, MONS_JOZEF
, MONS_AGNES
,
342 MONS_MAUD
, MONS_LOUISE
, MONS_FRANCES
,
343 MONS_RUPERT
, MONS_KIRKE
,
344 MONS_NORRIS
, MONS_FREDERICK
, MONS_MARGERY
, MONS_EUSTACHIO
,
346 _zotdef_fill_from_list(humans
, 4, power
); // reduced size due to banding
348 // Get too many hell knights with the defaults, due to their large band
350 for (int i
= 0; i
< NSLOTS
; i
++)
352 if (env
.mons_alloc
[i
] == MONS_HELL_KNIGHT
&& random2(power
) < 8)
353 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
356 _zotdef_choose_boss(boss
, power
);
357 _zotdef_danger_msg("War cries fill the air!");
360 static void _butterfly_wave(int power
)
362 wave_name("BUTTERFLY WAVE");
363 monster_type bfs
[] = {MONS_BUTTERFLY
, END
};
364 _zotdef_fill_from_list(bfs
, 0, power
); // full
365 _zotdef_danger_msg("You feel a sudden sense of peace!");
368 static void _beast_wave(int power
)
370 wave_name("BEAST WAVE");
371 monster_type bst
[] = {MONS_BEAST
, END
};
372 _zotdef_fill_from_list(bst
, 0, power
); // full
373 _zotdef_danger_msg("A hideous howling noise can be heard in the distance!");
376 static void _frog_wave(int power
)
378 wave_name("FROG WAVE");
379 monster_type frogs
[] = {MONS_GIANT_FROG
, MONS_GIANT_TOAD
,
380 MONS_SPINY_FROG
, MONS_BLINK_FROG
, END
};
381 monster_type boss
[] = {MONS_PRINCE_RIBBIT
, MONS_SPINY_FROG
, MONS_BLINK_FROG
, END
};
382 _zotdef_fill_from_list(frogs
, 0, power
); // full
383 _zotdef_choose_boss(boss
, power
);
384 _zotdef_danger_msg("Croaking noises echo off the walls!");
387 static void _bear_wave(int power
)
389 wave_name("BEAR WAVE");
390 monster_type bears
[] = {MONS_BEAR
, MONS_GRIZZLY_BEAR
, MONS_POLAR_BEAR
,
391 MONS_BLACK_BEAR
, END
};
392 monster_type boss
[] = {MONS_GRIZZLY_BEAR
, MONS_POLAR_BEAR
, END
};
393 _zotdef_fill_from_list(bears
, 0, power
); // full
394 _zotdef_choose_boss(boss
, power
);
395 _zotdef_danger_msg("Gravelly voices can be heard calling for porridge!");
398 static void _wraith_wave(int power
)
400 wave_name("WRAITH WAVE");
401 monster_type wraiths
[] = {MONS_WRAITH
, MONS_SHADOW_WRAITH
, MONS_FREEZING_WRAITH
,
402 MONS_EIDOLON
, MONS_PHANTASMAL_WARRIOR
, MONS_SPECTRAL_THING
, END
};
403 monster_type boss
[] = {MONS_EIDOLON
, MONS_PHANTASMAL_WARRIOR
,
404 MONS_SPECTRAL_THING
, END
};
405 _zotdef_fill_from_list(wraiths
, 0, power
); // full
406 _zotdef_choose_boss(boss
, power
);
407 _zotdef_danger_msg("The hair rises on the back of your neck!");
410 static void _giant_wave(int power
)
412 wave_name("GIANT WAVE");
413 monster_type giants
[] = {MONS_ETTIN
, MONS_CYCLOPS
, MONS_TWO_HEADED_OGRE
,
414 MONS_OGRE
, MONS_TROLL
, MONS_MINOTAUR
, MONS_HILL_GIANT
,
415 MONS_STONE_GIANT
, MONS_FIRE_GIANT
, MONS_FROST_GIANT
, MONS_OGRE_MAGE
,
416 MONS_ROCK_TROLL
, MONS_IRON_TROLL
, MONS_DEEP_TROLL
, MONS_TITAN
, END
};
417 monster_type boss
[] = {MONS_EROLCHA
, MONS_POLYPHEMUS
, MONS_ANTAEUS
,
418 MONS_SNORG
, MONS_PURGY
, MONS_STONE_GIANT
, MONS_FIRE_GIANT
,
419 MONS_FROST_GIANT
, MONS_TITAN
, END
};
420 _zotdef_fill_from_list(giants
, 0, power
); // full
421 _zotdef_choose_boss(boss
, power
);
422 _zotdef_danger_msg("The stamp of enormous boots can be heard in the distance.");
425 static void _yak_wave(int power
)
427 wave_name("YAK WAVE");
428 monster_type yaks
[] = {MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
429 MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
430 MONS_SHEEP
, MONS_YAK
, MONS_DEATH_YAK
,
432 monster_type boss
[] = {MONS_POLYPHEMUS
, MONS_CYCLOPS
, END
};
433 _zotdef_fill_from_list(yaks
, 0, power
); // full
434 _zotdef_choose_boss(boss
, power
);
435 _zotdef_danger_msg("Bleats and roars echo around!");
438 static void _insect_wave(int power
)
440 wave_name("INSECT WAVE");
441 monster_type insects
[] = {MONS_WORKER_ANT
, MONS_KILLER_BEE
, MONS_YELLOW_WASP
,
442 MONS_GOLIATH_BEETLE
, MONS_QUEEN_BEE
, MONS_WOLF_SPIDER
, MONS_BUTTERFLY
,
443 MONS_BOULDER_BEETLE
, MONS_GIANT_MITE
, MONS_BUMBLEBEE
, MONS_REDBACK
,
444 MONS_VAMPIRE_MOSQUITO
, MONS_RED_WASP
, MONS_SOLDIER_ANT
, MONS_QUEEN_ANT
,
445 MONS_GIANT_COCKROACH
, MONS_BORING_BEETLE
, MONS_TRAPDOOR_SPIDER
,
446 MONS_SCORPION
, MONS_GIANT_CENTIPEDE
, END
};
447 monster_type boss
[] = {MONS_GOLIATH_BEETLE
, MONS_BOULDER_BEETLE
,
448 MONS_QUEEN_ANT
, MONS_BORING_BEETLE
, MONS_QUEEN_BEE
, END
};
449 _zotdef_fill_from_list(insects
, 0, power
); // full
450 _zotdef_choose_boss(boss
, power
);
451 _zotdef_danger_msg("You hear an ominous buzzing.");
454 static void _pan_wave(int power
)
456 wave_name("PAN WAVE");
457 // The unique '&'s are a bit too strong at lower levels. Lom
458 // Lobon in particular is almost unkillable
459 monster_type boss
[] = {MONS_MNOLEG
, MONS_LOM_LOBON
, MONS_CEREBOV
,
460 MONS_GLOORX_VLOQ
, MONS_GERYON
, MONS_DISPATER
,
461 MONS_ASMODEUS
, MONS_ERESHKIGAL
, MONS_PANDEMONIUM_DEMON
, END
};
462 monster_type weakboss
[] = {MONS_PANDEMONIUM_DEMON
, MONS_FIEND
,
463 MONS_PIT_FIEND
, MONS_ICE_FIEND
, MONS_BLUE_DEATH
, END
};
465 for (int i
= 0; i
<= NSLOTS
; i
++)
467 env
.mons_alloc
[i
] = MONS_PROGRAM_BUG
;
468 while (env
.mons_alloc
[i
] == MONS_PROGRAM_BUG
)
470 monster_type mon_type
= static_cast<monster_type
>(random2(NUM_MONSTERS
));
471 monsterentry
*mentry
= get_monster_data(mon_type
);
472 int pow
= random2avg(power
, 2);
473 switch (mentry
->showchar
)
475 case '5': if (pow
> 4) continue; break;
476 case '4': if (pow
> 4) continue; break;
477 case '3': if (pow
> 6) continue; break;
478 case '2': if (pow
> 10) continue; break;
479 case '1': if (pow
> 12) continue; break;
482 env
.mons_alloc
[i
] = mon_type
;
485 // Weak bosses only at lower power
486 _zotdef_choose_boss((power
< 27 ? weakboss
: boss
), power
);
487 _zotdef_danger_msg("Hellish voices call for your blood. They are coming!");
490 static void _zotdef_set_special_wave(int power
)
492 void (*wave_fn
)(int) = NULL
;
495 while (wave_fn
== NULL
&& tries
++ < 10000)
500 case 0: wave_fn
= _hydra_wave
; wpow
= 10; break;
501 case 1: wave_fn
= _fire_wave
; wpow
= 12; break;
502 case 2: wave_fn
= _cold_wave
; wpow
= 12; break;
503 case 3: wave_fn
= _gnoll_wave
; wpow
= 4; break;
504 case 4: wave_fn
= _rat_wave
; wpow
= 2; break;
505 case 5: wave_fn
= _hound_wave
; wpow
= 2; break;
506 case 6: wave_fn
= _abomination_wave
; wpow
= 12; break;
507 case 7: wave_fn
= _ugly_wave
; wpow
= 14; break;
508 case 8: wave_fn
= _golem_wave
; wpow
= 22; break;
509 case 9: wave_fn
= _human_wave
; wpow
= 12; break;
510 case 10: wave_fn
= _butterfly_wave
; wpow
= 1; break;
511 case 11: wave_fn
= _beast_wave
; wpow
= 12; break;
512 case 12: wave_fn
= _frog_wave
; wpow
= 4; break;
513 case 13: wave_fn
= _bear_wave
; wpow
= 6; break;
514 case 14: wave_fn
= _wraith_wave
; wpow
= 8; break;
515 case 15: wave_fn
= _giant_wave
; wpow
= 16; break;
516 case 16: wave_fn
= _yak_wave
; wpow
= 12; break; // lots of bands
517 case 17: wave_fn
= _insect_wave
; wpow
= 4; break;
518 case 18: wave_fn
= _pan_wave
; wpow
= 24; break;
519 // extra copies of fire and cold at higher power
520 case 19: wave_fn
= _fire_wave
; wpow
= 20; break;
521 case 20: wave_fn
= _cold_wave
; wpow
= 20; break;
523 // Algorithm: doesn't appear before 'wpow-5'. Max probability
524 // at 'wpow'. Doesn't appear after 'wpow*2+4'.
525 // OK: do we keep this one?
526 if (power
>= (wpow
- 5) && power
<= (wpow
* 2 + 4))
528 int diff
= power
- wpow
;
530 diff
/= 2; // weaker waves more common
531 if (one_chance_in(diff
* diff
))
532 break; // keep this one
543 // Test more than just 15 runes, the player may stay longer, and if
544 // for some reason a rune is lost, he will have to, and get extra
546 for (int i
= 0; i
< 30 * FREQUENCY_OF_RUNES
; i
++)
548 you
.num_turns
+= CYCLE_LENGTH
;
550 // debuglog("%i: %s\n", i, zotdef_debug_wave_desc().c_str());
554 static monster_type
_get_zotdef_monster(level_id
&place
, int power
)
556 monster_type mon_type
;
557 monster_type mon_type_ret
= MONS_PROGRAM_BUG
;
558 for (int i
= 0; i
<= 10000; ++i
)
565 mon_type
= static_cast<monster_type
>(random2(NUM_MONSTERS
));
567 rarity
= (place
.branch
== NUM_BRANCHES
) ? 30 : mons_rarity(mon_type
, place
);
569 while (rarity
== 0 && count
< 2000);
572 return (MONS_PROGRAM_BUG
);
574 // Calculate strength
575 monsterentry
*mentry
= get_monster_data(mon_type
);
578 if (mentry
== get_monster_data(MONS_PROGRAM_BUG
))
580 if (mons_class_flag(mon_type
, M_NO_POLY_TO
))
582 if (mons_class_flag(mon_type
, M_UNFINISHED
))
584 if (mons_is_unique(mon_type
))
585 continue; // No uniques here!
586 if (mons_class_is_stationary(mon_type
))
587 continue; // Must be able to move!
589 int strength
= _mon_strength(mon_type
);
592 int lev_mons
= (place
.branch
== NUM_BRANCHES
)
593 ? ((strength
* 3) / 2)
594 : mons_level(mon_type
, place
);
596 // if >50, bail out - these are special flags
600 //int orig_lev_mons = lev_mons;
602 // adjust level based on strength, as weak monsters with high
603 // level pop up on some branches and we want to allow them
604 if (place
.branch
!= BRANCH_MAIN_DUNGEON
606 && lev_mons
> strength
* 3)
608 lev_mons
= (lev_mons
+ 2 * strength
) / 3;
611 // reduce power to 32 if that reduces diff
612 if (lev_mons
<= 32 && power
> 32)
614 int diff
= power
- lev_mons
;
616 diff
= diff
* 20 / power
; // reduce diff at high power
618 int chance
= rarity
- (diff
* diff
);
619 // Occasionally accept a weaker monster
620 if (diff
> 0 && chance
<= 0)
623 if (lev_mons
> 20) chance
= 3;
624 if (lev_mons
> 25) chance
= 5;
627 // Rarely accept monsters too far outside the power range
628 if ((diff
<- 5 || diff
> 5) && !one_chance_in(3))
631 // Less OOD allowed on early levels
632 if (diff
< std::min(-3,-power
))
635 const char *bn
= "RANDOM";
636 if (place
.branch
!= NUM_BRANCHES
)
637 bn
= branches
[place
.branch
].shortname
;
639 if (random2avg(100, 2) <= chance
)
641 dprf("ZOTDEF %d %s chose monster %s rarity %d power %d strength %d "
642 "level %d chance %d", i
, bn
,mentry
->name
, rarity
, power
,
643 strength
, lev_mons
, chance
);
644 mon_type_ret
= mon_type
;
649 return (MONS_PROGRAM_BUG
);
655 static void _zotdef_set_random_branch_wave(int power
)
657 wave_name("RANDOM WAVE");
658 for (int i
= 0; i
< NSLOTS
; i
++)
660 level_id
l(_zotdef_random_branch(), -1);
661 env
.mons_alloc
[i
] = _get_zotdef_monster(l
, _fuzz_mons_level(power
));
663 level_id
l(_zotdef_random_branch(), -1);
664 env
.mons_alloc
[BOSS_SLOT
] = _get_zotdef_monster(l
,
665 power
+ BOSS_MONSTER_EXTRA_POWER
);
668 static void _zotdef_set_branch_wave(branch_type b
, int power
)
672 snprintf(buf
, sizeof(buf
), "BRANCH WAVE: BRANCH %s",
673 (b
== NUM_BRANCHES
) ? "RANDOM" : branches
[b
].shortname
);
675 for (int i
= 0; i
< NSLOTS
; i
++)
676 env
.mons_alloc
[i
] = _get_zotdef_monster(l
, _fuzz_mons_level(power
));
677 env
.mons_alloc
[BOSS_SLOT
] = _get_zotdef_monster(l
,
678 power
+ BOSS_MONSTER_EXTRA_POWER
);
681 static void _zotdef_set_boss_unique()
683 for (int tries
= 0; tries
< 100; tries
++)
685 int level
= random2avg(you
.num_turns
/ CYCLE_LENGTH
, 2) + 1;
686 monster_type which_unique
= _pick_unique(level
);
688 // Sometimes, we just quit if a unique is already placed.
689 if (which_unique
== MONS_PROGRAM_BUG
690 || you
.unique_creatures
[which_unique
] && one_chance_in(5))
695 env
.mons_alloc
[BOSS_SLOT
] = which_unique
;
700 // Set the env.mons_alloc data for this wave. Note that
701 // mons_alloc[BOSS_SLOT] is the boss.
703 // A game lasts for 15 runes, each rune 1400 turns apart
704 // (assuming FREQUENCY_OF_RUNES=7, CYCLE_LENGTH=200). That's
705 // a total of 105 waves. Set probabilities accordingly.
706 void zotdef_set_wave()
708 // power ramps up from 1 to 35 over the course of the game.
709 int power
= (you
.num_turns
+ CYCLE_LENGTH
* 2) / (CYCLE_LENGTH
* 3);
711 // Early waves are all DUNGEON
712 if (you
.num_turns
< CYCLE_LENGTH
* 4)
714 _zotdef_set_branch_wave(BRANCH_MAIN_DUNGEON
, power
);
722 _zotdef_set_branch_wave(BRANCH_MAIN_DUNGEON
, power
);
727 branch_type b
= _zotdef_random_branch();
728 // HoB branch waves v. rare before 10K turns
729 if (b
== BRANCH_HALL_OF_BLADES
&& you
.num_turns
/ CYCLE_LENGTH
< 50)
730 b
= _zotdef_random_branch();
731 _zotdef_set_branch_wave(b
, power
);
734 // A random mixture of monsters from across the branches
736 _zotdef_set_random_branch_wave(power
);
740 // special waves have their own boss choices. Note that flavour
741 // messages can be emitted by each individual wave type
742 if (one_chance_in(8))
743 _zotdef_set_special_wave(power
);
746 // Truly random wave, (crappily) signalled by passing branch=NUM_BRANCHES
747 if (power
> 8 && one_chance_in(20))
749 _zotdef_danger_msg("The air ripples, and you hear distant laughter!");
750 _zotdef_set_branch_wave(NUM_BRANCHES
, power
);
753 // overwrite the previously-set boss with a random unique?
754 if (one_chance_in(3))
755 _zotdef_set_boss_unique();
758 dprf("NEW WAVE: %s", zotdef_debug_wave_desc().c_str());
761 std::string
zotdef_debug_wave_desc()
763 std::string list
= you
.zotdef_wave_name
+ " [";
764 for (int i
= 0; i
<= NSLOTS
; i
++)
768 monsterentry
*mentry
= get_monster_data(env
.mons_alloc
[i
]);
769 if (!env
.mons_alloc
[i
])
772 list
+= mentry
->name
;
774 list
+= make_stringf("!!!INVALID (%d)!!!", env
.mons_alloc
[i
]);
779 int zotdef_spawn(bool boss
)
781 monster_type mt
= env
.mons_alloc
[random2(NSLOTS
)];
784 mt
= env
.mons_alloc
[BOSS_SLOT
];
786 if (mons_is_unique(mt
) && you
.unique_creatures
[mt
])
787 mt
= env
.mons_alloc
[0]; // grab slot 0 as crap alternative
789 if (mt
== MONS_PROGRAM_BUG
)
792 // Generate a monster of the appropriate branch and strength
793 mgen_data
mg(mt
, BEH_SEEK
, NULL
, 0, 0, coord_def(), MHITYOU
);
794 mg
.proximity
= PROX_NEAR_STAIRS
;
795 mg
.flags
|= MG_PERMIT_BANDS
;
797 int mid
= mons_place(mg
);
799 // Boss monsters which aren't uniques are named, and beefed a bit further
800 if (mid
!= -1 && boss
&& !mons_is_unique(mt
))
802 // Use the proper name function: if that fails, fall back
803 // to the randart name generator
804 if (!menv
[mid
].is_named()) // Don't rename uniques!
806 if (!give_monster_proper_name(&menv
[mid
], false))
807 menv
[mid
].mname
= make_name(random_int(), false);
810 menv
[mid
].hit_points
= (menv
[mid
].hit_points
* 3) / 2;
811 menv
[mid
].max_hit_points
= menv
[mid
].hit_points
;
817 static rune_type
_get_rune(int runenumber
)
828 return RUNE_TARTARUS
;
830 return RUNE_SLIME_PITS
;
834 return RUNE_SNAKE_PIT
;
846 return RUNE_LOM_LOBON
;
850 return RUNE_GLOORX_VLOQ
;
856 // Dowan is automatically placed together with Duvessa.
857 static monster_type
_choose_unique_by_depth(int step
)
862 case 0: // depth <= 3
863 ret
= random_choose(MONS_TERENCE
, MONS_JESSICA
, MONS_IJYB
,
866 case 1: // depth <= 7
867 ret
= random_choose(MONS_IJYB
, MONS_SIGMUND
, MONS_BLORK_THE_ORC
,
868 MONS_EDMUND
, MONS_PRINCE_RIBBIT
, MONS_PURGY
,
869 MONS_MENKAURE
, MONS_DUVESSA
, MONS_PIKEL
, -1);
871 case 2: // depth <= 9
872 ret
= random_choose(MONS_BLORK_THE_ORC
, MONS_EDMUND
, MONS_PSYCHE
, MONS_JOSEPH
,
873 MONS_EROLCHA
, MONS_PRINCE_RIBBIT
, MONS_GRUM
,
874 MONS_GASTRONOK
, MONS_GRINDER
, MONS_MAURICE
,
877 case 3: // depth <= 13
878 ret
= random_choose(MONS_PSYCHE
, MONS_EROLCHA
, MONS_DONALD
, MONS_URUG
,
879 MONS_EUSTACHIO
, MONS_SONJA
, MONS_GRUM
, MONS_NIKOLA
,
880 MONS_ERICA
, MONS_JOSEPHINE
, MONS_JOZEF
,
881 MONS_HAROLD
, MONS_GASTRONOK
, MONS_ILSUIW
,
884 case 4: // depth <= 16
885 ret
= random_choose(MONS_URUG
, MONS_EUSTACHIO
, MONS_SONJA
,
886 MONS_SNORG
, MONS_ERICA
, MONS_JOSEPHINE
, MONS_HAROLD
,
887 MONS_ROXANNE
, MONS_RUPERT
, MONS_JOZEF
, MONS_NIKOLA
,
888 MONS_AZRAEL
, MONS_NESSOS
, MONS_AGNES
, MONS_AIZUL
,
889 MONS_MAUD
, MONS_LOUISE
, MONS_NERGALLE
, MONS_KIRKE
, -1);
891 case 5: // depth <= 19
892 ret
= random_choose(MONS_SNORG
, MONS_LOUISE
, MONS_FRANCES
, MONS_KHUFU
,
893 MONS_RUPERT
, MONS_NORRIS
, MONS_AGNES
,
894 MONS_AZRAEL
, MONS_NESSOS
, MONS_NERGALLE
,
895 MONS_ROXANNE
, MONS_SAINT_ROKA
, MONS_KIRKE
,
898 case 6: // depth > 19
900 ret
= random_choose(MONS_FRANCES
, MONS_MARA
, MONS_WIGLAF
, MONS_MENNAS
,
901 MONS_XTAHUA
, MONS_NORRIS
, MONS_FREDERICK
, MONS_TIAMAT
,
902 MONS_MARGERY
, MONS_BORIS
, MONS_SAINT_ROKA
, -1);
905 return static_cast<monster_type
>(ret
);
908 static monster_type
_pick_unique(int level
)
910 // Pick generic unique depending on depth.
912 ((level
<= 3) ? _choose_unique_by_depth(0) :
913 (level
<= 7) ? _choose_unique_by_depth(1) :
914 (level
<= 9) ? _choose_unique_by_depth(2) :
915 (level
<= 13) ? _choose_unique_by_depth(3) :
916 (level
<= 16) ? _choose_unique_by_depth(4) :
917 (level
<= 19) ? _choose_unique_by_depth(5) :
918 _choose_unique_by_depth(6));
920 return static_cast<monster_type
>(which_unique
);
923 // Ask for a location and place a trap there. Returns true
925 bool create_trap(trap_type spec_type
)
928 direction_chooser_args args
;
929 args
.restricts
= DIR_TARGET
;
930 args
.needs_path
= false;
931 args
.may_target_monster
= false;
932 args
.top_prompt
= "Make ";
933 args
.top_prompt
+= trap_name(spec_type
);
934 args
.top_prompt
+= " trap where?";
935 direction(abild
, args
);
936 const dungeon_feature_type grid
= grd(abild
.target
);
943 // only try to create on floor squares
944 if (!feat_is_floor(grid
))
946 mpr("You can't create a trap there!");
949 bool result
= place_specific_trap(abild
.target
, spec_type
);
952 grd(abild
.target
) = env
.trap
[env
.tgrid(abild
.target
)].category();
957 bool create_zotdef_ally(monster_type mtyp
, const char *successmsg
)
959 if (count_allies() > MAX_MONSTERS
/ 2)
961 mpr("The place is too crowded already!");
966 std::string msg
= "Make ";
967 msg
+= get_monster_data(mtyp
)->name
;
970 direction_chooser_args args
;
971 args
.restricts
= DIR_TARGET
;
972 args
.needs_path
= false;
973 args
.may_target_monster
= false;
974 args
.top_prompt
= msg
;
975 direction(abild
, args
);
983 if (mons_place(mgen_data(mtyp
, BEH_FRIENDLY
, &you
, 0, 0, abild
.target
,
984 you
.pet_target
)) == -1)
986 mpr("You can't create it there!");
993 void zotdef_bosses_check()
995 if ((you
.num_turns
+ 1) % CYCLE_LENGTH
== 0)
997 int mon
= zotdef_spawn(true); // boss monster=true
1001 const char *msg
= "You sense that a powerful threat has arrived.";
1002 if (!(((you
.num_turns
+ 1) / CYCLE_LENGTH
) % FREQUENCY_OF_RUNES
))
1004 const rune_type which_rune
=
1005 _get_rune(((you
.num_turns
+ 1) / CYCLE_LENGTH
)
1006 / FREQUENCY_OF_RUNES
);
1007 int ip
= items(1, OBJ_MISCELLANY
, MISC_RUNE_OF_ZOT
, true,
1008 which_rune
, which_rune
);
1009 int *const item_made
= &ip
;
1010 if (*item_made
!= NON_ITEM
&& *item_made
!= -1)
1012 mitm
[ip
].plus
= which_rune
;
1013 move_item_to_grid(item_made
, menv
[mon
].pos());
1014 msg
= "You feel a sense of great excitement!";
1017 _zotdef_danger_msg(msg
);
1020 // since you don't move between maps, any crash would be fatal
1024 if ((you
.num_turns
+ 1) % CYCLE_LENGTH
== CYCLE_INTERVAL
)
1026 // Set the next wave