Use cell_is_solid where appropriate.
[crawl:crawl.git] / crawl-ref / source / mon-stuff.cc
1 /**
2  * @file
3  * @brief Misc monster related functions.
4 **/
5
6 #include "AppHdr.h"
7 #include <math.h>
8 #include "mon-stuff.h"
9
10 #include "act-iter.h"
11 #include "areas.h"
12 #include "arena.h"
13 #include "art-enum.h"
14 #include "artefact.h"
15 #include "attitude-change.h"
16 #include "cloud.h"
17 #include "cluautil.h"
18 #include "coordit.h"
19 #include "database.h"
20 #include "delay.h"
21 #include "dactions.h"
22 #include "describe.h"
23 #include "dgnevent.h"
24 #include "dgn-overview.h"
25 #include "dlua.h"
26 #include "dungeon.h"
27 #include "effects.h"
28 #include "env.h"
29 #include "exclude.h"
30 #include "fprop.h"
31 #include "files.h"
32 #include "food.h"
33 #include "godabil.h"
34 #include "godcompanions.h"
35 #include "godconduct.h"
36 #include "hints.h"
37 #include "hiscores.h"
38 #include "itemname.h"
39 #include "itemprop.h"
40 #include "items.h"
41 #include "kills.h"
42 #include "libutil.h"
43 #include "losglobal.h"
44 #include "makeitem.h"
45 #include "mapmark.h"
46 #include "message.h"
47 #include "mgen_data.h"
48 #include "misc.h"
49 #include "mon-abil.h"
50 #include "mon-behv.h"
51 #include "mon-death.h"
52 #include "mon-place.h"
53 #include "mon-speak.h"
54 #include "notes.h"
55 #include "ouch.h"
56 #include "player.h"
57 #include "random.h"
58 #include "religion.h"
59 #include "shout.h"
60 #include "spl-damage.h"
61 #include "spl-miscast.h"
62 #include "spl-summoning.h"
63 #include "spl-util.h"
64 #include "state.h"
65 #include "stuff.h"
66 #include "target.h"
67 #include "teleport.h"
68 #include "terrain.h"
69 #include "transform.h"
70 #include "traps.h"
71 #include "unwind.h"
72 #include "view.h"
73 #include "viewchar.h"
74 #include "xom.h"
75
76 #include <vector>
77 #include <algorithm>
78
79 static bool _wounded_damaged(mon_holy_type holi);
80 static int _calc_player_experience(const monster* mons);
81
82 dungeon_feature_type get_mimic_feat(const monster* mimic)
83 {
84     if (mimic->props.exists("feat_type"))
85         return static_cast<dungeon_feature_type>(mimic->props["feat_type"].get_short());
86     else
87         return DNGN_FLOOR;
88 }
89
90 bool feature_mimic_at(const coord_def &c)
91 {
92     return map_masked(c, MMT_MIMIC);
93 }
94
95 item_def* item_mimic_at(const coord_def &c)
96 {
97     for (stack_iterator si(c); si; ++si)
98         if (si->flags & ISFLAG_MIMIC)
99             return &*si;
100     return NULL;
101 }
102
103 bool mimic_at(const coord_def &c)
104 {
105     return (feature_mimic_at(c) || item_mimic_at(c));
106 }
107
108 // Monster curses a random player inventory item.
109 bool curse_an_item(bool quiet)
110 {
111     // allowing these would enable mummy scumming
112     if (you_worship(GOD_ASHENZARI))
113     {
114         if (!quiet)
115         {
116             mprf(MSGCH_GOD, "The curse is absorbed by %s.",
117                  god_name(GOD_ASHENZARI).c_str());
118         }
119         return false;
120     }
121
122     int count = 0;
123     int item  = ENDOFPACK;
124
125     for (int i = 0; i < ENDOFPACK; i++)
126     {
127         if (!you.inv[i].defined())
128             continue;
129
130         if (is_weapon(you.inv[i])
131             || you.inv[i].base_type == OBJ_ARMOUR
132             || you.inv[i].base_type == OBJ_JEWELLERY)
133         {
134             if (you.inv[i].cursed())
135                 continue;
136
137             // Melded items cannot be cursed.
138             if (item_is_melded(you.inv[i]))
139                 continue;
140
141             // Item is valid for cursing, so we'll give it a chance.
142             count++;
143             if (one_chance_in(count))
144                 item = i;
145         }
146     }
147
148     // Any item to curse?
149     if (item == ENDOFPACK)
150         return false;
151
152     do_curse_item(you.inv[item], false);
153
154     return true;
155 }
156
157 // The default suitable() function for monster_drop_things().
158 bool is_any_item(const item_def& item)
159 {
160     return true;
161 }
162
163 void monster_drop_things(monster* mons,
164                           bool mark_item_origins,
165                           bool (*suitable)(const item_def& item),
166                           int owner_id)
167 {
168     // Drop weapons and missiles last (i.e., on top), so others pick up.
169     for (int i = NUM_MONSTER_SLOTS - 1; i >= 0; --i)
170     {
171         int item = mons->inv[i];
172
173         if (item != NON_ITEM && suitable(mitm[item]))
174         {
175             const bool summoned_item =
176                 testbits(mitm[item].flags, ISFLAG_SUMMONED);
177             if (summoned_item)
178             {
179                 item_was_destroyed(mitm[item], mons->mindex());
180                 destroy_item(item);
181             }
182             else
183             {
184                 if (mons->friendly() && mitm[item].defined())
185                     mitm[item].flags |= ISFLAG_DROPPED_BY_ALLY;
186
187                 if (mark_item_origins && mitm[item].defined())
188                     origin_set_monster(mitm[item], mons);
189
190                 if (mitm[item].props.exists("autoinscribe"))
191                 {
192                     add_inscription(mitm[item],
193                         mitm[item].props["autoinscribe"].get_string());
194                     mitm[item].props.erase("autoinscribe");
195                 }
196
197                 // Unrands held by fixed monsters would give awfully redundant
198                 // messages ("Cerebov hits you with the Sword of Cerebov."),
199                 // thus delay identification until drop/death.
200                 autoid_unrand(mitm[item]);
201
202                 // If a monster is swimming, the items are ALREADY
203                 // underwater.
204                 move_item_to_grid(&item, mons->pos(), mons->swimming());
205             }
206
207             mons->inv[i] = NON_ITEM;
208         }
209     }
210 }
211
212 // Initialises a corpse item using the given monster and monster type.
213 // The monster pointer is optional; you may pass in NULL to bypass
214 // per-monster checks.
215 //
216 // force_corpse forces creation of the corpse item even if the monster
217 // would not otherwise merit a corpse.
218 monster_type fill_out_corpse(const monster* mons,
219                              monster_type mtype,
220                              item_def& corpse,
221                              bool force_corpse)
222 {
223     ASSERT(!invalid_monster_type(mtype));
224     corpse.clear();
225
226     int summon_type;
227     if (mons && (mons->is_summoned(NULL, &summon_type)
228                     || (mons->flags & (MF_BANISHED | MF_HARD_RESET))))
229     {
230         return MONS_NO_MONSTER;
231     }
232
233     monster_type corpse_class = mons_species(mtype);
234
235     if (mons)
236     {
237         // If this was a corpse that was temporarily animated then turn the
238         // monster back into a corpse.
239         if (mons_class_is_zombified(mons->type)
240             && (summon_type == SPELL_ANIMATE_DEAD
241                 || summon_type == SPELL_ANIMATE_SKELETON
242                 || summon_type == MON_SUMM_ANIMATE))
243         {
244             corpse_class = mons_zombie_base(mons);
245         }
246
247         if (mons && mons_genus(mtype) == MONS_DRACONIAN)
248         {
249             if (mons->type == MONS_TIAMAT)
250                 corpse_class = MONS_DRACONIAN;
251             else
252                 corpse_class = draco_subspecies(mons);
253         }
254
255         if (mons->has_ench(ENCH_GLOWING_SHAPESHIFTER))
256             mtype = corpse_class = MONS_GLOWING_SHAPESHIFTER;
257         else if (mons->has_ench(ENCH_SHAPESHIFTER))
258             mtype = corpse_class = MONS_SHAPESHIFTER;
259     }
260
261     // Doesn't leave a corpse.
262     if (!mons_class_can_leave_corpse(corpse_class) && !force_corpse)
263         return MONS_NO_MONSTER;
264
265     corpse.flags       = 0;
266     corpse.base_type   = OBJ_CORPSES;
267     corpse.plus        = corpse_class;
268     corpse.plus2       = 0;    // butcher work done
269     corpse.sub_type    = CORPSE_BODY;
270     corpse.special     = FRESHEST_CORPSE;  // rot time
271     corpse.quantity    = 1;
272     corpse.orig_monnum = mtype;
273
274     if (mtype == MONS_PLAGUE_SHAMBLER)
275         corpse.special = ROTTING_CORPSE;
276
277     if (mons)
278     {
279         corpse.props[MONSTER_HIT_DICE] = short(mons->hit_dice);
280         corpse.props[MONSTER_NUMBER]   = short(mons->number);
281         // XXX: Appears to be a safe conversion?
282         corpse.props[MONSTER_MID]      = int(mons->mid);
283     }
284
285     corpse.colour = mons_class_colour(corpse_class);
286     if (corpse.colour == BLACK)
287     {
288         if (mons)
289             corpse.colour = mons->colour;
290         else
291         {
292             // [ds] Ick: no easy way to get a monster's colour
293             // otherwise:
294             monster m;
295             m.type = mtype;
296             define_monster(&m);
297             corpse.colour = m.colour;
298         }
299     }
300
301     if (mons && !mons->mname.empty() && !(mons->flags & MF_NAME_NOCORPSE))
302     {
303         corpse.props[CORPSE_NAME_KEY] = mons->mname;
304         corpse.props[CORPSE_NAME_TYPE_KEY].get_int64() = mons->flags;
305     }
306     else if (mons_is_unique(mtype))
307     {
308         corpse.props[CORPSE_NAME_KEY] = mons_type_name(mtype, DESC_PLAIN);
309         corpse.props[CORPSE_NAME_TYPE_KEY].get_int64() = 0;
310     }
311
312     return corpse_class;
313 }
314
315 bool explode_corpse(item_def& corpse, const coord_def& where)
316 {
317     // Don't want chunks to show up behind the player.
318     los_def ld(where, opc_no_actor);
319
320     if (mons_class_leaves_hide(corpse.mon_type)
321         && mons_genus(corpse.mon_type) == MONS_DRAGON)
322     {
323         // Uh... dragon hide is tough stuff and it keeps the monster in
324         // one piece?  More importantly, it prevents a flavour feature
325         // from becoming a trap for the unwary.
326
327         return false;
328     }
329
330     ld.update();
331
332     const int max_chunks = get_max_corpse_chunks(corpse.mon_type);
333
334     int nchunks = 1 + random2(max_chunks);
335     nchunks = stepdown_value(nchunks, 4, 4, 12, 12);
336
337     int ntries = 0;
338
339     corpse.base_type = OBJ_FOOD;
340     corpse.sub_type  = FOOD_CHUNK;
341     if (is_bad_food(corpse))
342         corpse.flags |= ISFLAG_DROPPED;
343
344     int blood = nchunks * 3;
345
346     if (food_is_rotten(corpse))
347         blood /= 3;
348
349     blood_spray(where, corpse.mon_type, blood);
350
351     while (nchunks > 0 && ntries < 10000)
352     {
353         ++ntries;
354
355         coord_def cp = where;
356         cp.x += random_range(-LOS_RADIUS, LOS_RADIUS);
357         cp.y += random_range(-LOS_RADIUS, LOS_RADIUS);
358
359         dprf("Trying to scatter chunk to %d, %d...", cp.x, cp.y);
360
361         if (!in_bounds(cp))
362             continue;
363
364         if (!ld.see_cell(cp))
365             continue;
366
367         dprf("Cell is visible...");
368
369         if (cell_is_solid(cp) || actor_at(cp))
370             continue;
371
372         --nchunks;
373
374         dprf("Success");
375
376         copy_item_to_grid(corpse, cp);
377     }
378
379     return true;
380 }
381
382 // Returns the item slot of a generated corpse, or -1 if no corpse.
383 int place_monster_corpse(const monster* mons, bool silent,
384                          bool force)
385 {
386     // The game can attempt to place a corpse for an out-of-bounds monster
387     // if a shifter turns into a giant spore and explodes.  In this
388     // case we place no corpse since the explosion means anything left
389     // over would be scattered, tiny chunks of shifter.
390     if (!in_bounds(mons->pos()))
391         return -1;
392
393     // Don't attempt to place corpses within walls, either.
394     // Currently, this only applies to (shapeshifter) rock worms.
395     if (feat_is_wall(grd(mons->pos())))
396         return -1;
397
398     // If we were told not to leave a corpse, don't.
399     if (mons->props.exists("never_corpse"))
400         return -1;
401
402     item_def corpse;
403     const monster_type corpse_class = fill_out_corpse(mons, mons->type,
404                                                       corpse);
405
406     bool vault_forced = false;
407
408     // Don't place a corpse?  If a zombified monster is somehow capable
409     // of leaving a corpse, then always place it.
410     if (mons_class_is_zombified(mons->type))
411         force = true;
412
413     // "always_corpse" forces monsters to always generate a corpse upon
414     // their deaths.
415     if (mons->props.exists("always_corpse")
416         || mons_class_flag(mons->type, M_ALWAYS_CORPSE))
417     {
418         vault_forced = true;
419     }
420
421     if (corpse_class == MONS_NO_MONSTER
422         || (!force && !vault_forced && coinflip())
423         || (mons_corpse_effect(corpse_class) == CE_MUTAGEN
424            && !one_chance_in(3)))
425     {
426         return -1;
427     }
428
429     if (mons && mons_is_phoenix(mons))
430         corpse.props["destroy_xp"].get_int() = _calc_player_experience(mons);
431
432     int o = get_mitm_slot();
433
434     // Zotdef corpse creation forces cleanup, otherwise starvation
435     // kicks in. The magic number 9 is less than the magic number of
436     // 10 in get_mitm_slot which indicates that a cull will be initiated
437     // if a free slot can't be found.
438     if (o == NON_ITEM && crawl_state.game_is_zotdef())
439         o = get_mitm_slot(9);
440
441     if (o == NON_ITEM)
442     {
443         item_was_destroyed(corpse);
444         return -1;
445     }
446
447     mitm[o] = corpse;
448
449     origin_set_monster(mitm[o], mons);
450
451     if ((mons->flags & MF_EXPLODE_KILL) && explode_corpse(corpse, mons->pos()))
452     {
453         // We already have a spray of chunks.
454         item_was_destroyed(mitm[o]);
455         destroy_item(o);
456         return -1;
457     }
458
459     move_item_to_grid(&o, mons->pos(), !mons->swimming());
460
461     if (you.see_cell(mons->pos()))
462     {
463         if (force && !silent)
464         {
465             if (you.can_see(mons))
466                 simple_monster_message(mons, " turns back into a corpse!");
467             else
468             {
469                 mprf("%s appears out of nowhere!",
470                      mitm[o].name(DESC_A).c_str());
471             }
472         }
473         if (o != NON_ITEM && !silent)
474         {
475             const bool poison =
476                 (chunk_is_poisonous(mons_corpse_effect(corpse_class))
477                  && player_res_poison() <= 0);
478             hints_dissection_reminder(!poison);
479         }
480     }
481
482     return (o == NON_ITEM ? -1 : o);
483 }
484
485 static void _hints_inspect_kill()
486 {
487     if (Hints.hints_events[HINT_KILLED_MONSTER])
488         learned_something_new(HINT_KILLED_MONSTER);
489 }
490
491 static string _milestone_kill_verb(killer_type killer)
492 {
493     return (killer == KILL_BANISHED ? "banished" :
494             killer == KILL_PACIFIED ? "pacified" :
495             killer == KILL_ENSLAVED ? "enslaved" : "killed");
496 }
497
498 void record_monster_defeat(monster* mons, killer_type killer)
499 {
500     if (crawl_state.game_is_arena())
501         return;
502     if (killer == KILL_RESET || killer == KILL_DISMISSED)
503         return;
504     if (mons->has_ench(ENCH_FAKE_ABJURATION))
505         return;
506     if (MONST_INTERESTING(mons))
507     {
508         take_note(Note(NOTE_DEFEAT_MONSTER, mons->type, mons->friendly(),
509                        mons->full_name(DESC_A).c_str(),
510                        _milestone_kill_verb(killer).c_str()));
511     }
512     // XXX: See comment in monster_polymorph.
513     bool is_unique = mons_is_unique(mons->type);
514     if (mons->props.exists("original_was_unique"))
515         is_unique = mons->props["original_was_unique"].get_bool();
516     if (mons->type == MONS_PLAYER_GHOST)
517     {
518         monster_info mi(mons);
519         string milestone = _milestone_kill_verb(killer) + " the ghost of ";
520         milestone += get_ghost_description(mi, true);
521         milestone += ".";
522         mark_milestone("ghost", milestone);
523     }
524     // Or summoned uniques, which a summoned ghost is treated as {due}
525     else if (is_unique && !mons->is_summoned())
526     {
527         mark_milestone("uniq",
528                        _milestone_kill_verb(killer)
529                        + " "
530                        + mons->name(DESC_THE, true)
531                        + ".");
532     }
533 }
534
535 static int _calc_monster_experience(monster* victim, killer_type killer,
536                                     int killer_index)
537 {
538     const int experience = exper_value(victim);
539     const bool no_xp = victim->has_ench(ENCH_ABJ) || !experience || victim->has_ench(ENCH_FAKE_ABJURATION);
540     const bool created_friendly = testbits(victim->flags, MF_NO_REWARD);
541
542     if (no_xp || !MON_KILL(killer) || invalid_monster_index(killer_index))
543         return 0;
544
545     monster* mon = &menv[killer_index];
546     if (!mon->alive())
547         return 0;
548
549     if ((created_friendly && mon->friendly())
550         || mons_aligned(mon, victim))
551     {
552         return 0;
553     }
554
555     return experience;
556 }
557
558 static void _give_monster_experience(int experience, int killer_index)
559 {
560     if (experience <= 0 || invalid_monster_index(killer_index))
561         return;
562
563     monster* mon = &menv[killer_index];
564     if (!mon->alive())
565         return;
566
567     if (mon->gain_exp(experience))
568     {
569         if (!you_worship(GOD_SHINING_ONE) && !you_worship(GOD_BEOGH)
570             || player_under_penance()
571             || !one_chance_in(3))
572         {
573             return;
574         }
575
576         // Randomly bless the follower who gained experience.
577         if (you_worship(GOD_SHINING_ONE)
578                 && random2(you.piety) >= piety_breakpoint(0)
579             || you_worship(GOD_BEOGH)
580                 && random2(you.piety) >= piety_breakpoint(2))
581         {
582             bless_follower(mon);
583         }
584     }
585 }
586
587 static void _beogh_spread_experience(int exp)
588 {
589     int total_hd = 0;
590
591     for (monster_near_iterator mi(&you); mi; ++mi)
592     {
593         if (is_orcish_follower(*mi))
594             total_hd += mi->hit_dice;
595     }
596
597     if (total_hd > 0)
598     {
599         for (monster_near_iterator mi(&you); mi; ++mi)
600         {
601             if (is_orcish_follower(*mi))
602             {
603                 _give_monster_experience(exp * mi->hit_dice / total_hd,
604                                          mi->mindex());
605             }
606         }
607     }
608 }
609
610 static int _calc_player_experience(const monster* mons)
611 {
612     int experience = exper_value(mons);
613
614     const bool created_friendly = testbits(mons->flags, MF_NO_REWARD);
615     const bool was_neutral = testbits(mons->flags, MF_WAS_NEUTRAL);
616     const bool no_xp = mons->has_ench(ENCH_ABJ) || !experience || mons->has_ench(ENCH_FAKE_ABJURATION);
617     const bool already_got_half_xp = testbits(mons->flags, MF_GOT_HALF_XP);
618     const int half_xp = (experience + 1) / 2;
619
620     // We give double exp for shedu here, rather than artificially
621     // adjusting the modifier.
622     if (mons->flags & MF_BAND_MEMBER && mons_is_shedu(mons))
623         experience *= 2;
624
625     if (created_friendly || was_neutral || no_xp
626         || mons_is_shedu(mons) && shedu_pair_alive(mons))
627     {
628         return 0; // No xp if monster was created friendly or summoned.
629                     // or if you've only killed one of two shedu.
630     }
631
632     if (!mons->damage_total)
633     {
634         mprf(MSGCH_WARN, "Error, exp for monster with no damage: %s",
635              mons->name(DESC_PLAIN, true).c_str());
636         return 0;
637     }
638
639     dprf("Damage ratio: %1.1f/%d (%d%%)",
640          0.5 * mons->damage_friendly, mons->damage_total,
641          50 * mons->damage_friendly / mons->damage_total);
642     experience = (experience * mons->damage_friendly / mons->damage_total
643                   + 1) / 2;
644     ASSERT(mons->damage_friendly <= 2 * mons->damage_total);
645
646     // All deaths of hostiles grant at least 50% XP in ZotDef.
647     if (crawl_state.game_is_zotdef() && experience < half_xp)
648         experience = half_xp;
649
650     // Note: This doesn't happen currently since monsters with
651     //       MF_GOT_HALF_XP have always gone through pacification,
652     //       hence also have MF_WAS_NEUTRAL. [rob]
653     if (already_got_half_xp)
654     {
655         experience -= half_xp;
656         if (experience < 0)
657             experience = 0;
658     }
659
660     return experience;
661 }
662
663 static void _give_player_experience(int experience, killer_type killer,
664                                     bool pet_kill, bool was_visible)
665 {
666     if (experience <= 0 || crawl_state.game_is_arena())
667         return;
668
669     unsigned int exp_gain = 0;
670     gain_exp(experience, &exp_gain);
671
672     kill_category kc =
673             (killer == KILL_YOU || killer == KILL_YOU_MISSILE) ? KC_YOU :
674             (pet_kill)                                         ? KC_FRIENDLY :
675                                                                  KC_OTHER;
676     PlaceInfo& curr_PlaceInfo = you.get_place_info();
677     PlaceInfo  delta;
678
679     delta.mon_kill_num[kc]++;
680     delta.mon_kill_exp       += exp_gain;
681
682     you.global_info += delta;
683     you.global_info.assert_validity();
684
685     curr_PlaceInfo += delta;
686     curr_PlaceInfo.assert_validity();
687
688     // Give a message for monsters dying out of sight.
689     if (exp_gain > 0 && !was_visible)
690         mpr("You feel a bit more experienced.");
691
692     if (kc == KC_YOU && you_worship(GOD_BEOGH))
693         _beogh_spread_experience(experience / 2);
694 }
695
696 static void _give_experience(int player_exp, int monster_exp,
697                              killer_type killer, int killer_index,
698                              bool pet_kill, bool was_visible)
699 {
700     _give_player_experience(player_exp, killer, pet_kill, was_visible);
701     _give_monster_experience(monster_exp, killer_index);
702 }
703
704 static bool _is_pet_kill(killer_type killer, int i)
705 {
706     if (!MON_KILL(killer))
707         return false;
708
709     if (i == ANON_FRIENDLY_MONSTER)
710         return true;
711
712     if (invalid_monster_index(i))
713         return false;
714
715     const monster* m = &menv[i];
716     if (m->friendly()) // This includes enslaved monsters.
717         return true;
718
719     // Check if the monster was confused by you or a friendly, which
720     // makes casualties to this monster collateral kills.
721     const mon_enchant me = m->get_ench(ENCH_CONFUSION);
722     const mon_enchant me2 = m->get_ench(ENCH_INSANE);
723     return (me.ench == ENCH_CONFUSION
724             && (me.who == KC_YOU || me.who == KC_FRIENDLY)
725             || me2.ench == ENCH_INSANE
726                && (me2.who == KC_YOU || me2.who == KC_FRIENDLY));
727 }
728
729 int exp_rate(int killer)
730 {
731     // Damage by the spectral weapon is considered to be the player's damage ---
732     // so the player does not lose any exp from dealing damage with a spectral weapon summon
733     if (!invalid_monster_index(killer)
734         && menv[killer].type == MONS_SPECTRAL_WEAPON
735         && menv[killer].summoner == MID_PLAYER)
736     {
737         return 2;
738     }
739
740     if (killer == MHITYOU || killer == YOU_FAULTLESS)
741         return 2;
742
743     if (_is_pet_kill(KILL_MON, killer))
744         return 1;
745
746     return 0;
747 }
748
749 // Elyvilon will occasionally (5% chance) protect the life of one of
750 // your allies.
751 static bool _ely_protect_ally(monster* mons, killer_type killer)
752 {
753     if (!you_worship(GOD_ELYVILON))
754         return false;
755
756     if (!MON_KILL(killer) && !YOU_KILL(killer))
757         return false;
758
759     if (!mons->is_holy()
760             && mons->holiness() != MH_NATURAL
761         || !mons->friendly()
762         || !you.can_see(mons) // for simplicity
763         || !one_chance_in(20))
764     {
765         return false;
766     }
767
768     mons->hit_points = 1;
769
770     snprintf(info, INFO_SIZE, " protects %s from harm!",
771              mons->name(DESC_THE).c_str());
772
773     simple_god_message(info);
774
775     return true;
776 }
777
778 // Elyvilon retribution effect: Heal hostile monsters that were about to
779 // be killed by you or one of your friends.
780 static bool _ely_heal_monster(monster* mons, killer_type killer, int i)
781 {
782     god_type god = GOD_ELYVILON;
783
784     if (!you.penance[god] || !god_hates_your_god(god))
785         return false;
786
787     const int ely_penance = you.penance[god];
788
789     if (mons->friendly() || !one_chance_in(10))
790         return false;
791
792     if (MON_KILL(killer) && !invalid_monster_index(i))
793     {
794         monster* mon = &menv[i];
795         if (!mon->friendly() || !one_chance_in(3))
796             return false;
797
798         if (!mons_near(mons))
799             return false;
800     }
801     else if (!YOU_KILL(killer))
802         return false;
803
804     dprf("monster hp: %d, max hp: %d", mons->hit_points, mons->max_hit_points);
805
806     mons->hit_points = min(1 + random2(ely_penance/3), mons->max_hit_points);
807
808     dprf("new hp: %d, ely penance: %d", mons->hit_points, ely_penance);
809
810     snprintf(info, INFO_SIZE, "%s heals %s%s",
811              god_name(god, false).c_str(),
812              mons->name(DESC_THE).c_str(),
813              mons->hit_points * 2 <= mons->max_hit_points ? "." : "!");
814
815     god_speaks(god, info);
816     dec_penance(god, 1);
817
818     return true;
819 }
820
821 static bool _yred_enslave_soul(monster* mons, killer_type killer)
822 {
823     if (you_worship(GOD_YREDELEMNUL) && mons_enslaved_body_and_soul(mons)
824         && mons_near(mons) && killer != KILL_RESET
825         && killer != KILL_DISMISSED
826         && killer != KILL_BANISHED)
827     {
828         record_monster_defeat(mons, killer);
829         record_monster_defeat(mons, KILL_ENSLAVED);
830         yred_make_enslaved_soul(mons, player_under_penance());
831         return true;
832     }
833
834     return false;
835 }
836
837 static bool _beogh_forcibly_convert_orc(monster* mons, killer_type killer,
838                                         int i)
839 {
840     if (you_worship(GOD_BEOGH)
841         && mons_genus(mons->type) == MONS_ORC
842         && !mons->is_summoned() && !mons->is_shapeshifter()
843         && !player_under_penance() && you.piety >= piety_breakpoint(2)
844         && mons_near(mons) && !mons_is_god_gift(mons))
845     {
846         bool convert = false;
847
848         if (YOU_KILL(killer))
849             convert = true;
850         else if (MON_KILL(killer) && !invalid_monster_index(i))
851         {
852             monster* mon = &menv[i];
853             if (is_follower(mon) && !one_chance_in(3))
854                 convert = true;
855         }
856
857         // Orcs may convert to Beogh under threat of death, either from
858         // you or, less often, your followers.  In both cases, the
859         // checks are made against your stats.  You're the potential
860         // messiah, after all.
861         if (convert)
862         {
863 #ifdef DEBUG_DIAGNOSTICS
864             mprf(MSGCH_DIAGNOSTICS, "Death convert attempt on %s, HD: %d, "
865                  "your xl: %d",
866                  mons->name(DESC_PLAIN).c_str(),
867                  mons->hit_dice,
868                  you.experience_level);
869 #endif
870             if (random2(you.piety) >= piety_breakpoint(0)
871                 && random2(you.experience_level) >= random2(mons->hit_dice)
872                 // Bias beaten-up-conversion towards the stronger orcs.
873                 && random2(mons->hit_dice) > 2)
874             {
875                 beogh_convert_orc(mons, true, MON_KILL(killer));
876                 return true;
877             }
878         }
879     }
880
881     return false;
882 }
883
884 static bool _monster_avoided_death(monster* mons, killer_type killer, int i)
885 {
886     if (mons->max_hit_points <= 0 || mons->hit_dice < 1)
887         return false;
888
889     // Before the hp check since this should not care about the power of the
890     // finishing blow
891     if (mons->holiness() == MH_UNDEAD && !mons_is_zombified(mons)
892         && soul_aura(mons->pos())
893         && killer != KILL_RESET
894         && killer != KILL_DISMISSED
895         && killer != KILL_BANISHED)
896     {
897         if (lost_soul_revive(mons))
898             return true;
899     }
900
901     if (mons->hit_points < -25 || mons->hit_points < -mons->max_hit_points)
902         return false;
903
904     // Elyvilon specials.
905     if (_ely_protect_ally(mons, killer))
906         return true;
907     if (_ely_heal_monster(mons, killer, i))
908         return true;
909
910     // Yredelemnul special.
911     if (_yred_enslave_soul(mons, killer))
912         return true;
913
914     // Beogh special.
915     if (_beogh_forcibly_convert_orc(mons, killer, i))
916         return true;
917
918     return false;
919 }
920
921 static void _jiyva_died()
922 {
923     if (you_worship(GOD_JIYVA))
924         return;
925
926     add_daction(DACT_REMOVE_JIYVA_ALTARS);
927
928     if (!player_in_branch(BRANCH_SLIME_PITS))
929         return;
930
931     if (silenced(you.pos()))
932     {
933         god_speaks(GOD_JIYVA, "With an infernal shudder, the power ruling "
934                    "this place vanishes!");
935     }
936     else
937     {
938         god_speaks(GOD_JIYVA, "With infernal noise, the power ruling this "
939                    "place vanishes!");
940     }
941 }
942
943 static void _fire_monster_death_event(monster* mons,
944                                       killer_type killer,
945                                       int i, bool polymorph)
946 {
947     int type = mons->type;
948
949     // Treat whatever the Royal Jelly polymorphed into as if it were still
950     // the Royal Jelly (but if a player chooses the character name
951     // "shaped Royal Jelly" don't unlock the vaults when the player's
952     // ghost is killed).
953     if (mons->mname == "shaped Royal Jelly"
954         && !mons_is_pghost(mons->type))
955     {
956         type = MONS_ROYAL_JELLY;
957     }
958
959     if (!polymorph)
960     {
961         dungeon_events.fire_event(
962             dgn_event(DET_MONSTER_DIED, mons->pos(), 0,
963                       mons->mid, killer));
964     }
965
966     if (killer == KILL_BANISHED)
967         return;
968
969     los_monster_died(mons);
970
971     if (type == MONS_ROYAL_JELLY && !polymorph)
972     {
973         you.royal_jelly_dead = true;
974
975         if (jiyva_is_dead())
976             _jiyva_died();
977     }
978 }
979
980 static void _mummy_curse(monster* mons, killer_type killer, int index)
981 {
982     int pow;
983
984     switch (killer)
985     {
986         // Mummy killed by trap or something other than the player or
987         // another monster, so no curse.
988         case KILL_MISC:
989         // Mummy sent to the Abyss wasn't actually killed, so no curse.
990         case KILL_RESET:
991         case KILL_DISMISSED:
992         case KILL_BANISHED:
993             return;
994
995         default:
996             break;
997     }
998
999     switch (mons->type)
1000     {
1001         case MONS_MENKAURE:
1002         case MONS_MUMMY:          pow = 1; break;
1003         case MONS_GUARDIAN_MUMMY: pow = 3; break;
1004         case MONS_MUMMY_PRIEST:   pow = 8; break;
1005         case MONS_GREATER_MUMMY:  pow = 11; break;
1006         case MONS_KHUFU:          pow = 15; break;
1007
1008         default:
1009             mpr("Unknown mummy type.", MSGCH_DIAGNOSTICS);
1010             return;
1011     }
1012
1013     // beam code might give an index of MHITYOU for the player.
1014     if (YOU_KILL(killer))
1015         index = NON_MONSTER;
1016
1017     // Killed by a Zot trap, a god, etc.
1018     if (index != NON_MONSTER && invalid_monster_index(index))
1019         return;
1020
1021     actor* target;
1022     if (index == NON_MONSTER)
1023         target = &you;
1024     else
1025     {
1026         // Mummies committing suicide don't cause a death curse.
1027         if (index == mons->mindex())
1028             return;
1029         target = &menv[index];
1030     }
1031
1032     // Mummy was killed by a giant spore or ball lightning?
1033     if (!target->alive())
1034         return;
1035
1036     if ((mons->type == MONS_MUMMY || mons->type == MONS_MENKAURE)
1037         && YOU_KILL(killer))
1038     {
1039         // Kiku protects you from ordinary mummy curses.
1040         if (you_worship(GOD_KIKUBAAQUDGHA) && !player_under_penance()
1041             && you.piety >= piety_breakpoint(1))
1042         {
1043             simple_god_message(" averts the curse.");
1044             return;
1045         }
1046
1047         mpr("You feel nervous for a moment...", MSGCH_MONSTER_SPELL);
1048         curse_an_item();
1049     }
1050     else
1051     {
1052         if (index == NON_MONSTER)
1053         {
1054             mpr("You feel extremely nervous for a moment...",
1055                 MSGCH_MONSTER_SPELL);
1056         }
1057         else if (you.can_see(target))
1058         {
1059             mprf(MSGCH_MONSTER_SPELL, "A malignant aura surrounds %s.",
1060                  target->name(DESC_THE).c_str());
1061         }
1062         MiscastEffect(target, mons->mindex(), SPTYP_NECROMANCY,
1063                       pow, random2avg(88, 3), "a mummy death curse");
1064     }
1065 }
1066
1067 static void _setup_base_explosion(bolt & beam, const monster& origin)
1068 {
1069     beam.is_tracer    = false;
1070     beam.is_explosion = true;
1071     beam.beam_source  = origin.mindex();
1072     beam.glyph        = dchar_glyph(DCHAR_FIRED_BURST);
1073     beam.source       = origin.pos();
1074     beam.source_name  = origin.base_name(DESC_BASENAME, true);
1075     beam.target       = origin.pos();
1076     beam.noise_msg    = "You hear an explosion!";
1077
1078     if (!crawl_state.game_is_arena() && origin.attitude == ATT_FRIENDLY
1079         && !origin.is_summoned())
1080     {
1081         beam.thrower = KILL_YOU;
1082     }
1083     else
1084         beam.thrower = KILL_MON;
1085
1086     beam.aux_source.clear();
1087     beam.attitude = origin.attitude;
1088 }
1089
1090 void setup_spore_explosion(bolt & beam, const monster& origin)
1091 {
1092     _setup_base_explosion(beam, origin);
1093     beam.flavour = BEAM_SPORE;
1094     beam.damage  = dice_def(3, 15);
1095     beam.name    = "explosion of spores";
1096     beam.colour  = LIGHTGREY;
1097     beam.ex_size = 2;
1098 }
1099
1100 static void _setup_lightning_explosion(bolt & beam, const monster& origin)
1101 {
1102     _setup_base_explosion(beam, origin);
1103     beam.flavour   = BEAM_ELECTRICITY;
1104     beam.damage    = dice_def(3, 20);
1105     beam.name      = "blast of lightning";
1106     beam.noise_msg = "You hear a clap of thunder!";
1107     beam.colour    = LIGHTCYAN;
1108     beam.ex_size   = coinflip() ? 3 : 2;
1109 }
1110
1111 static void _setup_prism_explosion(bolt& beam, const monster& origin)
1112 {
1113     _setup_base_explosion(beam, origin);
1114     beam.flavour = BEAM_MMISSILE;
1115     beam.damage  = (origin.number == 2 ? dice_def(3, 6 + origin.hit_dice * 7 / 4)
1116                     : dice_def(2, 6 + origin.hit_dice * 7 / 4));
1117     beam.name    = "blast of energy";
1118     beam.colour  = MAGENTA;
1119     beam.ex_size = origin.number;
1120 }
1121
1122 static void _setup_inner_flame_explosion(bolt & beam, const monster& origin,
1123                                          actor* agent)
1124 {
1125     _setup_base_explosion(beam, origin);
1126     const int size   = origin.body_size(PSIZE_BODY);
1127     beam.flavour     = BEAM_FIRE;
1128     beam.damage      = (size > SIZE_BIG)  ? dice_def(3, 25) :
1129                        (size > SIZE_TINY) ? dice_def(3, 20) :
1130                                             dice_def(3, 15);
1131     beam.name        = "fiery explosion";
1132     beam.colour      = RED;
1133     beam.ex_size     = (size > SIZE_BIG) ? 2 : 1;
1134     beam.source_name = origin.name(DESC_A, true);
1135     beam.thrower     = (agent && agent->is_player()) ? KILL_YOU_MISSILE
1136                                                      : KILL_MON_MISSILE;
1137 }
1138
1139 static bool _explode_monster(monster* mons, killer_type killer,
1140                              int killer_index, bool pet_kill, bool wizard)
1141 {
1142     if (mons->hit_points > 0 || mons->hit_points <= -15 || wizard
1143         || killer == KILL_RESET || killer == KILL_DISMISSED
1144         || killer == KILL_BANISHED)
1145     {
1146         if (killer != KILL_TIMEOUT)
1147             return false;
1148     }
1149
1150     bolt beam;
1151     const int type = mons->type;
1152     const char* sanct_msg = NULL;
1153     actor* agent = mons;
1154
1155     if (type == MONS_GIANT_SPORE)
1156     {
1157         setup_spore_explosion(beam, *mons);
1158         sanct_msg    = "By Zin's power, the giant spore's explosion is "
1159                        "contained.";
1160     }
1161     else if (type == MONS_BALL_LIGHTNING)
1162     {
1163         _setup_lightning_explosion(beam, *mons);
1164         sanct_msg    = "By Zin's power, the ball lightning's explosion "
1165                        "is contained.";
1166     }
1167     else if (type == MONS_LURKING_HORROR)
1168         sanct_msg = "The lurking horror fades away harmlessly.";
1169     else if (type == MONS_FULMINANT_PRISM)
1170     {
1171         _setup_prism_explosion(beam, *mons);
1172         sanct_msg = "By Zin's power, the prism's explosion is contained.";
1173     }
1174     else if (mons->has_ench(ENCH_INNER_FLAME))
1175     {
1176         mon_enchant i_f = mons->get_ench(ENCH_INNER_FLAME);
1177         ASSERT(i_f.ench == ENCH_INNER_FLAME);
1178         agent = actor_by_mid(i_f.source);
1179         _setup_inner_flame_explosion(beam, *mons, agent);
1180         // This might need to change if monsters ever get the ability to cast
1181         // Inner Flame...
1182         if (i_f.source == MID_ANON_FRIEND)
1183             mons_add_blame(mons, "hexed by Xom");
1184         else if (agent && agent->is_player())
1185             mons_add_blame(mons, "hexed by the player character");
1186         else if (agent)
1187             mons_add_blame(mons, "hexed by " + agent->name(DESC_A, true));
1188         mons->flags    |= MF_EXPLODE_KILL;
1189         sanct_msg       = "By Zin's power, the fiery explosion "
1190                           "is contained.";
1191         beam.aux_source = "exploding inner flame";
1192     }
1193     else
1194     {
1195         msg::streams(MSGCH_DIAGNOSTICS) << "Unknown spore type: "
1196                                         << static_cast<int>(type)
1197                                         << endl;
1198         return false;
1199     }
1200
1201     if (beam.aux_source.empty())
1202     {
1203         if (YOU_KILL(killer))
1204             beam.aux_source = "set off by themself";
1205         else if (pet_kill)
1206             beam.aux_source = "set off by their pet";
1207     }
1208
1209     bool saw = false;
1210     if (you.can_see(mons))
1211     {
1212         saw = true;
1213         viewwindow();
1214         if (is_sanctuary(mons->pos()))
1215             mpr(sanct_msg, MSGCH_GOD);
1216         else
1217             mprf(MSGCH_MONSTER_DAMAGE, MDAM_DEAD, "%s explodes!",
1218                  mons->full_name(DESC_THE).c_str());
1219     }
1220
1221     if (is_sanctuary(mons->pos()))
1222         return false;
1223
1224     // Explosion side-effects.
1225     if (type == MONS_LURKING_HORROR)
1226         torment(mons, mons->mindex(), mons->pos());
1227     else if (mons->has_ench(ENCH_INNER_FLAME))
1228     {
1229         for (adjacent_iterator ai(mons->pos(), false); ai; ++ai)
1230             if (!cell_is_solid(*ai) && env.cgrid(*ai) == EMPTY_CLOUD
1231                 && !one_chance_in(5))
1232             {
1233                 place_cloud(CLOUD_FIRE, *ai, 10 + random2(10), agent);
1234             }
1235     }
1236
1237     // Detach monster from the grid first, so it doesn't get hit by
1238     // its own explosion. (GDL)
1239     mgrd(mons->pos()) = NON_MONSTER;
1240
1241     // The explosion might cause a monster to be placed where the spore
1242     // used to be, so make sure that mgrd() doesn't get cleared a second
1243     // time (causing the new monster to become floating) when
1244     // mons->reset() is called.
1245     if (type == MONS_GIANT_SPORE)
1246         mons->set_position(coord_def(0,0));
1247
1248     // Exploding kills the monster a bit earlier than normal.
1249     mons->hit_points = -16;
1250     if (saw)
1251         viewwindow();
1252
1253     // FIXME: show_more == mons_near(mons)
1254     if (type == MONS_LURKING_HORROR)
1255     {
1256         targetter_los hitfunc(mons, LOS_SOLID);
1257         flash_view_delay(DARKGRAY, 300, &hitfunc);
1258     }
1259     else
1260         beam.explode();
1261
1262     activate_ballistomycetes(mons, beam.target, YOU_KILL(beam.killer()));
1263     // Monster died in explosion, so don't re-attach it to the grid.
1264     return true;
1265 }
1266
1267 static void _monster_die_cloud(const monster* mons, bool corpse, bool silent,
1268                         bool summoned)
1269 {
1270     // Chaos spawn always leave behind a cloud of chaos.
1271     if (mons->type == MONS_CHAOS_SPAWN)
1272     {
1273         summoned = true;
1274         corpse   = false;
1275     }
1276
1277     if (!summoned)
1278         return;
1279
1280     if (cell_is_solid(mons->pos()))
1281         return;
1282
1283     string prefix = " ";
1284     if (corpse)
1285     {
1286         if (mons_weight(mons_species(mons->type)) == 0)
1287             return;
1288
1289         prefix = "'s corpse ";
1290     }
1291
1292     string msg = summoned_poof_msg(mons) + "!";
1293
1294     cloud_type cloud = CLOUD_NONE;
1295     if (msg.find("smoke") != string::npos)
1296         cloud = random_smoke_type();
1297     else if (msg.find("chaos") != string::npos)
1298         cloud = CLOUD_CHAOS;
1299
1300     if (!silent)
1301         simple_monster_message(mons, (prefix + msg).c_str());
1302
1303     if (cloud != CLOUD_NONE)
1304         place_cloud(cloud, mons->pos(), 1 + random2(3), mons);
1305 }
1306
1307 void mons_relocated(monster* mons)
1308 {
1309     // If the main body teleports get rid of the tentacles
1310     if (mons_is_tentacle_head(mons_base_type(mons)))
1311     {
1312         int headnum = mons->mindex();
1313
1314         if (invalid_monster_index(headnum))
1315             return;
1316
1317         for (monster_iterator mi; mi; ++mi)
1318         {
1319             if (mi->is_child_tentacle_of(mons))
1320             {
1321                 for (monster_iterator connect; connect; ++connect)
1322                 {
1323                     if (connect->is_child_tentacle_of(*mi))
1324                         monster_die(*connect, KILL_RESET, -1, true, false);
1325                 }
1326                 monster_die(*mi, KILL_RESET, -1, true, false);
1327             }
1328         }
1329     }
1330     // If a tentacle/segment is relocated just kill the tentacle
1331     else if (mons->is_child_monster())
1332     {
1333         int base_id = mons->mindex();
1334
1335         monster* tentacle = mons;
1336
1337         if (mons->is_child_tentacle_segment()
1338                 && !::invalid_monster_index(base_id)
1339                 && menv[base_id].is_parent_monster_of(mons))
1340         {
1341             tentacle = &menv[base_id];
1342         }
1343
1344         for (monster_iterator connect; connect; ++connect)
1345         {
1346             if (connect->is_child_tentacle_of(tentacle))
1347                 monster_die(*connect, KILL_RESET, -1, true, false);
1348         }
1349
1350         monster_die(tentacle, KILL_RESET, -1, true, false);
1351     }
1352     else if (mons->type == MONS_ELDRITCH_TENTACLE
1353              || mons->type == MONS_ELDRITCH_TENTACLE_SEGMENT)
1354     {
1355         int base_id = mons->type == MONS_ELDRITCH_TENTACLE
1356                       ? mons->mindex() : mons->number;
1357
1358         monster_die(&menv[base_id], KILL_RESET, -1, true, false);
1359
1360         for (monster_iterator mit; mit; ++mit)
1361         {
1362             if (mit->type == MONS_ELDRITCH_TENTACLE_SEGMENT
1363                 && (int) mit->number == base_id)
1364             {
1365                 monster_die(*mit, KILL_RESET, -1, true, false);
1366             }
1367         }
1368
1369     }
1370
1371     mons->clear_clinging();
1372 }
1373
1374 // When given either a tentacle end or segment, kills the end and all segments
1375 // of that tentacle.
1376 static int _destroy_tentacle(monster* mons)
1377 {
1378     int seen = 0;
1379
1380     monster* head = mons_is_tentacle_segment(mons->type)
1381             ? mons_get_parent_monster(mons) : mons;
1382
1383     //If we tried to find the head, but failed (probably because it is already
1384     //dead), cancel trying to kill this tentacle
1385     if (head == NULL)
1386         return 0;
1387
1388     // Some issue with using monster_die leading to DEAD_MONSTER
1389     // or w/e. Using hurt seems to cause more problems though.
1390     for (monster_iterator mi; mi; ++mi)
1391     {
1392         if (mi->is_child_tentacle_of(head))
1393         {
1394             if (mons_near(*mi))
1395                 seen++;
1396             //mi->hurt(*mi, INSTANT_DEATH);
1397             monster_die(*mi, KILL_MISC, NON_MONSTER, true);
1398         }
1399     }
1400
1401     if (mons != head)
1402     {
1403         if (mons_near(head))
1404                 seen++;
1405
1406         //mprf("killing base, %d %d", origin->mindex(), tentacle_idx);
1407         //menv[tentacle_idx].hurt(&menv[tentacle_idx], INSTANT_DEATH);
1408         monster_die(head, KILL_MISC, NON_MONSTER, true);
1409     }
1410
1411     return seen;
1412 }
1413
1414 static int _destroy_tentacles(monster* head)
1415 {
1416     int seen = 0;
1417     for (monster_iterator mi; mi; ++mi)
1418     {
1419         if (mi->is_child_tentacle_of(head))
1420         {
1421             if (_destroy_tentacle(*mi))
1422                 seen++;
1423             if (!mi->is_child_tentacle_segment())
1424             {
1425                 monster_die(mi->as_monster(), KILL_MISC, NON_MONSTER, true);
1426                 seen++;
1427             }
1428         }
1429     }
1430     return seen;
1431 }
1432
1433 static string _killer_type_name(killer_type killer)
1434 {
1435     switch (killer)
1436     {
1437     case KILL_NONE:
1438         return "none";
1439     case KILL_YOU:
1440         return "you";
1441     case KILL_MON:
1442         return "mon";
1443     case KILL_YOU_MISSILE:
1444         return "you_missile";
1445     case KILL_MON_MISSILE:
1446         return "mon_missile";
1447     case KILL_YOU_CONF:
1448         return "you_conf";
1449     case KILL_MISCAST:
1450         return "miscast";
1451     case KILL_MISC:
1452         return "misc";
1453     case KILL_RESET:
1454         return "reset";
1455     case KILL_DISMISSED:
1456         return "dismissed";
1457     case KILL_BANISHED:
1458         return "banished";
1459     case KILL_UNSUMMONED:
1460         return "unsummoned";
1461     case KILL_TIMEOUT:
1462         return "timeout";
1463     case KILL_PACIFIED:
1464         return "pacified";
1465     case KILL_ENSLAVED:
1466         return "enslaved";
1467     }
1468     die("invalid killer type");
1469 }
1470
1471 static void _make_spectral_thing(monster* mons, bool quiet)
1472 {
1473     if (mons->holiness() == MH_NATURAL && mons_can_be_zombified(mons))
1474     {
1475         const monster_type spectre_type = mons_species(mons->type);
1476         enchant_type shapeshift = ENCH_NONE;
1477         if (mons->has_ench(ENCH_SHAPESHIFTER))
1478             shapeshift = ENCH_SHAPESHIFTER;
1479         else if (mons->has_ench(ENCH_GLOWING_SHAPESHIFTER))
1480             shapeshift = ENCH_GLOWING_SHAPESHIFTER;
1481
1482         // Headless hydras cannot be made spectral hydras, sorry.
1483         if (spectre_type == MONS_HYDRA && mons->number == 0)
1484         {
1485             mprf("A glowing mist gathers momentarily, then fades.");
1486             return;
1487         }
1488
1489         // Use the original monster type as the zombified type here, to
1490         // get the proper stats from it.
1491         if (monster *spectre = create_monster(
1492                 mgen_data(MONS_SPECTRAL_THING, BEH_FRIENDLY, &you,
1493                     0, SPELL_DEATH_CHANNEL, mons->pos(), MHITYOU,
1494                     0, static_cast<god_type>(you.attribute[ATTR_DIVINE_DEATH_CHANNEL]),
1495                     mons->type, mons->number)))
1496         {
1497             if (!quiet)
1498                 mpr("A glowing mist starts to gather...");
1499
1500             // If the original monster has been drained or levelled up,
1501             // its HD might be different from its class HD, in which
1502             // case its HP should be rerolled to match.
1503             if (spectre->hit_dice != mons->hit_dice)
1504             {
1505                 spectre->hit_dice = max(mons->hit_dice, 1);
1506                 roll_zombie_hp(spectre);
1507             }
1508
1509             name_zombie(spectre, mons);
1510
1511             spectre->add_ench(mon_enchant(ENCH_FAKE_ABJURATION, 6));
1512             if (shapeshift)
1513                 spectre->add_ench(shapeshift);
1514         }
1515     }
1516 }
1517
1518 static bool _mons_reaped(actor *killer, monster* victim);
1519
1520 static bool _reaping(monster *mons)
1521 {
1522     if (!mons->props.exists("reaping_damage"))
1523         return false;
1524
1525     int rd = mons->props["reaping_damage"].get_int();
1526     dprf("Reaping chance: %d/%d", rd, mons->damage_total);
1527     if (!x_chance_in_y(rd, mons->damage_total))
1528         return false;
1529
1530     actor *killer = actor_by_mid(mons->props["reaper"].get_int());
1531     if (killer)
1532         return _mons_reaped(killer, mons);
1533     return false;
1534 }
1535
1536 int monster_die(monster* mons, const actor *killer, bool silent,
1537                 bool wizard, bool fake)
1538 {
1539     killer_type ktype = KILL_YOU;
1540     int kindex = NON_MONSTER;
1541
1542     if (killer->is_monster())
1543     {
1544         const monster *kmons = killer->as_monster();
1545         ktype = kmons->confused_by_you() ? KILL_YOU_CONF : KILL_MON;
1546         kindex = kmons->mindex();
1547     }
1548
1549     return monster_die(mons, ktype, kindex, silent, wizard, fake);
1550 }
1551
1552 // Returns the slot of a possibly generated corpse or -1.
1553 int monster_die(monster* mons, killer_type killer,
1554                 int killer_index, bool silent, bool wizard, bool fake)
1555 {
1556     if (invalid_monster(mons))
1557         return -1;
1558
1559     const bool was_visible = you.can_see(mons);
1560
1561     // If a monster was banished to the Abyss and then killed there,
1562     // then its death wasn't a banishment.
1563     if (player_in_branch(BRANCH_ABYSS))
1564         mons->flags &= ~MF_BANISHED;
1565
1566     if (!silent && !fake
1567         && _monster_avoided_death(mons, killer, killer_index))
1568     {
1569         mons->flags &= ~MF_EXPLODE_KILL;
1570         return -1;
1571     }
1572
1573     // If the monster was calling the tide, let go now.
1574     mons->del_ench(ENCH_TIDE);
1575
1576     // Same for silencers.
1577     mons->del_ench(ENCH_SILENCE);
1578
1579     // ... and liquefiers.
1580     mons->del_ench(ENCH_LIQUEFYING);
1581
1582     // Clean up any blood from the flayed effect
1583     if (mons->has_ench(ENCH_FLAYED))
1584         heal_flayed_effect(mons, true, true);
1585
1586     crawl_state.inc_mon_acting(mons);
1587
1588     ASSERT(!(YOU_KILL(killer) && crawl_state.game_is_arena()));
1589
1590     if (mons->props.exists("monster_dies_lua_key"))
1591     {
1592         lua_stack_cleaner clean(dlua);
1593
1594         dlua_chunk &chunk = mons->props["monster_dies_lua_key"];
1595
1596         if (!chunk.load(dlua))
1597         {
1598             push_monster(dlua, mons);
1599             clua_pushcxxstring(dlua, _killer_type_name(killer));
1600             dlua.callfn(NULL, 2, 0);
1601         }
1602         else
1603         {
1604             mprf(MSGCH_ERROR,
1605                  "Lua death function for monster '%s' didn't load: %s",
1606                  mons->full_name(DESC_PLAIN).c_str(),
1607                  dlua.error.c_str());
1608         }
1609     }
1610
1611     mons_clear_trapping_net(mons);
1612     mons->stop_constricting_all(false);
1613     mons->stop_being_constricted();
1614
1615     you.remove_beholder(mons);
1616     you.remove_fearmonger(mons);
1617     // Uniques leave notes and milestones, so this information is already leaked.
1618     remove_unique_annotation(mons);
1619
1620     // Clear auto exclusion now the monster is killed - if we know about it.
1621     if (mons_near(mons) || wizard || mons_is_unique(mons->type))
1622         remove_auto_exclude(mons);
1623
1624           int  duration      = 0;
1625     const bool summoned      = mons->is_summoned(&duration);
1626     const int monster_killed = mons->mindex();
1627     const bool hard_reset    = testbits(mons->flags, MF_HARD_RESET);
1628     bool unsummoned          = killer == KILL_UNSUMMONED;
1629     bool timeout             = killer == KILL_TIMEOUT;
1630     const bool gives_xp      = (!summoned && !mons_class_flag(mons->type,
1631                                 M_NO_EXP_GAIN) && !mons_is_phoenix(mons));
1632
1633     bool drop_items    = !hard_reset;
1634
1635     const bool mons_reset(killer == KILL_RESET || killer == KILL_DISMISSED);
1636
1637     bool fake_abjuration = (mons->has_ench(ENCH_FAKE_ABJURATION));
1638
1639     const bool submerged     = mons->submerged();
1640
1641     bool in_transit          = false;
1642     bool was_banished        = (killer == KILL_BANISHED);
1643
1644     // Award experience for suicide if the suicide was caused by the
1645     // player.
1646     if (MON_KILL(killer) && monster_killed == killer_index)
1647     {
1648         if (mons->confused_by_you())
1649         {
1650             ASSERT(!crawl_state.game_is_arena());
1651             killer = KILL_YOU_CONF;
1652         }
1653     }
1654     else if (MON_KILL(killer) && mons->has_ench(ENCH_CHARM))
1655     {
1656         ASSERT(!crawl_state.game_is_arena());
1657         killer = KILL_YOU_CONF; // Well, it was confused in a sense... (jpeg)
1658     }
1659
1660     // Kills by the spectral weapon are considered as kills by the player instead
1661     if (killer == KILL_MON
1662         && !invalid_monster_index(killer_index)
1663         && menv[killer_index].type == MONS_SPECTRAL_WEAPON
1664         && menv[killer_index].summoner == MID_PLAYER)
1665     {
1666         killer = KILL_YOU;
1667         killer_index = you.mindex();
1668     }
1669
1670     // Take notes and mark milestones.
1671     record_monster_defeat(mons, killer);
1672
1673     // Various sources of berserk extension on kills.
1674     if (killer == KILL_YOU && you.berserk())
1675     {
1676         if (you_worship(GOD_TROG)
1677             && !player_under_penance() && you.piety > random2(1000))
1678         {
1679             const int bonus = (3 + random2avg(10, 2)) / 2;
1680
1681             you.increase_duration(DUR_BERSERK, bonus);
1682
1683             mpr("You feel the power of Trog in you as your rage grows.",
1684                 MSGCH_GOD, GOD_TROG);
1685         }
1686         else if (player_equip_unrand_effect(UNRAND_BLOODLUST))
1687         {
1688             if (coinflip())
1689             {
1690                 const int bonus = (2 + random2(4)) / 2;
1691                 you.increase_duration(DUR_BERSERK, bonus);
1692                 mpr("The necklace of Bloodlust glows a violent red.");
1693             }
1694         }
1695         else if (!you.suppressed()
1696                  && you.wearing(EQ_AMULET, AMU_RAGE)
1697                  && one_chance_in(30))
1698         {
1699             const int bonus = (2 + random2(4)) / 2;
1700             you.increase_duration(DUR_BERSERK, bonus);
1701             mpr("Your amulet glows a violent red.");
1702         }
1703     }
1704
1705     if (you.prev_targ == monster_killed)
1706     {
1707         you.prev_targ = MHITNOT;
1708         crawl_state.cancel_cmd_repeat();
1709     }
1710
1711     if (killer == KILL_YOU)
1712         crawl_state.cancel_cmd_repeat();
1713
1714     const bool pet_kill = _is_pet_kill(killer, killer_index);
1715
1716     bool did_death_message = false;
1717
1718     if (mons->type == MONS_GIANT_SPORE
1719         || mons->type == MONS_BALL_LIGHTNING
1720         || mons->type == MONS_LURKING_HORROR
1721         || (mons->type == MONS_FULMINANT_PRISM && mons->number > 0)
1722         || mons->has_ench(ENCH_INNER_FLAME))
1723     {
1724         did_death_message =
1725             _explode_monster(mons, killer, killer_index, pet_kill, wizard);
1726     }
1727     else if (mons->type == MONS_FULMINANT_PRISM && mons->number == 0)
1728     {
1729         if (!silent && !hard_reset && !was_banished)
1730         {
1731             simple_monster_message(mons, " detonates feebly.",
1732                                    MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
1733             silent = true;
1734         }
1735     }
1736     else if (mons->type == MONS_FIRE_VORTEX
1737              || mons->type == MONS_SPATIAL_VORTEX
1738              || mons->type == MONS_TWISTER)
1739     {
1740         if (!silent && !mons_reset && !was_banished)
1741         {
1742             simple_monster_message(mons, " dissipates!",
1743                                    MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
1744             silent = true;
1745         }
1746
1747         if (mons->type == MONS_FIRE_VORTEX && !wizard && !mons_reset
1748             && !submerged && !was_banished && !cell_is_solid(mons->pos()))
1749         {
1750             place_cloud(CLOUD_FIRE, mons->pos(), 2 + random2(4), mons);
1751         }
1752
1753         if (killer == KILL_RESET)
1754             killer = KILL_DISMISSED;
1755     }
1756     else if (mons->type == MONS_SIMULACRUM)
1757     {
1758         if (!silent && !mons_reset && !was_banished)
1759         {
1760             simple_monster_message(mons, " vapourises!",
1761                                    MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
1762             silent = true;
1763         }
1764
1765         if (!wizard && !mons_reset && !submerged && !was_banished
1766             && !cell_is_solid(mons->pos()))
1767         {
1768             place_cloud(CLOUD_COLD, mons->pos(), 2 + random2(4), mons);
1769         }
1770
1771         if (killer == KILL_RESET)
1772             killer = KILL_DISMISSED;
1773     }
1774     else if (mons->type == MONS_DANCING_WEAPON)
1775     {
1776         if (!hard_reset)
1777         {
1778             if (killer == KILL_RESET)
1779                 killer = KILL_DISMISSED;
1780         }
1781
1782         int w_idx = mons->inv[MSLOT_WEAPON];
1783         ASSERT(w_idx != NON_ITEM);
1784
1785         // XXX: This can probably become mons->is_summoned(): there's no
1786         // feasible way for a dancing weapon to "drop" it's weapon and somehow
1787         // gain a summoned one, or vice versa.
1788         bool summoned_it = mitm[w_idx].flags & ISFLAG_SUMMONED;
1789
1790         if (!silent && !hard_reset && !was_banished)
1791         {
1792             if (!summoned_it)
1793             {
1794                 simple_monster_message(mons, " falls from the air.",
1795                                        MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
1796                 silent = true;
1797             }
1798             else
1799                 killer = KILL_RESET;
1800         }
1801
1802         if (was_banished && !summoned_it && !hard_reset && mons->has_ench(ENCH_ABJ))
1803         {
1804             if (is_unrandom_artefact(mitm[w_idx]))
1805                 set_unique_item_status(mitm[w_idx], UNIQ_LOST_IN_ABYSS);
1806
1807             destroy_item(w_idx);
1808         }
1809     }
1810     else if (mons->type == MONS_ELDRITCH_TENTACLE)
1811     {
1812         if (!silent && !mons_reset && !mons->has_ench(ENCH_SEVERED) && !was_banished)
1813         {
1814             if (you.can_see(mons))
1815             {
1816                 mpr(silenced(mons->pos()) ?
1817                     "The tentacle is hauled back through the portal!" :
1818                     "With a roar, the tentacle is hauled back through the portal!",
1819                     MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
1820             }
1821             silent = true;
1822         }
1823
1824         if (killer == KILL_RESET)
1825             killer = KILL_DISMISSED;
1826     }
1827     else if (mons->type == MONS_BATTLESPHERE)
1828     {
1829         if (!wizard && !mons_reset && !was_banished)
1830             place_cloud(CLOUD_MAGIC_TRAIL, mons->pos(), 3 + random2(3), mons);
1831         end_battlesphere(mons, true);
1832     }
1833     else if (mons->type == MONS_BRIAR_PATCH)
1834     {
1835         if (timeout && !silent)
1836             simple_monster_message(mons, " crumbles away.");
1837     }
1838     else if (mons->type == MONS_SPECTRAL_WEAPON)
1839     {
1840         end_spectral_weapon(mons, true, killer == KILL_RESET);
1841         silent = true;
1842     }
1843
1844     const bool death_message = !silent && !did_death_message
1845                                && mons_near(mons)
1846                                && mons->visible_to(&you);
1847     const bool exploded      = mons->flags & MF_EXPLODE_KILL;
1848
1849     const bool created_friendly = testbits(mons->flags, MF_NO_REWARD);
1850           bool anon = (killer_index == ANON_FRIENDLY_MONSTER);
1851     mon_holy_type targ_holy = mons->holiness();
1852
1853     // Dual holiness, Trog and Kiku like dead demons but not undead.
1854     if ((mons->type == MONS_ABOMINATION_SMALL
1855          || mons->type == MONS_ABOMINATION_LARGE
1856          || mons->type == MONS_CRAWLING_CORPSE
1857          || mons->type == MONS_MACABRE_MASS)
1858         && (you_worship(GOD_TROG)
1859          || you_worship(GOD_KIKUBAAQUDGHA)))
1860     {
1861         targ_holy = MH_DEMONIC;
1862     }
1863
1864     // Adjust song of slaying bonus
1865     // Kills by the spectral weapon should be adjusted by this point to be
1866     // kills by the player --- so kills by the spectral weapon are considered here as well
1867     if (killer == KILL_YOU && you.duration[DUR_SONG_OF_SLAYING] && !mons->is_summoned() && gives_xp)
1868     {
1869         int sos_bonus = you.props["song_of_slaying_bonus"].get_int();
1870         mon_threat_level_type threat = mons_threat_level(mons, true);
1871         // Only certain kinds of threats at different sos levels will increase the bonus
1872         if (threat == MTHRT_TRIVIAL && sos_bonus < 3
1873             || threat == MTHRT_EASY && sos_bonus < 5
1874             || threat == MTHRT_TOUGH && sos_bonus < 7
1875             || threat == MTHRT_NASTY)
1876         {
1877             you.props["song_of_slaying_bonus"] = sos_bonus + 1;
1878         }
1879     }
1880
1881     switch (killer)
1882     {
1883         case KILL_YOU:          // You kill in combat.
1884         case KILL_YOU_MISSILE:  // You kill by missile or beam.
1885         case KILL_YOU_CONF:     // You kill by confusion.
1886         {
1887             const bool bad_kill    = god_hates_killing(you.religion, mons);
1888             const bool was_neutral = testbits(mons->flags, MF_WAS_NEUTRAL);
1889             // killing friendlies is good, more bloodshed!
1890             // Undead feel no pain though, tormenting them is not as satisfying.
1891             const bool good_kill   = !created_friendly && gives_xp
1892                 || (is_evil_god(you.religion) && !mons->is_summoned()
1893                     && !fake_abjuration
1894                     && (targ_holy == MH_NATURAL || targ_holy == MH_HOLY));
1895
1896             if (death_message)
1897             {
1898                 if (killer == KILL_YOU_CONF
1899                     && (anon || !invalid_monster_index(killer_index)))
1900                 {
1901                     mprf(MSGCH_MONSTER_DAMAGE, MDAM_DEAD, "%s is %s!",
1902                          mons->name(DESC_THE).c_str(),
1903                          exploded                        ? "blown up" :
1904                          _wounded_damaged(targ_holy)     ? "destroyed"
1905                                                          : "killed");
1906                 }
1907                 else
1908                 {
1909                     mprf(MSGCH_MONSTER_DAMAGE, MDAM_DEAD, "You %s %s!",
1910                          exploded                        ? "blow up" :
1911                          _wounded_damaged(targ_holy)     ? "destroy"
1912                                                          : "kill",
1913                          mons->name(DESC_THE).c_str());
1914                 }
1915
1916                 if ((created_friendly || was_neutral) && gives_xp)
1917                     mpr("That felt strangely unrewarding.");
1918             }
1919
1920             // Killing triggers hints mode lesson.
1921             if (gives_xp)
1922                 _hints_inspect_kill();
1923
1924             // Prevent summoned creatures from being good kills.
1925             if (bad_kill || good_kill)
1926             {
1927                 if (targ_holy == MH_NATURAL)
1928                 {
1929                     did_god_conduct(DID_KILL_LIVING,
1930                                     mons->hit_dice, true, mons);
1931
1932                     // TSO hates natural evil and unholy beings.
1933                     if (mons->is_unholy())
1934                     {
1935                         did_god_conduct(DID_KILL_NATURAL_UNHOLY,
1936                                         mons->hit_dice, true, mons);
1937                     }
1938                     else if (mons->is_evil())
1939                     {
1940                         did_god_conduct(DID_KILL_NATURAL_EVIL,
1941                                         mons->hit_dice, true, mons);
1942                     }
1943                 }
1944                 else if (targ_holy == MH_UNDEAD)
1945                 {
1946                     did_god_conduct(DID_KILL_UNDEAD,
1947                                     mons->hit_dice, true, mons);
1948                 }
1949                 else if (targ_holy == MH_DEMONIC)
1950                 {
1951                     did_god_conduct(DID_KILL_DEMON,
1952                                     mons->hit_dice, true, mons);
1953                 }
1954
1955                 // Zin hates unclean and chaotic beings.
1956                 if (mons->is_unclean())
1957                 {
1958                     did_god_conduct(DID_KILL_UNCLEAN,
1959                                     mons->hit_dice, true, mons);
1960                 }
1961                 else if (mons->is_chaotic())
1962                 {
1963                     did_god_conduct(DID_KILL_CHAOTIC,
1964                                     mons->hit_dice, true, mons);
1965                 }
1966
1967                 // jmf: Trog hates wizards.
1968                 if (mons->is_actual_spellcaster())
1969                 {
1970                     did_god_conduct(DID_KILL_WIZARD,
1971                                     mons->hit_dice, true, mons);
1972                 }
1973
1974                 // Beogh hates priests of other gods.
1975                 if (mons->is_priest())
1976                 {
1977                     did_god_conduct(DID_KILL_PRIEST,
1978                                     mons->hit_dice, true, mons);
1979                 }
1980
1981                 // Jiyva hates you killing slimes, but eyeballs
1982                 // mutation can confuse without you meaning it.
1983                 if (mons_is_slime(mons) && killer != KILL_YOU_CONF)
1984                 {
1985                     did_god_conduct(DID_KILL_SLIME, mons->hit_dice,
1986                                     true, mons);
1987                 }
1988
1989                 if (fedhas_protects(mons))
1990                 {
1991                     did_god_conduct(DID_KILL_PLANT, mons->hit_dice,
1992                                     true, mons);
1993                 }
1994
1995                 // Cheibriados hates fast monsters.
1996                 if (cheibriados_thinks_mons_is_fast(mons)
1997                     && !mons->cannot_move())
1998                 {
1999                     did_god_conduct(DID_KILL_FAST, mons->hit_dice,
2000                                     true, mons);
2001                 }
2002
2003                 // Yredelemnul hates artificial beings.
2004                 if (mons->is_artificial())
2005                 {
2006                     did_god_conduct(DID_KILL_ARTIFICIAL, mons->hit_dice,
2007                                     true, mons);
2008                 }
2009
2010                 // Holy kills are always noticed.
2011                 if (mons->is_holy())
2012                 {
2013                     did_god_conduct(DID_KILL_HOLY, mons->hit_dice,
2014                                     true, mons);
2015                 }
2016             }
2017
2018             // Divine health and mana restoration doesn't happen when
2019             // killing born-friendly monsters.
2020             if (good_kill
2021                 && (you_worship(GOD_MAKHLEB)
2022                     || you_worship(GOD_VEHUMET)
2023                     || you_worship(GOD_SHINING_ONE)
2024                        && (mons->is_evil() || mons->is_unholy()))
2025                 && !mons_is_object(mons->type)
2026                 && !player_under_penance()
2027                 && random2(you.piety) >= piety_breakpoint(0))
2028             {
2029                 int hp_heal = 0, mp_heal = 0;
2030
2031                 switch (you.religion)
2032                 {
2033                 case GOD_MAKHLEB:
2034                     hp_heal = mons->hit_dice + random2(mons->hit_dice);
2035                     break;
2036                 case GOD_SHINING_ONE:
2037                     hp_heal = random2(1 + 2 * mons->hit_dice);
2038                     mp_heal = random2(2 + mons->hit_dice / 3);
2039                     break;
2040                 case GOD_VEHUMET:
2041                     mp_heal = 1 + random2(mons->hit_dice / 2);
2042                     break;
2043                 default:
2044                     die("bad kill-on-healing god!");
2045                 }
2046
2047                 if (you.species == SP_DJINNI)
2048                     hp_heal = max(hp_heal, mp_heal * 2), mp_heal = 0;
2049
2050                 if (hp_heal && you.hp < you.hp_max
2051                     && !you.duration[DUR_DEATHS_DOOR])
2052                 {
2053                     mprf("You feel a little better.");
2054                     inc_hp(hp_heal);
2055                 }
2056
2057                 if (mp_heal && you.magic_points < you.max_magic_points)
2058                 {
2059                     mpr("You feel your power returning.");
2060                     inc_mp(mp_heal);
2061                 }
2062             }
2063
2064             // Randomly bless a follower.
2065             if (!created_friendly
2066                 && gives_xp
2067                 && (you_worship(GOD_BEOGH)
2068                     && random2(you.piety) >= piety_breakpoint(2))
2069                 && !mons_is_object(mons->type)
2070                 && !player_under_penance())
2071             {
2072                 bless_follower();
2073             }
2074
2075             if (you.duration[DUR_DEATH_CHANNEL] && gives_xp)
2076                 _make_spectral_thing(mons, !death_message);
2077             break;
2078         }
2079
2080         case KILL_MON:          // Monster kills in combat.
2081         case KILL_MON_MISSILE:  // Monster kills by missile or beam.
2082             if (death_message)
2083             {
2084                 const char* msg =
2085                     exploded                     ? " is blown up!" :
2086                     _wounded_damaged(targ_holy)  ? " is destroyed!"
2087                                                  : " dies!";
2088                 simple_monster_message(mons, msg, MSGCH_MONSTER_DAMAGE,
2089                                        MDAM_DEAD);
2090             }
2091
2092             if (crawl_state.game_is_arena())
2093                 break;
2094
2095             // No piety loss if god gifts killed by other monsters.
2096             // Also, dancing weapons aren't really friendlies.
2097             if (mons->friendly() && !mons_is_object(mons->type))
2098             {
2099                 const int mon_intel = mons_class_intel(mons->type) - I_ANIMAL;
2100
2101                 did_god_conduct(mon_intel > 0 ? DID_SOULED_FRIEND_DIED
2102                                               : DID_FRIEND_DIED,
2103                                 1 + (mons->hit_dice / 2),
2104                                 true, mons);
2105             }
2106
2107             if (pet_kill && fedhas_protects(mons))
2108             {
2109                 did_god_conduct(DID_PLANT_KILLED_BY_SERVANT, 1 + (mons->hit_dice / 2),
2110                                 true, mons);
2111             }
2112
2113             // Trying to prevent summoning abuse here, so we're trying to
2114             // prevent summoned creatures from being done_good kills.  Only
2115             // affects creatures which were friendly when summoned.
2116             if (!created_friendly && gives_xp && pet_kill
2117                 && (anon || !invalid_monster_index(killer_index)))
2118             {
2119                 bool notice = false;
2120
2121                 monster* killer_mon = NULL;
2122                 if (!anon)
2123                 {
2124                     killer_mon = &menv[killer_index];
2125
2126                     // If the killer is already dead, treat it like an
2127                     // anonymous monster.
2128                     if (killer_mon->type == MONS_NO_MONSTER)
2129                         anon = true;
2130                 }
2131
2132                 const mon_holy_type killer_holy =
2133                     anon ? MH_NATURAL : killer_mon->holiness();
2134
2135                 if (you_worship(GOD_ZIN)
2136                     || you_worship(GOD_SHINING_ONE)
2137                     || you_worship(GOD_YREDELEMNUL)
2138                     || you_worship(GOD_KIKUBAAQUDGHA)
2139                     || you_worship(GOD_MAKHLEB)
2140                     || you_worship(GOD_LUGONU)
2141                     || !anon && mons_is_god_gift(killer_mon))
2142                 {
2143                     if (killer_holy == MH_UNDEAD)
2144                     {
2145                         const bool confused =
2146                             anon ? false : !killer_mon->friendly();
2147
2148                         // Yes, these are hacks, but they make sure that
2149                         // confused monsters doing kills are not
2150                         // referred to as "slaves", and I think it's
2151                         // okay that e.g. Yredelemnul ignores kills done
2152                         // by confused monsters as opposed to enslaved
2153                         // or friendly ones. (jpeg)
2154                         if (targ_holy == MH_NATURAL)
2155                         {
2156                             notice |= did_god_conduct(
2157                                           !confused ? DID_LIVING_KILLED_BY_UNDEAD_SLAVE :
2158                                                       DID_LIVING_KILLED_BY_SERVANT,
2159                                           mons->hit_dice);
2160                         }
2161                         else if (targ_holy == MH_UNDEAD)
2162                         {
2163                             notice |= did_god_conduct(
2164                                           !confused ? DID_UNDEAD_KILLED_BY_UNDEAD_SLAVE :
2165                                                       DID_UNDEAD_KILLED_BY_SERVANT,
2166                                           mons->hit_dice);
2167                         }
2168                         else if (targ_holy == MH_DEMONIC)
2169                         {
2170                             notice |= did_god_conduct(
2171                                           !confused ? DID_DEMON_KILLED_BY_UNDEAD_SLAVE :
2172                                                       DID_DEMON_KILLED_BY_SERVANT,
2173                                           mons->hit_dice);
2174                         }
2175
2176                         if (mons->is_unclean())
2177                         {
2178                             notice |= did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT,
2179                                                       mons->hit_dice);
2180                         }
2181
2182                         if (mons->is_chaotic())
2183                         {
2184                             notice |= did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT,
2185                                                       mons->hit_dice);
2186                         }
2187
2188                         if (mons->is_artificial())
2189                         {
2190                             notice |= did_god_conduct(
2191                                           !confused ? DID_ARTIFICIAL_KILLED_BY_UNDEAD_SLAVE :
2192                                                       DID_ARTIFICIAL_KILLED_BY_SERVANT,
2193                                           mons->hit_dice);
2194                         }
2195                     }
2196                     // Yes, we are splitting undead pets from the others
2197                     // as a way to focus Necromancy vs. Summoning
2198                     // (ignoring Haunt here)... at least we're being
2199                     // nice and putting the natural creature summons
2200                     // together with the demonic ones.  Note that
2201                     // Vehumet gets a free pass here since those
2202                     // followers are assumed to come from summoning
2203                     // spells...  the others are from invocations (TSO,
2204                     // Makhleb, Kiku). - bwr
2205                     else if (targ_holy == MH_NATURAL)
2206                     {
2207                         notice |= did_god_conduct(DID_LIVING_KILLED_BY_SERVANT,
2208                                                   mons->hit_dice);
2209
2210                         if (mons->is_unholy())
2211                         {
2212                             notice |= did_god_conduct(
2213                                           DID_NATURAL_UNHOLY_KILLED_BY_SERVANT,
2214                                           mons->hit_dice);
2215                         }
2216
2217                         if (mons->is_evil())
2218                         {
2219                             notice |= did_god_conduct(
2220                                           DID_NATURAL_EVIL_KILLED_BY_SERVANT,
2221                                           mons->hit_dice);
2222                         }
2223                     }
2224                     else if (targ_holy == MH_UNDEAD)
2225                     {
2226                         notice |= did_god_conduct(DID_UNDEAD_KILLED_BY_SERVANT,
2227                                                   mons->hit_dice);
2228                     }
2229                     else if (targ_holy == MH_DEMONIC)
2230                     {
2231                         notice |= did_god_conduct(DID_DEMON_KILLED_BY_SERVANT,
2232                                                   mons->hit_dice);
2233                     }
2234
2235                     if (mons->is_unclean())
2236                     {
2237                         notice |= did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT,
2238                                                   mons->hit_dice);
2239                     }
2240
2241                     if (mons->is_chaotic())
2242                     {
2243                         notice |= did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT,
2244                                                   mons->hit_dice);
2245                     }
2246
2247                     if (mons->is_artificial())
2248                     {
2249                         notice |= did_god_conduct(DID_ARTIFICIAL_KILLED_BY_SERVANT,
2250                                                   mons->hit_dice);
2251                     }
2252                 }
2253
2254                 // Holy kills are always noticed.
2255                 if (mons->is_holy())
2256                 {
2257                     if (killer_holy == MH_UNDEAD)
2258                     {
2259                         const bool confused =
2260                             anon ? false : !killer_mon->friendly();
2261
2262                         // Yes, this is a hack, but it makes sure that
2263                         // confused monsters doing kills are not
2264                         // referred to as "slaves", and I think it's
2265                         // okay that Yredelemnul ignores kills done by
2266                         // confused monsters as opposed to enslaved or
2267                         // friendly ones. (jpeg)
2268                         notice |= did_god_conduct(
2269                                       !confused ? DID_HOLY_KILLED_BY_UNDEAD_SLAVE :
2270                                                   DID_HOLY_KILLED_BY_SERVANT,
2271                                       mons->hit_dice, true, mons);
2272                     }
2273                     else
2274                         notice |= did_god_conduct(DID_HOLY_KILLED_BY_SERVANT,
2275                                                   mons->hit_dice, true, mons);
2276                 }
2277
2278                 if (you_worship(GOD_SHINING_ONE)
2279                     && (mons->is_evil() || mons->is_unholy())
2280                     && !player_under_penance()
2281                     && random2(you.piety) >= piety_breakpoint(0)
2282                     && !invalid_monster_index(killer_index))
2283                 {
2284                     // Randomly bless the follower who killed.
2285                     if (!one_chance_in(3) && killer_mon->alive()
2286                         && bless_follower(killer_mon))
2287                     {
2288                         break;
2289                     }
2290
2291                     if (killer_mon->alive()
2292                         && killer_mon->hit_points < killer_mon->max_hit_points)
2293                     {
2294                         simple_monster_message(killer_mon,
2295                                                " looks invigorated.");
2296                         killer_mon->heal(1 + random2(mons->hit_dice / 4));
2297                     }
2298                 }
2299
2300                 if (you_worship(GOD_BEOGH)
2301                     && random2(you.piety) >= piety_breakpoint(2)
2302                     && !player_under_penance()
2303                     && !one_chance_in(3)
2304                     && !invalid_monster_index(killer_index))
2305                 {
2306                     // Randomly bless the follower who killed.
2307                     bless_follower(killer_mon);
2308                 }
2309
2310                 if (you.duration[DUR_DEATH_CHANNEL] && gives_xp && was_visible)
2311                     _make_spectral_thing(mons, !death_message);
2312             }
2313             break;
2314
2315         // Monster killed by trap/inanimate thing/itself/poison not from you.
2316         case KILL_MISC:
2317         case KILL_MISCAST:
2318             if (death_message)
2319             {
2320                 if (fake_abjuration)
2321                 {
2322                     if (mons_genus(mons->type) == MONS_ADDER)
2323                     {
2324                         // Sticks to Snake
2325                         simple_monster_message(mons, " withers and dies!",
2326                             MSGCH_MONSTER_DAMAGE, MDAM_DEAD);
2327                     }
2328                     else if (mons->type == MONS_SPECTRAL_THING)
2329                     {
2330                         // Death Channel
2331                         simple_monster_message(mons, " fades into mist!");
2332                     }
2333                     else
2334                     {
2335                         string msg = " " + summoned_poof_msg(mons) + "!";
2336                         simple_monster_message(mons, msg.c_str());
2337                     }
2338                 }
2339                 else
2340                 {
2341                     const char* msg =
2342                         exploded                     ? " is blown up!" :
2343                         _wounded_damaged(targ_holy)  ? " is destroyed!"
2344                                                      : " dies!";
2345                     simple_monster_message(mons, msg, MSGCH_MONSTER_DAMAGE,
2346                                            MDAM_DEAD);
2347                 }
2348             }
2349             break;
2350
2351         case KILL_BANISHED:
2352             // Monster doesn't die, just goes back to wherever it came from.
2353             // This must only be called by monsters running out of time (or
2354             // abjuration), because it uses the beam variables!  Or does it???
2355             // Pacified monsters leave the level when this happens.
2356
2357             // KILL_RESET monsters no longer lose their whole inventory, only
2358             // items they were generated with.
2359             if (mons->pacified() || !mons->needs_abyss_transit())
2360             {
2361                 // A banished monster that doesn't go on the transit list
2362                 // loses all items.
2363                 if (!mons->is_summoned())
2364                     drop_items = false;
2365                 break;
2366             }
2367
2368             // Monster goes to the Abyss.
2369             mons->flags |= MF_BANISHED;
2370             {
2371                 unwind_var<int> dt(mons->damage_total, 0);
2372                 unwind_var<int> df(mons->damage_friendly, 0);
2373                 mons->set_transit(level_id(BRANCH_ABYSS));
2374             }
2375             set_unique_annotation(mons, BRANCH_ABYSS);
2376             in_transit = true;
2377             drop_items = false;
2378             mons->firing_pos.reset();
2379             // Make monster stop patrolling and/or travelling.
2380             mons->patrol_point.reset();
2381             mons->travel_path.clear();
2382             mons->travel_target = MTRAV_NONE;
2383             break;
2384
2385         case KILL_RESET:
2386             drop_items = false;
2387             break;
2388
2389         case KILL_TIMEOUT:
2390         case KILL_UNSUMMONED:
2391         case KILL_DISMISSED:
2392             break;
2393
2394         default:
2395             drop_items = false;
2396             break;
2397     }
2398
2399     // Make sure Boris has a foe to address.
2400     if (mons->foe == MHITNOT)
2401     {
2402         if (!mons->wont_attack() && !crawl_state.game_is_arena())
2403             mons->foe = MHITYOU;
2404         else if (!invalid_monster_index(killer_index))
2405             mons->foe = killer_index;
2406     }
2407
2408     // Make sure that the monster looks dead.
2409     if (mons->alive() && (!summoned || duration > 0))
2410     {
2411         dprf("Granting xp for non-damage kill.");
2412         if (YOU_KILL(killer))
2413             mons->damage_friendly += mons->hit_points * 2;
2414         else if (pet_kill)
2415             mons->damage_friendly += mons->hit_points;
2416         mons->damage_total += mons->hit_points;
2417
2418         if (!in_transit) // banishment only
2419             mons->hit_points = -1;
2420     }
2421
2422     if (!silent && !wizard && you.see_cell(mons->pos()))
2423     {
2424         // Make sure that the monster looks dead.
2425         if (mons->alive() && !in_transit && (!summoned || duration > 0))
2426             mons->hit_points = -1;
2427         // Hack: with cleanup_dead=false, a tentacle [segment] of a dead
2428         // [malign] kraken has no valid head reference.
2429         if (!mons_is_tentacle_or_tentacle_segment(mons->type))
2430             mons_speaks(mons);
2431     }
2432
2433     if (mons->type == MONS_BORIS && !in_transit && !mons->pacified())
2434     {
2435         // XXX: Actual blood curse effect for Boris? - bwr
2436
2437         // Now that Boris is dead, he's a valid target for monster
2438         // creation again. - bwr
2439         you.unique_creatures.set(mons->type, false);
2440         // And his vault can be placed again.
2441         you.uniq_map_names.erase("uniq_boris");
2442     }
2443     if (mons->type == MONS_JORY && !in_transit)
2444         blood_spray(mons->pos(), MONS_JORY, 50);
2445     else if (mons_is_kirke(mons)
2446              && !in_transit
2447              && !testbits(mons->flags, MF_WAS_NEUTRAL))
2448     {
2449         hogs_to_humans();
2450     }
2451     else if (mons_is_pikel(mons))
2452     {
2453         // His slaves don't care if he's dead or not, just whether or not
2454         // he goes away.
2455         pikel_band_neutralise();
2456     }
2457     else if (mons->is_named() && mons->friendly() && killer != KILL_RESET)
2458         take_note(Note(NOTE_ALLY_DEATH, 0, 0, mons->mname.c_str()));
2459     else if (mons_is_tentacle_head(mons_base_type(mons)))
2460     {
2461         if (_destroy_tentacles(mons)
2462             && !in_transit
2463             && you.see_cell(mons->pos()))
2464         {
2465             if (mons_base_type(mons) == MONS_KRAKEN)
2466                 mpr("The dead kraken's tentacles slide back into the water.");
2467             else if (mons->type == MONS_TENTACLED_STARSPAWN)
2468                 mpr("The starspawn's tentacles wither and die.");
2469         }
2470     }
2471     else if (mons_is_tentacle_or_tentacle_segment(mons->type)
2472              && killer != KILL_MISC
2473                  || mons->type == MONS_ELDRITCH_TENTACLE
2474                  || mons->type == MONS_SNAPLASHER_VINE)
2475     {
2476         if (mons->type == MONS_SNAPLASHER_VINE)
2477         {
2478             if (mons->props.exists("vine_awakener"))
2479             {
2480                 monster* awakener =
2481                         monster_by_mid(mons->props["vine_awakener"].get_int());
2482                 if (awakener)
2483                     awakener->props["vines_awakened"].get_int()--;
2484             }
2485         }
2486         _destroy_tentacle(mons);
2487     }
2488     else if (mons->type == MONS_ELDRITCH_TENTACLE_SEGMENT
2489              && killer != KILL_MISC)
2490     {
2491         if (!invalid_monster_index(mons->number)
2492              && mons_base_type(&menv[mons->number]) == MONS_ELDRITCH_TENTACLE
2493              && menv[mons->number].alive())
2494         {
2495             monster_die(&menv[mons->number], killer, killer_index, silent,
2496                         wizard, fake);
2497         }
2498     }
2499     else if (mons_is_elven_twin(mons) && mons_near(mons))
2500         elven_twin_died(mons, in_transit, killer, killer_index);
2501     else if (mons_is_shedu(mons))
2502     {
2503         if (was_banished) // Don't try resurrecting them.
2504             mons->number = 0;
2505         else
2506             shedu_do_resurrection(mons);
2507     }
2508     else if (mons_is_phoenix(mons))
2509     {
2510         if (!was_banished)
2511             phoenix_died(mons);
2512     }
2513     else if (mons->type == MONS_VAULT_WARDEN)
2514         timeout_terrain_changes(0, true);
2515     else if (mons->type == MONS_FLAYED_GHOST)
2516         end_flayed_effect(mons);
2517     else if (mons->type == MONS_PLAGUE_SHAMBLER && !was_banished
2518              && !mons->pacified() && (!summoned || duration > 0) && !wizard)
2519     {
2520         if (you.can_see(mons))
2521         {
2522             mprf(MSGCH_WARN, "Miasma billows from the fallen %s!",
2523                  mons->name(DESC_PLAIN).c_str());
2524         }
2525
2526         map_cloud_spreader_marker *marker =
2527             new map_cloud_spreader_marker(mons->pos(), CLOUD_MIASMA, 10,
2528                                           18 + random2(7), 4, 8, mons);
2529         // Start the cloud at radius 1, regardless of the speed of the killing blow
2530         marker->speed_increment -= you.time_taken;
2531         env.markers.add(marker);
2532         env.markers.clear_need_activate();
2533     }
2534     // Give the treant a last chance to release its wasps if it is killed in a
2535     // single blow from above half health
2536     else if (mons->type == MONS_TREANT && !was_banished
2537              && !mons->pacified() && (!summoned || duration > 0) && !wizard)
2538     {
2539         treant_release_wasps(mons);
2540     }
2541     else if (mons_is_mimic(mons->type))
2542         drop_items = false;
2543     else if (!mons->is_summoned())
2544     {
2545         if (mons_genus(mons->type) == MONS_MUMMY)
2546             _mummy_curse(mons, killer, killer_index);
2547     }
2548
2549     if (mons->mons_species() == MONS_BALLISTOMYCETE)
2550     {
2551         activate_ballistomycetes(mons, mons->pos(),
2552                                  YOU_KILL(killer) || pet_kill);
2553     }
2554
2555     if (!wizard && !submerged && !was_banished)
2556     {
2557         _monster_die_cloud(mons, !mons_reset && !fake_abjuration && !unsummoned
2558                                  && !timeout, silent, summoned);
2559     }
2560
2561     int corpse = -1;
2562     if (!mons_reset && !summoned && !fake_abjuration && !unsummoned
2563         && !timeout && !was_banished)
2564     {
2565         // Have to add case for disintegration effect here? {dlb}
2566         int corpse2 = -1;
2567
2568         if (mons->type == MONS_SPRIGGAN_RIDER)
2569         {
2570             corpse2 = mounted_kill(mons, MONS_FIREFLY, killer, killer_index);
2571             mons->type = MONS_SPRIGGAN;
2572         }
2573         corpse = place_monster_corpse(mons, silent);
2574         if (corpse == -1)
2575             corpse = corpse2;
2576     }
2577
2578     if ((killer == KILL_YOU
2579          || killer == KILL_YOU_MISSILE
2580          || killer == KILL_YOU_CONF
2581          || pet_kill)
2582              && corpse >= 0 && player_mutation_level(MUT_POWERED_BY_DEATH))
2583     {
2584         const int pbd_dur = player_mutation_level(MUT_POWERED_BY_DEATH) * 8
2585                             + roll_dice(2, 8);
2586         if (pbd_dur > you.duration[DUR_POWERED_BY_DEATH])
2587             you.set_duration(DUR_POWERED_BY_DEATH, pbd_dur);
2588     }
2589
2590     unsigned int player_exp = 0, monster_exp = 0;
2591     if (!mons_reset && !fake_abjuration && !timeout && !unsummoned)
2592     {
2593         player_exp = _calc_player_experience(mons);
2594         monster_exp = _calc_monster_experience(mons, killer, killer_index);
2595     }
2596
2597     if (!mons_reset && !fake_abjuration && !crawl_state.game_is_arena()
2598         && !unsummoned && !timeout && !in_transit)
2599     {
2600         you.kills->record_kill(mons, killer, pet_kill);
2601     }
2602
2603     if (fake)
2604     {
2605         if (corpse != -1 && _reaping(mons))
2606             corpse = -1;
2607
2608         _give_experience(player_exp, monster_exp, killer, killer_index,
2609                          pet_kill, was_visible);
2610         crawl_state.dec_mon_acting(mons);
2611
2612         return corpse;
2613     }
2614
2615     mons_remove_from_grid(mons);
2616     _fire_monster_death_event(mons, killer, killer_index, false);
2617
2618     if (crawl_state.game_is_arena())
2619         arena_monster_died(mons, killer, killer_index, silent, corpse);
2620
2621     // Monsters haloes should be removed when they die.
2622     if (mons->holiness() == MH_HOLY)
2623         invalidate_agrid();
2624     // Likewise silence and umbras
2625     if (mons->type == MONS_SILENT_SPECTRE
2626         || mons->type == MONS_PROFANE_SERVITOR
2627         || mons->type == MONS_MOTH_OF_SUPPRESSION
2628         || mons->type == MONS_LOST_SOUL)
2629     {
2630         invalidate_agrid();
2631     }
2632
2633     // Done before items are dropped so that we can clone them
2634     if (soul_aura(mons->pos()) && mons->holiness() == MH_NATURAL
2635         && killer != KILL_RESET
2636         && killer != KILL_DISMISSED
2637         && killer != KILL_BANISHED)
2638     {
2639         lost_soul_spectralize(mons);
2640     }
2641
2642     const coord_def mwhere = mons->pos();
2643     if (drop_items)
2644         monster_drop_things(mons, YOU_KILL(killer) || pet_kill);
2645     else
2646     {
2647         // Destroy the items belonging to MF_HARD_RESET monsters so they
2648         // don't clutter up mitm[].
2649         mons->destroy_inventory();
2650     }
2651
2652     if (!silent && !wizard && !mons_reset && corpse != -1
2653         && !fake_abjuration
2654         && !timeout
2655         && !unsummoned
2656         && !(mons->flags & MF_KNOWN_SHIFTER)
2657         && mons->is_shapeshifter())
2658     {
2659         simple_monster_message(mons, "'s shape twists and changes as "
2660                                "it dies.");
2661     }
2662
2663     if (mons->is_divine_companion()
2664         && killer != KILL_RESET
2665         && !(mons->flags & MF_BANISHED))
2666     {
2667         remove_companion(mons);
2668     }
2669
2670     // If we kill an invisible monster reactivate autopickup.
2671     // We need to check for actual invisibility rather than whether we
2672     // can see the monster. There are several edge cases where a monster
2673     // is visible to the player but we still need to turn autopickup
2674     // back on, such as TSO's halo or sticky flame. (jpeg)
2675     if (mons_near(mons) && mons->has_ench(ENCH_INVIS))
2676         autotoggle_autopickup(false);
2677
2678     if (corpse != -1 && _reaping(mons))
2679         corpse = -1;
2680
2681     crawl_state.dec_mon_acting(mons);
2682     monster_cleanup(mons);
2683
2684     // Force redraw for monsters that die.
2685     if (in_bounds(mwhere) && you.see_cell(mwhere))
2686     {
2687         view_update_at(mwhere);
2688         update_screen();
2689     }
2690
2691     if (gives_xp)
2692     {
2693         _give_experience(player_exp, monster_exp, killer, killer_index,
2694                          pet_kill, was_visible);
2695     }
2696
2697     return corpse;
2698 }
2699
2700 void unawaken_vines(const monster* mons, bool quiet)
2701 {
2702     int vines_seen = 0;
2703     for (monster_iterator mi; mi; ++mi)
2704     {
2705         if (mi->type == MONS_SNAPLASHER_VINE
2706             && mi->props.exists("vine_awakener")
2707             && monster_by_mid(mi->props["vine_awakener"].get_int()) == mons)
2708         {
2709             if (you.can_see(*mi))
2710                 ++vines_seen;
2711             monster_die(*mi, KILL_RESET, NON_MONSTER);
2712         }
2713     }
2714
2715     if (!quiet && vines_seen)
2716     {
2717         mprf("The vine%s fall%s limply to the ground.",
2718               (vines_seen > 1 ? "s" : ""), (vines_seen == 1 ? "s" : ""));
2719     }
2720 }
2721
2722 // Clean up after a dead monster.
2723 void monster_cleanup(monster* mons)
2724 {
2725     crawl_state.mon_gone(mons);
2726
2727     if (mons->has_ench(ENCH_AWAKEN_FOREST))
2728     {
2729         forest_message(mons->pos(), "The forest abruptly stops moving.");
2730         env.forest_awoken_until = 0;
2731     }
2732
2733     if (mons->has_ench(ENCH_AWAKEN_VINES))
2734         unawaken_vines(mons, false);
2735
2736     // So that a message is printed for the effect ending
2737     if (mons->has_ench(ENCH_CONTROL_WINDS))
2738         mons->del_ench(ENCH_CONTROL_WINDS);
2739
2740     // So proper messages are printed
2741     if (mons->has_ench(ENCH_GRASPING_ROOTS_SOURCE))
2742         mons->del_ench(ENCH_GRASPING_ROOTS_SOURCE);
2743
2744     // May have been constricting something. No message because that depends
2745     // on the order in which things are cleaned up: If the constrictee is
2746     // cleaned up first, we wouldn't get a message anyway.
2747     mons->stop_constricting_all(false, true);
2748
2749     if (mons_is_tentacle_head(mons_base_type(mons)))
2750         _destroy_tentacles(mons);
2751
2752     env.mid_cache.erase(mons->mid);
2753     unsigned int monster_killed = mons->mindex();
2754     mons->reset();
2755
2756     for (monster_iterator mi; mi; ++mi)
2757         if (mi->foe == monster_killed)
2758             mi->foe = MHITNOT;
2759
2760     if (you.pet_target == monster_killed)
2761         you.pet_target = MHITNOT;
2762 }
2763
2764 int mounted_kill(monster* daddy, monster_type mc, killer_type killer,
2765                 int killer_index)
2766 {
2767     monster mon;
2768     mon.type = mc;
2769     mon.moveto(daddy->pos());
2770     define_monster(&mon);
2771     mon.flags = daddy->flags;
2772     mon.attitude = daddy->attitude;
2773     mon.damage_friendly = daddy->damage_friendly;
2774     mon.damage_total = daddy->damage_total;
2775     // Keep the rider's name, if it had one (Mercenary card).
2776     if (!daddy->mname.empty() && mon.type == MONS_SPRIGGAN)
2777         mon.mname = daddy->mname;
2778     if (daddy->props.exists("reaping_damage"))
2779     {
2780         dprf("Mounted kill: marking the other monster as reaped as well.");
2781         mon.props["reaping_damage"].get_int() = daddy->props["reaping_damage"].get_int();
2782         mon.props["reaper"].get_int() = daddy->props["reaper"].get_int();
2783     }
2784
2785     return monster_die(&mon, killer, killer_index, false, false, true);
2786 }
2787
2788 // If you're invis and throw/zap whatever, alerts menv to your position.
2789 void alert_nearby_monsters(void)
2790 {
2791     // Judging from the above comment, this function isn't
2792     // intended to wake up monsters, so we're only going to
2793     // alert monsters that aren't sleeping.  For cases where an
2794     // event should wake up monsters and alert them, I'd suggest
2795     // calling noisy() before calling this function. - bwr
2796     for (monster_near_iterator mi(you.pos()); mi; ++mi)
2797         if (!mi->asleep())
2798              behaviour_event(*mi, ME_ALERT, &you);
2799 }
2800
2801 static bool _valid_morph(monster* mons, monster_type new_mclass)
2802 {
2803     const dungeon_feature_type current_tile = grd(mons->pos());
2804
2805     monster_type old_mclass = mons_base_type(mons);
2806
2807     // Shapeshifters cannot polymorph into glowing shapeshifters or
2808     // vice versa.
2809     if ((new_mclass == MONS_GLOWING_SHAPESHIFTER
2810              && mons->has_ench(ENCH_SHAPESHIFTER))
2811          || (new_mclass == MONS_SHAPESHIFTER
2812              && mons->has_ench(ENCH_GLOWING_SHAPESHIFTER)))
2813     {
2814         return false;
2815     }
2816
2817     // [ds] Non-base draconians are much more trouble than their HD
2818     // suggests.
2819     if (mons_genus(new_mclass) == MONS_DRACONIAN
2820         && new_mclass != MONS_DRACONIAN
2821         && !player_in_branch(BRANCH_HALL_OF_ZOT)
2822         && !one_chance_in(10))
2823     {
2824         return false;
2825     }
2826
2827     // Various inappropriate polymorph targets.
2828     if (mons_class_holiness(new_mclass) != mons_class_holiness(old_mclass)
2829         || mons_class_flag(new_mclass, M_UNFINISHED)  // no unfinished monsters
2830         || mons_class_flag(new_mclass, M_CANT_SPAWN)  // no dummy monsters
2831         || mons_class_flag(new_mclass, M_NO_POLY_TO)  // explicitly disallowed
2832         || mons_class_flag(new_mclass, M_UNIQUE)      // no uniques
2833         || mons_class_flag(new_mclass, M_NO_EXP_GAIN) // not helpless
2834         || new_mclass == MONS_PROGRAM_BUG
2835
2836         // 'morph targets are _always_ "base" classes, not derived ones.
2837         || new_mclass != mons_species(new_mclass)
2838         || new_mclass == mons_species(old_mclass)