1 /*
2 * File: monplace.cc
3 * Summary: Functions used when placing monsters in the dungeon.
4 * Written by: Linley Henzell
5 *
6 * Change History (most recent first):
7 *
8 * <1> -/--/-- LRH Created
9 */
10
11 #include "AppHdr.h"
12 #include "monplace.h"
13
14 #include "externs.h"
15 #include "dungeon.h"
16 #include "monstuff.h"
17 #include "mon-pick.h"
18 #include "mon-util.h"
19 #include "misc.h"
20 #include "player.h"
21 #include "stuff.h"
22 #include "spells4.h"
23
24 // NEW place_monster -- note that power should be set to:
25 // 51 for abyss
26 // 52 for pandemonium
27 // x otherwise
28
29 // proximity is the same as for mons_place:
30 // 0 is no restrictions
31 // 1 attempts to place near player
32 // 2 attempts to avoid player LOS
33
34 #define BIG_BAND 20
35
36 static int band_member(int band, int power);
37 static int choose_band( int mon_type, int power, int &band_size );
38 static int place_monster_aux(int mon_type, char behaviour, int target,
39 int px, int py, int power, int extra, bool first_band_member);
40
place_monster(int & id,int mon_type,int power,char behaviour,int target,bool summoned,int px,int py,bool allow_bands,int proximity,int extra)41 bool place_monster(int &id, int mon_type, int power, char behaviour,
42 int target, bool summoned, int px, int py, bool allow_bands,
43 int proximity, int extra)
44 {
45 int band_size = 0;
46 int band_monsters[BIG_BAND]; // band monster types
47 int lev_mons = power; // final 'power'
48 int count;
49 int i;
50
51 // set initial id to -1 (unsuccessful create)
52 id = -1;
53
54 // (1) early out (summoned to occupied grid)
55 if (summoned && mgrd[px][py] != NON_MONSTER)
56 return (false);
57
58 // (2) take care of random monsters
59 if (mon_type == RANDOM_MONSTER
60 && player_in_branch( BRANCH_HALL_OF_BLADES ))
61 {
62 mon_type = MONS_DANCING_WEAPON;
63 }
64
65 if (mon_type == RANDOM_MONSTER)
66 {
67 if (player_in_branch( BRANCH_MAIN_DUNGEON )
68 && lev_mons != 51 && one_chance_in(4))
69 {
70 lev_mons = random2(power);
71 }
72
73 if (player_in_branch( BRANCH_MAIN_DUNGEON ) && lev_mons < 28)
74 {
75 // potentially nasty surprise, but very rare
76 if (one_chance_in(5000))
77 lev_mons = random2(27);
78
79 // slightly out of depth monsters are more common:
80 if (one_chance_in(50))
81 lev_mons += random2(6);
82
83 if (lev_mons > 27)
84 lev_mons = 27;
85 }
86
87 /* Abyss or Pandemonium. Almost never called from Pan;
88 probably only if a rand demon gets summon anything spell */
89 if (lev_mons == 51
90 || you.level_type == LEVEL_PANDEMONIUM
91 || you.level_type == LEVEL_ABYSS)
92 {
93 do
94 {
95 count = 0;
96
97 do
98 {
99 // was: random2(400) {dlb}
100 mon_type = random2(NUM_MONSTERS);
101 count++;
102 }
103 while (mons_abyss(mon_type) == 0 && count < 2000);
104
105 if (count == 2000)
106 return (false);
107 }
108 while (random2avg(100, 2) > mons_rare_abyss(mon_type)
109 && !one_chance_in(100));
110 }
111 else
112 {
113 int level, diff, chance;
114
115 if (lev_mons > 30)
116 lev_mons = 30;
117
118 for (i = 0; i < 10000; i++)
119 {
120 int count = 0;
121
122 do
123 {
124 mon_type = random2(NUM_MONSTERS);
125 count++;
126 }
127 while (mons_rarity(mon_type) == 0 && count < 2000);
128
129 if (count == 2000)
130 return (false);
131
132 level = mons_level( mon_type );
133 diff = level - lev_mons;
134 chance = mons_rarity( mon_type ) - (diff * diff);
135
136 if ((lev_mons >= level - 5 && lev_mons <= level + 5)
137 && random2avg(100, 2) <= chance)
138 {
139 break;
140 }
141 }
142
143 if (i == 10000)
144 return (false);
145 }
146 }
147
148 // (3) decide on banding (good lord!)
149 band_size = 1;
150 band_monsters[0] = mon_type;
151
152 if (allow_bands)
153 {
154 int band = choose_band(mon_type, power, band_size);
155 band_size ++;
156
157 for (i = 1; i < band_size; i++)
158 band_monsters[i] = band_member( band, power );
159 }
160
161 // Monsters that can't move shouldn't be taking the stairs -- bwr
162 if (proximity == PROX_NEAR_STAIRS && mons_speed( mon_type ) == 0)
163 proximity = PROX_AWAY_FROM_PLAYER;
164
165 // (4) for first monster, choose location. This is pretty intensive.
166 bool proxOK;
167 bool close_to_player;
168
169 // player shoved out of the way?
170 bool shoved = false;
171 unsigned char stair_gfx = 0;
172 int pval = 0;
173
174 if (!summoned)
175 {
176 int tries = 0;
177 // try to pick px, py that is
178 // a) not occupied
179 // b) compatible
180 // c) in the 'correct' proximity to the player
181 unsigned char grid_wanted = monster_habitat(mon_type);
182 while(true)
183 {
184 tries ++;
185 // give up on stair placement?
186 if (proximity == PROX_NEAR_STAIRS)
187 {
188 if (tries > 320)
189 {
190 proximity = PROX_AWAY_FROM_PLAYER;
191 tries = 0;
192 }
193 }
194 else if (tries > 60)
195 return (false);
196
197 px = 5 + random2(GXM - 10);
198 py = 5 + random2(GYM - 10);
199
200 // occupied?
201 if (mgrd[px][py] != NON_MONSTER
202 || (px == you.x_pos && py == you.y_pos))
203 {
204 continue;
205 }
206
207 // compatible - floor?
208 if (grid_wanted == DNGN_FLOOR && grd[px][py] < DNGN_FLOOR)
209 continue;
210
211 // compatible - others (must match, except for deep water monsters
212 // generated in shallow water)
213 if ((grid_wanted != DNGN_FLOOR && grd[px][py] != grid_wanted)
214 && (grid_wanted != DNGN_DEEP_WATER || grd[px][py] != DNGN_SHALLOW_WATER))
215 {
216 continue;
217 }
218
219 // don't generate monsters on top of teleport traps
220 // (how did they get there?)
221 int trap = trap_at_xy(px, py);
222 if (trap >= 0)
223 {
224 if (env.trap[trap].type == TRAP_TELEPORT)
225 continue;
226 }
227
228 // check proximity to player
229 proxOK = true;
230
231 switch (proximity)
232 {
233 case PROX_ANYWHERE:
234 if (grid_distance( you.x_pos, you.y_pos, px, py ) < 2 + random2(3))
235 {
236 proxOK = false;
237 }
238 break;
239
240 case PROX_CLOSE_TO_PLAYER:
241 case PROX_AWAY_FROM_PLAYER:
242 close_to_player = (distance(you.x_pos, you.y_pos, px, py) < 64);
243
244 if ((proximity == PROX_CLOSE_TO_PLAYER && !close_to_player)
245 || (proximity == PROX_AWAY_FROM_PLAYER && close_to_player))
246 {
247 proxOK = false;
248 }
249 break;
250
251 case PROX_NEAR_STAIRS:
252 pval = near_stairs(px, py, 1, stair_gfx);
253 if (pval == 2)
254 {
255 // 0 speed monsters can't shove player out of their way.
256 if (mons_speed(mon_type) == 0)
257 {
258 proxOK = false;
259 break;
260 }
261 // swap the monster and the player spots, unless the
262 // monster was generated in lava or deep water.
263 if (grd[px][py] == DNGN_LAVA || grd[px][py] == DNGN_DEEP_WATER)
264 {
265 proxOK = false;
266 break;
267 }
268 shoved = true;
269 int tpx = px;
270 int tpy = py;
271 px = you.x_pos;
272 py = you.y_pos;
273 you.x_pos = tpx;
274 you.y_pos = tpy;
275 }
276
277 proxOK = (pval > 0);
278 break;
279 default:
280 break;
281 }
282
283 if (!proxOK)
284 continue;
285
286 // cool.. passes all tests
287 break;
288 } // end while.. place first monster
289 }
290
291 id = place_monster_aux( mon_type, behaviour, target, px, py, lev_mons,
292 extra, true );
293
294 // now, forget about banding if the first placement failed, or there's too
295 // many monsters already, or we successfully placed by stairs
296 if (id < 0 || id+30 > MAX_MONSTERS)
297 return false;
298
299 // message to player from stairwell/gate appearance?
300 if (see_grid(px, py) && proximity == PROX_NEAR_STAIRS)
301 {
302 info[0] = '\0';
303
304 if (player_monster_visible( &menv[id] ))
305 strcpy(info, ptr_monam( &menv[id], DESC_CAP_A ));
306 else if (shoved)
307 strcpy(info, "Something");
308
309 if (shoved)
310 {
311 strcat(info, " shoves you out of the ");
312 strcat(info, (stair_gfx == '>' || stair_gfx == '<') ? "stairwell!"
313 : "gateway!");
314 mpr(info);
315 }
316 else if (info[0] != '\0')
317 {
318 strcat(info, (stair_gfx == '>') ? " comes up the stairs." :
319 (stair_gfx == '<') ? " comes down the stairs."
320 : " comes through the gate.");
321 mpr(info);
322 }
323
324 // special case: must update the view for monsters created in player LOS
325 viewwindow(1, false);
326 }
327
328 // monsters placed by stairs don't bring the whole band up/down/through
329 // with them
330 if (proximity == PROX_NEAR_STAIRS)
331 return (true);
332
333 // (5) for each band monster, loop call to place_monster_aux().
334 for(i = 1; i < band_size; i++)
335 {
336 place_monster_aux( band_monsters[i], behaviour, target, px, py,
337 lev_mons, extra, false );
338 }
339
340 // placement of first monster, at least, was a success.
341 return (true);
342 }
343
place_monster_aux(int mon_type,char behaviour,int target,int px,int py,int power,int extra,bool first_band_member)344 static int place_monster_aux( int mon_type, char behaviour, int target,
345 int px, int py, int power, int extra,
346 bool first_band_member )
347 {
348 int id, i;
349 char grid_wanted;
350 int fx=0, fy=0; // final x,y
351
352 // gotta be able to pick an ID
353 for (id = 0; id < MAX_MONSTERS; id++)
354 {
355 if (menv[id].type == -1)
356 break;
357 }
358
359 if (id == MAX_MONSTERS)
360 return -1;
361
362 // scrap monster inventory
363 for (i = 0; i < NUM_MONSTER_SLOTS; i++)
364 menv[id].inv[i] = NON_ITEM;
365
366 // scrap monster enchantments
367 for (i = 0; i < NUM_MON_ENCHANTS; i++)
368 menv[id].enchantment[i] = ENCH_NONE;
369
370 // setup habitat and placement
371 if (first_band_member)
372 {
373 fx = px;
374 fy = py;
375 }
376 else
377 {
378 grid_wanted = monster_habitat(mon_type);
379
380 // we'll try 1000 times for a good spot
381 for (i = 0; i < 1000; i++)
382 {
383 fx = px + random2(7) - 3;
384 fy = py + random2(7) - 3;
385
386 // occupied?
387 if (mgrd[fx][fy] != NON_MONSTER)
388 continue;
389
390 // compatible - floor?
391 if (grid_wanted == DNGN_FLOOR && grd[fx][fy] < DNGN_FLOOR)
392 continue;
393
394 // compatible - others (must match, except for deep water monsters
395 // generated in shallow water)
396 if ((grid_wanted != DNGN_FLOOR && grd[fx][fy] != grid_wanted)
397 && (grid_wanted != DNGN_DEEP_WATER || grd[fx][fy] != DNGN_SHALLOW_WATER))
398 continue;
399
400 // don't generate monsters on top of teleport traps
401 // (how do they get there?)
402 int trap = trap_at_xy(fx, fy);
403 if (trap >= 0)
404 if (env.trap[trap].type == TRAP_TELEPORT)
405 continue;
406
407 // cool.. passes all tests
408 break;
409 }
410
411 // did we really try 1000 times?
412 if (i == 1000)
413 return (-1);
414 }
415
416 // now, actually create the monster (wheeee!)
417 menv[id].type = mon_type;
418 menv[id].number = 250;
419
420 menv[id].x = fx;
421 menv[id].y = fy;
422
423 // link monster into monster grid
424 mgrd[fx][fy] = id;
425
426 // generate a brand shiny new monster, or zombie
427 if (mon_type == MONS_ZOMBIE_SMALL
428 || mon_type == MONS_ZOMBIE_LARGE
429 || mon_type == MONS_SIMULACRUM_SMALL
430 || mon_type == MONS_SIMULACRUM_LARGE
431 || mon_type == MONS_SKELETON_SMALL
432 || mon_type == MONS_SKELETON_LARGE
433 || mon_type == MONS_SPECTRAL_THING)
434 {
435 define_zombie( id, extra, mon_type, power );
436 }
437 else
438 {
439 define_monster(id);
440 }
441
442 // The return of Boris is now handled in monster_die()...
443 // not setting this for Boris here allows for multiple Borises
444 // in the dungeon at the same time. -- bwr
445 if (mon_type >= MONS_TERENCE && mon_type <= MONS_BORIS)
446 you.unique_creatures[mon_type - 280] = 1;
447
448 if (extra != 250)
449 menv[id].number = extra;
450
451 if (mons_flag(mon_type, M_INVIS))
452 mons_add_ench(&menv[id], ENCH_INVIS);
453
454 if (mons_flag(mon_type, M_CONFUSED))
455 mons_add_ench(&menv[id], ENCH_CONFUSION);
456
457 if (mon_type == MONS_SHAPESHIFTER)
458 mons_add_ench(&menv[id], ENCH_SHAPESHIFTER);
459
460 if (mon_type == MONS_GLOWING_SHAPESHIFTER)
461 mons_add_ench(&menv[id], ENCH_GLOWING_SHAPESHIFTER);
462
463 if (mon_type == MONS_GIANT_BAT || mon_type == MONS_UNSEEN_HORROR
464 || mon_type == MONS_GIANT_BLOWFLY)
465 {
466 menv[id].flags |= MF_BATTY;
467 }
468
469 if ((mon_type == MONS_BIG_FISH
470 || mon_type == MONS_GIANT_GOLDFISH
471 || mon_type == MONS_ELECTRICAL_EEL
472 || mon_type == MONS_JELLYFISH
473 || mon_type == MONS_WATER_ELEMENTAL
474 || mon_type == MONS_SWAMP_WORM)
475 && grd[fx][fy] == DNGN_DEEP_WATER
476 && !one_chance_in(5))
477 {
478 mons_add_ench( &menv[id], ENCH_SUBMERGED );
479 }
480
481 if ((mon_type == MONS_LAVA_WORM
482 || mon_type == MONS_LAVA_FISH
483 || mon_type == MONS_LAVA_SNAKE
484 || mon_type == MONS_SALAMANDER)
485 && grd[fx][fy] == DNGN_LAVA
486 && !one_chance_in(5))
487 {
488 mons_add_ench( &menv[id], ENCH_SUBMERGED );
489 }
490
491 menv[id].flags |= MF_JUST_SUMMONED;
492
493 if (mon_type == MONS_DANCING_WEAPON && extra != 1) // ie not from spell
494 {
495 give_item( id, power );
496
497 if (menv[id].inv[MSLOT_WEAPON] != NON_ITEM)
498 menv[id].number = mitm[ menv[id].inv[MSLOT_WEAPON] ].colour;
499 }
500 else if (mons_itemuse(mon_type) >= MONUSE_STARTING_EQUIPMENT)
501 {
502 give_item( id, power );
503
504 // Give these monsters a second weapon -- bwr
505 if (mon_type == MONS_TWO_HEADED_OGRE || mon_type == MONS_ETTIN)
506 {
507 give_item( id, power );
508 }
509 }
510
511
512 // give manticores 8 to 16 spike volleys.
513 // they're not spellcasters so this doesn't screw anything up.
514 if (mon_type == MONS_MANTICORE)
515 menv[id].number = 8 + random2(9);
516
517 // set attitude, behaviour and target
518 menv[id].attitude = ATT_HOSTILE;
519 menv[id].behaviour = behaviour;
520 menv[id].foe_memory = 0;
521
522 // setting attitude will always make the
523 // monster wander.. if you want sleeping
524 // hostiles, use BEH_SLEEP since the default
525 // attitude is hostile.
526 if (behaviour > NUM_BEHAVIOURS)
527 {
528 if (behaviour == BEH_FRIENDLY || behaviour == BEH_GOD_GIFT)
529 menv[id].attitude = ATT_FRIENDLY;
530
531 menv[id].behaviour = BEH_WANDER;
532 }
533
534 menv[id].foe = target;
535
536 return (id);
537 } // end place_monster_aux()
538
539
choose_band(int mon_type,int power,int & band_size)540 static int choose_band( int mon_type, int power, int &band_size )
541 {
542 // init
543 band_size = 0;
544 int band = BAND_NO_BAND;
545
546 switch (mon_type)
547 {
548 case MONS_ORC:
549 if (coinflip())
550 break;
551 // intentional fall-through {dlb}
552 case MONS_ORC_WARRIOR:
553 band = BAND_ORCS; // orcs
554 band_size = 2 + random2(3);
555 break;
556
557 case MONS_BIG_KOBOLD:
558 if (power > 3)
559 {
560 band = BAND_KOBOLDS;
561 band_size = 2 + random2(6);
562 }
563 break;
564
565 case MONS_ORC_WARLORD:
566 band_size = 5 + random2(5); // warlords have large bands
567 // intentional fall through
568 case MONS_ORC_KNIGHT:
569 band = BAND_ORC_KNIGHT; // orcs + knight
570 band_size += 3 + random2(4);
571 break;
572
573 case MONS_KILLER_BEE:
574 band = BAND_KILLER_BEES; // killer bees
575 band_size = 2 + random2(4);
576 break;
577
578 case MONS_FLYING_SKULL:
579 band = BAND_FLYING_SKULLS; // flying skulls
580 band_size = 2 + random2(4);
581 break;
582 case MONS_SLIME_CREATURE:
583 band = BAND_SLIME_CREATURES; // slime creatures
584 band_size = 2 + random2(4);
585 break;
586 case MONS_YAK:
587 band = BAND_YAKS; // yaks
588 band_size = 2 + random2(4);
589 break;
590 case MONS_UGLY_THING:
591 band = BAND_UGLY_THINGS; // ugly things
592 band_size = 2 + random2(4);
593 break;
594 case MONS_HELL_HOUND:
595 band = BAND_HELL_HOUNDS; // hell hound
596 band_size = 2 + random2(3);
597 break;
598 case MONS_JACKAL:
599 band = BAND_JACKALS; // jackal
600 band_size = 1 + random2(3);
601 break;
602 case MONS_HELL_KNIGHT:
603 case MONS_MARGERY:
604 band = BAND_HELL_KNIGHTS; // hell knight
605 band_size = 4 + random2(4);
606 break;
607 case MONS_JOSEPHINE:
608 case MONS_NECROMANCER:
609 case MONS_VAMPIRE_MAGE:
610 band = BAND_NECROMANCER; // necromancer
611 band_size = 4 + random2(4);
612 break;
613 case MONS_ORC_HIGH_PRIEST:
614 band = BAND_ORC_HIGH_PRIEST; // orc high priest
615 band_size = 4 + random2(4);
616 break;
617 case MONS_GNOLL:
618 band = BAND_GNOLLS; // gnoll
619 band_size = ((coinflip())? 3 : 2);
620 break;
621 case MONS_BUMBLEBEE:
622 band = BAND_BUMBLEBEES; // bumble bees
623 band_size = 2 + random2(4);
624 break;
625 case MONS_CENTAUR:
626 case MONS_CENTAUR_WARRIOR:
627 if (power > 9 && one_chance_in(3))
628 {
629 band = BAND_CENTAURS; // centaurs
630 band_size = 2 + random2(4);
631 }
632 break;
633
634 case MONS_YAKTAUR:
635 case MONS_YAKTAUR_CAPTAIN:
636 if (coinflip())
637 {
638 band = BAND_YAKTAURS; // yaktaurs
639 band_size = 2 + random2(3);
640 }
641 break;
642
643 case MONS_DEATH_YAK:
644 band = BAND_DEATH_YAKS; // death yaks
645 band_size = 2 + random2(4);
646 break;
647 case MONS_INSUBSTANTIAL_WISP:
648 band = BAND_INSUBSTANTIAL_WISPS; // wisps
649 band_size = 4 + random2(5);
650 break;
651 case MONS_OGRE_MAGE:
652 band = BAND_OGRE_MAGE; // ogre mage
653 band_size = 4 + random2(4);
654 break;
655 case MONS_BALRUG:
656 band = BAND_BALRUG; // RED gr demon
657 band_size = 2 + random2(3);
658 break;
659 case MONS_CACODEMON:
660 band = BAND_CACODEMON; // BROWN gr demon
661 band_size = 1 + random2(3);
662 break;
663
664 case MONS_EXECUTIONER:
665 if (coinflip())
666 {
667 band = BAND_EXECUTIONER; // DARKGREY gr demon
668 band_size = 1 + random2(3);
669 }
670 break;
671
672 case MONS_HELLWING:
673 if (coinflip())
674 {
675 band = BAND_HELLWING; // LIGHTGREY gr demon
676 band_size = 1 + random2(4);
677 }
678 break;
679
680 case MONS_DEEP_ELF_FIGHTER:
681 if (coinflip())
682 {
683 band = BAND_DEEP_ELF_FIGHTER; // deep elf warrior
684 band_size = 3 + random2(4);
685 }
686 break;
687
688 case MONS_DEEP_ELF_KNIGHT:
689 if (coinflip())
690 {
691 band = BAND_DEEP_ELF_KNIGHT; // deep elf knight
692 band_size = 3 + random2(4);
693 }
694 break;
695
696 case MONS_DEEP_ELF_HIGH_PRIEST:
697 if (coinflip())
698 {
699 band = BAND_DEEP_ELF_HIGH_PRIEST; // deep elf high priest
700 band_size = 3 + random2(4);
701 }
702 break;
703
704 case MONS_KOBOLD_DEMONOLOGIST:
705 if (coinflip())
706 {
707 band = BAND_KOBOLD_DEMONOLOGIST; // kobold demonologist
708 band_size = 3 + random2(6);
709 }
710 break;
711
712 case MONS_NAGA_MAGE:
713 case MONS_NAGA_WARRIOR:
714 band = BAND_NAGAS; // Nagas
715 band_size = 3 + random2(4);
716 break;
717 case MONS_WAR_DOG:
718 band = BAND_WAR_DOGS; // war dogs
719 band_size = 2 + random2(4);
720 break;
721 case MONS_GREY_RAT:
722 band = BAND_GREY_RATS; // grey rats
723 band_size = 4 + random2(6);
724 break;
725 case MONS_GREEN_RAT:
726 band = BAND_GREEN_RATS; // green rats
727 band_size = 4 + random2(6);
728 break;
729 case MONS_ORANGE_RAT:
730 band = BAND_ORANGE_RATS; // orange rats
731 band_size = 3 + random2(4);
732 break;
733 case MONS_SHEEP:
734 band = BAND_SHEEP; // sheep
735 band_size = 3 + random2(5);
736 break;
737 case MONS_GHOUL:
738 band = BAND_GHOULS; // ghoul
739 band_size = 2 + random2(3);
740 break;
741 case MONS_HOG:
742 band = BAND_HOGS; // hog
743 band_size = 1 + random2(3);
744 break;
745 case MONS_GIANT_MOSQUITO:
746 band = BAND_GIANT_MOSQUITOES; // mosquito
747 band_size = 1 + random2(3);
748 break;
749 case MONS_DEEP_TROLL:
750 band = BAND_DEEP_TROLLS; // deep troll
751 band_size = 3 + random2(3);
752 break;
753 case MONS_HELL_HOG:
754 band = BAND_HELL_HOGS; // hell-hog
755 band_size = 1 + random2(3);
756 break;
757 case MONS_BOGGART:
758 band = BAND_BOGGARTS; // boggart
759 band_size = 2 + random2(3);
760 break;
761 case MONS_BLINK_FROG:
762 band = BAND_BLINK_FROGS; // blink frog
763 band_size = 2 + random2(3);
764 break;
765 case MONS_SKELETAL_WARRIOR:
766 band = BAND_SKELETAL_WARRIORS; // skeletal warrior
767 band_size = 2 + random2(3);
768 break;
769 } // end switch
770
771 if (band != BAND_NO_BAND && band_size == 0)
772 band = BAND_NO_BAND;
773
774 if (band_size >= BIG_BAND)
775 band_size = BIG_BAND-1;
776
777 return (band);
778 }
779
band_member(int band,int power)780 static int band_member(int band, int power)
781 {
782 int mon_type = -1;
783 int temp_rand;
784
785 if (band == BAND_NO_BAND)
786 return -1;
787
788 switch (band)
789 {
790 case BAND_KOBOLDS:
791 mon_type = MONS_KOBOLD;
792 break;
793
794 case BAND_ORC_KNIGHT:
795 case BAND_ORC_HIGH_PRIEST:
796 temp_rand = random2(30);
797 mon_type = ((temp_rand > 17) ? MONS_ORC : // 12 in 30
798 (temp_rand > 8) ? MONS_ORC_WARRIOR : // 9 in 30
799 (temp_rand > 6) ? MONS_WARG : // 2 in 30
800 (temp_rand > 4) ? MONS_ORC_WIZARD : // 2 in 30
801 (temp_rand > 2) ? MONS_ORC_PRIEST : // 2 in 30
802 (temp_rand > 1) ? MONS_OGRE : // 1 in 30
803 (temp_rand > 0) ? MONS_TROLL // 1 in 30
804 : MONS_ORC_SORCERER); // 1 in 30
805 break;
806
807 case BAND_KILLER_BEES:
808 mon_type = MONS_KILLER_BEE;
809 break;
810
811 case BAND_FLYING_SKULLS:
812 mon_type = MONS_FLYING_SKULL;
813 break;
814
815 case BAND_SLIME_CREATURES:
816 mon_type = MONS_SLIME_CREATURE;
817 break;
818
819 case BAND_YAKS:
820 mon_type = MONS_YAK;
821 break;
822
823 case BAND_UGLY_THINGS:
824 mon_type = ((power > 21 && one_chance_in(4)) ?
825 MONS_VERY_UGLY_THING : MONS_UGLY_THING);
826 break;
827
828 case BAND_HELL_HOUNDS:
829 mon_type = MONS_HELL_HOUND;
830 break;
831
832 case BAND_JACKALS:
833 mon_type = MONS_JACKAL;
834 break;
835
836 case BAND_GNOLLS:
837 mon_type = MONS_GNOLL;
838 break;
839
840 case BAND_BUMBLEBEES:
841 mon_type = MONS_BUMBLEBEE;
842 break;
843
844 case BAND_CENTAURS:
845 mon_type = MONS_CENTAUR;
846 break;
847
848 case BAND_YAKTAURS:
849 mon_type = MONS_YAKTAUR;
850 break;
851
852 case BAND_INSUBSTANTIAL_WISPS:
853 mon_type = MONS_INSUBSTANTIAL_WISP;
854 break;
855
856 case BAND_DEATH_YAKS:
857 mon_type = MONS_DEATH_YAK;
858 break;
859
860 case BAND_NECROMANCER: // necromancer
861 temp_rand = random2(13);
862 mon_type = ((temp_rand > 9) ? MONS_ZOMBIE_SMALL : // 3 in 13
863 (temp_rand > 6) ? MONS_ZOMBIE_LARGE : // 3 in 13
864 (temp_rand > 3) ? MONS_SKELETON_SMALL : // 3 in 13
865 (temp_rand > 0) ? MONS_SKELETON_LARGE // 3 in 13
866 : MONS_NECROPHAGE); // 1 in 13
867 break;
868
869 case BAND_BALRUG:
870 mon_type = (coinflip()? MONS_NEQOXEC : MONS_ORANGE_DEMON);
871 break;
872
873 case BAND_CACODEMON:
874 mon_type = MONS_LEMURE;
875 break;
876
877 case BAND_EXECUTIONER:
878 mon_type = (coinflip() ? MONS_ABOMINATION_SMALL : MONS_ABOMINATION_LARGE);
879 break;
880
881 case BAND_HELLWING:
882 mon_type = (coinflip() ? MONS_HELLWING : MONS_SMOKE_DEMON);
883 break;
884
885 case BAND_DEEP_ELF_FIGHTER: // deep elf fighter
886 temp_rand = random2(11);
887 mon_type = ((temp_rand > 4) ? MONS_DEEP_ELF_SOLDIER : // 6 in 11
888 (temp_rand == 4) ? MONS_DEEP_ELF_FIGHTER : // 1 in 11
889 (temp_rand == 3) ? MONS_DEEP_ELF_KNIGHT : // 1 in 11
890 (temp_rand == 2) ? MONS_DEEP_ELF_CONJURER :// 1 in 11
891 (temp_rand == 1) ? MONS_DEEP_ELF_MAGE // 1 in 11
892 : MONS_DEEP_ELF_PRIEST); // 1 in 11
893 break;
894
895 case BAND_ORCS:
896 mon_type = MONS_ORC;
897 if (one_chance_in(5))
898 mon_type = MONS_ORC_WIZARD;
899 if (one_chance_in(7))
900 mon_type = MONS_ORC_PRIEST;
901 break;
902
903 case BAND_HELL_KNIGHTS:
904 mon_type = MONS_HELL_KNIGHT;
905 if (one_chance_in(4))
906 mon_type = MONS_NECROMANCER;
907 break;
908
909 //case 12 is orc high priest
910
911 case BAND_OGRE_MAGE:
912 mon_type = MONS_OGRE;
913 if (one_chance_in(3))
914 mon_type = MONS_TWO_HEADED_OGRE;
915 break; // ogre mage
916
917 // comment does not match value (30, TWO_HEADED_OGRE) prior to
918 // enum replacement [!!!] 14jan2000 {dlb}
919
920 case BAND_DEEP_ELF_KNIGHT: // deep elf knight
921 temp_rand = random2(208);
922 mon_type =
923 ((temp_rand > 159) ? MONS_DEEP_ELF_SOLDIER : // 23.08%
924 (temp_rand > 111) ? MONS_DEEP_ELF_FIGHTER : // 23.08%
925 (temp_rand > 79) ? MONS_DEEP_ELF_KNIGHT : // 15.38%
926 (temp_rand > 51) ? MONS_DEEP_ELF_MAGE : // 13.46%
927 (temp_rand > 35) ? MONS_DEEP_ELF_PRIEST : // 7.69%
928 (temp_rand > 19) ? MONS_DEEP_ELF_CONJURER : // 7.69%
929 (temp_rand > 3) ? MONS_DEEP_ELF_SUMMONER : // 7.69%
930 (temp_rand == 3) ? MONS_DEEP_ELF_DEMONOLOGIST :// 0.48%
931 (temp_rand == 2) ? MONS_DEEP_ELF_ANNIHILATOR : // 0.48%
932 (temp_rand == 1) ? MONS_DEEP_ELF_SORCERER // 0.48%
933 : MONS_DEEP_ELF_DEATH_MAGE); // 0.48%
934 break;
935
936 case BAND_DEEP_ELF_HIGH_PRIEST: // deep elf high priest
937 temp_rand = random2(16);
938 mon_type =
939 ((temp_rand > 12) ? MONS_DEEP_ELF_SOLDIER : // 3 in 16
940 (temp_rand > 9) ? MONS_DEEP_ELF_FIGHTER : // 3 in 16
941 (temp_rand > 6) ? MONS_DEEP_ELF_PRIEST : // 3 in 16
942 (temp_rand == 6) ? MONS_DEEP_ELF_MAGE : // 1 in 16
943 (temp_rand == 5) ? MONS_DEEP_ELF_SUMMONER : // 1 in 16
944 (temp_rand == 4) ? MONS_DEEP_ELF_CONJURER : // 1 in 16
945 (temp_rand == 3) ? MONS_DEEP_ELF_DEMONOLOGIST :// 1 in 16
946 (temp_rand == 2) ? MONS_DEEP_ELF_ANNIHILATOR : // 1 in 16
947 (temp_rand == 1) ? MONS_DEEP_ELF_SORCERER // 1 in 16
948 : MONS_DEEP_ELF_DEATH_MAGE); // 1 in 16
949 break;
950
951 case BAND_KOBOLD_DEMONOLOGIST:
952 temp_rand = random2(13);
953 mon_type = ((temp_rand > 4) ? MONS_KOBOLD : // 8 in 13
954 (temp_rand > 0) ? MONS_BIG_KOBOLD // 4 in 13
955 : MONS_KOBOLD_DEMONOLOGIST);// 1 in 13
956 break;
957
958 case BAND_NAGAS:
959 mon_type = MONS_NAGA;
960 break;
961 case BAND_WAR_DOGS:
962 mon_type = MONS_WAR_DOG;
963 break;
964 case BAND_GREY_RATS:
965 mon_type = MONS_GREY_RAT;
966 break;
967 case BAND_GREEN_RATS:
968 mon_type = MONS_GREEN_RAT;
969 break;
970 case BAND_ORANGE_RATS:
971 mon_type = MONS_ORANGE_RAT;
972 break;
973 case BAND_SHEEP:
974 mon_type = MONS_SHEEP;
975 break;
976 case BAND_GHOULS:
977 mon_type = (coinflip() ? MONS_GHOUL : MONS_NECROPHAGE);
978 break;
979 case BAND_DEEP_TROLLS:
980 mon_type = MONS_DEEP_TROLL;
981 break;
982 case BAND_HOGS:
983 mon_type = MONS_HOG;
984 break;
985 case BAND_HELL_HOGS:
986 mon_type = MONS_HELL_HOG;
987 break;
988 case BAND_GIANT_MOSQUITOES:
989 mon_type = MONS_GIANT_MOSQUITO;
990 break;
991 case BAND_BOGGARTS:
992 mon_type = MONS_BOGGART;
993 break;
994 case BAND_BLINK_FROGS:
995 mon_type = MONS_BLINK_FROG;
996 break;
997 case BAND_SKELETAL_WARRIORS:
998 mon_type = MONS_SKELETAL_WARRIOR;
999 break;
1000 }
1001
1002 return (mon_type);
1003 }
1004
1005 // PUBLIC FUNCTION -- mons_place().
1006
mons_place(int mon_type,char behaviour,int target,bool summoned,int px,int py,int level_type,int proximity,int extra)1007 int mons_place( int mon_type, char behaviour, int target, bool summoned,
1008 int px, int py, int level_type, int proximity, int extra )
1009 {
1010 int mon_count = 0;
1011 int temp_rand; // probabilty determination {dlb}
1012 bool permit_bands = false;
1013
1014 for (int il = 0; il < MAX_MONSTERS; il++)
1015 {
1016 if (menv[il].type != -1)
1017 mon_count++;
1018 }
1019
1020 if (mon_type == WANDERING_MONSTER)
1021 {
1022 if (mon_count > 150)
1023 return (-1);
1024
1025 mon_type = RANDOM_MONSTER;
1026 }
1027
1028 // all monsters have been assigned? {dlb}
1029 if (mon_count > MAX_MONSTERS - 2)
1030 return (-1);
1031
1032 // this gives a slight challenge to the player as they ascend the
1033 // dungeon with the Orb
1034 if (you.char_direction == DIR_ASCENDING && mon_type == RANDOM_MONSTER
1035 && you.level_type == LEVEL_DUNGEON)
1036 {
1037 temp_rand = random2(276);
1038
1039 mon_type = ((temp_rand > 184) ? MONS_WHITE_IMP + random2(15) : // 33.33%
1040 (temp_rand > 104) ? MONS_HELLION + random2(10) : // 28.99%
1041 (temp_rand > 78) ? MONS_HELL_HOUND : // 9.06%
1042 (temp_rand > 54) ? MONS_ABOMINATION_LARGE : // 8.70%
1043 (temp_rand > 33) ? MONS_ABOMINATION_SMALL : // 7.61%
1044 (temp_rand > 13) ? MONS_RED_DEVIL // 7.25%
1045 : MONS_PIT_FIEND); // 5.07%
1046 }
1047
1048 if (mon_type == RANDOM_MONSTER || level_type == LEVEL_PANDEMONIUM)
1049 permit_bands = true;
1050
1051 int mid = -1;
1052
1053 // translate level_type
1054 int power;
1055
1056 switch (level_type)
1057 {
1058 case LEVEL_PANDEMONIUM:
1059 power = 52; // sigh..
1060 break;
1061 case LEVEL_ABYSS:
1062 power = 51;
1063 break;
1064 case LEVEL_DUNGEON: // intentional fallthrough
1065 default:
1066 power = you.your_level;
1067 break;
1068 }
1069
1070 if (place_monster( mid, mon_type, power, behaviour, target, summoned,
1071 px, py, permit_bands, proximity, extra ) == false)
1072 {
1073 return (-1);
1074 }
1075
1076 if (mid != -1)
1077 {
1078 struct monsters *const creation = &menv[mid];
1079
1080 // look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
1081 // alert summoned being to player's presence
1082 if (behaviour > NUM_BEHAVIOURS)
1083 {
1084 if (behaviour == BEH_FRIENDLY || behaviour == BEH_GOD_GIFT)
1085 creation->flags |= MF_CREATED_FRIENDLY;
1086
1087 if (behaviour == BEH_GOD_GIFT)
1088 creation->flags |= MF_GOD_GIFT;
1089
1090 if (behaviour == BEH_CHARMED)
1091 {
1092 creation->attitude = ATT_HOSTILE;
1093 mons_add_ench(creation, ENCH_CHARM);
1094 }
1095
1096 // make summoned being aware of player's presence
1097 behaviour_event(creation, ME_ALERT, MHITYOU);
1098 }
1099 }
1100
1101 return (mid);
1102 } // end mons_place()
1103
1104
create_monster(int cls,int dur,int beha,int cr_x,int cr_y,int hitting,int zsec)1105 int create_monster( int cls, int dur, int beha, int cr_x, int cr_y,
1106 int hitting, int zsec )
1107 {
1108 int summd = -1;
1109 FixedVector < char, 2 > empty;
1110
1111 unsigned char spcw = ((cls == RANDOM_MONSTER) ? DNGN_FLOOR
1112 : monster_habitat( cls ));
1113
1114 empty[0] = 0;
1115 empty[1] = 0;
1116
1117 // Might be better if we chose a space and tried to match the monster
1118 // to it in the case of RANDOM_MONSTER, that way if the target square
1119 // is surrounded by water of lava this function would work. -- bwr
1120 if (empty_surrounds( cr_x, cr_y, spcw, true, empty ))
1121 {
1122 summd = mons_place( cls, beha, hitting, true, empty[0], empty[1],
1123 you.level_type, 0, zsec );
1124 }
1125
1126 // determine whether creating a monster is successful (summd != -1) {dlb}:
1127 // then handle the outcome {dlb}:
1128 if (summd == -1)
1129 {
1130 if (see_grid( cr_x, cr_y ))
1131 mpr("You see a puff of smoke.");
1132 }
1133 else
1134 {
1135 struct monsters *const creation = &menv[summd];
1136
1137 // dur should always be ENCH_ABJ_xx
1138 if (dur >= ENCH_ABJ_I && dur <= ENCH_ABJ_VI)
1139 mons_add_ench(creation, dur );
1140
1141 // look at special cases: CHARMED, FRIENDLY, HOSTILE, GOD_GIFT
1142 // alert summoned being to player's presence
1143 if (beha > NUM_BEHAVIOURS)
1144 {
1145 if (beha == BEH_FRIENDLY || beha == BEH_GOD_GIFT)
1146 creation->flags |= MF_CREATED_FRIENDLY;
1147
1148 if (beha == BEH_GOD_GIFT)
1149 creation->flags |= MF_GOD_GIFT;
1150
1151 if (beha == BEH_CHARMED)
1152 {
1153 creation->attitude = ATT_HOSTILE;
1154 mons_add_ench(creation, ENCH_CHARM);
1155 }
1156
1157 // make summoned being aware of player's presence
1158 behaviour_event(creation, ME_ALERT, MHITYOU);
1159 }
1160
1161 if (creation->type == MONS_RAKSHASA_FAKE && !one_chance_in(3))
1162 mons_add_ench(creation, ENCH_INVIS);
1163 }
1164
1165 // the return value is either -1 (failure of some sort)
1166 // or the index of the monster placed (if I read things right) {dlb}
1167 return (summd);
1168 } // end create_monster()
1169
1170
empty_surrounds(int emx,int emy,unsigned char spc_wanted,bool allow_centre,FixedVector<char,2> & empty)1171 bool empty_surrounds(int emx, int emy, unsigned char spc_wanted,
1172 bool allow_centre, FixedVector < char, 2 > &empty)
1173 {
1174 bool success;
1175 // assume all player summoning originates from player x,y
1176 bool playerSummon = (emx == you.x_pos && emy == you.y_pos);
1177
1178 int xpos[25]; // good x pos
1179 int ypos[25]; // good y pos
1180 int good_count = 0;
1181 int count_x, count_y;
1182
1183 char minx = -2;
1184 char maxx = 2;
1185 char miny = -2;
1186 char maxy = 2;
1187
1188 for (count_x = minx; count_x <= maxx; count_x++)
1189 {
1190 for (count_y = miny; count_y <= maxy; count_y++)
1191 {
1192 success = false;
1193
1194 if (!allow_centre && count_x == 0 && count_y == 0)
1195 continue;
1196
1197 int tx = emx + count_x;
1198 int ty = emy + count_y;
1199
1200 if (tx == you.x_pos && ty == you.y_pos)
1201 continue;
1202
1203 if (mgrd[tx][ty] != NON_MONSTER)
1204 continue;
1205
1206 // players won't summon out of LOS
1207 if (!see_grid(tx, ty) && playerSummon)
1208 continue;
1209
1210 if (grd[tx][ty] == spc_wanted)
1211 success = true;
1212
1213 // those seeking ground can stand in shallow water or better
1214 if (spc_wanted == DNGN_FLOOR && grd[tx][ty] >= DNGN_SHALLOW_WATER)
1215 success = true;
1216
1217 // water monsters can be created in shallow as well as deep water
1218 if (spc_wanted == DNGN_DEEP_WATER && grd[tx][ty] == DNGN_SHALLOW_WATER)
1219 success = true;
1220
1221 if (success)
1222 {
1223 // add point to list of good points
1224 xpos[good_count] = tx;
1225 ypos[good_count] = ty;
1226 good_count ++;
1227 }
1228 } // end "for count_y"
1229 } // end "for count_x"
1230
1231 if (good_count > 0)
1232 {
1233 int pick = random2(good_count);
1234 empty[0] = xpos[pick];
1235 empty[1] = ypos[pick];
1236 }
1237
1238 return (good_count > 0);
1239 } // end empty_surrounds()
1240
summon_any_demon(char demon_class)1241 int summon_any_demon(char demon_class)
1242 {
1243 int summoned; // error trapping {dlb}
1244 int temp_rand; // probability determination {dlb}
1245
1246 switch (demon_class)
1247 {
1248 case DEMON_LESSER:
1249 temp_rand = random2(60);
1250 summoned = ((temp_rand > 49) ? MONS_IMP : // 10 in 60
1251 (temp_rand > 40) ? MONS_WHITE_IMP : // 9 in 60
1252 (temp_rand > 31) ? MONS_LEMURE : // 9 in 60
1253 (temp_rand > 22) ? MONS_UFETUBUS : // 9 in 60
1254 (temp_rand > 13) ? MONS_MANES : // 9 in 60
1255 (temp_rand > 4) ? MONS_MIDGE // 9 in 60
1256 : MONS_SHADOW_IMP); // 5 in 60
1257 break;
1258
1259 case DEMON_COMMON:
1260 temp_rand = random2(3948);
1261 summoned = ((temp_rand > 3367) ? MONS_NEQOXEC : // 14.69%
1262 (temp_rand > 2787) ? MONS_ORANGE_DEMON : // 14.69%
1263 (temp_rand > 2207) ? MONS_HELLWING : // 14.69%
1264 (temp_rand > 1627) ? MONS_SMOKE_DEMON : // 14.69%
1265 (temp_rand > 1047) ? MONS_YNOXINUL : // 14.69%
1266 (temp_rand > 889) ? MONS_RED_DEVIL : // 4.00%
1267 (temp_rand > 810) ? MONS_HELLION : // 2.00%
1268 (temp_rand > 731) ? MONS_ROTTING_DEVIL : // 2.00%
1269 (temp_rand > 652) ? MONS_TORMENTOR : // 2.00%
1270 (temp_rand > 573) ? MONS_REAPER : // 2.00%
1271 (temp_rand > 494) ? MONS_SOUL_EATER : // 2.00%
1272 (temp_rand > 415) ? MONS_HAIRY_DEVIL : // 2.00%
1273 (temp_rand > 336) ? MONS_ICE_DEVIL : // 2.00%
1274 (temp_rand > 257) ? MONS_BLUE_DEVIL : // 2.00%
1275 (temp_rand > 178) ? MONS_BEAST : // 2.00%
1276 (temp_rand > 99) ? MONS_IRON_DEVIL : // 2.00%
1277 (temp_rand > 49) ? MONS_SUN_DEMON // 1.26%
1278 : MONS_SHADOW_IMP); // 1.26%
1279 break;
1280
1281 case DEMON_GREATER:
1282 temp_rand = random2(1000);
1283 summoned = ((temp_rand > 868) ? MONS_CACODEMON : // 13.1%
1284 (temp_rand > 737) ? MONS_BALRUG : // 13.1%
1285 (temp_rand > 606) ? MONS_BLUE_DEATH : // 13.1%
1286 (temp_rand > 475) ? MONS_GREEN_DEATH : // 13.1%
1287 (temp_rand > 344) ? MONS_EXECUTIONER : // 13.1%
1288 (temp_rand > 244) ? MONS_FIEND : // 10.0%
1289 (temp_rand > 154) ? MONS_ICE_FIEND : // 9.0%
1290 (temp_rand > 73) ? MONS_SHADOW_FIEND // 8.1%
1291 : MONS_PIT_FIEND); // 7.4%
1292 break;
1293
1294 default:
1295 summoned = MONS_GIANT_ANT; // this was the original behaviour {dlb}
1296 break;
1297 }
1298
1299 return summoned;
1300 } // end summon_any_demon()
1301