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