1 /**
2  * @file
3  * @brief Monster abilities.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "mon-abil.h"
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <map>
13 #include <queue>
14 #include <set>
15 
16 #include "act-iter.h"
17 #include "actor.h"
18 #include "areas.h"
19 #include "arena.h"
20 #include "beam.h"
21 #include "cloud.h"
22 #include "colour.h"
23 #include "coordit.h"
24 #include "delay.h"
25 #include "dgn-overview.h"
26 #include "directn.h"
27 #include "english.h"
28 #include "env.h"
29 #include "fprop.h"
30 #include "item-prop.h"
31 #include "libutil.h"
32 #include "losglobal.h"
33 #include "message.h"
34 #include "mgen-data.h"
35 #include "mon-act.h"
36 #include "mon-behv.h"
37 #include "mon-cast.h"
38 #include "mon-death.h"
39 #include "mon-pathfind.h"
40 #include "mon-place.h"
41 #include "mon-poly.h"
42 #include "mon-util.h"
43 #include "ouch.h"
44 #include "random.h"
45 #include "religion.h"
46 #include "spl-damage.h"
47 #include "spl-util.h"
48 #include "state.h"
49 #include "stringutil.h"
50 #include "target.h"
51 #include "teleport.h"
52 #include "terrain.h"
53 #include "view.h"
54 
55 static bool _slime_split_merge(monster* thing);
56 
57 // Currently only used for Tiamat.
draconian_change_colour(monster * drac)58 void draconian_change_colour(monster* drac)
59 {
60     if (mons_genus(drac->type) != MONS_DRACONIAN)
61         return;
62 
63     drac->base_monster = random_choose(MONS_RED_DRACONIAN,
64                                        MONS_WHITE_DRACONIAN,
65                                        MONS_BLACK_DRACONIAN,
66                                        MONS_GREEN_DRACONIAN,
67                                        MONS_PURPLE_DRACONIAN,
68                                        MONS_YELLOW_DRACONIAN);
69     drac->colour = mons_class_colour(drac->base_monster);
70 
71     // Get rid of the old breath weapon first.
72     monster_spells oldspells = drac->spells;
73     drac->spells.clear();
74     for (const mon_spell_slot &slot : oldspells)
75         if (!(slot.flags & MON_SPELL_BREATH))
76             drac->spells.push_back(slot);
77 
78     drac->spells.push_back(drac_breath(draco_or_demonspawn_subspecies(*drac)));
79 }
80 
boris_covet_orb(monster * boris)81 void boris_covet_orb(monster* boris)
82 {
83     if (boris->type != MONS_BORIS || !player_has_orb())
84         return;
85 
86     if (boris->observable())
87         simple_monster_message(*boris, " is empowered by the presence of the orb!");
88 
89     boris->add_ench(mon_enchant(ENCH_HASTE, 1, boris, INFINITE_DURATION));
90     boris->add_ench(mon_enchant(ENCH_EMPOWERED_SPELLS, 1, boris,
91                     INFINITE_DURATION));
92 }
93 
ugly_thing_mutate(monster & ugly,bool force)94 bool ugly_thing_mutate(monster& ugly, bool force)
95 {
96     if (!(one_chance_in(9) || force))
97         return false;
98 
99     const char* msg = nullptr;
100     // COLOUR_UNDEF means "pick a random colour".
101     colour_t new_colour = COLOUR_UNDEF;
102 
103     for (fair_adjacent_iterator ai(ugly.pos()); ai && !msg; ++ai)
104     {
105         const actor* act = actor_at(*ai);
106 
107         if (!act)
108             continue;
109 
110         if (act->is_player() && get_contamination_level())
111             msg = " basks in your mutagenic energy and changes!";
112         else if (mons_genus(act->type) == MONS_UGLY_THING)
113         {
114             msg = " basks in the mutagenic energy from its kin and changes!";
115             const colour_t other_colour =
116                 make_low_colour(act->as_monster()->colour);
117             if (make_low_colour(ugly.colour) != other_colour)
118                 new_colour = other_colour;
119         }
120     }
121 
122     if (force)
123         msg = " basks in the mutagenic energy and changes!";
124 
125     if (!msg) // didn't find anything to mutate off of
126         return false;
127 
128     simple_monster_message(ugly, msg);
129     ugly.uglything_mutate(new_colour);
130     return true;
131 }
132 
133 // Inflict any enchantments the parent slime has on its offspring,
134 // leaving durations unchanged, I guess. -cao
_split_ench_durations(monster * initial_slime,monster * split_off)135 static void _split_ench_durations(monster* initial_slime, monster* split_off)
136 {
137     for (const auto &entry : initial_slime->enchantments)
138         // Don't let new slimes inherit being held by a web or net
139         if (entry.second.ench != ENCH_HELD)
140             split_off->add_ench(entry.second);
141 }
142 
143 // What to do about any enchantments these two creatures may have?
144 // For now, we are averaging the durations, weighted by slime size
145 // or by hit dice, depending on usehd.
merge_ench_durations(monster & initial,monster & merge_to,bool usehd)146 void merge_ench_durations(monster& initial, monster& merge_to, bool usehd)
147 {
148     int initial_count = usehd ? initial.get_hit_dice() : initial.blob_size;
149     int merge_to_count = usehd ? merge_to.get_hit_dice() : merge_to.blob_size;
150     int total_count = initial_count + merge_to_count;
151 
152     mon_enchant_list &from_ench = initial.enchantments;
153 
154     for (auto &entry : from_ench)
155     {
156         // Does the other creature have this enchantment as well?
157         const mon_enchant temp = merge_to.get_ench(entry.first);
158         // If not, use duration 0 for their part of the average.
159         const bool no_initial = temp.ench == ENCH_NONE;
160         const int duration = no_initial ? 0 : temp.duration;
161 
162         entry.second.duration = (entry.second.duration * initial_count
163                                  + duration * merge_to_count)/total_count;
164 
165         if (!entry.second.duration)
166             entry.second.duration = 1;
167 
168         if (no_initial)
169             merge_to.add_ench(entry.second);
170         else
171             merge_to.update_ench(entry.second);
172     }
173 
174     for (auto &entry : merge_to.enchantments)
175     {
176         if (from_ench.find(entry.first) == from_ench.end()
177             && entry.second.duration > 1)
178         {
179             entry.second.duration = (merge_to_count * entry.second.duration)
180                                     / total_count;
181 
182             merge_to.update_ench(entry.second);
183         }
184     }
185 }
186 
187 // Calculate slime creature hp based on how many are merged.
_stats_from_blob_count(monster * slime,float max_per_blob,float current_per_blob)188 static void _stats_from_blob_count(monster* slime, float max_per_blob,
189                                    float current_per_blob)
190 {
191     slime->max_hit_points = (int)(slime->blob_size * max_per_blob);
192     slime->hit_points = (int)(slime->blob_size * current_per_blob);
193 }
194 
195 // Create a new slime creature at 'target', and split 'thing''s hp and
196 // merge count with the new monster.
197 // Now it returns index of new slime (-1 if it fails).
_do_split(monster * thing,const coord_def & target)198 static monster* _do_split(monster* thing, const coord_def & target)
199 {
200     ASSERT(thing); // XXX: change to monster &thing
201     ASSERT(thing->alive());
202 
203     // Create a new slime.
204     mgen_data new_slime_data = mgen_data(thing->type,
205                                          SAME_ATTITUDE(thing),
206                                          target,
207                                          thing->foe,
208                                          MG_FORCE_PLACE);
209 
210     // Don't explicitly announce the child slime coming into view if you
211     // saw the split that created it
212     if (you.can_see(*thing))
213         new_slime_data.extra_flags |= MF_WAS_IN_VIEW;
214 
215     monster *new_slime = create_monster(new_slime_data);
216 
217     if (!new_slime)
218         return 0;
219 
220     if (you.can_see(*thing))
221         mprf("%s splits.", thing->name(DESC_A).c_str());
222 
223     // Inflict the new slime with any enchantments on the parent.
224     _split_ench_durations(thing, new_slime);
225     new_slime->attitude = thing->attitude;
226     new_slime->behaviour = thing->behaviour;
227     new_slime->flags = thing->flags;
228     new_slime->props = thing->props;
229     new_slime->summoner = thing->summoner;
230     if (thing->props.exists("blame"))
231         new_slime->props["blame"] = thing->props["blame"].get_vector();
232 
233     int split_off = thing->blob_size / 2;
234     float max_per_blob = thing->max_hit_points / float(thing->blob_size);
235     float current_per_blob = thing->hit_points / float(thing->blob_size);
236 
237     thing->blob_size -= split_off;
238     new_slime->blob_size = split_off;
239 
240     new_slime->set_hit_dice(thing->get_experience_level());
241 
242     _stats_from_blob_count(thing, max_per_blob, current_per_blob);
243     _stats_from_blob_count(new_slime, max_per_blob, current_per_blob);
244 
245     if (crawl_state.game_is_arena())
246         arena_split_monster(thing, new_slime);
247 
248     ASSERT(thing->alive());
249     ASSERT(new_slime->alive());
250 
251     return new_slime;
252 }
253 
254 // Cause a monster to lose a turn. has_gone should be true if the
255 // monster has already moved this turn.
_lose_turn(monster * mons,bool has_gone)256 static void _lose_turn(monster* mons, bool has_gone)
257 {
258     const monsterentry* entry = get_monster_data(mons->type);
259 
260     // We want to find out if mons will move next time it has a turn
261     // (assuming for the sake of argument the next delay is 10). If it's
262     // already going to lose a turn we don't need to do anything.
263     mons->speed_increment += entry->speed;
264     if (!mons->has_action_energy())
265         return;
266     mons->speed_increment -= entry->speed;
267 
268     mons->speed_increment -= entry->energy_usage.move;
269 
270     // So we subtracted some energy above, but if mons hasn't moved yet
271     // /this turn, that will just cancel its turn in this round of
272     // world_reacts().
273     if (!has_gone)
274         mons->speed_increment -= entry->energy_usage.move;
275 }
276 
277 // Actually merge two slime creatures, pooling their hp, etc.
278 // initial_slime is the one that gets killed off by this process.
_do_merge_slimes(monster * initial_slime,monster * merge_to)279 static void _do_merge_slimes(monster* initial_slime, monster* merge_to)
280 {
281     const string old_name = merge_to->name(DESC_A);
282     const bool merge_to_was_visible = you.can_see(*merge_to);
283 
284     // Combine enchantment durations.
285     merge_ench_durations(*initial_slime, *merge_to);
286 
287     merge_to->blob_size += initial_slime->blob_size;
288     merge_to->max_hit_points += initial_slime->max_hit_points;
289     merge_to->hit_points += initial_slime->hit_points;
290 
291     // Merge monster flags (mostly so that MF_CREATED_NEUTRAL, etc. are
292     // passed on if the merged slime subsequently splits. Hopefully
293     // this won't do anything weird.
294     merge_to->flags |= initial_slime->flags;
295 
296     // Merging costs the combined slime some energy. The idea is that if 2
297     // slimes merge you can gain a space by moving away the turn after (maybe
298     // this is too nice but there will probably be a lot of complaints about
299     // the damage on higher level slimes). We see if mons has gone already by
300     // checking its mindex (this works because handle_monsters just iterates
301     // over env.mons in ascending order).
302     _lose_turn(merge_to, merge_to->mindex() < initial_slime->mindex());
303 
304     // Overwrite the state of the slime getting merged into, because it
305     // might have been resting or something.
306     merge_to->behaviour = initial_slime->behaviour;
307     merge_to->foe = initial_slime->foe;
308 
309     behaviour_event(merge_to, ME_EVAL);
310 
311     // Messaging cases:
312     // 1. MT & I were both visible & still are
313     // 2. MT was visible, I wasn't but now both are
314     // 3. MT was visible, I wasn't and now both aren't
315     // 4. MT wasn't visible, I was and now both are
316     // 5. MT and I weren't visible & still aren't
317     if (merge_to_was_visible)
318     {
319         if (you.can_see(*merge_to))
320         {
321             // cases 1 and 2
322             mprf("Two slime creatures merge to form %s.",
323                  merge_to->name(DESC_A).c_str());
324         }
325         else
326         {
327             // case 3
328             mprf("Something merges into %s, and it vanishes!",
329                  old_name.c_str());
330         }
331 
332         flash_view_delay(UA_MONSTER, LIGHTGREEN, 150);
333     }
334     else if (you.can_see(*initial_slime))
335     {
336         // case 4
337         mprf("%s merges with something you can't see.",
338              initial_slime->name(DESC_A).c_str());
339     }
340     // case 5 (no-op)
341 
342     // Have to 'kill' the slime doing the merging.
343     monster_die(*initial_slime, KILL_DISMISSED, NON_MONSTER, true);
344 }
345 
346 // Slime creatures can split but not merge under these conditions.
_unoccupied_slime(monster * thing)347 static bool _unoccupied_slime(monster* thing)
348 {
349     return thing->asleep() || mons_is_wandering(*thing)
350            || thing->foe == MHITNOT;
351 }
352 
353 // Slime creatures cannot split or merge under these conditions.
_disabled_merge(monster * thing)354 static bool _disabled_merge(monster* thing)
355 {
356     return !thing
357            || mons_is_fleeing(*thing)
358            || mons_is_confused(*thing)
359            || thing->paralysed();
360 }
361 
362 // See if there are any appropriate adjacent slime creatures for 'thing'
363 // to merge with. If so, carry out the merge.
364 //
365 // A slime creature will merge if there is an adjacent slime, merging
366 // onto that slime would reduce the distance to the original slime's
367 // target, and there are no empty squares that would also reduce the
368 // distance to the target.
_slime_merge(monster * thing)369 static bool _slime_merge(monster* thing)
370 {
371     if (!thing || _disabled_merge(thing) || _unoccupied_slime(thing))
372         return false;
373 
374     int max_slime_merge = 5;
375     int target_distance = grid_distance(thing->target, thing->pos());
376 
377     // Check for adjacent slime creatures.
378     monster* merge_target = nullptr;
379     for (fair_adjacent_iterator ai(thing->pos()); ai; ++ai)
380     {
381         // If this square won't reduce the distance to our target, don't
382         // look for a potential merge, and don't allow this square to
383         // prevent a merge if empty.
384         if (grid_distance(thing->target, *ai) >= target_distance)
385             continue;
386 
387         // Don't merge if there is an open square that reduces distance
388         // to target, even if we found a possible slime to merge with.
389         if (!actor_at(*ai)
390             && mons_class_can_pass(MONS_SLIME_CREATURE, env.grid(*ai)))
391         {
392             return false;
393         }
394 
395         // Is there a slime creature on this square we can consider
396         // merging with?
397         monster* other_thing = monster_at(*ai);
398         if (!merge_target
399             && other_thing
400             && other_thing->type == MONS_SLIME_CREATURE
401             && other_thing->attitude == thing->attitude
402             && other_thing->has_ench(ENCH_CHARM) == thing->has_ench(ENCH_CHARM)
403             && other_thing->has_ench(ENCH_HEXED) == thing->has_ench(ENCH_HEXED)
404             && other_thing->is_summoned() == thing->is_summoned()
405             && !other_thing->is_shapeshifter()
406             && !_disabled_merge(other_thing))
407         {
408             // We can potentially merge if doing so won't take us over
409             // the merge cap.
410             int new_blob_count = other_thing->blob_size + thing->blob_size;
411             if (new_blob_count <= max_slime_merge)
412                 merge_target = other_thing;
413         }
414     }
415 
416     // We found a merge target and didn't find an open square that
417     // would reduce distance to target, so we can actually merge.
418     if (merge_target)
419     {
420         _do_merge_slimes(thing, merge_target);
421         return true;
422     }
423 
424     // No adjacent slime creatures we could merge with.
425     return false;
426 }
427 
_slime_can_spawn(const coord_def target)428 static bool _slime_can_spawn(const coord_def target)
429 {
430     return mons_class_can_pass(MONS_SLIME_CREATURE, env.grid(target))
431            && !actor_at(target);
432 }
433 
434 // See if slime creature 'thing' can split, and carry out the split if
435 // we can find a square to place the new slime creature on.
_slime_split(monster * thing,bool force_split)436 static monster *_slime_split(monster* thing, bool force_split)
437 {
438     if (!thing || thing->blob_size <= 1 || thing->hit_points < 4
439         || (coinflip() && !force_split) // Don't make splitting quite so reliable. (jpeg)
440         || _disabled_merge(thing))
441     {
442         return 0;
443     }
444 
445     const coord_def origin  = thing->pos();
446 
447     const actor* foe        = thing->get_foe();
448     const bool has_foe      = (foe != nullptr && thing->can_see(*foe));
449     const coord_def foe_pos = (has_foe ? foe->position : coord_def(0,0));
450     const int old_dist      = (has_foe ? grid_distance(origin, foe_pos) : 0);
451 
452     if ((has_foe && old_dist > 1) && !force_split)
453     {
454         // If we're not already adjacent to the foe, check whether we can
455         // move any closer. If so, do that rather than splitting.
456         for (adjacent_iterator ri(origin); ri; ++ri)
457         {
458             if (_slime_can_spawn(*ri)
459                 && grid_distance(*ri, foe_pos) < old_dist)
460             {
461                 return 0;
462             }
463         }
464     }
465 
466     // Anywhere we can place an offspring?
467     for (fair_adjacent_iterator ai(origin); ai; ++ai)
468     {
469         // Don't split if this increases the distance to the target.
470         if (has_foe && grid_distance(*ai, foe_pos) > old_dist
471             && !force_split)
472         {
473             continue;
474         }
475 
476         if (_slime_can_spawn(*ai))
477         {
478             // This can fail if placing a new monster fails. That
479             // probably means we have too many monsters on the level,
480             // so just return in that case.
481             return _do_split(thing, *ai);
482         }
483     }
484 
485     // No free squares.
486     return 0;
487 }
488 
489 // See if a given slime creature can split or merge.
_slime_split_merge(monster * thing)490 static bool _slime_split_merge(monster* thing)
491 {
492     // No merging/splitting shapeshifters.
493     if (!thing
494         || thing->is_shapeshifter()
495         || thing->type != MONS_SLIME_CREATURE)
496     {
497         return false;
498     }
499 
500     if (_slime_split(thing, false))
501         return true;
502 
503     return _slime_merge(thing);
504 }
505 
506 // Splits and polymorphs merged slime creatures.
slime_creature_polymorph(monster & slime,poly_power_type power)507 bool slime_creature_polymorph(monster& slime, poly_power_type power)
508 {
509     ASSERT(slime.type == MONS_SLIME_CREATURE);
510 
511     if (slime.blob_size > 1 && x_chance_in_y(4, 5))
512     {
513         int count = 0;
514         while (slime.blob_size > 1 && count <= 10)
515         {
516             if (monster *splinter = _slime_split(&slime, true))
517                 slime_creature_polymorph(*splinter, power);
518             else
519                 break;
520             count++;
521         }
522     }
523 
524     return monster_polymorph(&slime, RANDOM_POLYMORPH_MONSTER, power);
525 }
526 
_starcursed_split(monster * mon)527 static bool _starcursed_split(monster* mon)
528 {
529     if (!mon || mon->blob_size <= 1 || mon->type != MONS_STARCURSED_MASS)
530         return false;
531 
532     // Anywhere we can place an offspring?
533     for (fair_adjacent_iterator ai(mon->pos()); ai; ++ai)
534     {
535         if (mons_class_can_pass(MONS_STARCURSED_MASS, env.grid(*ai))
536             && !actor_at(*ai))
537         {
538             return _do_split(mon, *ai);
539         }
540     }
541 
542     // No free squares.
543     return false;
544 }
545 
_starcursed_scream(monster * mon,actor * target)546 static void _starcursed_scream(monster* mon, actor* target)
547 {
548     if (!target || !target->alive())
549         return;
550 
551     //Gather the chorus
552     vector<monster*> chorus;
553 
554     for (monster_near_iterator mi(target->pos(), LOS_NO_TRANS); mi; ++mi)
555     {
556         if (mi->type == MONS_STARCURSED_MASS)
557             chorus.push_back(*mi);
558     }
559 
560     int n = chorus.size();
561     int dam = 0; int stun = 0;
562     const char* message = nullptr;
563 
564     dprf("Chorus size: %d", n);
565 
566     if (n > 7)
567     {
568         message = "A cacophony of accursed wailing tears at your sanity!";
569         if (coinflip())
570             stun = 2;
571     }
572     else if (n > 4)
573     {
574         message = "A deafening chorus of shrieks assaults your mind!";
575         if (one_chance_in(3))
576             stun = 1;
577     }
578     else if (n > 1)
579         message = "A chorus of shrieks assaults your mind.";
580     else
581         message = "The starcursed mass shrieks in your mind.";
582 
583     dam = 4 + random2(5) + random2(n * 3 / 2);
584 
585     if (!target->is_player())
586     {
587         if (you.see_cell(target->pos()))
588         {
589             mprf(target->as_monster()->friendly() ? MSGCH_FRIEND_SPELL
590                                                   : MSGCH_MONSTER_SPELL,
591                  "%s writhes in pain as voices assail %s mind.",
592                  target->name(DESC_THE).c_str(),
593                  target->pronoun(PRONOUN_POSSESSIVE).c_str());
594         }
595     }
596     else
597         mprf(MSGCH_MONSTER_SPELL, "%s", message);
598     target->hurt(mon, dam, BEAM_MISSILE, KILLED_BY_BEAM, "",
599                  "accursed screaming");
600 
601     if (stun && target->alive())
602         target->paralyse(mon, stun, "accursed screaming");
603 
604     for (monster *voice : chorus)
605         if (voice->alive())
606             voice->add_ench(mon_enchant(ENCH_SCREAMED, 1, voice, 1));
607 }
608 
_will_starcursed_scream(monster * mon)609 static bool _will_starcursed_scream(monster* mon)
610 {
611     int n = 0;
612 
613     for (monster_near_iterator mi(mon->pos(), LOS_NO_TRANS); mi; ++mi)
614     {
615         if (mi->type != MONS_STARCURSED_MASS)
616             continue;
617 
618         // Don't scream if any part of the chorus has a scream timeout
619         // (This prevents it being staggered into a bunch of mini-screams)
620         if (mi->has_ench(ENCH_SCREAMED))
621             return false;
622         else
623             n++;
624     }
625 
626     return one_chance_in(n);
627 }
628 
629 /**
630  * Can a lost soul revive the given monster, assuming one is nearby?
631  *
632  * @param mons      The monster potentially being revived.
633  * @return          Whether it's a possible target for lost souls.
634  */
_lost_soul_affectable(const monster & mons)635 static bool _lost_soul_affectable(const monster &mons)
636 {
637     // zombies are boring
638     if (mons_is_zombified(mons))
639         return false;
640 
641     // undead can be reknit, naturals ghosted, everyone else is out of luck
642     if (!(mons.holiness() & (MH_UNDEAD | MH_NATURAL)))
643         return false;
644 
645     // already been revived once
646     if (testbits(mons.flags, MF_SPECTRALISED))
647         return false;
648 
649     // just silly
650     if (mons.type == MONS_LOST_SOUL)
651         return false;
652 
653     // for ely, I guess?
654     if (is_good_god(mons.god))
655         return false;
656 
657     if (mons.is_summoned())
658         return false;
659 
660     if (!mons_class_gives_xp(mons.type))
661         return false;
662 
663     return true;
664 }
665 
666 // Is it worth sacrificing ourselves to revive this monster? This is based
667 // on monster HD, with a lower chance for weaker monsters so long as other
668 // monsters are present, but always true if there are only as many valid
669 // targets as nearby lost souls.
_worthy_sacrifice(monster * soul,const monster * target)670 static bool _worthy_sacrifice(monster* soul, const monster* target)
671 {
672     int count = 0;
673     for (monster_near_iterator mi(soul, LOS_NO_TRANS); mi; ++mi)
674     {
675         if (_lost_soul_affectable(**mi))
676             ++count;
677         else if (mi->type == MONS_LOST_SOUL)
678             --count;
679     }
680 
681     const int target_hd = target->get_experience_level();
682     return count <= -1 || target_hd > 9
683            || x_chance_in_y(target_hd * target_hd * target_hd, 1200);
684 }
685 
686 /**
687  * Check to see if the given monster can be revived by lost souls (if it's a
688  * valid target for revivication & if there are any lost souls nearby), and
689  * revive it if so.
690  *
691  * @param mons  The monster in question.
692  * @return      Whether the monster was revived/reknitted, or whether it
693  *              remains dead (dying?).
694  */
lost_soul_revive(monster & mons,killer_type killer)695 bool lost_soul_revive(monster& mons, killer_type killer)
696 {
697     if (killer == KILL_RESET
698         || killer == KILL_DISMISSED
699         || killer == KILL_BANISHED)
700     {
701         return false;
702     }
703 
704     if (!_lost_soul_affectable(mons))
705         return false;
706 
707     for (monster_near_iterator mi(&mons, LOS_NO_TRANS); mi; ++mi)
708     {
709         if (mi->type != MONS_LOST_SOUL || !mons_aligned(&mons, *mi))
710             continue;
711 
712         if (!_worthy_sacrifice(*mi, &mons))
713             continue;
714 
715         // save this before we revive it
716         const string revivee_name = mons.name(DESC_THE);
717         const bool was_alive = bool(mons.holiness() & MH_NATURAL);
718 
719         // In this case the old monster will be replaced by
720         // a ghostly version, so we should record defeat now.
721         if (was_alive)
722         {
723             record_monster_defeat(&mons, killer);
724             remove_unique_annotation(&mons);
725         }
726 
727         targeter_radius hitfunc(*mi, LOS_SOLID);
728         flash_view_delay(UA_MONSTER, GREEN, 200, &hitfunc);
729 
730         mons.heal(mons.max_hit_points);
731         mons.del_ench(ENCH_CONFUSION, true);
732         mons.timeout_enchantments(10);
733 
734         coord_def newpos = mi->pos();
735         if (was_alive)
736         {
737             mons.move_to_pos(newpos);
738             mons.flags |= (MF_SPECTRALISED | MF_FAKE_UNDEAD);
739         }
740 
741         // check if you can see the monster *after* it maybe moved
742         if (you.can_see(mons))
743         {
744             if (!was_alive)
745             {
746                 mprf("%s sacrifices itself to reknit %s!",
747                      mi->name(DESC_THE).c_str(),
748                      revivee_name.c_str());
749             }
750             else
751             {
752                 mprf("%s assumes the form of %s%s!",
753                      mi->name(DESC_THE).c_str(),
754                      revivee_name.c_str(),
755                      (mi->is_summoned() ? " and becomes anchored to this"
756                       " world" : ""));
757             }
758         }
759 
760         monster_die(**mi, KILL_MISC, -1, true);
761 
762         return true;
763     }
764 
765     return false;
766 }
767 
treant_release_fauna(monster & mons)768 void treant_release_fauna(monster& mons)
769 {
770     // FIXME: this should be a fineff, at least when called from monster_die.
771     int count = mons.mangrove_pests;
772     bool created = false;
773 
774     monster_type fauna_t = MONS_HORNET;
775 
776     mon_enchant abj = mons.get_ench(ENCH_ABJ);
777 
778     for (int i = 0; i < count; ++i)
779     {
780         mgen_data fauna_data(fauna_t, SAME_ATTITUDE(&mons),
781                             mons.pos(),  mons.foe);
782         fauna_data.set_summoned(&mons, 0, SPELL_NO_SPELL);
783         fauna_data.extra_flags |= MF_WAS_IN_VIEW;
784         monster* fauna = create_monster(fauna_data);
785 
786         if (fauna)
787         {
788             fauna->props["band_leader"].get_int() = mons.mid;
789 
790             // Give released fauna the same summon duration as their 'parent'
791             if (abj.ench != ENCH_NONE)
792                 fauna->add_ench(abj);
793 
794             created = true;
795             mons.mangrove_pests--;
796         }
797     }
798 
799     if (created && you.can_see(mons))
800     {
801         mprf("Angry insects surge out from beneath %s foliage!",
802              mons.name(DESC_ITS).c_str());
803     }
804 }
805 
_adj_to_tree(coord_def p)806 static bool _adj_to_tree(coord_def p)
807 {
808     for (adjacent_iterator ai(p); ai; ++ai)
809         if (feat_is_tree(env.grid(*ai)))
810             return true;
811     return false;
812 }
813 
_find_nearer_tree(coord_def cur_loc,coord_def target)814 static coord_def _find_nearer_tree(coord_def cur_loc, coord_def target)
815 {
816     coord_def p = {0, 0};
817     int seen = 0;
818     // don't bother teleporting to something that's at the same distance
819     // from the target as you already are
820     int closest = grid_distance(cur_loc, target) - 1;
821     for (distance_iterator di(target); di; ++di)
822     {
823         const int dist = grid_distance(target, *di);
824         if (dist > closest)
825             break;
826 
827         if (!cell_see_cell(target, *di, LOS_NO_TRANS) // there might be a better iterator
828             || !_adj_to_tree(*di)
829             || !monster_habitable_grid(MONS_ELEIONOMA, env.grid(*di)))
830         {
831             continue;
832         }
833         // XXX: also check for dangerous clouds?
834 
835         closest = dist;
836 
837         seen++;
838         if (x_chance_in_y(1, seen))
839             p = *di;
840     }
841     return p;
842 }
843 
_mons_cast_abil(monster * mons,bolt & pbolt,spell_type spell_cast)844 static inline void _mons_cast_abil(monster* mons, bolt &pbolt,
845                                    spell_type spell_cast)
846 {
847     mons_cast(mons, pbolt, spell_cast, MON_SPELL_NATURAL);
848 }
849 
mon_special_ability(monster * mons)850 bool mon_special_ability(monster* mons)
851 {
852     bool used = false;
853 
854     const monster_type mclass = (mons_genus(mons->type) == MONS_DRACONIAN)
855                                   ? draco_or_demonspawn_subspecies(*mons)
856                                   : mons->type;
857 
858     // Slime creatures can split while out of sight.
859     if ((!mons->near_foe() || mons->asleep() || mons->submerged())
860          && mons->type != MONS_SLIME_CREATURE
861          && mons->type != MONS_LOST_SOUL)
862     {
863         return false;
864     }
865 
866     switch (mclass)
867     {
868     case MONS_UGLY_THING:
869     case MONS_VERY_UGLY_THING:
870         // A (very) ugly thing may mutate if it's next to other ones (or
871         // next to you if you're contaminated).
872         used = ugly_thing_mutate(*mons, false);
873         break;
874 
875     case MONS_SLIME_CREATURE:
876         // Slime creatures may split or merge depending on the
877         // situation.
878         used = _slime_split_merge(mons);
879         if (!mons->alive())
880             return true;
881         break;
882 
883     case MONS_BALL_LIGHTNING:
884         if (is_sanctuary(mons->pos()))
885             break;
886 
887         if (mons->attitude == ATT_HOSTILE
888             && grid_distance(you.pos(), mons->pos()) <= 2)
889         {
890             mons->suicide();
891             used = true;
892             break;
893         }
894 
895         for (monster_near_iterator targ(mons, LOS_NO_TRANS); targ; ++targ)
896         {
897             if (mons_aligned(mons, *targ) || mons_is_firewood(**targ)
898                 || grid_distance(mons->pos(), targ->pos()) > 2
899                 || !you.see_cell(targ->pos()))
900             {
901                 continue;
902             }
903 
904             if (!cell_is_solid(targ->pos()))
905             {
906                 mons->suicide();
907                 used = true;
908                 break;
909             }
910         }
911         break;
912 
913     case MONS_FOXFIRE:
914         if (is_sanctuary(mons->pos()))
915             break;
916 
917         if (mons->attitude == ATT_HOSTILE
918             && grid_distance(you.pos(), mons->pos()) == 1)
919         {
920             foxfire_attack(mons, &you);
921             check_place_cloud(CLOUD_FLAME, mons->pos(), 2, mons);
922             mons->suicide();
923             used = true;
924             break;
925         }
926 
927         for (monster_near_iterator targ(mons, LOS_NO_TRANS); targ; ++targ)
928         {
929             if (mons_aligned(mons, *targ) || mons_is_firewood(**targ)
930                 || grid_distance(mons->pos(), targ->pos()) > 1
931                 || !you.see_cell(targ->pos()))
932             {
933                 continue;
934             }
935 
936             if (!cell_is_solid(targ->pos()))
937             {
938                 foxfire_attack(mons, *targ);
939                 mons->suicide();
940                 used = true;
941                 break;
942             }
943         }
944         break;
945 
946     case MONS_SKY_BEAST:
947         if (one_chance_in(8))
948         {
949             // If we're invisible, become visible.
950             if (mons->invisible())
951             {
952                 mons->del_ench(ENCH_INVIS);
953                 place_cloud(CLOUD_RAIN, mons->pos(), 2, mons);
954             }
955             // Otherwise, go invisible.
956             else
957                 enchant_monster_invisible(mons, "flickers out of sight");
958         }
959         break;
960 
961     case MONS_STARCURSED_MASS:
962         if (x_chance_in_y(mons->blob_size,8) && x_chance_in_y(2,3)
963             && mons->hit_points >= 8)
964         {
965             _starcursed_split(mons), used = true;
966         }
967 
968         if (!mons_is_confused(*mons)
969                 && !is_sanctuary(mons->pos()) && !is_sanctuary(mons->target)
970                 && _will_starcursed_scream(mons)
971                 && coinflip())
972         {
973             _starcursed_scream(mons, actor_at(mons->target));
974             used = true;
975         }
976         break;
977 
978     case MONS_THORN_HUNTER:
979     {
980         // If we would try to move into a briar (that we might have just created
981         // defensively), let's see if we can shoot our foe through it instead
982         if (actor_at(mons->pos() + mons->props["mmov"].get_coord())
983             && actor_at(mons->pos() + mons->props["mmov"].get_coord())->type == MONS_BRIAR_PATCH
984             && !one_chance_in(3))
985         {
986             actor *foe = mons->get_foe();
987             if (foe && mons->can_see(*foe))
988             {
989                 bolt beem = setup_targetting_beam(*mons);
990                 beem.target = foe->pos();
991                 setup_mons_cast(mons, beem, SPELL_THORN_VOLLEY);
992 
993                 fire_tracer(mons, beem);
994                 if (mons_should_fire(beem))
995                 {
996                     make_mons_stop_fleeing(mons);
997                     _mons_cast_abil(mons, beem, SPELL_THORN_VOLLEY);
998                     used = true;
999                 }
1000             }
1001         }
1002         // Otherwise, if our foe is approaching us, we might want to raise a
1003         // defensive wall of brambles (use the number of brambles in the area
1004         // as some indication if we've already done this, and shouldn't repeat)
1005         else if (mons->props["foe_approaching"].get_bool() == true
1006                  && !mons_is_confused(*mons)
1007                  && coinflip())
1008         {
1009             int briar_count = 0;
1010             for (monster_near_iterator mi(mons, LOS_NO_TRANS); mi; ++mi)
1011             {
1012                 if (mi->type == MONS_BRIAR_PATCH
1013                     && grid_distance(mons->pos(), mi->pos()) > 3)
1014                 {
1015                     briar_count++;
1016                 }
1017             }
1018             if (briar_count < 4) // Probably no solid wall here
1019             {
1020                 bolt beem; // unused
1021                 _mons_cast_abil(mons, beem, SPELL_WALL_OF_BRAMBLES);
1022                 used = true;
1023             }
1024         }
1025     }
1026     break;
1027 
1028     case MONS_WATER_NYMPH:
1029     {
1030         if (one_chance_in(5))
1031         {
1032             actor *foe = mons->get_foe();
1033             if (foe && !feat_is_water(env.grid(foe->pos())))
1034             {
1035                 coord_def spot;
1036                 if (find_habitable_spot_near(foe->pos(), MONS_ELECTRIC_EEL, 3, false, spot)
1037                     && foe->pos().distance_from(spot)
1038                      < foe->pos().distance_from(mons->pos()))
1039                 {
1040                     if (mons->move_to_pos(spot))
1041                     {
1042                         simple_monster_message(*mons, " flows with the water.");
1043                         used = true;
1044                     }
1045                 }
1046             }
1047         }
1048     }
1049     break;
1050 
1051     case MONS_ELEIONOMA:
1052     {
1053         if (!one_chance_in(3))
1054             break;
1055 
1056         actor *foe = mons->get_foe();
1057         if (!foe)
1058             break;
1059 
1060         const int dist = grid_distance(foe->pos(), mons->pos());
1061         if (dist < 3)
1062             break;
1063 
1064         const coord_def target = _find_nearer_tree(mons->pos(), foe->pos());
1065         if (target.origin() || !mons->move_to_pos(target))
1066             break;
1067 
1068         simple_monster_message(*mons, " flows through the trees.");
1069         used = true;
1070     }
1071     break;
1072 
1073     case MONS_SHAMBLING_MANGROVE:
1074     {
1075         if (mons->hit_points * 2 < mons->max_hit_points
1076             && mons->mangrove_pests > 0)
1077         {
1078             treant_release_fauna(*mons);
1079             // Intentionally takes no energy; the creatures are flying free
1080             // on their own time.
1081         }
1082     }
1083     break;
1084 
1085     case MONS_GUARDIAN_GOLEM:
1086         if (mons->hit_points * 2 < mons->max_hit_points
1087              && !mons->has_ench(ENCH_INNER_FLAME))
1088         {
1089             simple_monster_message(*mons, " overheats!");
1090             mid_t act = mons->summoner == MID_PLAYER ? MID_YOU_FAULTLESS :
1091                         mons->summoner;
1092             mons->add_ench(mon_enchant(ENCH_INNER_FLAME, 0, actor_by_mid(act),
1093                                        INFINITE_DURATION));
1094         }
1095         break;
1096 
1097     default:
1098         break;
1099     }
1100 
1101     if (used)
1102         mons->lose_energy(EUT_SPECIAL);
1103 
1104     return used;
1105 }
1106 
guardian_golem_bond(monster & mons)1107 void guardian_golem_bond(monster& mons)
1108 {
1109     for (monster_near_iterator mi(&mons, LOS_NO_TRANS); mi; ++mi)
1110     {
1111         if (mons_aligned(&mons, *mi) && !mi->has_ench(ENCH_CHARM)
1112             && *mi != &mons)
1113         {
1114             mi->add_ench(mon_enchant(ENCH_INJURY_BOND, 1, &mons, INFINITE_DURATION));
1115         }
1116     }
1117 }
1118