1 /**
2  * @file
3  * @brief Misc function related to player transformations.
4 **/
5 
6 #include "AppHdr.h"
7 
8 #include "transform.h"
9 
10 #include <cstdio>
11 #include <cstring>
12 
13 #include "artefact.h"
14 #include "art-enum.h"
15 #include "delay.h"
16 #include "english.h"
17 #include "env.h"
18 #include "god-item.h"
19 #include "god-passive.h" // passive_t::resist_polymorph
20 #include "invent.h" // check_old_item_warning
21 #include "item-use.h"
22 #include "item-name.h"
23 #include "item-prop.h"
24 #include "items.h"
25 #include "message.h"
26 #include "mon-death.h"
27 #include "mutation.h"
28 #include "output.h"
29 #include "player-equip.h"
30 #include "player-stats.h"
31 #include "prompt.h"
32 #include "religion.h"
33 #include "spl-cast.h"
34 #include "state.h"
35 #include "stringutil.h"
36 #include "tag-version.h"
37 #include "terrain.h"
38 #include "traps.h"
39 #include "xom.h"
40 
41 // transform slot enums into flags
42 #define SLOTF(s) (1 << s)
43 
44 static const int EQF_NONE = 0;
45 // "hand" slots (not rings)
46 static const int EQF_HANDS = SLOTF(EQ_WEAPON) | SLOTF(EQ_SHIELD)
47                              | SLOTF(EQ_GLOVES);
48 // head and feet (beastly appendage);
49 static const int EQF_HEAD_FOOT = SLOTF(EQ_BOOTS) | SLOTF(EQ_HELMET);
50 // core body slots (statue form)
51 static const int EQF_STATUE = SLOTF(EQ_GLOVES) | SLOTF(EQ_BOOTS)
52                               | SLOTF(EQ_BODY_ARMOUR);
53 // more core body slots (Lear's Hauberk)
54 static const int EQF_LEAR = EQF_STATUE | SLOTF(EQ_HELMET);
55 // everything you can (W)ear
56 static const int EQF_WEAR = EQF_LEAR | SLOTF(EQ_CLOAK) | SLOTF(EQ_SHIELD);
57 // everything but jewellery
58 static const int EQF_PHYSICAL = EQF_HANDS | EQF_WEAR;
59 // all rings (except for the macabre finger amulet's)
60 static const int EQF_RINGS = SLOTF(EQ_LEFT_RING) | SLOTF(EQ_RIGHT_RING)
61                              | SLOTF(EQ_RING_ONE) | SLOTF(EQ_RING_TWO)
62                              | SLOTF(EQ_RING_THREE) | SLOTF(EQ_RING_FOUR)
63                              | SLOTF(EQ_RING_FIVE) | SLOTF(EQ_RING_SIX)
64                              | SLOTF(EQ_RING_SEVEN) | SLOTF(EQ_RING_EIGHT);
65 // amulet & pal
66 static const int EQF_AMULETS = SLOTF(EQ_AMULET) | SLOTF(EQ_RING_AMULET);
67 // everything
68 static const int EQF_ALL = EQF_PHYSICAL | EQF_RINGS | EQF_AMULETS;
69 
melding_description() const70 string Form::melding_description() const
71 {
72     // this is a bit rough and ready...
73     // XX simplify slot melding rather than complicate this function?
74     if (blocked_slots == EQF_ALL)
75         return "Your equipment is entirely melded.";
76     else if (blocked_slots == EQF_PHYSICAL)
77         return "Your armour is entirely melded.";
78     else if ((blocked_slots & EQF_PHYSICAL) == EQF_PHYSICAL)
79         return "Your equipment is almost entirely melded.";
80     else if ((blocked_slots & EQF_STATUE) == EQF_STATUE
81              && (you_can_wear(EQ_GLOVES, false)
82                  || you_can_wear(EQ_BOOTS, false)
83                  || you_can_wear(EQ_BODY_ARMOUR, false)))
84     {
85         return "Your equipment is partially melded.";
86     }
87     // otherwise, rely on the form description to convey what is melded.
88     return "";
89 }
90 
91 static const FormAttackVerbs DEFAULT_VERBS = FormAttackVerbs(nullptr, nullptr,
92                                                              nullptr, nullptr);
93 static const FormAttackVerbs ANIMAL_VERBS = FormAttackVerbs("hit", "bite",
94                                                             "maul", "maul");
95 
96 static const FormDuration DEFAULT_DURATION = FormDuration(20, PS_DOUBLE, 100);
97 static const FormDuration BAD_DURATION = FormDuration(15, PS_ONE_AND_A_HALF,
98                                                       100);
99 
100 // Class form_entry and the formdata array
101 #include "form-data.h"
102 
_find_form_entry(transformation form)103 static const form_entry &_find_form_entry(transformation form)
104 {
105     for (const form_entry &entry : formdata)
106         if (entry.tran == form)
107             return entry;
108     die("No formdata entry found for form %d", (int)form);
109 }
110 
Form(const form_entry & fe)111 Form::Form(const form_entry &fe)
112     : short_name(fe.short_name), wiz_name(fe.wiz_name),
113       duration(fe.duration),
114       str_mod(fe.str_mod), dex_mod(fe.dex_mod),
115       blocked_slots(fe.blocked_slots), size(fe.size), hp_mod(fe.hp_mod),
116       can_cast(fe.can_cast), spellcasting_penalty(fe.spellcasting_penalty),
117       unarmed_hit_bonus(fe.unarmed_hit_bonus), uc_colour(fe.uc_colour),
118       uc_attack_verbs(fe.uc_attack_verbs),
119       can_bleed(fe.can_bleed),
120       keeps_mutations(fe.keeps_mutations),
121       shout_verb(fe.shout_verb),
122       shout_volume_modifier(fe.shout_volume_modifier),
123       hand_name(fe.hand_name), foot_name(fe.foot_name),
124       flesh_equivalent(fe.flesh_equivalent),
125       long_name(fe.long_name), description(fe.description),
126       resists(fe.resists),
127       base_unarmed_damage(fe.base_unarmed_damage),
128       can_fly(fe.can_fly), can_swim(fe.can_swim),
129       flat_ac(fe.flat_ac), power_ac(fe.power_ac), xl_ac(fe.xl_ac),
130       uc_brand(fe.uc_brand), uc_attack(fe.uc_attack),
131       prayer_action(fe.prayer_action), equivalent_mons(fe.equivalent_mons),
132       fakemuts(fe.fakemuts)
133 { }
134 
Form(transformation tran)135 Form::Form(transformation tran)
136     : Form(_find_form_entry(tran))
137 { }
138 /**
139  * Is the given equipment slot available for use in this form?
140  *
141  * @param slot      The equipment slot in question. (May be a weird fake
142  *                  slot - EQ_STAFF or EQ_ALL_ARMOUR.)
143  * @return          Whether at least some items can be worn in this slot in
144  *                  this form.
145  *                  (The player's race, or mutations, may still block the
146  *                  slot, or it may be restricted to subtypes.)
147  */
slot_available(int slot) const148 bool Form::slot_available(int slot) const
149 {
150     if (slot == EQ_ALL_ARMOUR)
151         return !all_blocked(EQF_WEAR);
152     if (slot == EQ_RINGS || slot == EQ_RINGS_PLUS)
153         return !all_blocked(EQF_RINGS);
154 
155     if (slot == EQ_STAFF)
156         slot = EQ_WEAPON;
157     return !(blocked_slots & SLOTF(slot));
158 }
159 
160 /**
161  * Can the player wear the given item while in this form?
162  *
163  * Does not take mutations into account.
164  *
165  * @param item  The item in question
166  * @return      Whether this form prevents the player from wearing the
167  *              item. (Other things may also prevent it, of course)
168  */
can_wear_item(const item_def & item) const169 bool Form::can_wear_item(const item_def& item) const
170 {
171     if (item.base_type == OBJ_JEWELLERY)
172     {
173         if (jewellery_is_amulet(item))
174             return slot_available(EQ_AMULET);
175         return !all_blocked(EQF_RINGS);
176     }
177 
178     if (is_unrandom_artefact(item, UNRAND_LEAR))
179         return !(blocked_slots & EQF_LEAR); // ok if no body slots blocked
180 
181     return slot_available(get_armour_slot(item));
182 }
183 
184 /**
185  * Get the bonus to form duration granted for a given (spell)power.
186  *
187  * @param pow               The spellpower/equivalent of the form.
188  * @return                  A bonus to form duration.
189  */
power_bonus(int pow) const190 int FormDuration::power_bonus(int pow) const
191 {
192     switch (scaling_type)
193     {
194         case PS_NONE:
195             return 0;
196         case PS_SINGLE:
197             return random2(pow);
198         case PS_ONE_AND_A_HALF:
199             return random2(pow) + random2(pow/2);
200         case PS_DOUBLE:
201             return random2(pow) + random2(pow);
202         default:
203             die("Unknown scaling type!");
204             return -1;
205     }
206 }
207 
208 /**
209  * Get the duration for this form, when newly entered.
210  *
211  * @param pow   The power of the effect creating this form. (Spellpower, etc.)
212  * @return      The duration of the form. (XXX: in turns...?)
213  */
get_duration(int pow) const214 int Form::get_duration(int pow) const
215 {
216     return min(duration.base + duration.power_bonus(pow), duration.max);
217 }
218 
219 /**
220  * Get a verbose description for the form.
221  *
222  * @param past_tense     Whether the description should be in past or present
223  *                       tense.
224  * @return               A description for the form.
225  */
get_description(bool past_tense) const226 string Form::get_description(bool past_tense) const
227 {
228     return make_stringf("You %s %s",
229                         past_tense ? "were" : "are",
230                         get_transform_description().c_str());
231 }
232 
233 /**
234  * Get a message for transforming into this form, based on your current
235  * situation (e.g. in water...)
236  *
237  * @return The message for turning into this form.
238  */
transform_message(transformation previous_trans) const239 string Form::transform_message(transformation previous_trans) const
240 {
241     // XXX: refactor this into a second function (and also rethink the logic)
242     string start = "Buggily, y";
243     if (you.in_water() && player_can_fly())
244         start = "You fly out of the water as y";
245     else if (get_form(previous_trans)->player_can_fly()
246              && player_can_swim()
247              && feat_is_water(env.grid(you.pos())))
248         start = "As you dive into the water, y";
249     else
250         start = "Y";
251 
252     return make_stringf("%sou turn into %s", start.c_str(),
253                         get_transform_description().c_str());
254 }
255 
256 /**
257  * Get a message for untransforming from this form.
258  *
259  * @return "Your transform has ended."
260  */
get_untransform_message() const261 string Form::get_untransform_message() const
262 {
263     return "Your transformation has ended.";
264 }
265 
266 /**
267  * What AC bonus does the player get while in this form?
268  *
269  * Many forms are power-dependent, so the answer given may be strange if the
270  * player isn't currently in the form in question.
271  *
272  * @return  The AC bonus currently granted by the form, multiplied by 100 to
273  *          allow for pseudo-decimal flexibility (& to match
274  *          player::armour_class())
275  */
get_ac_bonus() const276 int Form::get_ac_bonus() const
277 {
278     return flat_ac * 100
279            + power_ac * you.props[TRANSFORM_POW_KEY].get_int()
280            + xl_ac * you.experience_level;
281 }
282 
283 /**
284  * (freeze)
285  */
_brand_suffix(brand_type brand)286 static string _brand_suffix(brand_type brand)
287 {
288     if (brand == SPWPN_NORMAL)
289         return "";
290     return make_stringf(" (%s)", brand_type_name(brand, true));
291 }
292 
293 /**
294  * What name should be used for the player's means of unarmed attack while
295  * in this form?
296  *
297  * (E.g. for display in the top-right of the UI.)
298  *
299  * @param   The player's UC weapon when not in a form (claws, etc)
300  * @return  A string describing the form's UC attack 'weapon'.
301  */
get_uc_attack_name(string default_name) const302 string Form::get_uc_attack_name(string default_name) const
303 {
304     const string brand_suffix = _brand_suffix(get_uc_brand());
305     if (uc_attack.empty())
306         return default_name + brand_suffix;
307     return uc_attack + brand_suffix;
308 }
309 
310 /**
311  * How many levels of resistance against fire does this form provide?
312  */
res_fire() const313 int Form::res_fire() const
314 {
315     return get_resist(resists, MR_RES_FIRE);
316 }
317 
318 /**
319  * How many levels of resistance against cold does this form provide?
320  */
res_cold() const321 int Form::res_cold() const
322 {
323     return get_resist(resists, MR_RES_COLD);
324 }
325 
326 /**
327  * How many levels of resistance against negative energy does this form give?
328  */
res_neg() const329 int Form::res_neg() const
330 {
331     return get_resist(resists, MR_RES_NEG);
332 }
333 
334 /**
335  * Does this form provide resistance to electricity?
336  */
res_elec() const337 bool Form::res_elec() const
338 {
339     return get_resist(resists, MR_RES_ELEC);
340 }
341 
342 /**
343  * How many levels of resistance against poison does this form give?
344  */
res_pois() const345 int Form::res_pois() const
346 {
347     return get_resist(resists, MR_RES_POISON);
348 }
349 
350 /**
351  * Does this form provide resistance to miasma?
352  */
res_miasma() const353 bool Form::res_miasma() const
354 {
355     return get_resist(resists, MR_RES_MIASMA);
356 }
357 
358 /**
359  * Does this form provide resistance against acid?
360  */
res_acid() const361 bool Form::res_acid() const
362 {
363     return get_resist(resists, MR_RES_ACID);
364 }
365 
366 /**
367  * Does this form provide resistance to sticky flame?
368  */
res_sticky_flame() const369 bool Form::res_sticky_flame() const
370 {
371     return get_resist(resists, MR_RES_STICKY_FLAME);
372 }
373 
374 /**
375  * Does this form provide resistance to petrification?
376  */
res_petrify() const377 bool Form::res_petrify() const
378 {
379     return get_resist(resists, MR_RES_PETRIFY);
380 }
381 
382 
383 /**
384  * Does this form enable flight?
385  *
386  * @return Whether this form allows flight for characters which don't already
387  *         have access to it.
388  */
enables_flight() const389 bool Form::enables_flight() const
390 {
391     return can_fly == FC_ENABLE;
392 }
393 
394 /**
395  * Does this form disable flight?
396  *
397  * @return Whether flight is always impossible while in this form.
398  */
forbids_flight() const399 bool Form::forbids_flight() const
400 {
401     return can_fly == FC_FORBID;
402 }
403 
404 /**
405  * Does this form disable swimming?
406  *
407  * @return Whether swimming is always impossible while in this form.
408  */
forbids_swimming() const409 bool Form::forbids_swimming() const
410 {
411     return can_swim == FC_FORBID;
412 }
413 
414 /**
415  * Can the player fly, if in this form?
416  *
417  * DOES consider player state besides form.
418  * @return  Whether the player will be able to fly in this form.
419  */
player_can_fly() const420 bool Form::player_can_fly() const
421 {
422     return !forbids_flight()
423            && (enables_flight()
424                || you.racial_permanent_flight()); // XX other cases??
425 }
426 
427 /**
428  * Can the player swim, if in this form?
429  *
430  * DOES consider player state besides form.
431  * @return  Whether the player will be able to swim in this form.
432  */
player_can_swim() const433 bool Form::player_can_swim() const
434 {
435     // XX this is kind of a mess w.r.t. player::can_swim
436     const size_type player_size = size == SIZE_CHARACTER ?
437                                           you.body_size(PSIZE_BODY, true) :
438                                           size;
439     return can_swim == FC_ENABLE
440            || species::can_swim(you.species)
441               && can_swim != FC_FORBID
442            || player_size >= SIZE_GIANT;
443 }
444 
445 /**
446  * Are all of the given equipment slots blocked while in this form?
447  *
448  * @param slotflags     A set of flags, corresponding to the union of
449  (1 << the slot enum) for each slot in question.
450  * @return              Whether all of the given slots are blocked.
451  */
all_blocked(int slotflags) const452 bool Form::all_blocked(int slotflags) const
453 {
454     return slotflags == (blocked_slots & slotflags);
455 }
456 
457 /**
458  * What message should be printed when the player prays at an altar?
459  * To be inserted into "You %s the altar of foo."
460  *
461  * If the form has a valid custom action, print that; otherwise, default to the
462  * 'flying' or species-specific actions, as appropriate.
463  *
464  * @return  An action to be printed when the player prays at an altar.
465  *          E.g., "perch on", "crawl onto", "sway towards", etc.
466  */
player_prayer_action() const467 string Form::player_prayer_action() const
468 {
469     // If the form is naturally flying & specifies an action, use that.
470     if (can_fly == FC_ENABLE && !prayer_action.empty())
471         return prayer_action;
472     // Otherwise, if you're flying, use the generic flying action.
473     // XXX: if we ever get a default-permaflying species again that wants to
474     // have a separate verb, we'll want to check for that right here.
475     if (you.airborne())
476         return "hover solemnly before";
477     // Otherwise, if you have a verb, use that...
478     if (!prayer_action.empty())
479         return prayer_action;
480     // Finally, default to your species' verb.
481     return species::prayer_action(you.species);
482 }
483 
get_fakemuts(bool terse) const484 vector<string> Form::get_fakemuts(bool terse) const
485 {
486     vector<string> result;
487     for (const auto &p : fakemuts)
488         result.push_back(terse ? p.first : p.second);
489     return result;
490 }
491 
492 
493 class FormNone : public Form
494 {
495 private:
FormNone()496     FormNone() : Form(transformation::none) { }
497     DISALLOW_COPY_AND_ASSIGN(FormNone);
498 public:
instance()499     static const FormNone &instance() { static FormNone inst; return inst; }
500 
501     /**
502      * Get a string describing the form you're turning into. (If not the same
503      * as the one used to describe this form in @.
504      */
get_transform_description() const505     string get_transform_description() const override { return "your old self."; }
506 };
507 
508 class FormSpider : public Form
509 {
510 private:
FormSpider()511     FormSpider() : Form(transformation::spider) { }
512     DISALLOW_COPY_AND_ASSIGN(FormSpider);
513 public:
instance()514     static const FormSpider &instance() { static FormSpider inst; return inst; }
515 };
516 
517 class FormBlade : public Form
518 {
519 private:
FormBlade()520     FormBlade() : Form(transformation::blade_hands) { }
521     DISALLOW_COPY_AND_ASSIGN(FormBlade);
522 public:
instance()523     static const FormBlade &instance() { static FormBlade inst; return inst; }
524 
525     /**
526      * % screen description
527      */
get_long_name() const528     string get_long_name() const override
529     {
530         return you.base_hand_name(true, true);
531     }
532 
533     /**
534      * @ description
535      */
get_description(bool past_tense) const536     string get_description(bool past_tense) const override
537     {
538         return make_stringf("You %s blades for %s.",
539                             past_tense ? "had" : "have",
540                             blade_parts().c_str());
541     }
542 
543     /**
544      * Get a message for transforming into this form.
545      */
transform_message(transformation) const546     string transform_message(transformation /*previous_trans*/) const override
547     {
548         const bool singular = you.arm_count() == 1;
549 
550         // XXX: a little ugly
551         return make_stringf("Your %s turn%s into%s razor-sharp scythe blade%s.",
552                             blade_parts().c_str(), singular ? "s" : "",
553                             singular ? " a" : "", singular ? "" : "s");
554     }
555 
556     /**
557      * Get a message for untransforming from this form.
558      */
get_untransform_message() const559     string get_untransform_message() const override
560     {
561         const bool singular = you.arm_count() == 1;
562 
563         // XXX: a little ugly
564         return make_stringf("Your %s revert%s to %s normal proportions.",
565                             blade_parts().c_str(), singular ? "s" : "",
566                             singular ? "its" : "their");
567     }
568 
can_offhand_punch() const569     bool can_offhand_punch() const override { return true; }
570 
571     /**
572      * Get the name displayed in the UI for the form's unarmed-combat 'weapon'.
573      */
get_uc_attack_name(string) const574     string get_uc_attack_name(string /*default_name*/) const override
575     {
576         return "Blade " + blade_parts(true);
577     }
578 };
579 
580 class FormStatue : public Form
581 {
582 private:
FormStatue()583     FormStatue() : Form(transformation::statue) { }
584     DISALLOW_COPY_AND_ASSIGN(FormStatue);
585 public:
instance()586     static const FormStatue &instance() { static FormStatue inst; return inst; }
587 
588     /**
589      * Get a message for transforming into this form.
590      */
transform_message(transformation previous_trans) const591     string transform_message(transformation previous_trans) const override
592     {
593         if (you.species == SP_DEEP_DWARF && one_chance_in(10))
594             return "You inwardly fear your resemblance to a lawn ornament.";
595         else if (you.species == SP_GARGOYLE)
596             return "Your body stiffens and grows slower.";
597         else
598             return Form::transform_message(previous_trans);
599     }
600 
601     /**
602      * Get a string describing the form you're turning into. (If not the same
603      * as the one used to describe this form in @.
604      */
get_transform_description() const605     string get_transform_description() const override
606     {
607         return "a living statue of rough stone.";
608     }
609 
610     /**
611      * Get a message for untransforming from this form.
612      */
get_untransform_message() const613     string get_untransform_message() const override
614     {
615         // This only handles lava orcs going statue -> stoneskin.
616         if (you.species == SP_GARGOYLE)
617             return "You revert to a slightly less stony form.";
618         return "You revert to your normal fleshy form.";
619     }
620 
621     /**
622      * Get the name displayed in the UI for the form's unarmed-combat 'weapon'.
623      */
get_uc_attack_name(string) const624     string get_uc_attack_name(string /*default_name*/) const override
625     {
626         // there's special casing in base_hand_name to get "fists"
627         string hand = you.base_hand_name(true, true);
628         return make_stringf("Stone %s", hand.c_str());
629     }
630 };
631 
632 class FormIce : public Form
633 {
634 private:
FormIce()635     FormIce() : Form(transformation::ice_beast) { }
636     DISALLOW_COPY_AND_ASSIGN(FormIce);
637 public:
instance()638     static const FormIce &instance() { static FormIce inst; return inst; }
639 
640     /**
641      * Get a message for untransforming from this form.
642      */
get_untransform_message() const643     string get_untransform_message() const override
644     {
645         return "You warm up again.";
646     }
647 
648     /**
649      * Get the name displayed in the UI for the form's unarmed-combat 'weapon'.
650      */
get_uc_attack_name(string) const651     string get_uc_attack_name(string /*default_name*/) const override
652     {
653         const bool singular = you.get_mutation_level(MUT_MISSING_HAND);
654         // paws for consistency with form-data and the tile
655         // XX does this imply the behavior of feline paws?
656         return make_stringf("Ice paw%s", singular ? "" : "s");
657     }
658 };
659 
660 class FormDragon : public Form
661 {
662 private:
FormDragon()663     FormDragon() : Form(transformation::dragon) { }
664     DISALLOW_COPY_AND_ASSIGN(FormDragon);
665 public:
instance()666     static const FormDragon &instance() { static FormDragon inst; return inst; }
667 
668     /**
669      * Get an monster type corresponding to the transformation.
670      *
671      * (Used for console player glyphs.)
672      *
673      * @return  A monster type corresponding to the player in this form.
674      */
get_equivalent_mons() const675     monster_type get_equivalent_mons() const override
676     {
677         return species::dragon_form(you.species);
678     }
679 
get_transform_description() const680     string get_transform_description() const override
681     {
682         if (species::is_draconian(you.species))
683         {
684             return make_stringf("a fearsome %s!",
685                           mons_class_name(get_equivalent_mons()));
686         }
687         else
688             return description;
689     }
690 
691     /**
692      * The AC bonus of the form, multiplied by 100 to match
693      * player::armour_class().
694      */
get_ac_bonus() const695     int get_ac_bonus() const override
696     {
697         if (species::is_draconian(you.species))
698             return 1000;
699         return Form::get_ac_bonus();
700     }
701 
702     /**
703      * How many levels of resistance against fire does this form provide?
704      */
res_fire() const705     int res_fire() const override
706     {
707         switch (species::dragon_form(you.species))
708         {
709             case MONS_FIRE_DRAGON:
710                 return 2;
711             case MONS_ICE_DRAGON:
712                 return -1;
713             default:
714                 return 0;
715         }
716     }
717 
718     /**
719      * How many levels of resistance against cold does this form provide?
720      */
res_cold() const721     int res_cold() const override
722     {
723         switch (species::dragon_form(you.species))
724         {
725             case MONS_ICE_DRAGON:
726                 return 2;
727             case MONS_FIRE_DRAGON:
728                 return -1;
729             default:
730                 return 0;
731         }
732     }
733 
can_offhand_punch() const734     bool can_offhand_punch() const override { return true; }
735 };
736 
737 class FormLich : public Form
738 {
739 private:
FormLich()740     FormLich() : Form(transformation::lich) { }
741     DISALLOW_COPY_AND_ASSIGN(FormLich);
742 public:
instance()743     static const FormLich &instance() { static FormLich inst; return inst; }
744 
745     /**
746      * Get a message for transforming into this form.
747      */
transform_message(transformation) const748     string transform_message(transformation /*previous_trans*/) const override
749     {
750         return "Your body is suffused with negative energy!";
751     }
752 
753     /**
754      * Get a message for untransforming from this form.
755      */
get_untransform_message() const756     string get_untransform_message() const override
757     {
758         if (you.undead_state() == US_ALIVE)
759             return "You feel yourself come back to life.";
760         return "You feel your undeath return to normal.";
761         // ^^^ vampires only, probably
762     }
763 };
764 
765 class FormBat : public Form
766 {
767 private:
FormBat()768     FormBat() : Form(transformation::bat) { }
769     DISALLOW_COPY_AND_ASSIGN(FormBat);
770 public:
instance()771     static const FormBat &instance() { static FormBat inst; return inst; }
772 
773     /**
774      * Get an monster type corresponding to the transformation.
775      *
776      * (Used for console player glyphs.)
777      *
778      * @return  A monster type corresponding to the player in this form.
779      */
get_equivalent_mons() const780     monster_type get_equivalent_mons() const override
781     {
782         return you.has_mutation(MUT_VAMPIRISM) ? MONS_VAMPIRE_BAT : MONS_BAT;
783     }
784 
785     /**
786      * Get a string describing the form you're turning into. (If not the same
787      * as the one used to describe this form in @.
788      */
get_transform_description() const789     string get_transform_description() const override
790     {
791         return make_stringf("a %sbat.",
792                             you.has_mutation(MUT_VAMPIRISM) ? "vampire " : "");
793     }
794 };
795 
796 class FormPig : public Form
797 {
798 private:
FormPig()799     FormPig() : Form(transformation::pig) { }
800     DISALLOW_COPY_AND_ASSIGN(FormPig);
801 public:
instance()802     static const FormPig &instance() { static FormPig inst; return inst; }
803 };
804 
805 class FormAppendage : public Form
806 {
807 private:
FormAppendage()808     FormAppendage() : Form(transformation::appendage) { }
809     DISALLOW_COPY_AND_ASSIGN(FormAppendage);
810 public:
instance()811     static const FormAppendage &instance()
812     {
813         static FormAppendage inst;
814         return inst;
815     }
816 
get_description(bool past_tense) const817     string get_description(bool past_tense) const override
818     {
819         ostringstream desc;
820         bool spike = false;
821         vector<string> muts;
822         for (auto app : you.props[APPENDAGE_KEY].get_vector())
823         {
824             mutation_type mut = static_cast<mutation_type>(app.get_int());
825             if (mut == MUT_TENTACLE_SPIKE)
826                 spike = true;
827             else
828                 muts.push_back(mutation_name(mut));
829         }
830 
831         if (spike)
832         {
833             string tense =  past_tense ? "had" : "has";
834             desc << "One of your tentacles " << tense;
835             desc << " grown a beastly spike";
836             if (muts.empty())
837                 desc << ".";
838             else
839                 desc << ", and you ";
840         }
841         else if (!muts.empty())
842             desc << "You ";
843 
844         if (!muts.empty())
845         {
846             string tense =  past_tense ? "had" : "have";
847             desc << tense << " temporarily grown beastly ";
848             desc << comma_separated_line(muts.begin(), muts.end()) << ".";
849         }
850 
851         return trimmed_string(desc.str());
852     }
853 
854     /**
855      * Get a message for transforming into this form.
856      */
transform_message(transformation) const857     string transform_message(transformation /*previous_trans*/) const override
858     {
859         ostringstream msg;
860         for (auto app : you.props[APPENDAGE_KEY].get_vector())
861         {
862             mutation_type mut = static_cast<mutation_type>(app.get_int());
863             switch (mut)
864             {
865                 case MUT_HORNS:
866                     msg << "You grow a pair of large bovine horns. ";
867                     break;
868                 case MUT_TENTACLE_SPIKE:
869                     msg << "One of your tentacles grows a vicious spike. ";
870                     break;
871                 case MUT_TALONS:
872                     msg << "Your feet morph into talons. ";
873                     break;
874                 default:
875                     die("Unknown appendage type");
876                     break;
877             }
878         }
879 
880         return trimmed_string(msg.str());
881     }
882 
883     /**
884      * Get a message for untransforming from this form. (Handled elsewhere.)
885      */
get_untransform_message() const886     string get_untransform_message() const override { return ""; }
887 };
888 
889 class FormTree : public Form
890 {
891 private:
FormTree()892     FormTree() : Form(transformation::tree) { }
893     DISALLOW_COPY_AND_ASSIGN(FormTree);
894 public:
instance()895     static const FormTree &instance() { static FormTree inst; return inst; }
896 
897     /**
898      * Get a message for untransforming from this form.
899      */
get_untransform_message() const900     string get_untransform_message() const override { return "You feel less wooden."; }
901 };
902 
903 #if TAG_MAJOR_VERSION == 34
904 class FormPorcupine : public Form
905 {
906 private:
FormPorcupine()907     FormPorcupine() : Form(transformation::porcupine) { }
908     DISALLOW_COPY_AND_ASSIGN(FormPorcupine);
909 public:
instance()910     static const FormPorcupine &instance()
911     {
912         static FormPorcupine inst;
913         return inst;
914     }
915 };
916 #endif
917 
918 class FormWisp : public Form
919 {
920 private:
FormWisp()921     FormWisp() : Form(transformation::wisp) { }
922     DISALLOW_COPY_AND_ASSIGN(FormWisp);
923 public:
instance()924     static const FormWisp &instance() { static FormWisp inst; return inst; }
925 };
926 
927 #if TAG_MAJOR_VERSION == 34
928 class FormJelly : public Form
929 {
930 private:
FormJelly()931     FormJelly() : Form(transformation::jelly) { }
932     DISALLOW_COPY_AND_ASSIGN(FormJelly);
933 public:
instance()934     static const FormJelly &instance() { static FormJelly inst; return inst; }
935 };
936 #endif
937 
938 class FormFungus : public Form
939 {
940 private:
FormFungus()941     FormFungus() : Form(transformation::fungus) { }
942     DISALLOW_COPY_AND_ASSIGN(FormFungus);
943 public:
instance()944     static const FormFungus &instance() { static FormFungus inst; return inst; }
945 
946     /**
947      * Get a message for untransforming from this form.
948      */
get_untransform_message() const949     string get_untransform_message() const override { return "You stop sporulating."; }
950 };
951 
952 class FormShadow : public Form
953 {
954 private:
FormShadow()955     FormShadow() : Form(transformation::shadow) { }
956     DISALLOW_COPY_AND_ASSIGN(FormShadow);
957 public:
instance()958     static const FormShadow &instance() { static FormShadow inst; return inst; }
959 
960     /**
961      * Get a message for untransforming from this form.
962      */
get_untransform_message() const963     string get_untransform_message() const override
964     {
965         if (you.invisible())
966             return "You feel less shadowy.";
967         return "You emerge from the shadows.";
968     }
969 };
970 
set_airform_power(int pow)971 void set_airform_power(int pow)
972 {
973     you.props[AIRFORM_POWER_KEY] = pow;
974 }
975 
976 class FormStorm : public Form
977 {
978 private:
FormStorm()979     FormStorm() : Form(transformation::storm) { }
980     DISALLOW_COPY_AND_ASSIGN(FormStorm);
981 public:
instance()982     static const FormStorm &instance() { static FormStorm inst; return inst; }
983 
984     /**
985      * Find the player's base unarmed damage in this form.
986      */
get_base_unarmed_damage() const987     int get_base_unarmed_damage() const override
988     {
989         int power = 0;
990         if (you.props.exists(AIRFORM_POWER_KEY))
991             power = you.props[AIRFORM_POWER_KEY].get_int();
992         return 2 + div_rand_round(power * 2, 5);
993     }
994 
can_offhand_punch() const995     bool can_offhand_punch() const override { return true; }
996 };
997 
998 #if TAG_MAJOR_VERSION == 34
999 
1000 /**
1001  * Set the number of hydra heads that the player currently has.
1002  *
1003  * @param heads the new number of heads you should have.
1004  */
set_hydra_form_heads(int heads)1005 void set_hydra_form_heads(int heads)
1006 {
1007     you.props[HYDRA_FORM_HEADS_KEY] = min(MAX_HYDRA_HEADS, max(1, heads));
1008     you.wield_change = true;
1009 }
1010 
1011 class FormHydra : public Form
1012 {
1013 private:
FormHydra()1014     FormHydra() : Form(transformation::hydra) { }
1015     DISALLOW_COPY_AND_ASSIGN(FormHydra);
1016 public:
instance()1017     static const FormHydra &instance() { static FormHydra inst; return inst; }
1018 
1019     /**
1020      * Get a string describing the form you're turning into.
1021      */
get_transform_description() const1022     string get_transform_description() const override
1023     {
1024         const auto heads = you.heads();
1025         const string headstr = (heads < 11 ? number_in_words(heads)
1026                                            : to_string(heads))
1027                              + "-headed hydra.";
1028         return article_a(headstr);
1029     }
1030 
1031     /**
1032      * @ description
1033      */
get_description(bool past_tense) const1034     string get_description(bool past_tense) const override
1035     {
1036         return make_stringf("You %s %s",
1037                             past_tense ? "were" : "are",
1038                             get_transform_description().c_str());
1039     }
1040 
1041     /**
1042      * Get the name displayed in the UI for the form's unarmed-combat 'weapon'.
1043      */
get_uc_attack_name(string) const1044     string get_uc_attack_name(string /*default_name*/) const override
1045     {
1046         return make_stringf("Bite (x%d)", you.heads());
1047     }
1048 
1049     /**
1050      * Find the player's base unarmed damage in this form.
1051      */
get_base_unarmed_damage() const1052     int get_base_unarmed_damage() const override
1053     {
1054         // 3 damage per head for 1-10
1055         const int normal_heads_damage = min(you.heads(), 10) * 3;
1056         // 3/2 damage per head for 11-20 (they get in each-other's way)
1057             // (and also a 62-base-damage form scares me)
1058         const int too_many_heads_damage = max(0, you.heads() - 10)
1059                                             * 3 / 2;
1060         // 2-47 (though more like 14-32 in practical ranges...)
1061         return 2 + normal_heads_damage + too_many_heads_damage;
1062     }
1063 
1064 };
1065 #endif
1066 
1067 static const Form* forms[] =
1068 {
1069     &FormNone::instance(),
1070     &FormSpider::instance(),
1071     &FormBlade::instance(),
1072     &FormStatue::instance(),
1073 
1074     &FormIce::instance(),
1075     &FormDragon::instance(),
1076     &FormLich::instance(),
1077     &FormBat::instance(),
1078 
1079     &FormPig::instance(),
1080     &FormAppendage::instance(),
1081     &FormTree::instance(),
1082 #if TAG_MAJOR_VERSION == 34
1083     &FormPorcupine::instance(),
1084 #endif
1085 
1086     &FormWisp::instance(),
1087 #if TAG_MAJOR_VERSION == 34
1088     &FormJelly::instance(),
1089 #endif
1090     &FormFungus::instance(),
1091     &FormShadow::instance(),
1092 #if TAG_MAJOR_VERSION == 34
1093     &FormHydra::instance(),
1094 #endif
1095     &FormStorm::instance(),
1096 };
1097 
get_form(transformation xform)1098 const Form* get_form(transformation xform)
1099 {
1100     COMPILE_CHECK(ARRAYSZ(forms) == NUM_TRANSFORMS);
1101     const int form = static_cast<int>(xform);
1102     ASSERT_RANGE(form, 0, NUM_TRANSFORMS);
1103     return forms[form];
1104 }
1105 
1106 
1107 /**
1108  * Get the wizmode name of a form.
1109  *
1110  * @param form      The form in question.
1111  * @return          The form's casual, wizmode name.
1112  */
transform_name(transformation form)1113 const char* transform_name(transformation form)
1114 {
1115     return get_form(form)->wiz_name.c_str();
1116 }
1117 
1118 /**
1119  * Can the player (w)ield weapons when in the given form?
1120  *
1121  * @param form      The form in question.
1122  * @return          Whether the player can wield items when in that form.
1123 */
form_can_wield(transformation form)1124 bool form_can_wield(transformation form)
1125 {
1126     return get_form(form)->can_wield();
1127 }
1128 
1129 /**
1130  * Can the player (W)ear armour when in the given form?
1131  *
1132  * @param form      The form in question.
1133  * @return          Whether the player can wear armour when in that form.
1134  */
form_can_wear(transformation form)1135 bool form_can_wear(transformation form)
1136 {
1137     return !testbits(get_form(form)->blocked_slots, EQF_WEAR);
1138 }
1139 
1140 /**
1141  * Can the player fly, if in this form?
1142  *
1143  * DOES consider player state besides form.
1144  * @param form      The form in question.
1145  * @return          Whether the player will be able to fly in this form.
1146  */
form_can_fly(transformation form)1147 bool form_can_fly(transformation form)
1148 {
1149     return get_form(form)->player_can_fly();
1150 }
1151 
1152 
1153 /**
1154  * Can the player swim, if in this form?
1155  *
1156  * (Swimming = traversing deep & shallow water without penalties; includes
1157  * floating (ice form) and wading forms (giants - currently just dragon form,
1158  * which normally flies anyway...))
1159  *
1160  * DOES consider player state besides form.
1161  * @param form      The form in question.
1162  * @return          Whether the player will be able to swim in this form.
1163  */
form_can_swim(transformation form)1164 bool form_can_swim(transformation form)
1165 {
1166     return get_form(form)->player_can_swim();
1167 }
1168 
1169 /**
1170  * Can the player survive in deep water when in the given form?
1171  *
1172  * Doesn't count flight or beogh water-walking.
1173  *
1174  * @param form      The form in question.
1175  * @return          Whether the player won't be killed when entering deep water
1176  *                  in that form.
1177  */
form_likes_water(transformation form)1178 bool form_likes_water(transformation form)
1179 {
1180     // Grey dracs can't swim, so can't statue form merfolk/octopodes
1181     // -- yet they can still survive in water.
1182     if (species::likes_water(you.species)
1183         && (form == transformation::statue
1184             || !get_form(form)->forbids_swimming()))
1185     {
1186         return true;
1187     }
1188 
1189     // otherwise, you gotta swim to survive!
1190     return form_can_swim(form);
1191 }
1192 
1193 // Used to mark transformations which override species intrinsics.
form_changed_physiology(transformation form)1194 bool form_changed_physiology(transformation form)
1195 {
1196     return form != transformation::none
1197         && form != transformation::appendage
1198         && form != transformation::blade_hands;
1199 }
1200 
1201 /**
1202  * Does this form have blood?
1203  *
1204  * @param form      The form in question.
1205  * @return          Whether the form can bleed, sublime, etc.
1206  */
form_can_bleed(transformation form)1207 bool form_can_bleed(transformation form)
1208 {
1209     return get_form(form)->can_bleed != FC_FORBID;
1210 }
1211 
1212 // Used to mark forms which keep most form-based mutations.
form_keeps_mutations(transformation form)1213 bool form_keeps_mutations(transformation form)
1214 {
1215     return get_form(form)->keeps_mutations;
1216 }
1217 
1218 static set<equipment_type>
_init_equipment_removal(transformation form)1219 _init_equipment_removal(transformation form)
1220 {
1221     set<equipment_type> result;
1222     if (!form_can_wield(form) && you.weapon() || you.melded[EQ_WEAPON])
1223         result.insert(EQ_WEAPON);
1224 
1225     // Liches can't wield holy weapons.
1226     if (form == transformation::lich && you.weapon()
1227         && is_holy_item(*you.weapon()))
1228     {
1229         result.insert(EQ_WEAPON);
1230     }
1231 
1232     for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; ++i)
1233     {
1234         if (i == EQ_WEAPON)
1235             continue;
1236         const equipment_type eq = static_cast<equipment_type>(i);
1237         const item_def *pitem = you.slot_item(eq, true);
1238 
1239         if (pitem && (get_form(form)->blocked_slots & SLOTF(i)
1240                       || (i != EQ_RING_AMULET
1241                           && !get_form(form)->can_wear_item(*pitem))))
1242         {
1243             result.insert(eq);
1244         }
1245     }
1246     return result;
1247 }
1248 
_remove_equipment(const set<equipment_type> & removed,transformation form,bool meld=true,bool mutation=false)1249 static void _remove_equipment(const set<equipment_type>& removed,
1250                               transformation form,
1251                               bool meld = true, bool mutation = false)
1252 {
1253     // Meld items into you in (reverse) order. (set is a sorted container)
1254     for (const equipment_type e : removed)
1255     {
1256         item_def *equip = you.slot_item(e, true);
1257         if (equip == nullptr)
1258             continue;
1259 
1260         bool unequip = !meld;
1261         if (!unequip && e == EQ_WEAPON)
1262         {
1263             if (form_can_wield(form))
1264                 unequip = true;
1265             if (!is_weapon(*equip))
1266                 unequip = true;
1267         }
1268 
1269         const string msg = make_stringf("%s %s%s %s",
1270              equip->name(DESC_YOUR).c_str(),
1271              unequip ? "fall" : "meld",
1272              equip->quantity > 1 ? "" : "s",
1273              unequip ? "away" : "into your body.");
1274 
1275         if (you_worship(GOD_ASHENZARI) && unequip && equip->cursed())
1276             mprf(MSGCH_GOD, "%s, shattering the curse!", msg.c_str());
1277         else if (unequip)
1278             mprf("%s!", msg.c_str());
1279         else
1280             mpr(msg);
1281 
1282         if (unequip)
1283         {
1284             if (e == EQ_WEAPON)
1285             {
1286                 unwield_item(!you.berserk());
1287                 canned_msg(MSG_EMPTY_HANDED_NOW);
1288             }
1289             else
1290                 unequip_item(e);
1291 
1292             if (mutation)
1293             {
1294                 // A mutation made us not only lose an equipment slot
1295                 // but actually removed a worn item: Funny!
1296                 xom_is_stimulated(is_artefact(*equip) ? 200 : 100);
1297             }
1298         }
1299         else
1300             meld_slot(e);
1301     }
1302 
1303     if (meld)
1304     {
1305         for (const equipment_type e : removed)
1306             if (you.slot_item(e, true) != nullptr)
1307                 unequip_effect(e, you.equip[e], true, true);
1308     }
1309 }
1310 
_unmeld_equipment_type(equipment_type e)1311 static void _unmeld_equipment_type(equipment_type e)
1312 {
1313     item_def& item = you.inv[you.equip[e]];
1314     bool force_remove = false;
1315 
1316     if (e == EQ_WEAPON)
1317     {
1318         if (you.slot_item(EQ_SHIELD)
1319             && is_shield_incompatible(item, you.slot_item(EQ_SHIELD)))
1320         {
1321             force_remove = true;
1322         }
1323     }
1324     else if (item.base_type != OBJ_JEWELLERY)
1325     {
1326         // This could happen if the player was mutated during the form.
1327         if (!can_wear_armour(item, false, true))
1328             force_remove = true;
1329 
1330         // If you switched weapons during the transformation, make
1331         // sure you can still wear your shield.
1332         // (This is only possible with Statue Form.)
1333         if (e == EQ_SHIELD && you.weapon()
1334             && is_shield_incompatible(*you.weapon(), &item))
1335         {
1336             force_remove = true;
1337         }
1338     }
1339 
1340     if (force_remove)
1341     {
1342         mprf("%s is pushed off your body!", item.name(DESC_YOUR).c_str());
1343         unequip_item(e);
1344     }
1345     else
1346     {
1347         mprf("%s unmelds from your body.", item.name(DESC_YOUR).c_str());
1348         unmeld_slot(e);
1349     }
1350 }
1351 
_unmeld_equipment(const set<equipment_type> & melded)1352 static void _unmeld_equipment(const set<equipment_type>& melded)
1353 {
1354     // Unmeld items in order.
1355     for (const equipment_type e : melded)
1356     {
1357         if (you.equip[e] == -1)
1358             continue;
1359 
1360         _unmeld_equipment_type(e);
1361     }
1362 
1363     for (const equipment_type e : melded)
1364         if (you.equip[e] != -1)
1365             equip_effect(e, you.equip[e], true, true);
1366 }
1367 
_lears_takes_slot(equipment_type eq)1368 static bool _lears_takes_slot(equipment_type eq)
1369 {
1370     return eq >= EQ_HELMET && eq <= EQ_BOOTS
1371         || eq == EQ_BODY_ARMOUR;
1372 }
1373 
_form_melds_lears(transformation which_trans)1374 static bool _form_melds_lears(transformation which_trans)
1375 {
1376     for (equipment_type eq : _init_equipment_removal(which_trans))
1377         if (_lears_takes_slot(eq))
1378             return true;
1379     return false;
1380 }
1381 
unmeld_one_equip(equipment_type eq)1382 void unmeld_one_equip(equipment_type eq)
1383 {
1384     if (_lears_takes_slot(eq))
1385     {
1386         const item_def* arm = you.slot_item(EQ_BODY_ARMOUR, true);
1387         if (arm && is_unrandom_artefact(*arm, UNRAND_LEAR))
1388         {
1389             // Don't unmeld lears when de-fishtailing if you're in
1390             // a form that should keep it melded.
1391             if (_form_melds_lears(you.form))
1392                 return;
1393             eq = EQ_BODY_ARMOUR;
1394         }
1395     }
1396 
1397     set<equipment_type> e;
1398     e.insert(eq);
1399     _unmeld_equipment(e);
1400 }
1401 
remove_one_equip(equipment_type eq,bool meld,bool mutation)1402 void remove_one_equip(equipment_type eq, bool meld, bool mutation)
1403 {
1404     if (player_equip_unrand(UNRAND_LEAR) && _lears_takes_slot(eq))
1405         eq = EQ_BODY_ARMOUR;
1406 
1407     set<equipment_type> r;
1408     r.insert(eq);
1409     _remove_equipment(r, you.form, meld, mutation);
1410 }
1411 
1412 /**
1413  * Get an monster type corresponding to the player's current form.
1414  *
1415  * (Used for console player glyphs.)
1416  *
1417  * @return  A monster type corresponding to the player in the form.
1418  */
transform_mons()1419 monster_type transform_mons()
1420 {
1421     return get_form()->get_equivalent_mons();
1422 }
1423 
1424 /**
1425  * What is the name of the player parts that will become blades?
1426  */
blade_parts(bool terse)1427 string blade_parts(bool terse)
1428 {
1429     // there's special casing in base_hand_name to use "blade" everywhere, so
1430     // use the non-temp name
1431     string str = you.base_hand_name(true, false);
1432 
1433     // creatures with paws (aka felids) have four paws, but only two of them
1434     // turn into blades.
1435     if (!terse && you.has_mutation(MUT_PAWS, false))
1436         str = "front " + str;
1437     else if (!terse && you.arm_count() > 2)
1438         str = "main " + str; // Op have four main tentacles
1439 
1440     return str;
1441 }
1442 
1443 // with a denominator of 10
form_hp_mod()1444 int form_hp_mod()
1445 {
1446     return get_form()->hp_mod;
1447 }
1448 
_flying_in_new_form(transformation which_trans)1449 static bool _flying_in_new_form(transformation which_trans)
1450 {
1451     if (get_form(which_trans)->forbids_flight())
1452         return false;
1453 
1454     // sources of permanent flight besides equipment
1455     if (you.permanent_flight(false))
1456         return true;
1457 
1458     // not airborne right now (XX does this handle emergency flight correctly?)
1459     if (!you.duration[DUR_FLIGHT] && !you.attribute[ATTR_PERM_FLIGHT])
1460         return false;
1461 
1462     // Finally, do the calculation about what would be melded: are there equip
1463     // sources left?
1464     int sources = you.equip_flight();
1465     int sources_removed = 0;
1466     for (auto eq : _init_equipment_removal(which_trans))
1467     {
1468         item_def *item = you.slot_item(eq, true);
1469         if (item == nullptr)
1470             continue;
1471         item_def inf = get_item_known_info(*item);
1472 
1473         //similar code to safe_to_remove from item-use.cc
1474         if (inf.is_type(OBJ_JEWELLERY, RING_FLIGHT))
1475             sources_removed++;
1476         if (inf.base_type == OBJ_ARMOUR && inf.brand == SPARM_FLYING)
1477             sources_removed++;
1478         if (is_artefact(inf) && artefact_known_property(inf, ARTP_FLY))
1479             sources_removed++;
1480     }
1481 
1482     return sources > sources_removed;
1483 }
1484 
1485 /**
1486  * Check if it'd be lethal for the player to enter a form in a given terrain.
1487  *
1488  * In addition to checking whether the feature is dangerous for the form
1489  * itself (form_likes_*), the function checks to see if the player is safe
1490  * due to flying or similar effects.
1491  *
1492  * @param which_trans       The form being checked.
1493  * @param feat              The dungeon feature to be checked for danger.
1494  * @return                  If the feat is lethal for the player in the form.
1495  */
feat_dangerous_for_form(transformation which_trans,dungeon_feature_type feat)1496 bool feat_dangerous_for_form(transformation which_trans,
1497                              dungeon_feature_type feat)
1498 {
1499     // Everything is okay if we can fly.
1500     if (form_can_fly(which_trans) || _flying_in_new_form(which_trans))
1501         return false;
1502 
1503     if (feat == DNGN_LAVA)
1504         return true;
1505 
1506     if (feat == DNGN_DEEP_WATER)
1507         return !you.can_water_walk() && !form_likes_water(which_trans);
1508 
1509     return false;
1510 }
1511 
1512 static mutation_type appendages[] =
1513 {
1514     MUT_HORNS,
1515     MUT_TENTACLE_SPIKE,
1516     MUT_TALONS,
1517 };
1518 
_beastly_level(mutation_type mut)1519 static int _beastly_level(mutation_type mut)
1520 {
1521     switch (mut)
1522     {
1523         case MUT_TENTACLE_SPIKE:
1524             return 3;
1525         default:
1526             return 2;
1527     }
1528 }
1529 
_transformation_is_safe(transformation which_trans,dungeon_feature_type feat,string * fail_reason)1530 static bool _transformation_is_safe(transformation which_trans,
1531                                     dungeon_feature_type feat,
1532                                     string *fail_reason)
1533 {
1534     if (!feat_dangerous_for_form(which_trans, feat) || you.duration[DUR_FLIGHT])
1535         return true;
1536 
1537     if (fail_reason)
1538     {
1539         *fail_reason = make_stringf("You would %s in your new form.",
1540                                     feat == DNGN_DEEP_WATER ? "drown" : "burn");
1541     }
1542 
1543     return false;
1544 }
1545 
1546 /**
1547  * If we transform into the given form, will all of our stats remain above 0,
1548  * based purely on the stat modifiers of the current & destination form?
1549  *
1550  * May prompt the player.
1551  *
1552  * @param new_form  The form to check the safety of.
1553  * @param quiet     Whether to prompt the player.
1554  * @return          Whether it's okay to go ahead with the transformation.
1555  */
check_form_stat_safety(transformation new_form,bool quiet)1556 bool check_form_stat_safety(transformation new_form, bool quiet)
1557 {
1558     const int str_mod = get_form(new_form)->str_mod - get_form()->str_mod;
1559     const int dex_mod = get_form(new_form)->dex_mod - get_form()->dex_mod;
1560 
1561     const bool bad_str = you.strength() > 0 && str_mod + you.strength() <= 0;
1562     const bool bad_dex = you.dex() > 0 && dex_mod + you.dex() <= 0;
1563     if (!bad_str && !bad_dex)
1564         return true;
1565     if (quiet)
1566         return false;
1567 
1568     string prompt = make_stringf("%s will reduce your %s to zero. Continue?",
1569                                  new_form == transformation::none
1570                                      ? "Turning back"
1571                                      : "Transforming",
1572                                  bad_str ? "strength" : "dexterity");
1573     if (yesno(prompt.c_str(), false, 'n'))
1574         return true;
1575 
1576     canned_msg(MSG_OK);
1577     return false;
1578 }
1579 
_transform_duration(transformation which_trans,int pow)1580 static int _transform_duration(transformation which_trans, int pow)
1581 {
1582     return get_form(which_trans)->get_duration(pow);
1583 }
1584 
1585 /**
1586  * Is the player alive enough to become the given form?
1587  *
1588  * All undead can enter shadow form; vampires also can enter batform, and, when
1589  * full, other forms (excepting lichform).
1590  *
1591  * @param which_trans   The tranformation which the player is undergoing
1592  *                      (default you.form).
1593  * @param involuntary   Whether the transformation is involuntary or not.
1594  * @return              UFR_GOOD if the player is not blocked from entering the
1595  *                      given form by their undead race; UFR_TOO_ALIVE if the
1596  *                      player is too satiated as a vampire; UFR_TOO_DEAD if
1597  *                      the player is too dead (or too thirsty as a vampire).
1598  */
lifeless_prevents_form(transformation which_trans,bool involuntary)1599 undead_form_reason lifeless_prevents_form(transformation which_trans,
1600                                           bool involuntary)
1601 {
1602     if (!you.undead_state(false))
1603         return UFR_GOOD; // not undead!
1604 
1605     if (which_trans == transformation::none)
1606         return UFR_GOOD; // everything can become itself
1607 
1608     if (which_trans == transformation::shadow)
1609         return UFR_GOOD; // even the undead can use dith's shadow form
1610 
1611     if (!you.has_mutation(MUT_VAMPIRISM))
1612         return UFR_TOO_DEAD; // ghouls & mummies can't become anything else
1613 
1614     if (which_trans == transformation::lich)
1615         return UFR_TOO_DEAD; // vampires can never lichform
1616 
1617     if (which_trans == transformation::bat) // can batform bloodless
1618     {
1619         if (involuntary)
1620             return UFR_TOO_DEAD; // but not as a forced polymorph effect
1621 
1622         return !you.vampire_alive ? UFR_GOOD : UFR_TOO_ALIVE;
1623     }
1624 
1625     // other forms can only be entered when alive
1626     return you.vampire_alive ? UFR_GOOD : UFR_TOO_DEAD;
1627 }
1628 
1629 /**
1630  * Attempts to transform the player into the specified form.
1631  *
1632  * If the player is already in that form, attempt to refresh its duration and
1633  * power.
1634  *
1635  * @param pow               Thw power of the transformation (equivalent to
1636  *                          spellpower of form spells)
1637  * @param which_trans       The form which the player should become.
1638  * @param involuntary       Checks for inscription warnings are skipped, and
1639  *                          failure is silent.
1640  * @param just_check        A dry run; just check to see whether the player
1641  *                          *can* enter the given form, but don't actually
1642  *                          transform them.
1643  * @return                  If the player was transformed, or if they were
1644  *                          already in the given form, returns true.
1645  *                          Otherwise, false.
1646  *                          If just_check is set, returns true if the player
1647  *                          could enter the form (or is in it already) and
1648  *                          false otherwise.
1649  *                          N.b. that transform() can fail even when a
1650  *                          just_check run returns true; e.g. when Zin decides
1651  *                          to intervene. (That may be the only case.)
1652  */
transform(int pow,transformation which_trans,bool involuntary,bool just_check,string * fail_reason)1653 bool transform(int pow, transformation which_trans, bool involuntary,
1654                bool just_check, string *fail_reason)
1655 {
1656     const transformation previous_trans = you.form;
1657     const bool was_flying = you.airborne();
1658     bool success = true;
1659     string msg;
1660 
1661     // Zin's protection.
1662     if (!just_check && have_passive(passive_t::resist_polymorph)
1663         && x_chance_in_y(you.piety, MAX_PIETY)
1664         && which_trans != transformation::none)
1665     {
1666         simple_god_message(" protects your body from unnatural transformation!");
1667         return false;
1668     }
1669 
1670     if (!involuntary && crawl_state.is_god_acting())
1671         involuntary = true;
1672 
1673     if (you.transform_uncancellable)
1674     {
1675         msg = "You are stuck in your current form!";
1676         success = false;
1677     }
1678     else if (!_transformation_is_safe(which_trans, env.grid(you.pos()), &msg))
1679         success = false;
1680 
1681     if (!success)
1682     {
1683         // Message is not printed if we're updating fail_reason.
1684         if (fail_reason)
1685             *fail_reason = msg;
1686         else if (!involuntary)
1687             mpr(msg);
1688         return false;
1689     }
1690 
1691     // This must occur before the untransform() and the undead_state() check.
1692     if (previous_trans == which_trans)
1693     {
1694         if (just_check)
1695             return true;
1696 
1697         // update power
1698         if (which_trans != transformation::none)
1699         {
1700             you.props[TRANSFORM_POW_KEY] = pow;
1701             you.redraw_armour_class = true;
1702             // ^ could check more carefully for the exact cases, but I'm
1703             // worried about making the code too fragile
1704         }
1705 
1706         int dur = _transform_duration(which_trans, pow);
1707         if (you.duration[DUR_TRANSFORMATION] < dur * BASELINE_DELAY)
1708         {
1709             mpr("You extend your transformation's duration.");
1710             you.duration[DUR_TRANSFORMATION] = dur * BASELINE_DELAY;
1711 
1712         }
1713         else if (!involuntary && which_trans != transformation::none)
1714             mpr("You fail to extend your transformation any further.");
1715 
1716         return true;
1717     }
1718 
1719     // the undead cannot enter most forms.
1720     if (lifeless_prevents_form(which_trans, involuntary) == UFR_TOO_DEAD)
1721     {
1722         msg = "Your unliving flesh cannot be transformed in this way.";
1723         success = false;
1724     }
1725     else if (which_trans == transformation::lich
1726              && you.duration[DUR_DEATHS_DOOR])
1727     {
1728         msg = "You cannot become a lich while in death's door.";
1729         success = false;
1730     }
1731 
1732     if (!just_check && previous_trans != transformation::none)
1733         untransform(true);
1734 
1735     set<equipment_type> rem_stuff = _init_equipment_removal(which_trans);
1736 
1737     // if going into lichform causes us to drop a holy weapon with consequences
1738     // for unwielding (e.g. contam), warn first.
1739     item_def nil_item;
1740     nil_item.link = -1;
1741     if (just_check && !involuntary
1742         && which_trans == transformation::lich && rem_stuff.count(EQ_WEAPON)
1743         && !check_old_item_warning(nil_item, OPER_WIELD, true))
1744     {
1745         canned_msg(MSG_OK);
1746         return false;
1747     }
1748 
1749     if (which_trans == transformation::appendage)
1750     {
1751         // Need to set the appendages here for messaging
1752         for (mutation_type app : appendages)
1753         {
1754             if (physiology_mutation_conflict(app)
1755                 || you.get_base_mutation_level(app) > 0)
1756             {
1757                 continue;
1758             }
1759             you.props[APPENDAGE_KEY].get_vector().push_back(app);
1760             dprf("Setting appendage mutation %s.", mutation_name(app));
1761         }
1762 
1763         if (you.props[APPENDAGE_KEY].get_vector().empty())
1764         {
1765             msg = "You have no appropriate body parts free.";
1766             success = false; // XXX: VERY dubious, since an untransform occurred
1767         }
1768 
1769         if (just_check || !success)
1770         {
1771             you.props.erase(APPENDAGE_KEY);
1772             dprf("Erasing, just check");
1773         }
1774         dprf("Set appendages");
1775     }
1776 
1777     if (!success)
1778     {
1779         // Message is not printed if we're updating fail_reason.
1780         if (fail_reason)
1781             *fail_reason = msg;
1782         else if (!involuntary)
1783             mpr(msg);
1784         return false;
1785     }
1786 
1787     // If we're just pretending return now.
1788     if (just_check)
1789         return true;
1790 
1791     // All checks done, transformation will take place now.
1792     you.redraw_evasion      = true;
1793     you.redraw_armour_class = true;
1794     you.wield_change        = true;
1795     quiver::set_needs_redraw();
1796 
1797     if (form_changed_physiology(which_trans))
1798         merfolk_stop_swimming();
1799 
1800     if (which_trans == transformation::storm)
1801         set_airform_power(pow);
1802 
1803     // Give the transformation message.
1804     mpr(get_form(which_trans)->transform_message(previous_trans));
1805 
1806     // Update your status.
1807     // Order matters here, take stuff off (and handle attendant HP and stat
1808     // changes) before adjusting the player to be transformed.
1809     _remove_equipment(rem_stuff, which_trans);
1810 
1811     you.form = which_trans;
1812     you.set_duration(DUR_TRANSFORMATION, _transform_duration(which_trans, pow));
1813     update_player_symbol();
1814 
1815     you.props[TRANSFORM_POW_KEY] = pow;
1816 
1817     const int str_mod = get_form(which_trans)->str_mod;
1818     const int dex_mod = get_form(which_trans)->dex_mod;
1819 
1820     if (str_mod)
1821         notify_stat_change(STAT_STR, str_mod, true);
1822 
1823     if (dex_mod)
1824         notify_stat_change(STAT_DEX, dex_mod, true);
1825 
1826     calc_hp(true, false);
1827 
1828     if (you.digging && !form_keeps_mutations(which_trans))
1829     {
1830         mpr("Your mandibles meld away.");
1831         you.digging = false;
1832     }
1833 
1834     // Extra effects
1835     switch (which_trans)
1836     {
1837     case transformation::statue:
1838         if (you.duration[DUR_ICY_ARMOUR])
1839         {
1840             mprf(MSGCH_DURATION, "Your new body cracks your icy armour.");
1841             you.duration[DUR_ICY_ARMOUR] = 0;
1842         }
1843         break;
1844 
1845     case transformation::spider:
1846         leave_web();
1847         break;
1848 
1849     case transformation::tree:
1850         mpr("Your roots penetrate the ground.");
1851         if (you.duration[DUR_TELEPORT])
1852         {
1853             you.duration[DUR_TELEPORT] = 0;
1854             mpr("You feel strangely stable.");
1855         }
1856         you.duration[DUR_FLIGHT] = 0;
1857         // break out of webs/nets as well
1858 
1859     case transformation::dragon:
1860         if (you.attribute[ATTR_HELD])
1861         {
1862             trap_def *trap = trap_at(you.pos());
1863             if (trap && trap->type == TRAP_WEB)
1864             {
1865                 mpr("You shred the web into pieces!");
1866                 destroy_trap(you.pos());
1867             }
1868             int net = get_trapping_net(you.pos());
1869             if (net != NON_ITEM)
1870             {
1871                 mpr("The net rips apart!");
1872                 destroy_item(net);
1873             }
1874 
1875             stop_being_held();
1876         }
1877         break;
1878 
1879     case transformation::lich:
1880         if (you.duration[DUR_WEREBLOOD])
1881         {
1882             you.duration[DUR_WEREBLOOD] = 0;
1883             mpr("Your lifeless body cannot sustain the wereblood!");
1884         }
1885         you.redraw_status_lights = true;
1886         break;
1887 
1888     case transformation::appendage:
1889         {
1890             auto& apps = you.props[APPENDAGE_KEY].get_vector();
1891             for (auto app : apps)
1892             {
1893                 const mutation_type mut = static_cast<mutation_type>(app.get_int());
1894                 you.mutation[mut] = _beastly_level(mut);
1895             }
1896         }
1897         break;
1898 
1899     case transformation::shadow:
1900         drain_player(25, true, true);
1901         if (you.invisible())
1902             mpr("You fade into the shadows.");
1903         else
1904             mpr("You feel less conspicuous.");
1905         break;
1906 
1907     default:
1908         break;
1909     }
1910 
1911     // Stop constricting if we can no longer constrict. If any size-changing
1912     // transformations were to allow constriction, we would have to check
1913     // relative sizes as well. Likewise, if any transformations were to allow
1914     // normally non-constricting players to constrict, this would need to
1915     // be changed.
1916     if (!form_keeps_mutations(which_trans))
1917         you.stop_directly_constricting_all(false);
1918 
1919     // Stop being constricted if we are now too large.
1920     if (you.is_directly_constricted())
1921     {
1922         actor* const constrictor = actor_by_mid(you.constricted_by);
1923         ASSERT(constrictor);
1924 
1925         if (you.body_size(PSIZE_BODY) > constrictor->body_size(PSIZE_BODY))
1926             you.stop_being_constricted();
1927     }
1928 
1929 
1930     // If we are no longer living, end an effect that afflicts only the living
1931     if (you.duration[DUR_FLAYED] && !(you.holiness() & MH_NATURAL))
1932     {
1933         // Heal a little extra if we gained max hp from this transformation
1934         if (form_hp_mod() != 10)
1935         {
1936             int dam = you.props["flay_damage"].get_int();
1937             you.heal((dam * form_hp_mod() / 10) - dam);
1938         }
1939         heal_flayed_effect(&you);
1940     }
1941 
1942     // This only has an effect if the transformation happens passively,
1943     // for example if Xom decides to transform you while you're busy
1944     // running around or butchering corpses.
1945     // If you're turned into a tree, you stop taking stairs.
1946     stop_delay(which_trans == transformation::tree);
1947 
1948     if (crawl_state.which_god_acting() == GOD_XOM)
1949        you.transform_uncancellable = true;
1950 
1951     // Land the player if we stopped flying.
1952     if (was_flying && !you.airborne())
1953         move_player_to_grid(you.pos(), false);
1954 
1955     // Stop emergency flight if it's activated and this form can fly
1956     if (you.props[EMERGENCY_FLIGHT_KEY]
1957         && form_can_fly()
1958         && you.airborne())
1959     {
1960         you.props.erase(EMERGENCY_FLIGHT_KEY);
1961     }
1962 
1963     // Update merfolk swimming for the form change.
1964     if (you.has_innate_mutation(MUT_MERTAIL))
1965         merfolk_check_swimming(false);
1966 
1967     // Update skill boosts for the current state of equipment melds
1968     // Must happen before the HP check!
1969     ash_check_bondage();
1970 
1971     if (you.hp <= 0)
1972     {
1973         ouch(0, KILLED_BY_FRAILTY, MID_NOBODY,
1974              make_stringf("gaining the %s transformation",
1975                           transform_name(which_trans)).c_str());
1976     }
1977 
1978     return true;
1979 }
1980 
1981 /**
1982  * End the player's transformation and return them to their normal
1983  * form.
1984  * @param skip_move      If true, skip any move that was in progress before
1985  *                       the transformation ended.
1986  */
untransform(bool skip_move)1987 void untransform(bool skip_move)
1988 {
1989     const bool was_flying = you.airborne();
1990 
1991     // Must be unset first or else infinite loops might result. -- bwr
1992     const transformation old_form = you.form;
1993 
1994     quiver::set_needs_redraw();
1995     you.redraw_evasion          = true;
1996     you.redraw_armour_class     = true;
1997     you.wield_change            = true;
1998     if (!form_can_wield(old_form))
1999         you.received_weapon_warning = false;
2000     if (you.props.exists(TRANSFORM_POW_KEY))
2001         you.props.erase(TRANSFORM_POW_KEY);
2002     if (you.props.exists(HYDRA_FORM_HEADS_KEY))
2003         you.props.erase(HYDRA_FORM_HEADS_KEY);
2004     if (you.props.exists(AIRFORM_POWER_KEY))
2005         you.props.erase(AIRFORM_POWER_KEY);
2006 
2007     // We may have to unmeld a couple of equipment types.
2008     set<equipment_type> melded = _init_equipment_removal(old_form);
2009 
2010     you.form = transformation::none;
2011     you.duration[DUR_TRANSFORMATION] = 0;
2012     update_player_symbol();
2013 
2014     if (old_form == transformation::appendage)
2015     {
2016         const auto& apps = you.props[APPENDAGE_KEY].get_vector();
2017         for (auto mut : apps)
2018         {
2019             const mutation_type app = static_cast<mutation_type>(mut.get_int());
2020             const int levels = you.get_base_mutation_level(app);
2021             // Preserve extra mutation levels acquired after transforming.
2022             const int extra = max(0, levels - you.get_innate_mutation_level(app)
2023                                             - _beastly_level(app));
2024             you.mutation[app] = you.get_innate_mutation_level(app) + extra;
2025 
2026             // The mutation might have been removed already by a conflicting
2027             // demonspawn innate mutation; no message then.
2028             if (levels)
2029             {
2030                 const char * const verb = you.has_mutation(app) ? "shrink"
2031                                                                 : "disappear";
2032                 mprf(MSGCH_DURATION, "Your %s %s%s.",
2033                      mutation_name(app), verb,
2034                      app == MUT_TENTACLE_SPIKE ? "s" : "");
2035             }
2036         }
2037         you.props.erase(APPENDAGE_KEY);
2038     }
2039 
2040     calc_hp(true, false);
2041 
2042     const string message = get_form(old_form)->get_untransform_message();
2043     if (!message.empty())
2044         mprf(MSGCH_DURATION, "%s", message.c_str());
2045 
2046     const int str_mod = get_form(old_form)->str_mod;
2047     const int dex_mod = get_form(old_form)->dex_mod;
2048 
2049     if (str_mod)
2050         notify_stat_change(STAT_STR, -str_mod, true);
2051 
2052     if (dex_mod)
2053         notify_stat_change(STAT_DEX, -dex_mod, true);
2054 
2055     // If you're a mer in water, boots stay melded even after the form ends.
2056     if (you.fishtail)
2057     {
2058         melded.erase(EQ_BOOTS);
2059         const item_def* arm = you.slot_item(EQ_BODY_ARMOUR, true);
2060         if (arm && is_unrandom_artefact(*arm, UNRAND_LEAR))
2061         {
2062             // I hate you, King Lear.
2063             melded.erase(EQ_HELMET);
2064             melded.erase(EQ_GLOVES);
2065             melded.erase(EQ_BODY_ARMOUR);
2066         }
2067     }
2068     _unmeld_equipment(melded);
2069 
2070     // Update skill boosts for the current state of equipment melds
2071     // Must happen before the HP check!
2072     ash_check_bondage();
2073 
2074     if (!skip_move)
2075     {
2076         // Land the player if we stopped flying.
2077         if (is_feat_dangerous(env.grid(you.pos())))
2078             enable_emergency_flight();
2079         else if (was_flying && !you.airborne())
2080             move_player_to_grid(you.pos(), false);
2081 
2082         // Update merfolk swimming for the form change.
2083         if (you.has_innate_mutation(MUT_MERTAIL))
2084             merfolk_check_swimming(false);
2085     }
2086 
2087 #ifdef USE_TILE
2088     if (you.has_innate_mutation(MUT_MERTAIL))
2089         init_player_doll();
2090 #endif
2091 
2092     // If nagas wear boots while transformed, they fall off again afterwards:
2093     // I don't believe this is currently possible, and if it is we
2094     // probably need something better to cover all possibilities.  -bwr
2095 
2096     // Removed barding check, no transformed creatures can wear barding
2097     // anyway.
2098     // *coughs* Ahem, blade hands... -- jpeg
2099     if (you.wear_barding())
2100     {
2101         const int arm = you.equip[EQ_BOOTS];
2102 
2103         if (arm != -1 && you.inv[arm].sub_type == ARM_BOOTS)
2104             remove_one_equip(EQ_BOOTS);
2105     }
2106 
2107     if (you.hp <= 0)
2108     {
2109         ouch(0, KILLED_BY_FRAILTY, MID_NOBODY,
2110              make_stringf("losing the %s form",
2111                           transform_name(old_form)).c_str());
2112     }
2113 
2114     // Stop being constricted if we are now too large.
2115     if (you.is_directly_constricted())
2116     {
2117         actor* const constrictor = actor_by_mid(you.constricted_by);
2118         if (you.body_size(PSIZE_BODY) > constrictor->body_size(PSIZE_BODY))
2119             you.stop_being_constricted();
2120     }
2121 
2122     you.turn_is_over = true;
2123     if (you.transform_uncancellable)
2124         you.transform_uncancellable = false;
2125 }
2126 
emergency_untransform()2127 void emergency_untransform()
2128 {
2129     mpr("You quickly transform back into your natural form.");
2130     untransform(true); // We're already entering the water.
2131 
2132     if (you.has_innate_mutation(MUT_MERTAIL))
2133         merfolk_start_swimming(false);
2134 }
2135 
2136 /**
2137  * Update whether a merfolk should be swimming.
2138  *
2139  * Idempotent, so can be called after position/transformation change without
2140  * redundantly checking conditions.
2141  *
2142  * @param stepped Whether the player is performing a normal walking move.
2143  */
merfolk_check_swimming(bool stepped)2144 void merfolk_check_swimming(bool stepped)
2145 {
2146     const dungeon_feature_type grid = env.grid(you.pos());
2147     if (you.ground_level()
2148         && feat_is_water(grid)
2149         && you.has_mutation(MUT_MERTAIL))
2150     {
2151         merfolk_start_swimming(stepped);
2152     }
2153     else
2154         merfolk_stop_swimming();
2155 }
2156 
merfolk_start_swimming(bool stepped)2157 void merfolk_start_swimming(bool stepped)
2158 {
2159     if (you.fishtail)
2160         return;
2161 
2162     if (stepped)
2163         mpr("Your legs become a tail as you enter the water.");
2164     else
2165         mpr("Your legs become a tail as you dive into the water.");
2166 
2167     if (you.invisible())
2168         mpr("...but don't expect to remain undetected.");
2169 
2170     you.fishtail = true;
2171     remove_one_equip(EQ_BOOTS);
2172     you.redraw_evasion = true;
2173 
2174     ash_check_bondage();
2175 
2176 #ifdef USE_TILE
2177     init_player_doll();
2178 #endif
2179 }
2180 
merfolk_stop_swimming()2181 void merfolk_stop_swimming()
2182 {
2183     if (!you.fishtail)
2184         return;
2185     you.fishtail = false;
2186     unmeld_one_equip(EQ_BOOTS);
2187     you.redraw_evasion = true;
2188 
2189     ash_check_bondage();
2190 
2191 #ifdef USE_TILE
2192     init_player_doll();
2193 #endif
2194 }
2195 
vampire_update_transformations()2196 void vampire_update_transformations()
2197 {
2198     const undead_form_reason form_reason = lifeless_prevents_form();
2199     if (form_reason != UFR_GOOD && you.duration[DUR_TRANSFORMATION])
2200     {
2201         print_stats();
2202         update_screen();
2203         mprf(MSGCH_WARN,
2204              "Your blood-%s body can't sustain your transformation.",
2205              form_reason == UFR_TOO_DEAD ? "deprived" : "filled");
2206         untransform();
2207     }
2208 }
2209 
2210 // TODO: dataify? move to member functions?
form_base_movespeed(transformation tran)2211 int form_base_movespeed(transformation tran)
2212 {
2213     // statue form is handled as a multiplier in player_speed, not a movespeed.
2214     if (tran == transformation::bat)
2215         return 5; // but allowed minimum is six
2216     else if (tran == transformation::pig)
2217         return 7;
2218     else
2219         return 10;
2220 }
2221