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