1 /**
2  * @file
3  * @brief Misc monster poly/mimic functions.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "mon-poly.h"
9 
10 #include "artefact.h"
11 #include "art-enum.h"
12 #include "attitude-change.h"
13 #include "delay.h"
14 #include "describe.h"
15 #include "dgn-overview.h"
16 #include "dungeon.h"
17 #include "fineff.h"
18 #include "god-conduct.h"
19 #include "hints.h"
20 #include "item-prop.h"
21 #include "item-status-flag-type.h"
22 #include "items.h"
23 #include "level-state-type.h"
24 #include "libutil.h"
25 #include "message.h"
26 #include "mon-death.h"
27 #include "mon-gear.h"
28 #include "mon-place.h"
29 #include "mon-tentacle.h"
30 #include "notes.h"
31 #include "religion.h"
32 #include "state.h"
33 #include "stringutil.h"
34 #include "terrain.h"
35 #include "traps.h"
36 #include "xom.h"
37 
feature_mimic_at(const coord_def & c)38 bool feature_mimic_at(const coord_def &c)
39 {
40     return map_masked(c, MMT_MIMIC);
41 }
42 
item_mimic_at(const coord_def & c)43 item_def* item_mimic_at(const coord_def &c)
44 {
45     for (stack_iterator si(c); si; ++si)
46         if (si->flags & ISFLAG_MIMIC)
47             return &*si;
48     return nullptr;
49 }
50 
mimic_at(const coord_def & c)51 bool mimic_at(const coord_def &c)
52 {
53     return feature_mimic_at(c) || item_mimic_at(c);
54 }
55 
monster_drop_things(monster * mons,bool mark_item_origins,bool (* suitable)(const item_def & item))56 void monster_drop_things(monster* mons,
57                           bool mark_item_origins,
58                           bool (*suitable)(const item_def& item))
59 {
60     // Drop weapons and missiles last (i.e., on top), so others pick up.
61     for (int i = NUM_MONSTER_SLOTS - 1; i >= 0; --i)
62     {
63         int item = mons->inv[i];
64 
65         if (item != NON_ITEM && suitable(env.item[item]))
66         {
67             const bool summoned_item =
68                 testbits(env.item[item].flags, ISFLAG_SUMMONED);
69             if (summoned_item)
70             {
71                 item_was_destroyed(env.item[item]);
72                 destroy_item(item);
73             }
74             else
75             {
76                 if (mark_item_origins && env.item[item].defined())
77                     origin_set_monster(env.item[item], mons);
78 
79                 env.item[item].props[DROPPER_MID_KEY].get_int() = mons->mid;
80 
81                 if (env.item[item].props.exists("autoinscribe"))
82                 {
83                     add_inscription(env.item[item],
84                         env.item[item].props["autoinscribe"].get_string());
85                     env.item[item].props.erase("autoinscribe");
86                 }
87 
88                 // Unrands held by fixed monsters would give awfully redundant
89                 // messages ("Cerebov hits you with the Sword of Cerebov."),
90                 // thus delay identification until drop/death.
91                 autoid_unrand(env.item[item]);
92 
93                 // If a monster is swimming, the items are ALREADY
94                 // underwater.
95                 move_item_to_grid(&item, mons->pos(), mons->swimming());
96             }
97 
98             mons->inv[i] = NON_ITEM;
99         }
100     }
101 }
102 
_valid_type_morph(const monster * mons,monster_type new_mclass)103 static bool _valid_type_morph(const monster* mons, monster_type new_mclass)
104 {
105     // Shapeshifters cannot polymorph into glowing shapeshifters or
106     // vice versa.
107     if ((new_mclass == MONS_GLOWING_SHAPESHIFTER
108              && mons->has_ench(ENCH_SHAPESHIFTER))
109          || (new_mclass == MONS_SHAPESHIFTER
110              && mons->has_ench(ENCH_GLOWING_SHAPESHIFTER)))
111     {
112         return false;
113     }
114 
115     // Various inappropriate polymorph targets.
116     if (   new_mclass == MONS_PROGRAM_BUG
117         || new_mclass == MONS_NO_MONSTER
118         || mons_class_flag(new_mclass, M_UNFINISHED)  // no unfinished monsters
119         || mons_class_flag(new_mclass, M_CANT_SPAWN)  // no dummy monsters
120         || mons_class_flag(new_mclass, M_NO_POLY_TO)  // explicitly disallowed
121         || mons_class_flag(new_mclass, M_UNIQUE)      // no uniques
122         || !mons_class_gives_xp(new_mclass)           // no tentacle parts or
123                                                       // harmless things
124         || !(mons_class_holiness(new_mclass) & mons_class_holiness(mons->type))
125         // normally holiness just needs to overlap, but we don't want
126         // shapeshifters to become demons
127         || mons->is_shapeshifter() && !(mons_class_holiness(new_mclass) & MH_NATURAL)
128         || !mons_class_is_threatening(new_mclass)
129 
130         // 'morph targets are _always_ "base" classes, not derived ones.
131         || new_mclass != mons_species(new_mclass)
132         || new_mclass == mons_species(mons->type)
133         // They act as separate polymorph classes on their own.
134         || mons_class_is_zombified(new_mclass)
135 
136         // These require manual setting of the ghost demon struct to
137         // indicate their characteristics, which we currently aren't
138         // smart enough to handle.
139         || mons_is_ghost_demon(new_mclass)
140 
141         // Other poly-unsuitable things.
142         || mons_is_statue(new_mclass)
143         || mons_is_projectile(new_mclass)
144 
145         // The spell on Prince Ribbit can't be broken so easily.
146         || (new_mclass == MONS_HUMAN
147             && (mons->type == MONS_PRINCE_RIBBIT
148                 || mons->mname == "Prince Ribbit")))
149     {
150         return false;
151     }
152 
153     return true;
154 }
155 
156 
157 
_valid_morph(monster * mons,monster_type new_mclass)158 static bool _valid_morph(monster* mons, monster_type new_mclass)
159 {
160     if (!_valid_type_morph(mons, new_mclass))
161         return false;
162 
163     // [hm] Lower base draconian chances since there are nine of them,
164     // and they shouldn't each count for a full chance.
165     if (mons_genus(new_mclass) == MONS_DRACONIAN
166         && new_mclass != MONS_DRACONIAN
167         && !one_chance_in(9))
168     {
169         return false;
170     }
171 
172     // Determine if the monster is happy on current tile.
173     return monster_habitable_grid(new_mclass, env.grid(mons->pos()));
174 }
175 
_is_poly_power_unsuitable(poly_power_type power,int src_pow,int tgt_pow,int relax)176 static bool _is_poly_power_unsuitable(poly_power_type power,
177                                        int src_pow, int tgt_pow, int relax)
178 {
179     switch (power)
180     {
181     case PPT_LESS:
182         return tgt_pow > src_pow - 3 + relax * 3 / 2
183                 || (power == PPT_LESS && tgt_pow < src_pow - relax / 2);
184     case PPT_MORE:
185         return tgt_pow < src_pow + 2 - relax
186                 || (power == PPT_MORE && tgt_pow > src_pow + relax);
187     default:
188     case PPT_SAME:
189         return tgt_pow < src_pow - relax
190                 || tgt_pow > src_pow + relax * 3 / 2;
191     }
192 }
193 
_jiyva_slime_target(monster_type targetc)194 static bool _jiyva_slime_target(monster_type targetc)
195 {
196     return you_worship(GOD_JIYVA)
197            && (targetc == MONS_ENDOPLASM
198               || targetc == MONS_JELLY
199               || targetc == MONS_SLIME_CREATURE
200               || targetc == MONS_ACID_BLOB
201               || targetc == MONS_AZURE_JELLY);
202 }
203 
change_monster_type(monster * mons,monster_type targetc)204 void change_monster_type(monster* mons, monster_type targetc)
205 {
206     ASSERT(mons); // XXX: change to monster &mons
207     bool could_see     = you.can_see(*mons);
208     bool slimified = _jiyva_slime_target(targetc);
209 
210     // Quietly remove the old monster's invisibility before transforming
211     // it. If we don't do this, it'll stay invisible even after losing
212     // the invisibility enchantment below.
213     mons->del_ench(ENCH_INVIS, false, false);
214 
215     // Remove replacement tile, since it probably doesn't work for the
216     // new monster.
217     mons->props.erase("monster_tile_name");
218     mons->props.erase("monster_tile");
219 
220     // Even if the monster transforms from one type that can behold the
221     // player into a different type which can also behold the player,
222     // the polymorph disrupts the beholding process. Do this before
223     // changing mons->type, since unbeholding can only happen while
224     // the monster is still a siren/merfolk avatar.
225     you.remove_beholder(*mons);
226     you.remove_fearmonger(mons);
227 
228     if (mons_is_tentacle_head(mons_base_type(*mons)))
229         destroy_tentacles(mons);
230 
231     // trj spills out jellies when polied, as if he'd been hit for mhp.
232     if (mons->type == MONS_ROYAL_JELLY)
233     {
234         simple_monster_message(*mons, "'s form twists and warps, and jellies "
235                                "spill out!");
236         trj_spawn_fineff::schedule(nullptr, mons, mons->pos(),
237                                    mons->hit_points);
238     }
239 
240     // Inform listeners that the original monster is gone.
241     fire_monster_death_event(mons, KILL_MISC, true);
242 
243     // the actual polymorphing:
244     auto flags =
245         mons->flags & ~(MF_SEEN | MF_ATT_CHANGE_ATTEMPT
246                            | MF_WAS_IN_VIEW | MF_BAND_MEMBER | MF_KNOWN_SHIFTER
247                            | MF_MELEE_MASK);
248     flags |= MF_POLYMORPHED;
249     string name;
250 
251     // Preserve the names of uniques and named monsters.
252     if (mons->type == MONS_ROYAL_JELLY
253         || mons->mname == "shaped Royal Jelly")
254     {
255         name   = "shaped Royal Jelly";
256         flags |= MF_NAME_SUFFIX;
257     }
258     else if (mons->type == MONS_LERNAEAN_HYDRA
259              || mons->mname == "shaped Lernaean hydra")
260     {
261         name   = "shaped Lernaean hydra";
262         flags |= MF_NAME_SUFFIX;
263     }
264     else if (mons->mons_species() == MONS_SERPENT_OF_HELL
265              || mons->mname == "shaped Serpent of Hell")
266     {
267         name   = "shaped Serpent of Hell";
268         flags |= MF_NAME_SUFFIX;
269     }
270     else if (!mons->mname.empty())
271     {
272         if (flags & MF_NAME_MASK)
273         {
274             // Remove the replacement name from the new monster
275             flags = flags & ~(MF_NAME_MASK | MF_NAME_DESCRIPTOR
276                               | MF_NAME_DEFINITE | MF_NAME_SPECIES
277                               | MF_NAME_ZOMBIE | MF_NAME_NOCORPSE);
278         }
279         else
280             name = mons->mname;
281     }
282     else if (mons_is_unique(mons->type))
283     {
284         name = mons->name(DESC_PLAIN, true);
285 
286         // "Blork the orc" and similar.
287         const size_t the_pos = name.find(" the ");
288         if (the_pos != string::npos)
289             name = name.substr(0, the_pos);
290     }
291 
292     const god_type old_god        = mons->god;
293     const int  old_hp             = mons->hit_points;
294     const int  old_hp_max         = mons->max_hit_points;
295     const bool old_mon_caught     = mons->caught();
296     const char old_ench_countdown = mons->ench_countdown;
297 
298     const bool old_mon_unique = mons_is_or_was_unique(*mons);
299 
300     if (!mons->props.exists(ORIGINAL_TYPE_KEY))
301     {
302         const monster_type type = mons_is_job(mons->type)
303                                 ? draco_or_demonspawn_subspecies(*mons)
304                                 : mons->type;
305         mons->props[ORIGINAL_TYPE_KEY].get_int() = type;
306         if (mons->mons_species() == MONS_HYDRA)
307             mons->props["old_heads"].get_int() = mons->num_heads;
308     }
309 
310     mon_enchant abj       = mons->get_ench(ENCH_ABJ);
311     mon_enchant fabj      = mons->get_ench(ENCH_FAKE_ABJURATION);
312     mon_enchant charm     = mons->get_ench(ENCH_CHARM);
313     mon_enchant shifter   = mons->get_ench(ENCH_GLOWING_SHAPESHIFTER,
314                                            ENCH_SHAPESHIFTER);
315     mon_enchant sub       = mons->get_ench(ENCH_SUBMERGED);
316     mon_enchant summon    = mons->get_ench(ENCH_SUMMON);
317     mon_enchant tp        = mons->get_ench(ENCH_TP);
318     mon_enchant vines     = mons->get_ench(ENCH_AWAKEN_VINES);
319     mon_enchant forest    = mons->get_ench(ENCH_AWAKEN_FOREST);
320     mon_enchant hexed     = mons->get_ench(ENCH_HEXED);
321     mon_enchant insanity  = mons->get_ench(ENCH_INSANE);
322 
323     mons->number       = 0;
324 
325     // Note: define_monster(*) will clear out all enchantments! - bwr
326     if (!slimified && mons_is_zombified(*mons))
327         define_zombie(mons, targetc, mons->type);
328     else
329     {
330         mons->type         = targetc;
331         mons->base_monster = MONS_NO_MONSTER;
332         define_monster(*mons);
333     }
334 
335     mons->mname = name;
336     mons->props["no_annotate"] = slimified && old_mon_unique;
337     mons->props.erase("dbname");
338 
339     // Forget seen spells, since they are likely to have changed.
340     mons->props.erase(SEEN_SPELLS_KEY);
341 
342     mons->flags = flags;
343     // Line above might clear melee and/or spell flags; restore.
344     mons->bind_melee_flags();
345     mons->bind_spell_flags();
346 
347     // Forget various speech/shout Lua functions.
348     mons->props.erase("speech_prefix");
349 
350     // Make sure we have a god if we've been polymorphed into a priest.
351     mons->god = (mons->is_priest() && old_god == GOD_NO_GOD) ? GOD_NAMELESS
352                                                              : old_god;
353 
354     mons->add_ench(abj);
355     mons->add_ench(fabj);
356     mons->add_ench(charm);
357     mons->add_ench(shifter);
358     mons->add_ench(sub);
359     mons->add_ench(summon);
360     mons->add_ench(tp);
361     mons->add_ench(vines);
362     mons->add_ench(forest);
363     mons->add_ench(hexed);
364     mons->add_ench(insanity);
365 
366     // Allows for handling of submerged monsters which polymorph into
367     // monsters that can't submerge on this square.
368     if (mons->has_ench(ENCH_SUBMERGED)
369         && !monster_can_submerge(mons, env.grid(mons->pos())))
370     {
371         mons->del_ench(ENCH_SUBMERGED);
372     }
373 
374     mons->ench_countdown = old_ench_countdown;
375 
376     if (mons_class_flag(mons->type, M_INVIS))
377         mons->add_ench(ENCH_INVIS);
378 
379     mons->hit_points = mons->max_hit_points * old_hp / old_hp_max
380                        + random2(mons->max_hit_points);
381 
382     mons->hit_points = min(mons->max_hit_points, mons->hit_points);
383 
384     // Don't kill it.
385     mons->hit_points = max(mons->hit_points, 1);
386 
387     mons->speed_increment = 67 + random2(6);
388 
389     monster_drop_things(mons);
390 
391     // If new monster is visible to player, then we've seen it.
392     if (you.can_see(*mons))
393     {
394         seen_monster(mons);
395         // If the player saw both the beginning and end results of a
396         // shifter changing, then s/he knows it must be a shifter.
397         if (could_see && shifter.ench != ENCH_NONE)
398             discover_shifter(*mons);
399     }
400     // generate a new polymorph set
401     mons->props.erase(POLY_SET_KEY);
402     init_poly_set(mons);
403 
404     if (old_mon_caught)
405         check_net_will_hold_monster(mons);
406 
407     // Even if the new form can constrict, it might be with a different
408     // body part. Likewise, the new form might be too large for its
409     // current constrictor. Rather than trying to handle these as special
410     // cases, just stop the constriction entirely. The usual message about
411     // evaporating and reforming justifies this behaviour.
412     mons->stop_constricting_all();
413     mons->stop_being_constricted();
414     mons->clear_far_engulf();
415 }
416 
417 // Is the new monster able to live in *any* habitat that the original
418 // monster could?
419 // NOTE: this doesn't check for item-based flight, so if we
420 // poly an item-using flying monster into a non-item-using,
421 // non-flying monster, they could be in trouble. Not much way
422 // around this and it's a very very niche case.
423 // Also assumes the monster is not a derived (zombie etc) monster.
_habitat_matches(bool orig_flies,habitat_type orig_hab,monster_type new_type)424 static bool _habitat_matches(bool orig_flies, habitat_type orig_hab,
425                              monster_type new_type)
426 {
427     if (monster_class_flies(new_type))
428         return true;
429     if (orig_flies)
430         return false;
431 
432     const habitat_type new_hab = mons_habitat_type(new_type, new_type, false);
433     switch (orig_hab)
434     {
435         case HT_AMPHIBIOUS:
436         case HT_AMPHIBIOUS_LAVA:
437             return new_hab == orig_hab;
438         case HT_WATER:
439             return new_hab == orig_hab || new_hab == HT_AMPHIBIOUS;
440         case HT_LAVA:
441             return new_hab == orig_hab || new_hab == HT_AMPHIBIOUS_LAVA;
442         case HT_LAND:
443             return new_hab == orig_hab
444                 || new_hab == HT_AMPHIBIOUS
445                 || new_hab == HT_AMPHIBIOUS_LAVA;
446         case NUM_HABITATS:
447             break;
448     }
449     return false; // should never happen
450 }
451 
init_poly_set(monster * mons)452 void init_poly_set(monster *mons)
453 {
454     rng::subgenerator poly_rng;
455 
456     if (mons->props.exists(POLY_SET_KEY))
457         return;
458 
459     const int orig_tier = mons_demon_tier(mons->type);
460     if (orig_tier == -1)
461     {
462         // panlords & hell lords get poly immunity. why? unclear to me
463         // TODO: allow polying panlords into other random panlords, ha
464         return;
465     }
466 
467     const int orig_hd = mons_power(mons->type);
468     const bool orig_flies = monster_inherently_flies(*mons);
469     const habitat_type orig_hab
470         = mons_habitat_type(mons->type, mons_base_type(*mons), false);
471 
472     map<monster_type, int> weights;
473     for (monster_type mt = MONS_0; mt < NUM_MONSTERS; ++mt)
474     {
475         if (invalid_monster_type(mt))
476             continue; // no polying into bugs
477 
478         const monster_type species = mons_species(mt);
479         if (weights.find(species) != weights.end())
480             continue; // already saw this one
481         if (!_valid_type_morph(mons, species))
482             continue; // no polying into statues, same species, etc
483 
484         if (!_habitat_matches(orig_flies, orig_hab, species))
485             continue;
486 
487         // OK, we're good. Let's look at weights.
488         const int new_tier = mons_demon_tier(species);
489         const int new_hd = mons_power(species);
490         // make HD upgrades less likely.
491         const int hd_delta = abs(orig_hd - new_hd) * (new_hd > orig_hd ? 2 : 1);
492         const int tier_delta = abs(orig_tier - new_tier);
493         const int total_delta = hd_delta + tier_delta;
494         const int max_delta = 8;
495         if (total_delta > max_delta)
496             continue;
497         // halve weight for each HD of difference and each demon tier level apart
498         const int weight = 1 << (max_delta - total_delta) ;
499         weights[species] = weight;
500     }
501 
502     CrawlVector &set = mons->props[POLY_SET_KEY];
503     for (int i = 0; i < 3; i++)
504     {
505         if (weights.size() <= 0)
506             return; // can't choose any more
507         const monster_type *chosen = random_choose_weighted<map<monster_type,int>>(weights);
508         ASSERT(chosen);
509         set.push_back(*chosen);
510         weights.erase(*chosen);
511     }
512 }
513 
_poly_from_set(monster * mons)514 static monster_type _poly_from_set(monster *mons)
515 {
516     if (!mons->props.exists(POLY_SET_KEY))
517         return MONS_NO_MONSTER;
518     const CrawlVector &set = mons->props[POLY_SET_KEY];
519     if (set.size() <= 0)
520         return MONS_NO_MONSTER;
521     return (monster_type)set[random2(set.size())].get_int();
522 }
523 
524 // If targetc == RANDOM_MONSTER, then relpower indicates the desired
525 // power of the new monster, relative to the current monster.
526 // Relaxation still takes effect when needed, no matter what relpower
527 // says.
monster_polymorph(monster * mons,monster_type targetc,poly_power_type power)528 bool monster_polymorph(monster* mons, monster_type targetc,
529                        poly_power_type power)
530 {
531     // Don't attempt to polymorph a monster that is busy using the stairs.
532     if (mons->flags & MF_TAKING_STAIRS)
533         return false;
534     ASSERT(!(mons->flags & MF_BANISHED) || player_in_branch(BRANCH_ABYSS));
535 
536     int source_power, target_power, relax;
537     int source_tier, target_tier;
538     int tries = 1000;
539 
540     // Used to be mons_power, but that just returns hit_dice
541     // for the monster class. By using the current hit dice
542     // the player gets the opportunity to use draining more
543     // effectively against shapeshifters. - bwr
544     source_power = mons->get_hit_dice();
545     source_tier = mons_demon_tier(mons->type);
546 
547     // There's not a single valid target on the '&' demon tier, so unless we
548     // make one, let's ban this outright.
549     if (source_tier == -1)
550     {
551         return simple_monster_message(*mons,
552             "'s appearance momentarily alters.");
553     }
554     relax = 1;
555 
556     if (targetc == RANDOM_MONSTER)
557     {
558         do
559         {
560             // Pick a monster species that's guaranteed happy at this grid.
561             targetc = random_monster_at_grid(mons->pos(), true);
562 
563             target_power = mons_power(targetc);
564             // Can't compare tiers in valid_morph, since we want to affect only
565             // random polymorphs, and not absolutely, too.
566             target_tier = mons_demon_tier(targetc);
567 
568             if (one_chance_in(200))
569                 relax++;
570 
571             if (relax > 50)
572                 return simple_monster_message(*mons, " shudders.");
573         }
574         while (tries-- && (!_valid_morph(mons, targetc)
575                            || source_tier != target_tier && !x_chance_in_y(relax, 200)
576                            || _is_poly_power_unsuitable(power, source_power,
577                                                         target_power, relax)));
578     }
579 
580     if (targetc == RANDOM_POLYMORPH_MONSTER)
581         targetc = _poly_from_set(mons);
582 
583     bool could_see = you.can_see(*mons);
584     bool need_note = could_see && mons_is_notable(*mons);
585     string old_name_a = mons->full_name(DESC_A);
586     string old_name_the = mons->full_name(DESC_THE);
587     monster_type oldc = mons->type;
588 
589     if (targetc == RANDOM_TOUGHER_MONSTER)
590     {
591         vector<monster_type> target_types;
592         for (monster_type mc = MONS_0; mc < NUM_MONSTERS; ++mc)
593         {
594             const monsterentry *me = get_monster_data(mc);
595             const int delta = me->HD - mons->get_hit_dice();
596             if (delta != 1)
597                 continue;
598             if (!_valid_morph(mons, mc))
599                 continue;
600             target_types.push_back(mc);
601         }
602         if (target_types.empty())
603             return false;
604 
605         targetc = target_types[random2(target_types.size())];
606     }
607 
608     if (power != PPT_SLIME && !_valid_morph(mons, targetc))
609         return simple_monster_message(*mons, " looks momentarily different.");
610 
611     change_monster_type(mons, targetc);
612 
613     bool can_see = you.can_see(*mons);
614 
615     // Messaging
616     bool player_messaged = true;
617     if (could_see)
618     {
619         string verb = "";
620         string obj = can_see ? mons_type_name(targetc, DESC_A)
621                              : "something you cannot see";
622 
623         if (oldc == MONS_OGRE && targetc == MONS_TWO_HEADED_OGRE)
624         {
625             verb = "grows a second head";
626             obj = "";
627         }
628         else if (mons->is_shapeshifter())
629             verb = "changes into ";
630         else if (_jiyva_slime_target(targetc))
631             verb = "quivers uncontrollably and liquefies into ";
632         else
633             verb = "evaporates and reforms as ";
634 
635         mprf("%s %s%s!", old_name_the.c_str(), verb.c_str(), obj.c_str());
636     }
637     else if (can_see)
638     {
639         mprf("%s appears out of thin air!", mons->name(DESC_A).c_str());
640         autotoggle_autopickup(false);
641     }
642     else
643         player_messaged = false;
644 
645     if (need_note || could_see && can_see && mons_is_notable(*mons))
646     {
647         string new_name = can_see ? mons->full_name(DESC_A)
648                                   : "something unseen";
649 
650         take_note(Note(NOTE_POLY_MONSTER, 0, 0, old_name_a, new_name));
651 
652         if (can_see)
653             mons->flags |= MF_SEEN;
654     }
655 
656     // Xom likes watching monsters being polymorphed.
657     if (can_see)
658     {
659         xom_is_stimulated(mons->is_shapeshifter()               ? 12 :
660                           power == PPT_LESS || mons->friendly() ? 25 :
661                           power == PPT_SAME                     ? 50
662                                                                 : 100);
663     }
664 
665     return player_messaged;
666 }
667 
mon_can_be_slimified(const monster * mons)668 bool mon_can_be_slimified(const monster* mons)
669 {
670     const mon_holy_type holi = mons->holiness();
671 
672     return !mons->is_insubstantial()
673            && !mons_is_tentacle_or_tentacle_segment(mons->type)
674            && (holi & (MH_UNDEAD | MH_NATURAL) && !mons_is_slime(*mons));
675 }
676 
slimify_monster(monster * mon)677 void slimify_monster(monster* mon)
678 {
679     monster_type target = MONS_JELLY;
680 
681     const int x = mon->get_hit_dice() + random_choose(1, -1) * random2(5);
682 
683     if (x < 3)
684         target = MONS_ENDOPLASM;
685     else if (x >= 3 && x < 5)
686         target = MONS_JELLY;
687     else if (x >= 5 && x <= 11)
688         target = MONS_SLIME_CREATURE;
689     else
690     {
691         if (coinflip())
692             target = MONS_ACID_BLOB;
693         else
694             target = MONS_AZURE_JELLY;
695     }
696 
697     if (feat_is_water(env.grid(mon->pos()))) // Pick something amphibious.
698         target = (x < 7) ? MONS_JELLY : MONS_SLIME_CREATURE;
699 
700     // Bail out if jellies can't live here.
701     if (!monster_habitable_grid(target, env.grid(mon->pos())))
702     {
703         simple_monster_message(*mon, " quivers momentarily.");
704         return;
705     }
706 
707     record_monster_defeat(mon, KILL_SLIMIFIED);
708     remove_unique_annotation(mon);
709 
710     monster_polymorph(mon, target, PPT_SLIME);
711 
712     mon->attitude = ATT_STRICT_NEUTRAL;
713 
714     mons_make_god_gift(*mon, GOD_JIYVA);
715 
716     // Don't want shape-shifters to shift into non-slimes.
717     mon->del_ench(ENCH_GLOWING_SHAPESHIFTER);
718     mon->del_ench(ENCH_SHAPESHIFTER);
719 
720     mons_att_changed(mon);
721 }
722 
seen_monster(monster * mons)723 void seen_monster(monster* mons)
724 {
725     set_unique_annotation(mons);
726 
727     // id equipment (do this every time we see them, it may have changed)
728     view_monster_equipment(mons);
729 
730     item_def* weapon = mons->weapon();
731     if (weapon && is_range_weapon(*weapon))
732         mons->flags |= MF_SEEN_RANGED;
733 
734     // Monster was viewed this turn
735     mons->flags |= MF_WAS_IN_VIEW;
736 
737     if (mons->flags & MF_SEEN)
738         return;
739 
740     // First time we've seen this particular monster.
741     mons->flags |= MF_SEEN;
742 
743     if (crawl_state.game_is_hints())
744         hints_monster_seen(*mons);
745 
746     if (mons_is_notable(*mons))
747     {
748         string name = mons->name(DESC_A, true);
749         if (mons->type == MONS_PLAYER_GHOST)
750         {
751             name += make_stringf(" (%s)",
752                                  short_ghost_description(mons, true).c_str());
753         }
754         take_note(Note(NOTE_SEEN_MONSTER, mons->type, 0, name));
755     }
756 
757     if (player_equip_unrand(UNRAND_WYRMBANE))
758     {
759         const item_def *wyrmbane = you.weapon();
760         if (wyrmbane && mons->dragon_level() > wyrmbane->plus)
761             mprf("<green>Wyrmbane glows as a worthy foe approaches.</green>");
762     }
763 
764     // attempt any god conversions on first sight
765     do_conversions(mons);
766 
767     if (!(mons->flags & MF_TSO_SEEN))
768     {
769         if (mons_gives_xp(*mons, you) && !crawl_state.game_is_arena())
770         {
771             did_god_conduct(DID_SEE_MONSTER, mons->get_experience_level(),
772                             true, mons);
773         }
774         mons->flags |= MF_TSO_SEEN;
775     }
776 
777     if (mons_allows_beogh(*mons))
778         env.level_state |= LSTATE_BEOGH;
779 }
780