1 #include "AppHdr.h"
2 #include <map>
3 
4 #include "mpr.h"
5 #include "species.h"
6 
7 #include "item-prop.h"
8 #include "mutation.h"
9 #include "output.h"
10 #include "playable.h"
11 #include "player.h"
12 #include "player-stats.h"
13 #include "random.h"
14 #include "skills.h"
15 #include "stringutil.h"
16 #include "tag-version.h"
17 #include "tiledoll.h"
18 
19 #include "species-data.h"
20 
21 /*
22  * Get the species_def for the given species type. Asserts if the species_type
23  * is not less than NUM_SPECIES.
24  *
25  * @param species The species type.
26  * @returns The species_def of that species.
27  */
get_species_def(species_type species)28 const species_def& get_species_def(species_type species)
29 {
30     if (species != SP_UNKNOWN)
31         ASSERT_RANGE(species, 0, NUM_SPECIES);
32     return species_data.at(species);
33 }
34 
35 namespace species
36 {
37     /**
38      * Return the name of the given species.
39      * @param speci       the species to be named.
40      * @param spname_type the kind of name to get: adjectival, the genus, or plain.
41      * @returns the requested name, which will just be plain if no adjective
42      *          or genus is defined.
43      */
name(species_type speci,name_type spname_type)44     string name(species_type speci, name_type spname_type)
45     {
46         const species_def& def = get_species_def(speci);
47         if (spname_type == SPNAME_GENUS && def.genus_name)
48             return def.genus_name;
49         else if (spname_type == SPNAME_ADJ && def.adj_name)
50             return def.adj_name;
51         return def.name;
52     }
53 
54     /// Does exact case-sensitive lookup of a species name
from_str(const string & species)55     species_type from_str(const string &species)
56     {
57         species_type sp;
58         if (species.empty())
59             return SP_UNKNOWN;
60 
61         for (int i = 0; i < NUM_SPECIES; ++i)
62         {
63             sp = static_cast<species_type>(i);
64             if (species == name(sp))
65                 return sp;
66         }
67 
68         return SP_UNKNOWN;
69     }
70 
71     /// Does loose, non-case-sensitive lookup of a species based on a string
from_str_loose(const string & species,bool initial_only)72     species_type from_str_loose(const string &species, bool initial_only)
73     {
74         // XX consolidate with from_str?
75         string spec = lowercase_string(species);
76 
77         species_type sp = SP_UNKNOWN;
78 
79         for (int i = 0; i < NUM_SPECIES; ++i)
80         {
81             const species_type si = static_cast<species_type>(i);
82             const string sp_name = lowercase_string(name(si));
83 
84             string::size_type pos = sp_name.find(spec);
85             if (pos != string::npos)
86             {
87                 if (pos == 0)
88                 {
89                     // We prefer prefixes over partial matches.
90                     sp = si;
91                     break;
92                 }
93                 else if (!initial_only)
94                     sp = si;
95             }
96         }
97 
98         return sp;
99     }
100 
101 
from_abbrev(const char * abbrev)102     species_type from_abbrev(const char *abbrev)
103     {
104         if (lowercase_string(abbrev) == "dr")
105             return SP_BASE_DRACONIAN;
106 
107         for (auto& entry : species_data)
108             if (lowercase_string(abbrev) == lowercase_string(entry.second.abbrev))
109                 return entry.first;
110 
111         return SP_UNKNOWN;
112     }
113 
get_abbrev(species_type which_species)114     const char *get_abbrev(species_type which_species)
115     {
116         return get_species_def(which_species).abbrev;
117     }
118 
is_elven(species_type species)119     bool is_elven(species_type species)
120     {
121         return species == SP_DEEP_ELF;
122     }
123 
is_orcish(species_type species)124     bool is_orcish(species_type species)
125     {
126         return species == SP_HILL_ORC;
127     }
128 
is_undead(species_type species)129     bool is_undead(species_type species)
130     {
131         return undead_type(species) != US_ALIVE;
132     }
133 
is_draconian(species_type species)134     bool is_draconian(species_type species)
135     {
136         return bool(get_species_def(species).flags & SPF_DRACONIAN);
137     }
138 
139     // A random non-base draconian colour appropriate for the player.
random_draconian_colour()140     species_type random_draconian_colour()
141     {
142         species_type species;
143         do {
144             species =
145                 static_cast<species_type>(random_range(0, NUM_SPECIES - 1));
146         } while (!is_draconian(species)
147                || is_removed(species)
148                || species == SP_BASE_DRACONIAN);
149 
150         return species;
151     }
152 
153     /**
154      * Where does a given species fall on the Undead Spectrum?
155      *
156      * @param species   The species in question.
157      * @return          What class of undead the given species falls on, if any.
158      */
undead_type(species_type species)159     undead_state_type undead_type(species_type species)
160     {
161         return get_species_def(species).undeadness;
162     }
163 
to_mons_species(species_type species)164     monster_type to_mons_species(species_type species)
165     {
166         return get_species_def(species).monster_species;
167     }
168 
169     // XX non-draconians, unify with skin names?
scale_type(species_type species)170     const char* scale_type(species_type species)
171     {
172         switch (species)
173         {
174             case SP_RED_DRACONIAN:
175                 return "fiery red";
176             case SP_WHITE_DRACONIAN:
177                 return "icy white";
178             case SP_GREEN_DRACONIAN:
179                 return "lurid green";
180             case SP_YELLOW_DRACONIAN:
181                 return "golden yellow";
182             case SP_GREY_DRACONIAN:
183                 return "dull iron-grey";
184             case SP_BLACK_DRACONIAN:
185                 return "glossy black";
186             case SP_PURPLE_DRACONIAN:
187                 return "rich purple";
188             case SP_PALE_DRACONIAN:
189                 return "pale cyan-grey";
190             case SP_BASE_DRACONIAN:
191                 return "plain brown";
192             default:
193                 return "";
194         }
195     }
196 
dragon_form(species_type s)197     monster_type dragon_form(species_type s)
198     {
199         switch (s)
200         {
201         case SP_WHITE_DRACONIAN:
202             return MONS_ICE_DRAGON;
203         case SP_GREEN_DRACONIAN:
204             return MONS_SWAMP_DRAGON;
205         case SP_YELLOW_DRACONIAN:
206             return MONS_GOLDEN_DRAGON;
207         case SP_GREY_DRACONIAN:
208             return MONS_IRON_DRAGON;
209         case SP_BLACK_DRACONIAN:
210             return MONS_STORM_DRAGON;
211         case SP_PURPLE_DRACONIAN:
212             return MONS_QUICKSILVER_DRAGON;
213         case SP_PALE_DRACONIAN:
214             return MONS_STEAM_DRAGON;
215         case SP_RED_DRACONIAN:
216         default:
217             return MONS_FIRE_DRAGON;
218         }
219     }
220 
draconian_breath(species_type species)221     ability_type draconian_breath(species_type species)
222     {
223         switch (species)
224         {
225         case SP_GREEN_DRACONIAN:   return ABIL_BREATHE_MEPHITIC;
226         case SP_RED_DRACONIAN:     return ABIL_BREATHE_FIRE;
227         case SP_WHITE_DRACONIAN:   return ABIL_BREATHE_FROST;
228         case SP_YELLOW_DRACONIAN:  return ABIL_BREATHE_ACID;
229         case SP_BLACK_DRACONIAN:   return ABIL_BREATHE_LIGHTNING;
230         case SP_PURPLE_DRACONIAN:  return ABIL_BREATHE_POWER;
231         case SP_PALE_DRACONIAN:    return ABIL_BREATHE_STEAM;
232         case SP_BASE_DRACONIAN: case SP_GREY_DRACONIAN:
233         default: return ABIL_NON_ABILITY;
234         }
235     }
236 
237     /// Does the species have (real) mutation `mut`? Not for demonspawn.
238     /// @return the first xl at which the species gains the mutation, or 0 if it
239     ///         does not ever gain it.
mutation_level(species_type species,mutation_type mut,int mut_level)240     int mutation_level(species_type species, mutation_type mut, int mut_level)
241     {
242         int total = 0;
243         // relies on levels being in order -- I think this is safe?
244         for (const auto& lum : get_species_def(species).level_up_mutations)
245             if (mut == lum.mut)
246             {
247                 total += lum.mut_level;
248                 if (total >= mut_level)
249                     return lum.xp_level;
250             }
251 
252         return 0;
253     }
254 
fake_mutations(species_type species,bool terse)255     const vector<string>& fake_mutations(species_type species, bool terse)
256     {
257         return terse ? get_species_def(species).terse_fake_mutations
258                      : get_species_def(species).verbose_fake_mutations;
259     }
260 
has_hair(species_type species)261     bool has_hair(species_type species)
262     {
263         return !bool(get_species_def(species).flags & (SPF_NO_HAIR | SPF_DRACONIAN));
264     }
265 
has_bones(species_type species)266     bool has_bones(species_type species)
267     {
268         return !bool(get_species_def(species).flags & SPF_NO_BONES);
269     }
270 
can_throw_large_rocks(species_type species)271     bool can_throw_large_rocks(species_type species)
272     {
273         return size(species) >= SIZE_LARGE;
274     }
275 
wears_barding(species_type species)276     bool wears_barding(species_type species)
277     {
278         return bool(get_species_def(species).flags & SPF_SMALL_TORSO);
279     }
280 
has_claws(species_type species)281     bool has_claws(species_type species)
282     {
283         return mutation_level(species, MUT_CLAWS) == 1;
284     }
285 
is_nonliving(species_type species)286     bool is_nonliving(species_type species)
287     {
288         // XXX: move to data?
289         return species == SP_GARGOYLE || species == SP_DJINNI;
290     }
291 
can_swim(species_type species)292     bool can_swim(species_type species)
293     {
294         return get_species_def(species).habitat == HT_WATER;
295     }
296 
likes_water(species_type species)297     bool likes_water(species_type species)
298     {
299         return can_swim(species)
300                || get_species_def(species).habitat == HT_AMPHIBIOUS;
301     }
302 
size(species_type species,size_part_type psize)303     size_type size(species_type species, size_part_type psize)
304     {
305         const size_type size = get_species_def(species).size;
306         if (psize == PSIZE_TORSO
307             && bool(get_species_def(species).flags & SPF_SMALL_TORSO))
308         {
309             return static_cast<size_type>(static_cast<int>(size) - 1);
310         }
311         return size;
312     }
313 
314 
315     /** What walking-like thing does this species do?
316      *
317      *  @param sp what kind of species to look at
318      *  @returns a "word" to which "-er" or "-ing" can be appended.
319      */
walking_verb(species_type sp)320     string walking_verb(species_type sp)
321     {
322         auto verb = get_species_def(sp).walking_verb;
323         return verb ? verb : "Walk";
324     }
325 
326     /**
327      * What message should be printed when a character of the specified species
328      * prays at an altar, if not in some form?
329      * To be inserted into "You %s the altar of foo."
330      *
331      * @param species   The species in question.
332      * @return          An action to be printed when the player prays at an altar.
333      *                  E.g., "coil in front of", "kneel at", etc.
334      */
prayer_action(species_type species)335     string prayer_action(species_type species)
336     {
337       auto action = get_species_def(species).altar_action;
338       return action ? action : "kneel at";
339     }
340 
341     static const string shout_verbs[] = {"shout", "yell", "scream"};
342     static const string felid_shout_verbs[] = {"meow", "yowl", "caterwaul"};
343     static const string frog_shout_verbs[] = {"croak", "ribbit", "bellow"};
344     static const string dog_shout_verbs[] = {"bark", "howl", "screech"};
345 
346     /**
347      * What verb should be used to describe the species' shouting?
348      * @param sp a species
349      * @param screaminess a loudness level; in range [0,2]
350      * @param directed with this is to be directed at another actor
351      * @return A shouty kind of verb
352      */
shout_verb(species_type sp,int screaminess,bool directed)353     string shout_verb(species_type sp, int screaminess, bool directed)
354     {
355         screaminess = max(min(screaminess,
356                                 static_cast<int>(sizeof(shout_verbs) - 1)), 0);
357         switch (sp)
358         {
359         case SP_GNOLL:
360             if (screaminess == 0 && directed && coinflip())
361                 return "growl";
362             return dog_shout_verbs[screaminess];
363         case SP_BARACHI:
364             return frog_shout_verbs[screaminess];
365         case SP_FELID:
366             if (screaminess == 0 && directed)
367                 return "hiss"; // hiss at, not meow at
368             return felid_shout_verbs[screaminess];
369         default:
370             return shout_verbs[screaminess];
371         }
372     }
373 
374     /**
375      * Return an adjective or noun for the species' skin.
376      * @param adj whether to provide an adjective (if true), or a noun (if false).
377      * @return a non-empty string. Nouns will be pluralised if they are count nouns.
378      *         Right now, plurality can be determined by `ends_with(noun, "s")`.
379      */
skin_name(species_type species,bool adj)380     string skin_name(species_type species, bool adj)
381     {
382         // Aside from direct uses, some flavor stuff checks the strings
383         // here. TODO: should some of these be species flags a la hair?
384         // Also, some skin mutations should have a way of overriding these perhaps
385         if (is_draconian(species) || species == SP_NAGA)
386             return adj ? "scaled" : "scales";
387         else if (species == SP_TENGU)
388             return adj ? "feathered" : "feathers";
389         else if (species == SP_FELID)
390             return adj ? "furry" : "fur";
391         else if (species == SP_MUMMY)
392             return adj ? "bandage-wrapped" : "bandages";
393         else
394             return adj ? "fleshy" : "skin";
395     }
396 
arm_name(species_type species)397     string arm_name(species_type species)
398     {
399         if (mutation_level(species, MUT_TENTACLE_ARMS))
400             return "tentacle";
401         else if (species == SP_FELID)
402             return "leg";
403         else
404             return "arm";
405     }
406 
hand_name(species_type species)407     string hand_name(species_type species)
408     {
409         // see also player::hand_name
410         if (mutation_level(species, MUT_PAWS))
411             return "paw";
412         else if (mutation_level(species, MUT_TENTACLE_ARMS))
413             return "tentacle";
414         else if (mutation_level(species, MUT_CLAWS))
415             return "claw"; // overridden for felids by first check
416         else
417             return "hand";
418     }
419 
arm_count(species_type species)420     int arm_count(species_type species)
421     {
422         return species == SP_OCTOPODE ? 8 : 2;
423     }
424 
sacrificial_arm(species_type species)425     equipment_type sacrificial_arm(species_type species)
426     {
427         // this is a bit special-case-y because the sac slot doesn't follow
428         // from the enum; for 2-armed species it is the left ring (which is first),
429         // but for 8-armed species it is ring 8 (which is last).
430         // XX maybe swap the targeted sac hand? But this requires some painful
431         // save compat
432         return arm_count(species) == 2 ? EQ_LEFT_RING : EQ_RING_EIGHT;
433     }
434 
435     /**
436      *  Checks some species-level equipment slot constraints. Anything hard-coded
437      *  per species, but not handled by a mutation should be here. See also
438      *  player.cc::you_can_wear and item-use.cc::can_wear_armour for the full
439      *  division of labor. This function is guaranteed to handle species ring
440      *  slots.
441      *
442      *  @param species the species type to check
443      *  @param eq the equipment slot to check
444      *  @return true if the equipment slot is not used by the species; false
445      *          indicates only that nothing in this check bans the slot. For
446      *          example, this function does not check felid mutations.
447      */
bans_eq(species_type species,equipment_type eq)448     bool bans_eq(species_type species, equipment_type eq)
449     {
450         const int arms = arm_count(species);
451         // only handles 2 or 8
452         switch (eq)
453         {
454         case EQ_LEFT_RING:
455         case EQ_RIGHT_RING:
456             return arms > 2;
457         case EQ_RING_ONE:
458         case EQ_RING_TWO:
459         case EQ_RING_THREE:
460         case EQ_RING_FOUR:
461         case EQ_RING_FIVE:
462         case EQ_RING_SIX:
463         case EQ_RING_SEVEN:
464         case EQ_RING_EIGHT:
465             return arms <= 2;
466         // not banned by any species
467         case EQ_AMULET:
468         case EQ_RING_AMULET:
469         // not handled here:
470         case EQ_WEAPON:
471         case EQ_STAFF:
472         case EQ_RINGS:
473         case EQ_RINGS_PLUS: // what is this stuff
474         case EQ_ALL_ARMOUR:
475             return false;
476         default:
477             break;
478         }
479         // remaining should be armour only
480         if (species == SP_OCTOPODE && eq != EQ_HELMET && eq != EQ_SHIELD)
481             return true;
482 
483         if (is_draconian(species) && eq == EQ_BODY_ARMOUR)
484             return true;
485 
486         // for everything else that is handled by mutations, including felid
487         // restrictions, see item-use.cc::can_wear_armour. (TODO: move more of the
488         // code here to mutations?)
489         return false;
490     }
491 
492     /**
493      * Get ring slots available to a species.
494      * @param species the species to check
495      * @param missing_hand if true, removes a designated hand from the result
496      */
ring_slots(species_type species,bool missing_hand)497     vector<equipment_type> ring_slots(species_type species, bool missing_hand)
498     {
499         vector<equipment_type> result;
500 
501         const equipment_type missing = missing_hand
502                             ? sacrificial_arm(species) : EQ_NONE;
503 
504         for (int i = EQ_FIRST_JEWELLERY; i <= EQ_LAST_JEWELLERY; i++)
505         {
506             const auto eq = static_cast<equipment_type>(i);
507             if (eq != EQ_AMULET
508                 && eq != EQ_RING_AMULET
509                 && eq != missing
510                 && !bans_eq(species, eq))
511             {
512                 result.push_back(eq);
513             }
514         }
515         return result;
516     }
517 
get_exp_modifier(species_type species)518     int get_exp_modifier(species_type species)
519     {
520         return get_species_def(species).xp_mod;
521     }
522 
get_hp_modifier(species_type species)523     int get_hp_modifier(species_type species)
524     {
525         return get_species_def(species).hp_mod;
526     }
527 
get_mp_modifier(species_type species)528     int get_mp_modifier(species_type species)
529     {
530         return get_species_def(species).mp_mod;
531     }
532 
get_wl_modifier(species_type species)533     int get_wl_modifier(species_type species)
534     {
535         return get_species_def(species).wl_mod;
536     }
537 
get_stat_gain_multiplier(species_type species)538     int get_stat_gain_multiplier(species_type species)
539     {
540         // TODO: is this worth dataifying? Currently matters only for
541         // player-stats.cc:attribute_increase
542         return species == SP_DEMIGOD ? 4 : 1;
543     }
544 
545     /**
546      *  Does this species have (relatively) low strength?
547      *  Used to generate the title for UC ghosts.
548      *
549      *  @param species the speciecs to check.
550      *  @returns whether the starting str is lower than the starting dex.
551      */
has_low_str(species_type species)552     bool has_low_str(species_type species)
553     {
554         return get_species_def(species).d >= get_species_def(species).s;
555     }
556 
557 
recommends_job(species_type species,job_type job)558     bool recommends_job(species_type species, job_type job)
559     {
560         return find(get_species_def(species).recommended_jobs.begin(),
561                     get_species_def(species).recommended_jobs.end(),
562                     job) != get_species_def(species).recommended_jobs.end();
563     }
564 
recommends_weapon(species_type species,weapon_type wpn)565     bool recommends_weapon(species_type species, weapon_type wpn)
566     {
567         const skill_type sk =
568               wpn == WPN_THROWN  ? SK_THROWING :
569               wpn == WPN_UNARMED ? SK_UNARMED_COMBAT :
570                                    item_attack_skill(OBJ_WEAPONS, wpn);
571 
572         return find(get_species_def(species).recommended_weapons.begin(),
573                     get_species_def(species).recommended_weapons.end(),
574                     sk) != get_species_def(species).recommended_weapons.end();
575     }
576 
is_valid(species_type species)577     bool is_valid(species_type species)
578     {
579         return 0 <= species && species < NUM_SPECIES;
580     }
581 
582 
583     // Ensure the species isn't SP_RANDOM/SP_VIABLE and it has recommended jobs
584     // (old disabled species have none).
is_starting_species(species_type species)585     bool is_starting_species(species_type species)
586     {
587         return is_valid(species)
588             && !get_species_def(species).recommended_jobs.empty();
589     }
590 
591     // A random valid (selectable on the new game screen) species.
random_starting_species()592     species_type random_starting_species()
593     {
594         const auto species = playable_species();
595         return species[random2(species.size())];
596     }
597 
is_removed(species_type species)598     bool is_removed(species_type species)
599     {
600     #if TAG_MAJOR_VERSION == 34
601         if (species == SP_MOTTLED_DRACONIAN)
602             return true;
603     #endif
604         // all other derived Dr are ok and don't have recommended jobs
605         if (is_draconian(species))
606             return false;
607         if (get_species_def(species).recommended_jobs.empty())
608             return true;
609         return false;
610     }
611 
612 
613     /** All non-removed species, including base and derived species */
get_all_species()614     vector<species_type> get_all_species()
615     {
616         vector<species_type> species;
617         for (int i = 0; i < NUM_SPECIES; ++i)
618         {
619             const auto sp = static_cast<species_type>(i);
620             if (!is_removed(sp))
621                 species.push_back(sp);
622         }
623         return species;
624     }
625 }
626 
give_basic_mutations(species_type species)627 void give_basic_mutations(species_type species)
628 {
629     // Don't perma_mutate since that gives messages.
630     for (const auto& lum : get_species_def(species).level_up_mutations)
631         if (lum.xp_level == 1)
632             you.mutation[lum.mut] = you.innate_mutation[lum.mut] = lum.mut_level;
633 }
634 
give_level_mutations(species_type species,int xp_level)635 void give_level_mutations(species_type species, int xp_level)
636 {
637     for (const auto& lum : get_species_def(species).level_up_mutations)
638         if (lum.xp_level == xp_level)
639         {
640             perma_mutate(lum.mut, lum.mut_level,
641                          species::name(species) + " growth");
642         }
643 }
644 
species_stat_init(species_type species)645 void species_stat_init(species_type species)
646 {
647     you.base_stats[STAT_STR] = get_species_def(species).s;
648     you.base_stats[STAT_INT] = get_species_def(species).i;
649     you.base_stats[STAT_DEX] = get_species_def(species).d;
650 }
651 
species_stat_gain(species_type species)652 void species_stat_gain(species_type species)
653 {
654     const species_def& sd = get_species_def(species);
655     if (sd.level_stats.size() > 0 && you.experience_level % sd.how_often == 0)
656     {
657         modify_stat(*random_iterator(sd.level_stats),
658                         species::get_stat_gain_multiplier(species), false);
659     }
660 }
661 
_swap_equip(equipment_type a,equipment_type b)662 static void _swap_equip(equipment_type a, equipment_type b)
663 {
664     swap(you.equip[a], you.equip[b]);
665     bool tmp = you.melded[a];
666     you.melded.set(a, you.melded[b]);
667     you.melded.set(b, tmp);
668 }
669 
670 /**
671  * Change the player's species to something else.
672  *
673  * This is used primarily in wizmode, but is also used for extreme
674  * cases of save compatibility (see `files.cc:_convert_obsolete_species`).
675  * This does *not* check for obsoleteness -- as long as it's in
676  * species_data it'll do something.
677  *
678  * @param sp the new species.
679  */
change_species_to(species_type sp)680 void change_species_to(species_type sp)
681 {
682     ASSERT(sp != SP_UNKNOWN);
683 
684     // Re-scale skill-points.
685     for (skill_type sk = SK_FIRST_SKILL; sk < NUM_SKILLS; ++sk)
686     {
687         you.skill_points[sk] *= species_apt_factor(sk, sp)
688                                 / species_apt_factor(sk);
689     }
690 
691     species_type old_sp = you.species;
692     you.species = sp;
693     you.chr_species_name = species::name(sp);
694 
695     // Change permanent mutations, but preserve non-permanent ones.
696     uint8_t prev_muts[NUM_MUTATIONS];
697 
698     // remove all innate mutations
699     for (int i = 0; i < NUM_MUTATIONS; ++i)
700     {
701         if (you.has_innate_mutation(static_cast<mutation_type>(i)))
702         {
703             you.mutation[i] -= you.innate_mutation[i];
704             you.innate_mutation[i] = 0;
705         }
706         prev_muts[i] = you.mutation[i];
707     }
708     // add the appropriate innate mutations for the new species and xl
709     give_basic_mutations(sp);
710     for (int i = 2; i <= you.experience_level; ++i)
711         give_level_mutations(sp, i);
712 
713     for (int i = 0; i < NUM_MUTATIONS; ++i)
714     {
715         // TODO: why do previous non-innate mutations override innate ones?  Shouldn't this be the other way around?
716         if (prev_muts[i] > you.innate_mutation[i])
717             you.innate_mutation[i] = 0;
718         else
719             you.innate_mutation[i] -= prev_muts[i];
720     }
721 
722     if (sp == SP_DEMONSPAWN)
723     {
724         roll_demonspawn_mutations();
725         for (int i = 0; i < int(you.demonic_traits.size()); ++i)
726         {
727             mutation_type m = you.demonic_traits[i].mutation;
728 
729             if (you.demonic_traits[i].level_gained > you.experience_level)
730                 continue;
731 
732             ++you.mutation[m];
733             ++you.innate_mutation[m];
734         }
735     }
736 
737     update_vision_range(); // for Ba, and for Ko
738 
739     // XX not general if there are ever any other options
740     if ((old_sp == SP_OCTOPODE) != (sp == SP_OCTOPODE))
741     {
742         _swap_equip(EQ_LEFT_RING, EQ_RING_ONE);
743         _swap_equip(EQ_RIGHT_RING, EQ_RING_TWO);
744         // All species allow exactly one amulet.
745     }
746 
747     // FIXME: this checks only for valid slots, not for suitability of the
748     // item in question. This is enough to make assertions happy, though.
749     for (int i = EQ_FIRST_EQUIP; i < NUM_EQUIP; ++i)
750         if (you_can_wear(static_cast<equipment_type>(i)) == MB_FALSE
751             && you.equip[i] != -1)
752         {
753             mprf("%s fall%s away.",
754                  you.inv[you.equip[i]].name(DESC_YOUR).c_str(),
755                  you.inv[you.equip[i]].quantity > 1 ? "" : "s");
756             // Unwear items without the usual processing.
757             you.equip[i] = -1;
758             you.melded.set(i, false);
759         }
760 
761     // Sanitize skills.
762     fixup_skills();
763 
764     calc_hp();
765     calc_mp();
766 
767     // The player symbol depends on species.
768     update_player_symbol();
769 #ifdef USE_TILE
770     init_player_doll();
771 #endif
772     redraw_screen();
773     update_screen();
774 }
775