c53bdb80882a4dfdcb7e95d23b19c9f74cba04a7
[crawl.git] / crawl-ref / source / item-name.cc
1 /**
2  * @file
3  * @brief Misc functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "item-name.h"
9
10 #include <cctype>
11 #include <cstring>
12 #include <iomanip>
13 #include <sstream>
14
15 #include "areas.h"
16 #include "artefact.h"
17 #include "art-enum.h"
18 #include "branch.h"
19 #include "cio.h"
20 #include "colour.h"
21 #include "decks.h"
22 #include "describe.h"
23 #include "dgn-overview.h"
24 #include "english.h"
25 #include "env.h" // LSTATE_STILL_WINDS
26 #include "errors.h" // sysfail
27 #include "god-item.h"
28 #include "god-passive.h" // passive_t::want_curses, no_haste
29 #include "invent.h"
30 #include "item-prop.h"
31 #include "item-status-flag-type.h"
32 #include "items.h"
33 #include "item-use.h"
34 #include "level-state-type.h"
35 #include "libutil.h"
36 #include "makeitem.h"
37 #include "notes.h"
38 #include "options.h"
39 #include "orb-type.h"
40 #include "player.h"
41 #include "prompt.h"
42 #include "religion.h"
43 #include "shopping.h"
44 #include "showsymb.h"
45 #include "skills.h"
46 #include "spl-book.h"
47 #include "state.h"
48 #include "stringutil.h"
49 #include "tag-version.h"
50 #include "throw.h"
51 #include "transform.h"
52 #include "unicode.h"
53 #include "unwind.h"
54 #include "viewgeom.h"
55
56 static bool _is_consonant(char let);
57 static char _random_vowel();
58 static char _random_cons();
59 static string _random_consonant_set(size_t seed);
60
61 static void _maybe_identify_pack_item()
62 {
63     for (auto &item : you.inv)
64         if (item.defined() && !get_ident_type(item))
65             maybe_identify_base_type(item);
66 }
67
68 // quant_name is useful since it prints out a different number of items
69 // than the item actually contains.
70 string quant_name(const item_def &item, int quant,
71                   description_level_type des, bool terse)
72 {
73     // item_name now requires a "real" item, so we'll mangle a tmp
74     item_def tmp = item;
75     tmp.quantity = quant;
76
77     return tmp.name(des, terse);
78 }
79
80 static const char* _interesting_origin(const item_def &item)
81 {
82     if (origin_as_god_gift(item) != GOD_NO_GOD)
83         return "god gift";
84
85     if (item.orig_monnum == MONS_DONALD && get_equip_desc(item)
86         && item.is_type(OBJ_ARMOUR, ARM_KITE_SHIELD))
87     {
88         return "Donald";
89     }
90
91     return nullptr;
92 }
93
94 /**
95  * What inscription should be appended to the given item's name?
96  */
97 static string _item_inscription(const item_def &item)
98 {
99     vector<string> insparts;
100
101     if (const char *orig = _interesting_origin(item))
102     {
103         if (Options.show_god_gift == MB_TRUE
104             || Options.show_god_gift == MB_MAYBE && !fully_identified(item))
105         {
106             insparts.push_back(orig);
107         }
108     }
109
110     if (is_artefact(item))
111     {
112         const string part = artefact_inscription(item);
113         if (!part.empty())
114             insparts.push_back(part);
115     }
116
117     if (!item.inscription.empty())
118         insparts.push_back(item.inscription);
119
120     if (insparts.empty())
121         return "";
122
123     return make_stringf(" {%s}",
124                         comma_separated_line(begin(insparts),
125                                              end(insparts),
126                                              ", ").c_str());
127 }
128
129 string item_def::name(description_level_type descrip, bool terse, bool ident,
130                       bool with_inscription, bool quantity_in_words,
131                       iflags_t ignore_flags) const
132 {
133     if (crawl_state.game_is_arena())
134         ignore_flags |= ISFLAG_KNOW_PLUSES | ISFLAG_COSMETIC_MASK;
135
136     if (descrip == DESC_NONE)
137         return "";
138
139     ostringstream buff;
140
141     const string auxname = name_aux(descrip, terse, ident, with_inscription,
142                                     ignore_flags);
143
144     const bool startvowel     = is_vowel(auxname[0]);
145     const bool qualname       = (descrip == DESC_QUALNAME);
146
147     if (descrip == DESC_INVENTORY_EQUIP || descrip == DESC_INVENTORY)
148     {
149         if (in_inventory(*this)) // actually in inventory
150         {
151             buff << index_to_letter(link);
152             if (terse)
153                 buff << ") ";
154             else
155                 buff << " - ";
156         }
157         else
158             descrip = DESC_A;
159     }
160
161     if (base_type == OBJ_BOOKS && (ident || item_type_known(*this))
162         && book_has_title(*this))
163     {
164         if (descrip != DESC_DBNAME)
165             descrip = DESC_PLAIN;
166     }
167
168     if (terse && descrip != DESC_DBNAME)
169         descrip = DESC_PLAIN;
170
171     monster_flags_t corpse_flags;
172
173     // no "a dragon scales"
174     const bool always_plural = armour_is_hide(*this)
175                                && sub_type != ARM_TROLL_LEATHER_ARMOUR;
176
177     if ((base_type == OBJ_CORPSES && is_named_corpse(*this)
178          && !(((corpse_flags.flags = props[CORPSE_NAME_TYPE_KEY].get_int64())
179                & MF_NAME_SPECIES)
180               && !(corpse_flags & MF_NAME_DEFINITE))
181          && !(corpse_flags & MF_NAME_SUFFIX)
182          && !starts_with(get_corpse_name(*this), "shaped "))
183         || item_is_orb(*this) || item_is_horn_of_geryon(*this)
184         || (ident || item_type_known(*this)) && is_artefact(*this)
185             && special != UNRAND_OCTOPUS_KING_RING)
186     {
187         // Artefacts always get "the" unless we just want the plain name.
188         switch (descrip)
189         {
190         default:
191             buff << "the ";
192         case DESC_PLAIN:
193         case DESC_DBNAME:
194         case DESC_BASENAME:
195         case DESC_QUALNAME:
196             break;
197         }
198     }
199     else if (quantity > 1 || always_plural)
200     {
201         switch (descrip)
202         {
203         case DESC_THE:        buff << "the "; break;
204         case DESC_YOUR:       buff << "your "; break;
205         case DESC_ITS:        buff << "its "; break;
206         case DESC_A:
207         case DESC_INVENTORY_EQUIP:
208         case DESC_INVENTORY:
209         case DESC_PLAIN:
210         default:
211             break;
212         }
213
214         if (descrip != DESC_BASENAME && descrip != DESC_QUALNAME
215             && descrip != DESC_DBNAME && !always_plural)
216         {
217             if (quantity_in_words)
218                 buff << number_in_words(quantity) << " ";
219             else
220                 buff << quantity << " ";
221         }
222     }
223     else
224     {
225         switch (descrip)
226         {
227         case DESC_THE:        buff << "the "; break;
228         case DESC_YOUR:       buff << "your "; break;
229         case DESC_ITS:        buff << "its "; break;
230         case DESC_A:
231         case DESC_INVENTORY_EQUIP:
232         case DESC_INVENTORY:
233                               buff << (startvowel ? "an " : "a "); break;
234         case DESC_PLAIN:
235         default:
236             break;
237         }
238     }
239
240     buff << auxname;
241
242     if (descrip == DESC_INVENTORY_EQUIP)
243     {
244         equipment_type eq = item_equip_slot(*this);
245         if (eq != EQ_NONE)
246         {
247             if (you.melded[eq])
248                 buff << " (melded)";
249             else
250             {
251                 switch (eq)
252                 {
253                 case EQ_WEAPON:
254                     if (is_weapon(*this))
255                         buff << " (weapon)";
256                     else if (you.species == SP_FELID)
257                         buff << " (in mouth)";
258                     else
259                         buff << " (in " << you.hand_name(false) << ")";
260                     break;
261                 case EQ_CLOAK:
262                 case EQ_HELMET:
263                 case EQ_GLOVES:
264                 case EQ_BOOTS:
265                 case EQ_SHIELD:
266                 case EQ_BODY_ARMOUR:
267                     buff << " (worn)";
268                     break;
269                 case EQ_LEFT_RING:
270                 case EQ_RIGHT_RING:
271                 case EQ_RING_ONE:
272                 case EQ_RING_TWO:
273                     buff << " (";
274                     buff << ((eq == EQ_LEFT_RING || eq == EQ_RING_ONE)
275                              ? "left" : "right");
276                     buff << " ";
277                     buff << you.hand_name(false);
278                     buff << ")";
279                     break;
280                 case EQ_AMULET:
281                     if (you.species == SP_OCTOPODE && form_keeps_mutations())
282                         buff << " (around mantle)";
283                     else
284                         buff << " (around neck)";
285                     break;
286                 case EQ_RING_THREE:
287                 case EQ_RING_FOUR:
288                 case EQ_RING_FIVE:
289                 case EQ_RING_SIX:
290                 case EQ_RING_SEVEN:
291                 case EQ_RING_EIGHT:
292                     buff << " (on tentacle)";
293                     break;
294                 case EQ_RING_AMULET:
295                     buff << " (on amulet)";
296                     break;
297                 default:
298                     die("Item in an invalid slot");
299                 }
300             }
301         }
302         else if (you.launcher_action.item_is_quivered(*this))
303             buff << " (quivered ammo)";
304         else if (you.quiver_action.item_is_quivered(*this))
305             buff << " (quivered)";
306     }
307
308     if (descrip != DESC_BASENAME && descrip != DESC_DBNAME && with_inscription)
309         buff << _item_inscription(*this);
310
311     // These didn't have "cursed " prepended; add them here so that
312     // it comes after the inscription.
313     if (terse && descrip != DESC_DBNAME && descrip != DESC_BASENAME
314         && !qualname
315         && is_artefact(*this) && cursed())
316     {
317         buff << " (curse)";
318     }
319
320     return buff.str();
321 }
322
323 static bool _missile_brand_is_prefix(special_missile_type brand)
324 {
325     switch (brand)
326     {
327     case SPMSL_POISONED:
328     case SPMSL_CURARE:
329     case SPMSL_BLINDING:
330     case SPMSL_FRENZY:
331     case SPMSL_EXPLODING:
332 #if TAG_MAJOR_VERSION == 34
333     case SPMSL_STEEL:
334 #endif
335     case SPMSL_SILVER:
336         return true;
337     default:
338         return false;
339     }
340 }
341
342 static bool _missile_brand_is_postfix(special_missile_type brand)
343 {
344     return brand != SPMSL_NORMAL && !_missile_brand_is_prefix(brand);
345 }
346
347 const char* missile_brand_name(const item_def &item, mbn_type t)
348 {
349     const special_missile_type brand
350         = static_cast<special_missile_type>(item.brand);
351     switch (brand)
352     {
353 #if TAG_MAJOR_VERSION == 34
354     case SPMSL_FLAME:
355         return "flame";
356     case SPMSL_FROST:
357         return "frost";
358 #endif
359     case SPMSL_POISONED:
360         return t == MBN_NAME ? "poisoned" : "poison";
361     case SPMSL_CURARE:
362         return t == MBN_NAME ? "curare-tipped" : "curare";
363 #if TAG_MAJOR_VERSION == 34
364     case SPMSL_EXPLODING:
365         return t == MBN_TERSE ? "explode" : "exploding";
366     case SPMSL_STEEL:
367         return "steel";
368     case SPMSL_RETURNING:
369         return t == MBN_TERSE ? "return" : "returning";
370     case SPMSL_PENETRATION:
371         return t == MBN_TERSE ? "penet" : "penetration";
372 #endif
373     case SPMSL_SILVER:
374         return "silver";
375 #if TAG_MAJOR_VERSION == 34
376     case SPMSL_PARALYSIS:
377         return "paralysis";
378     case SPMSL_SLOW:
379         return t == MBN_TERSE ? "slow" : "slowing";
380     case SPMSL_SLEEP:
381         return t == MBN_TERSE ? "sleep" : "sleeping";
382     case SPMSL_CONFUSION:
383         return t == MBN_TERSE ? "conf" : "confusion";
384     case SPMSL_SICKNESS:
385         return t == MBN_TERSE ? "sick" : "sickness";
386 #endif
387     case SPMSL_FRENZY:
388         return t == MBN_NAME ? "datura-tipped" : "datura";
389     case SPMSL_CHAOS:
390         return "chaos";
391     case SPMSL_DISPERSAL:
392         return t == MBN_TERSE ? "disperse" : "dispersal";
393     case SPMSL_BLINDING:
394         return t == MBN_NAME ? "atropa-tipped" : "atropa";
395     case SPMSL_NORMAL:
396         return "";
397     default:
398         return t == MBN_TERSE ? "buggy" : "bugginess";
399     }
400 }
401
402 static const char *weapon_brands_terse[] =
403 {
404     "", "flame", "freeze", "holy", "elec",
405 #if TAG_MAJOR_VERSION == 34
406     "obsolete", "obsolete",
407 #endif
408     "venom", "protect", "drain", "speed", "vorpal",
409 #if TAG_MAJOR_VERSION == 34
410     "obsolete", "obsolete",
411 #endif
412     "vamp", "pain", "antimagic", "distort",
413 #if TAG_MAJOR_VERSION == 34
414     "obsolete", "obsolete",
415 #endif
416     "chaos",
417 #if TAG_MAJOR_VERSION == 34
418     "evade", "confuse",
419 #endif
420     "penet", "reap", "spect", "vorpal", "acid",
421 #if TAG_MAJOR_VERSION > 34
422     "confuse",
423 #endif
424     "debug",
425 };
426
427 static const char *weapon_brands_verbose[] =
428 {
429     "", "flaming", "freezing", "holy wrath", "electrocution",
430 #if TAG_MAJOR_VERSION == 34
431     "orc slaying", "dragon slaying",
432 #endif
433     "venom", "protection", "draining", "speed", "vorpality",
434 #if TAG_MAJOR_VERSION == 34
435     "flame", "frost",
436 #endif
437     "vampirism", "pain", "antimagic", "distortion",
438 #if TAG_MAJOR_VERSION == 34
439     "reaching", "returning",
440 #endif
441     "chaos",
442 #if TAG_MAJOR_VERSION == 34
443     "evasion", "confusion",
444 #endif
445     "penetration", "reaping", "spectralizing", "vorpal", "acid",
446 #if TAG_MAJOR_VERSION > 34
447     "confusion",
448 #endif
449     "debug",
450 };
451
452 static const char *weapon_brands_adj[] =
453 {
454     "", "flaming", "freezing", "holy", "electric",
455 #if TAG_MAJOR_VERSION == 34
456     "orc-killing", "dragon-slaying",
457 #endif
458     "venomous", "protective", "draining", "fast", "vorpal",
459 #if TAG_MAJOR_VERSION == 34
460     "flaming", "freezing",
461 #endif
462     "vampiric", "painful", "antimagic", "distorting",
463 #if TAG_MAJOR_VERSION == 34
464     "reaching", "returning",
465 #endif
466     "chaotic",
467 #if TAG_MAJOR_VERSION == 34
468     "evasive", "confusing",
469 #endif
470     "penetrating", "reaping", "spectral", "vorpal", "acidic",
471 #if TAG_MAJOR_VERSION > 34
472     "confusing",
473 #endif
474     "debug",
475 };
476
477 static const set<brand_type> brand_prefers_adj =
478             { SPWPN_VAMPIRISM, SPWPN_ANTIMAGIC, SPWPN_VORPAL, SPWPN_SPECTRAL };
479
480 /**
481  * What's the name of a type of weapon brand?
482  *
483  * @param brand             The type of brand in question.
484  * @param bool              Whether to use a terse or verbose name.
485  * @return                  The name of the given brand.
486  */
487 const char* brand_type_name(brand_type brand, bool terse)
488 {
489     COMPILE_CHECK(ARRAYSZ(weapon_brands_terse) == NUM_SPECIAL_WEAPONS);
490     COMPILE_CHECK(ARRAYSZ(weapon_brands_verbose) == NUM_SPECIAL_WEAPONS);
491
492     if (brand < 0 || brand >= NUM_SPECIAL_WEAPONS)
493         return terse ? "buggy" : "bugginess";
494
495     return (terse ? weapon_brands_terse : weapon_brands_verbose)[brand];
496 }
497
498 const char* brand_type_adj(brand_type brand)
499 {
500     COMPILE_CHECK(ARRAYSZ(weapon_brands_terse) == NUM_SPECIAL_WEAPONS);
501     COMPILE_CHECK(ARRAYSZ(weapon_brands_verbose) == NUM_SPECIAL_WEAPONS);
502
503     if (brand < 0 || brand >= NUM_SPECIAL_WEAPONS)
504         return "buggy";
505
506     return weapon_brands_adj[brand];
507 }
508
509 /**
510  * What's the name of a given weapon's brand?
511  *
512  * @param item              The weapon with the brand.
513  * @param bool              Whether to use a terse or verbose name.
514  * @return                  The name of the given item's brand.
515  */
516 const char* weapon_brand_name(const item_def& item, bool terse,
517                               brand_type override_brand)
518 {
519     const brand_type brand = override_brand ? override_brand : get_weapon_brand(item);
520
521     return brand_type_name(brand, terse);
522 }
523
524 const char* armour_ego_name(const item_def& item, bool terse)
525 {
526     if (!terse)
527     {
528         switch (get_armour_ego_type(item))
529         {
530         case SPARM_NORMAL:            return "";
531 #if TAG_MAJOR_VERSION == 34
532         case SPARM_RUNNING:
533             // "naga barding of running" doesn't make any sense, and yes,
534             // they are possible. The terse ego name for these is {run}
535             // still to avoid player confusion, it used to be {sslith}.
536             if (item.sub_type == ARM_BARDING && you.species == SP_NAGA)
537                                       return "speedy slithering";
538             else
539                                       return "running";
540 #endif
541         case SPARM_FIRE_RESISTANCE:   return "fire resistance";
542         case SPARM_COLD_RESISTANCE:   return "cold resistance";
543         case SPARM_POISON_RESISTANCE: return "poison resistance";
544         case SPARM_SEE_INVISIBLE:     return "see invisible";
545         case SPARM_INVISIBILITY:      return "invisibility";
546         case SPARM_STRENGTH:          return "strength";
547         case SPARM_DEXTERITY:         return "dexterity";
548         case SPARM_INTELLIGENCE:      return "intelligence";
549         case SPARM_PONDEROUSNESS:     return "ponderousness";
550         case SPARM_FLYING:            return "flying";
551
552         case SPARM_WILLPOWER:  return "willpower";
553         case SPARM_PROTECTION:        return "protection";
554         case SPARM_STEALTH:           return "stealth";
555         case SPARM_RESISTANCE:        return "resistance";
556         case SPARM_POSITIVE_ENERGY:   return "positive energy";
557         case SPARM_ARCHMAGI:          return "the Archmagi";
558 #if TAG_MAJOR_VERSION == 34
559         case SPARM_JUMPING:           return "jumping";
560 #endif
561         case SPARM_PRESERVATION:      return "preservation";
562         case SPARM_REFLECTION:        return "reflection";
563         case SPARM_SPIRIT_SHIELD:     return "spirit shield";
564         case SPARM_ARCHERY:           return "archery";
565         case SPARM_REPULSION:         return "repulsion";
566 #if TAG_MAJOR_VERSION == 34
567         case SPARM_CLOUD_IMMUNE:      return "cloud immunity";
568 #endif
569         case SPARM_HARM:              return "harm";
570         case SPARM_SHADOWS:           return "shadows";
571         case SPARM_RAMPAGING:         return "rampaging";
572         default:                      return "bugginess";
573         }
574     }
575     else
576     {
577         switch (get_armour_ego_type(item))
578         {
579         case SPARM_NORMAL:            return "";
580 #if TAG_MAJOR_VERSION == 34
581         case SPARM_RUNNING:           return "obsolete";
582 #endif
583         case SPARM_FIRE_RESISTANCE:   return "rF+";
584         case SPARM_COLD_RESISTANCE:   return "rC+";
585         case SPARM_POISON_RESISTANCE: return "rPois";
586         case SPARM_SEE_INVISIBLE:     return "SInv";
587         case SPARM_INVISIBILITY:      return "+Inv";
588         case SPARM_STRENGTH:          return "Str+3";
589         case SPARM_DEXTERITY:         return "Dex+3";
590         case SPARM_INTELLIGENCE:      return "Int+3";
591         case SPARM_PONDEROUSNESS:     return "ponderous";
592         case SPARM_FLYING:            return "Fly";
593         case SPARM_WILLPOWER:         return "Will+";
594         case SPARM_PROTECTION:        return "AC+3";
595         case SPARM_STEALTH:           return "Stlth+";
596         case SPARM_RESISTANCE:        return "rC+ rF+";
597         case SPARM_POSITIVE_ENERGY:   return "rN+";
598         case SPARM_ARCHMAGI:          return "Archmagi";
599 #if TAG_MAJOR_VERSION == 34
600         case SPARM_JUMPING:           return "obsolete";
601 #endif
602         case SPARM_PRESERVATION:      return "rCorr";
603         case SPARM_REFLECTION:        return "reflect";
604         case SPARM_SPIRIT_SHIELD:     return "Spirit";
605         case SPARM_ARCHERY:           return "archery";
606         case SPARM_REPULSION:         return "repulsion";
607 #if TAG_MAJOR_VERSION == 34
608         case SPARM_CLOUD_IMMUNE:      return "obsolete";
609 #endif
610         case SPARM_HARM:              return "harm";
611         case SPARM_SHADOWS:           return "shadows";
612         case SPARM_RAMPAGING:         return "rampage";
613         default:                      return "buggy";
614         }
615     }
616 }
617
618 static const char* _wand_type_name(int wandtype)
619 {
620     switch (wandtype)
621     {
622     case WAND_FLAME:           return "flame";
623     case WAND_PARALYSIS:       return "paralysis";
624     case WAND_DIGGING:         return "digging";
625     case WAND_ICEBLAST:        return "iceblast";
626     case WAND_POLYMORPH:       return "polymorph";
627     case WAND_CHARMING:     return "charming";
628     case WAND_ACID:            return "acid";
629     case WAND_RANDOM_EFFECTS:  return "random effects";
630     case WAND_MINDBURST:       return "mindburst";
631     default:                   return item_type_removed(OBJ_WANDS, wandtype)
632                                     ? "removedness"
633                                     : "bugginess";
634     }
635 }
636
637 static const char* wand_secondary_string(uint32_t s)
638 {
639     static const char* const secondary_strings[] = {
640         "", "jewelled ", "curved ", "long ", "short ", "twisted ", "crooked ",
641         "forked ", "shiny ", "blackened ", "tapered ", "glowing ", "worn ",
642         "encrusted ", "runed ", "sharpened "
643     };
644     COMPILE_CHECK(ARRAYSZ(secondary_strings) == NDSC_WAND_SEC);
645     return secondary_strings[s % NDSC_WAND_SEC];
646 }
647
648 static const char* wand_primary_string(uint32_t p)
649 {
650     static const char* const primary_strings[] = {
651         "iron", "brass", "bone", "wooden", "copper", "gold", "silver",
652         "bronze", "ivory", "glass", "lead", "fluorescent"
653     };
654     COMPILE_CHECK(ARRAYSZ(primary_strings) == NDSC_WAND_PRI);
655     return primary_strings[p % NDSC_WAND_PRI];
656 }
657
658 const char* potion_type_name(int potiontype)
659 {
660     switch (static_cast<potion_type>(potiontype))
661     {
662     case POT_CURING:            return "curing";
663     case POT_HEAL_WOUNDS:       return "heal wounds";
664     case POT_HASTE:             return "haste";
665     case POT_MIGHT:             return "might";
666     case POT_ATTRACTION:        return "attraction";
667     case POT_BRILLIANCE:        return "brilliance";
668     case POT_FLIGHT:            return "flight";
669     case POT_CANCELLATION:      return "cancellation";
670     case POT_AMBROSIA:          return "ambrosia";
671     case POT_INVISIBILITY:      return "invisibility";
672     case POT_DEGENERATION:      return "degeneration";
673     case POT_EXPERIENCE:        return "experience";
674     case POT_MAGIC:             return "magic";
675     case POT_BERSERK_RAGE:      return "berserk rage";
676     case POT_MUTATION:          return "mutation";
677     case POT_RESISTANCE:        return "resistance";
678     case POT_LIGNIFY:           return "lignification";
679
680     // FIXME: Remove this once known-items no longer uses this as a sentinel.
681     default:
682                                 return "bugginess";
683     CASE_REMOVED_POTIONS(potiontype); // TODO: this will crash, is that correct??
684     }
685 }
686
687 static const char* scroll_type_name(int scrolltype)
688 {
689     switch (static_cast<scroll_type>(scrolltype))
690     {
691     case SCR_IDENTIFY:           return "identify";
692     case SCR_TELEPORTATION:      return "teleportation";
693     case SCR_FEAR:               return "fear";
694     case SCR_NOISE:              return "noise";
695     case SCR_SUMMONING:          return "summoning";
696     case SCR_ENCHANT_WEAPON:     return "enchant weapon";
697     case SCR_ENCHANT_ARMOUR:     return "enchant armour";
698     case SCR_TORMENT:            return "torment";
699     case SCR_RANDOM_USELESSNESS: return "random uselessness";
700     case SCR_IMMOLATION:         return "immolation";
701     case SCR_BLINKING:           return "blinking";
702     case SCR_MAGIC_MAPPING:      return "magic mapping";
703     case SCR_FOG:                return "fog";
704     case SCR_ACQUIREMENT:        return "acquirement";
705     case SCR_BRAND_WEAPON:       return "brand weapon";
706     case SCR_HOLY_WORD:          return "holy word";
707     case SCR_VULNERABILITY:      return "vulnerability";
708     case SCR_SILENCE:            return "silence";
709     case SCR_AMNESIA:            return "amnesia";
710 #if TAG_MAJOR_VERSION == 34
711     case SCR_CURSE_WEAPON:       return "curse weapon";
712     case SCR_CURSE_ARMOUR:       return "curse armour";
713     case SCR_CURSE_JEWELLERY:    return "curse jewellery";
714 #endif
715     default:                     return item_type_removed(OBJ_SCROLLS,
716                                                           scrolltype)
717                                      ? "removedness"
718                                      : "bugginess";
719     }
720 }
721
722 /**
723  * Get the name for the effect provided by a kind of jewellery.
724  *
725  * @param jeweltype     The jewellery_type of the item in question.
726  * @return              A string describing the effect of the given jewellery
727  *                      subtype.
728  */
729 const char* jewellery_effect_name(int jeweltype, bool terse)
730 {
731     if (!terse)
732     {
733         switch (static_cast<jewellery_type>(jeweltype))
734         {
735 #if TAG_MAJOR_VERSION == 34
736         case RING_REGENERATION:          return "obsoleteness";
737         case RING_ATTENTION:             return "obsoleteness";
738 #endif
739         case RING_PROTECTION:            return "protection";
740         case RING_PROTECTION_FROM_FIRE:  return "protection from fire";
741         case RING_POISON_RESISTANCE:     return "poison resistance";
742         case RING_PROTECTION_FROM_COLD:  return "protection from cold";
743         case RING_STRENGTH:              return "strength";
744         case RING_SLAYING:               return "slaying";
745         case RING_SEE_INVISIBLE:         return "see invisible";
746         case RING_RESIST_CORROSION:      return "resist corrosion";
747         case RING_EVASION:               return "evasion";
748 #if TAG_MAJOR_VERSION == 34
749         case RING_SUSTAIN_ATTRIBUTES:    return "sustain attributes";
750 #endif
751         case RING_STEALTH:               return "stealth";
752         case RING_DEXTERITY:             return "dexterity";
753         case RING_INTELLIGENCE:          return "intelligence";
754         case RING_WIZARDRY:              return "wizardry";
755         case RING_MAGICAL_POWER:         return "magical power";
756         case RING_FLIGHT:                return "flight";
757         case RING_LIFE_PROTECTION:       return "positive energy";
758         case RING_WILLPOWER: return "willpower";
759         case RING_FIRE:                  return "fire";
760         case RING_ICE:                   return "ice";
761 #if TAG_MAJOR_VERSION == 34
762         case RING_TELEPORTATION:         return "teleportation";
763         case RING_TELEPORT_CONTROL:      return "teleport control";
764 #endif
765         case AMU_MANA_REGENERATION: return "magic regeneration";
766         case AMU_ACROBAT:           return "the acrobat";
767 #if TAG_MAJOR_VERSION == 34
768         case AMU_RAGE:              return "rage";
769         case AMU_THE_GOURMAND:      return "gourmand";
770         case AMU_HARM:              return "harm";
771         case AMU_CONSERVATION:      return "conservation";
772         case AMU_CONTROLLED_FLIGHT: return "controlled flight";
773         case AMU_INACCURACY:        return "inaccuracy";
774 #endif
775         case AMU_NOTHING:           return "nothing";
776         case AMU_GUARDIAN_SPIRIT:   return "guardian spirit";
777         case AMU_FAITH:             return "faith";
778         case AMU_REFLECTION:        return "reflection";
779         case AMU_REGENERATION:      return "regeneration";
780         default: return "buggy jewellery";
781         }
782     }
783     else
784     {
785         if (jewellery_base_ability_string(jeweltype)[0] != '\0')
786             return jewellery_base_ability_string(jeweltype);
787         switch (static_cast<jewellery_type>(jeweltype))
788         {
789 #if TAG_MAJOR_VERSION == 34
790         case RING_REGENERATION:          return "obsoleteness";
791         case RING_ATTENTION:             return "obsoleteness";
792 #endif
793         case RING_PROTECTION:            return "AC";
794         case RING_PROTECTION_FROM_FIRE:  return "rF+";
795         case RING_POISON_RESISTANCE:     return "rPois";
796         case RING_PROTECTION_FROM_COLD:  return "rC+";
797         case RING_STRENGTH:              return "Str";
798         case RING_SLAYING:               return "Slay";
799         case RING_SEE_INVISIBLE:         return "sInv";
800         case RING_RESIST_CORROSION:      return "rCorr";
801         case RING_EVASION:               return "EV";
802         case RING_STEALTH:               return "Stlth+";
803         case RING_DEXTERITY:             return "Dex";
804         case RING_INTELLIGENCE:          return "Int";
805         case RING_MAGICAL_POWER:         return "MP+9";
806         case RING_FLIGHT:                return "+Fly";
807         case RING_LIFE_PROTECTION:       return "rN+";
808         case RING_WILLPOWER:             return "Will+";
809         case AMU_REGENERATION:           return "Regen";
810 #if TAG_MAJOR_VERSION == 34
811         case AMU_RAGE:                   return "+Rage";
812 #endif
813         case AMU_ACROBAT:                return "Acrobat";
814         case AMU_NOTHING:                return "";
815         default: return "buggy";
816         }
817     }
818 }
819
820 /**
821  * Get the name for the category of a type of jewellery.
822  *
823  * @param jeweltype     The jewellery_type of the item in question.
824  * @return              A string describing the kind of jewellery it is.
825  */
826 static const char* _jewellery_class_name(int jeweltype)
827 {
828 #if TAG_MAJOR_VERSION == 34
829     if (jeweltype == RING_REGENERATION)
830         return "ring of";
831 #endif
832
833     if (jeweltype < RING_FIRST_RING || jeweltype >= NUM_JEWELLERY
834         || jeweltype >= NUM_RINGS && jeweltype < AMU_FIRST_AMULET)
835     {
836         return "buggy"; // "buggy buggy jewellery"
837     }
838
839     if (jeweltype < NUM_RINGS)
840         return "ring of";
841     return "amulet of";
842 }
843
844 /**
845  * Get the name for a type of jewellery.
846  *
847  * @param jeweltype     The jewellery_type of the item in question.
848  * @return              The full name of the jewellery type in question.
849  */
850 static string jewellery_type_name(int jeweltype)
851 {
852     return make_stringf("%s %s", _jewellery_class_name(jeweltype),
853                                  jewellery_effect_name(jeweltype));
854 }
855
856
857 static const char* ring_secondary_string(uint32_t s)
858 {
859     static const char* const secondary_strings[] = {
860         "", "encrusted ", "glowing ", "tubular ", "runed ", "blackened ",
861         "scratched ", "small ", "large ", "twisted ", "shiny ", "notched ",
862         "knobbly "
863     };
864     COMPILE_CHECK(ARRAYSZ(secondary_strings) == NDSC_JEWEL_SEC);
865     return secondary_strings[s % NDSC_JEWEL_SEC];
866 }
867
868 static const char* ring_primary_string(uint32_t p)
869 {
870     static const char* const primary_strings[] = {
871         "wooden", "silver", "golden", "iron", "steel", "tourmaline", "brass",
872         "copper", "granite", "ivory", "ruby", "marble", "jade", "glass",
873         "agate", "bone", "diamond", "emerald", "peridot", "garnet", "opal",
874         "pearl", "coral", "sapphire", "cabochon", "gilded", "onyx", "bronze",
875         "moonstone"
876     };
877     COMPILE_CHECK(ARRAYSZ(primary_strings) == NDSC_JEWEL_PRI);
878     return primary_strings[p % NDSC_JEWEL_PRI];
879 }
880
881 static const char* amulet_secondary_string(uint32_t s)
882 {
883     static const char* const secondary_strings[] = {
884         "dented ", "square ", "thick ", "thin ", "runed ", "blackened ",
885         "glowing ", "small ", "large ", "twisted ", "tiny ", "triangular ",
886         "lumpy "
887     };
888     COMPILE_CHECK(ARRAYSZ(secondary_strings) == NDSC_JEWEL_SEC);
889     return secondary_strings[s % NDSC_JEWEL_SEC];
890 }
891
892 static const char* amulet_primary_string(uint32_t p)
893 {
894     static const char* const primary_strings[] = {
895         "sapphire", "zirconium", "golden", "emerald", "garnet", "bronze",
896         "brass", "copper", "ruby", "citrine", "bone", "platinum", "jade",
897         "fluorescent", "amethyst", "cameo", "pearl", "blue", "peridot",
898         "jasper", "diamond", "malachite", "steel", "cabochon", "silver",
899         "soapstone", "lapis lazuli", "filigree", "beryl"
900     };
901     COMPILE_CHECK(ARRAYSZ(primary_strings) == NDSC_JEWEL_PRI);
902     return primary_strings[p % NDSC_JEWEL_PRI];
903 }
904
905 const char* rune_type_name(short p)
906 {
907     switch (static_cast<rune_type>(p))
908     {
909     case RUNE_DIS:         return "iron";
910     case RUNE_GEHENNA:     return "obsidian";
911     case RUNE_COCYTUS:     return "icy";
912     case RUNE_TARTARUS:    return "bone";
913     case RUNE_SLIME:       return "slimy";
914     case RUNE_VAULTS:      return "silver";
915     case RUNE_SNAKE:       return "serpentine";
916     case RUNE_ELF:         return "elven";
917     case RUNE_TOMB:        return "golden";
918     case RUNE_SWAMP:       return "decaying";
919     case RUNE_SHOALS:      return "barnacled";
920     case RUNE_SPIDER:      return "gossamer";
921     case RUNE_FOREST:      return "mossy";
922
923     // pandemonium and abyss runes:
924     case RUNE_DEMONIC:     return "demonic";
925     case RUNE_ABYSSAL:     return "abyssal";
926
927     // special pandemonium runes:
928     case RUNE_MNOLEG:      return "glowing";
929     case RUNE_LOM_LOBON:   return "magical";
930     case RUNE_CEREBOV:     return "fiery";
931     case RUNE_GLOORX_VLOQ: return "dark";
932     default:               return "buggy";
933     }
934 }
935
936 static string misc_type_name(int type)
937 {
938 #if TAG_MAJOR_VERSION == 34
939     if (is_deck_type(type))
940         return "removed deck";
941 #endif
942
943     switch (static_cast<misc_item_type>(type))
944     {
945 #if TAG_MAJOR_VERSION == 34
946     case MISC_CRYSTAL_BALL_OF_ENERGY:    return "removed crystal ball";
947 #endif
948     case MISC_BOX_OF_BEASTS:             return "box of beasts";
949 #if TAG_MAJOR_VERSION == 34
950     case MISC_BUGGY_EBONY_CASKET:        return "removed ebony casket";
951     case MISC_FAN_OF_GALES:              return "removed fan of gales";
952     case MISC_LAMP_OF_FIRE:              return "removed lamp of fire";
953     case MISC_BUGGY_LANTERN_OF_SHADOWS:  return "removed lantern of shadows";
954 #endif
955     case MISC_HORN_OF_GERYON:            return "horn of Geryon";
956     case MISC_LIGHTNING_ROD:             return "lightning rod";
957 #if TAG_MAJOR_VERSION == 34
958     case MISC_BOTTLED_EFREET:            return "empty flask";
959     case MISC_RUNE_OF_ZOT:               return "obsolete rune of zot";
960     case MISC_STONE_OF_TREMORS:          return "removed stone of tremors";
961 #endif
962     case MISC_QUAD_DAMAGE:               return "quad damage";
963     case MISC_PHIAL_OF_FLOODS:           return "phial of floods";
964 #if TAG_MAJOR_VERSION == 34
965     case MISC_SACK_OF_SPIDERS:           return "removed sack of spiders";
966 #endif
967     case MISC_PHANTOM_MIRROR:            return "phantom mirror";
968     case MISC_ZIGGURAT:                  return "figurine of a ziggurat";
969 #if TAG_MAJOR_VERSION == 34
970     case MISC_XOMS_CHESSBOARD:           return "removed chess piece";
971 #endif
972     case MISC_TIN_OF_TREMORSTONES:       return "tin of tremorstones";
973     case MISC_CONDENSER_VANE:            return "condenser vane";
974
975     default:
976         return "buggy miscellaneous item";
977     }
978 }
979
980 static bool _book_visually_special(uint32_t s)
981 {
982     return s & 128; // one in ten books; c.f. item_colour()
983 }
984
985 static const char* book_secondary_string(uint32_t s)
986 {
987     if (!_book_visually_special(s))
988         return "";
989
990     static const char* const secondary_strings[] = {
991         "", "chunky ", "thick ", "thin ", "wide ", "glowing ",
992         "dog-eared ", "oblong ", "runed ", "", "", ""
993     };
994     return secondary_strings[(s / NDSC_BOOK_PRI) % ARRAYSZ(secondary_strings)];
995 }
996
997 static const char* book_primary_string(uint32_t p)
998 {
999     static const char* const primary_strings[] = {
1000         "paperback", "hardcover", "leatherbound", "metal-bound", "papyrus",
1001     };
1002     COMPILE_CHECK(NDSC_BOOK_PRI == ARRAYSZ(primary_strings));
1003
1004     return primary_strings[p % ARRAYSZ(primary_strings)];
1005 }
1006
1007 static const char* _book_type_name(int booktype)
1008 {
1009     switch (static_cast<book_type>(booktype))
1010     {
1011     case BOOK_MINOR_MAGIC:            return "Minor Magic";
1012     case BOOK_CONJURATIONS:           return "Conjurations";
1013     case BOOK_FLAMES:                 return "Flames";
1014     case BOOK_FROST:                  return "Frost";
1015     case BOOK_SUMMONINGS:             return "Summonings";
1016     case BOOK_FIRE:                   return "Fire";
1017     case BOOK_ICE:                    return "Ice";
1018     case BOOK_SPATIAL_TRANSLOCATIONS: return "Spatial Translocations";
1019     case BOOK_HEXES:                  return "Hexes";
1020     case BOOK_TEMPESTS:               return "the Tempests";
1021     case BOOK_DEATH:                  return "Death";
1022     case BOOK_MISFORTUNE:             return "Misfortune";
1023     case BOOK_CHANGES:                return "Changes";
1024     case BOOK_TRANSFIGURATIONS:       return "Transfigurations";
1025 #if TAG_MAJOR_VERSION == 34
1026     case BOOK_BATTLE:                 return "Battle";
1027 #endif
1028     case BOOK_CLOUDS:                 return "Clouds";
1029     case BOOK_NECROMANCY:             return "Necromancy";
1030     case BOOK_CALLINGS:               return "Callings";
1031     case BOOK_MALEDICT:               return "Maledictions";
1032     case BOOK_AIR:                    return "Air";
1033     case BOOK_SKY:                    return "the Sky";
1034     case BOOK_WARP:                   return "the Warp";
1035 #if TAG_MAJOR_VERSION == 34
1036     case BOOK_ENVENOMATIONS:          return "Envenomations";
1037 #endif
1038     case BOOK_ANNIHILATIONS:          return "Annihilations";
1039     case BOOK_UNLIFE:                 return "Unlife";
1040 #if TAG_MAJOR_VERSION == 34
1041     case BOOK_CONTROL:                return "Control";
1042 #endif
1043     case BOOK_GEOMANCY:               return "Geomancy";
1044     case BOOK_EARTH:                  return "the Earth";
1045 #if TAG_MAJOR_VERSION == 34
1046     case BOOK_WIZARDRY:               return "Wizardry";
1047 #endif
1048     case BOOK_POWER:                  return "Power";
1049     case BOOK_CANTRIPS:               return "Cantrips";
1050     case BOOK_PARTY_TRICKS:           return "Party Tricks";
1051     case BOOK_DEBILITATION:           return "Debilitation";
1052     case BOOK_DRAGON:                 return "the Dragon";
1053     case BOOK_BURGLARY:               return "Burglary";
1054     case BOOK_DREAMS:                 return "Dreams";
1055     case BOOK_ALCHEMY:                return "Alchemy";
1056 #if TAG_MAJOR_VERSION == 34
1057     case BOOK_BEASTS:                 return "Beasts";
1058 #endif
1059     case BOOK_RANDART_LEVEL:          return "Fixed Level";
1060     case BOOK_RANDART_THEME:          return "Fixed Theme";
1061     default:                          return "Bugginess";
1062     }
1063 }
1064
1065 static const char* staff_secondary_string(uint32_t s)
1066 {
1067     static const char* const secondary_strings[] = {
1068         "crooked ", "knobbly ", "weird ", "gnarled ", "thin ", "curved ",
1069         "twisted ", "thick ", "long ", "short ",
1070     };
1071     COMPILE_CHECK(NDSC_STAVE_SEC == ARRAYSZ(secondary_strings));
1072     return secondary_strings[s % ARRAYSZ(secondary_strings)];
1073 }
1074
1075 static const char* staff_primary_string(uint32_t p)
1076 {
1077     static const char* const primary_strings[] = {
1078         "glowing ", "jewelled ", "runed ", "smoking "
1079     };
1080     COMPILE_CHECK(NDSC_STAVE_PRI == ARRAYSZ(primary_strings));
1081     return primary_strings[p % ARRAYSZ(primary_strings)];
1082 }
1083
1084 static const char* staff_type_name(int stafftype)
1085 {
1086     switch ((stave_type)stafftype)
1087     {
1088     case STAFF_FIRE:        return "fire";
1089     case STAFF_COLD:        return "cold";
1090     case STAFF_POISON:      return "poison";
1091     case STAFF_DEATH:       return "death";
1092     case STAFF_CONJURATION: return "conjuration";
1093     case STAFF_AIR:         return "air";
1094     case STAFF_EARTH:       return "earth";
1095     default:                return item_type_removed(OBJ_STAVES, stafftype)
1096                                 ? "removedness"
1097                                 : "bugginess";
1098     }
1099 }
1100
1101 const char *base_type_string(const item_def &item)
1102 {
1103     return base_type_string(item.base_type);
1104 }
1105
1106 const char *base_type_string(object_class_type type)
1107 {
1108     switch (type)
1109     {
1110     case OBJ_WEAPONS: return "weapon";
1111     case OBJ_MISSILES: return "missile";
1112     case OBJ_ARMOUR: return "armour";
1113     case OBJ_WANDS: return "wand";
1114     case OBJ_SCROLLS: return "scroll";
1115     case OBJ_JEWELLERY: return "jewellery";
1116     case OBJ_POTIONS: return "potion";
1117     case OBJ_BOOKS: return "book";
1118     case OBJ_STAVES: return "staff";
1119 #if TAG_MAJOR_VERSION == 34
1120     case OBJ_RODS: return "removed rod";
1121 #endif
1122     case OBJ_ORBS: return "orb";
1123     case OBJ_MISCELLANY: return "miscellaneous";
1124     case OBJ_CORPSES: return "corpse";
1125     case OBJ_GOLD: return "gold";
1126     case OBJ_RUNES: return "rune";
1127     default: return "";
1128     }
1129 }
1130
1131 string sub_type_string(const item_def &item, bool known)
1132 {
1133     const object_class_type type = item.base_type;
1134     const int sub_type = item.sub_type;
1135
1136     switch (type)
1137     {
1138     case OBJ_WEAPONS:  // deliberate fall through, as XXX_prop is a local
1139     case OBJ_MISSILES: // variable to item-prop.cc.
1140     case OBJ_ARMOUR:
1141         return item_base_name(type, sub_type);
1142     case OBJ_WANDS: return _wand_type_name(sub_type);
1143     case OBJ_SCROLLS: return scroll_type_name(sub_type);
1144     case OBJ_JEWELLERY: return jewellery_type_name(sub_type);
1145     case OBJ_POTIONS: return potion_type_name(sub_type);
1146     case OBJ_BOOKS:
1147     {
1148         if (sub_type == BOOK_MANUAL)
1149         {
1150             if (!known)
1151                 return "manual";
1152             string bookname = "manual of ";
1153             bookname += skill_name(static_cast<skill_type>(item.plus));
1154             return bookname;
1155         }
1156         else if (sub_type == BOOK_NECRONOMICON)
1157             return "Necronomicon";
1158         else if (sub_type == BOOK_GRAND_GRIMOIRE)
1159             return "Grand Grimoire";
1160 #if TAG_MAJOR_VERSION == 34
1161         else if (sub_type == BOOK_BUGGY_DESTRUCTION)
1162             return "tome of obsoleteness";
1163 #endif
1164         else if (sub_type == BOOK_YOUNG_POISONERS)
1165             return "Young Poisoner's Handbook";
1166         else if (sub_type == BOOK_FEN)
1167             return "Fen Folio";
1168 #if TAG_MAJOR_VERSION == 34
1169         else if (sub_type == BOOK_AKASHIC_RECORD)
1170             return "Akashic Record";
1171 #endif
1172
1173         return string("book of ") + _book_type_name(sub_type);
1174     }
1175     case OBJ_STAVES: return staff_type_name(static_cast<stave_type>(sub_type));
1176 #if TAG_MAJOR_VERSION == 34
1177     case OBJ_RODS:   return "removed rod";
1178 #endif
1179     case OBJ_MISCELLANY: return misc_type_name(sub_type);
1180     // these repeat as base_type_string
1181     case OBJ_ORBS: return "orb of Zot";
1182     case OBJ_CORPSES: return "corpse";
1183     case OBJ_GOLD: return "gold";
1184     case OBJ_RUNES: return "rune of Zot";
1185     default: return "";
1186     }
1187 }
1188
1189 /**
1190  * What's the name for the weapon used by a given ghost / pan lord?
1191  *
1192  * There's no actual weapon info, just brand, so we have to improvise...
1193  *
1194  * @param brand     The brand_type used by the ghost or pan lord.
1195  * @param mtype     Monster type; determines whether the fake weapon is
1196  *                  described as a `weapon` or a `touch`.
1197  * @return          The name of the ghost's weapon (e.g. "weapon of flaming",
1198  *                  "antimagic weapon"). SPWPN_NORMAL returns "".
1199  */
1200 string ghost_brand_name(brand_type brand, monster_type mtype)
1201 {
1202     if (brand == SPWPN_NORMAL)
1203         return "";
1204     const bool weapon = mtype != MONS_PANDEMONIUM_LORD;
1205     if (weapon)
1206     {
1207         // n.b. vorpal only works if it is adjectival
1208         if (brand_prefers_adj.count(brand))
1209             return make_stringf("%s weapon", brand_type_adj(brand));
1210         else
1211             return make_stringf("weapon of %s", brand_type_name(brand, false));
1212     }
1213     else
1214         return make_stringf("%s touch", brand_type_adj(brand));
1215 }
1216
1217 string ego_type_string(const item_def &item, bool terse)
1218 {
1219     switch (item.base_type)
1220     {
1221     case OBJ_ARMOUR:
1222         return armour_ego_name(item, terse);
1223     case OBJ_WEAPONS:
1224         if (get_weapon_brand(item) != SPWPN_NORMAL)
1225             return weapon_brand_name(item, terse);
1226         else
1227             return "";
1228     case OBJ_MISSILES:
1229         // HACKHACKHACK
1230         if (item.props.exists(DAMNATION_BOLT_KEY))
1231             return "damnation";
1232         return missile_brand_name(item, terse ? MBN_TERSE : MBN_BRAND);
1233     case OBJ_JEWELLERY:
1234         return jewellery_effect_name(item.sub_type, terse);
1235     default:
1236         return "";
1237     }
1238 }
1239
1240 /**
1241  * When naming the given item, should the base name be used?
1242  */
1243 static bool _use_basename(const item_def &item, description_level_type desc,
1244                           bool ident)
1245 {
1246     const bool know_type = ident || item_type_known(item);
1247     return desc == DESC_BASENAME
1248            || desc == DESC_DBNAME && !know_type;
1249 }
1250
1251 /**
1252  * When naming the given item, should identifiable properties be mentioned?
1253  */
1254 static bool _know_any_ident(const item_def &item, description_level_type desc,
1255                             bool ident)
1256 {
1257     return desc != DESC_QUALNAME && desc != DESC_DBNAME
1258            && !_use_basename(item, desc, ident);
1259 }
1260
1261 /**
1262  * When naming the given item, should the specified identifiable property be
1263  * mentioned?
1264  */
1265 static bool _know_ident(const item_def &item, description_level_type desc,
1266                         bool ident, iflags_t ignore_flags,
1267                         item_status_flag_type vprop)
1268 {
1269     return _know_any_ident(item, desc, ident)
1270             && !testbits(ignore_flags, vprop)
1271             && (ident || item_ident(item, vprop));
1272 }
1273
1274 /**
1275  * When naming the given item, should the pluses be mentioned?
1276  */
1277 static bool _know_pluses(const item_def &item, description_level_type desc,
1278                           bool ident, iflags_t ignore_flags)
1279 {
1280     return _know_ident(item, desc, ident, ignore_flags, ISFLAG_KNOW_PLUSES);
1281 }
1282
1283 /**
1284  * When naming the given item, should the brand be mentioned?
1285  */
1286 static bool _know_ego(const item_def &item, description_level_type desc,
1287                          bool ident, iflags_t ignore_flags)
1288 {
1289     return _know_any_ident(item, desc, ident)
1290            && !testbits(ignore_flags, ISFLAG_KNOW_TYPE)
1291            && (ident || item_type_known(item));
1292 }
1293
1294 /**
1295  * The plus-describing prefix to a weapon's name, including trailing space.
1296  */
1297 static string _plus_prefix(const item_def &weap)
1298 {
1299     if (is_unrandom_artefact(weap, UNRAND_WOE))
1300         return "+∞ ";
1301     return make_stringf("%+d ", weap.plus);
1302 }
1303
1304 /**
1305  * Cosmetic text for weapons (e.g. glowing, runed). Includes trailing space,
1306  * if appropriate. (Empty if there is no cosmetic property, or if it's
1307  * marked to be ignored.)
1308  */
1309 static string _cosmetic_text(const item_def &weap, iflags_t ignore_flags)
1310 {
1311     const iflags_t desc = get_equip_desc(weap);
1312     if (testbits(ignore_flags, desc))
1313         return "";
1314
1315     switch (desc)
1316     {
1317         case ISFLAG_RUNED:
1318             return "runed ";
1319         case ISFLAG_GLOWING:
1320             return "glowing ";
1321         default:
1322             return "";
1323     }
1324 }
1325
1326 /**
1327  * Surrounds a given string with the weapon's brand-describing prefix/suffix
1328  * as appropriate.
1329  */
1330 string weapon_brand_desc(const char *body, const item_def &weap,
1331                          bool terse, brand_type override_brand)
1332 {
1333
1334     const string brand_name = weapon_brand_name(weap, terse, override_brand);
1335
1336     if (brand_name.empty())
1337         return body;
1338
1339     if (terse)
1340         return make_stringf("%s (%s)", body, brand_name.c_str());
1341
1342     const brand_type brand = override_brand ? override_brand :
1343                              get_weapon_brand(weap);
1344
1345     if (brand_prefers_adj.count(brand))
1346         return make_stringf("%s %s", brand_type_adj(brand), body);
1347     else if (brand == SPWPN_NORMAL)
1348     {
1349         if (get_equip_desc(weap))
1350             return make_stringf("enchanted %s", body);
1351         else
1352             return body;
1353     }
1354     else
1355         return make_stringf("%s of %s", body, brand_name.c_str());
1356 }
1357
1358 /**
1359  * Build the appropriate name for a given weapon.
1360  *
1361  * @param weap          The weapon in question.
1362  * @param desc          The type of name to provide. (E.g. the name to be used
1363  *                      in database lookups for description, or...)
1364  * @param terse         Whether to provide a terse version of the name for
1365  *                      display in the HUD.
1366  * @param ident         Whether the weapon should be named as if it were
1367  *                      identified.
1368  * @param inscr         Whether an inscription will be added later.
1369  * @param ignore_flags  Identification flags on the weapon to ignore.
1370  *
1371  * @return              A name for the weapon.
1372  *                      TODO: example
1373  */
1374 static string _name_weapon(const item_def &weap, description_level_type desc,
1375                            bool terse, bool ident, bool inscr,
1376                            iflags_t ignore_flags)
1377 {
1378     const bool dbname   = (desc == DESC_DBNAME);
1379     const bool basename = _use_basename(weap, desc, ident);
1380     const bool qualname = (desc == DESC_QUALNAME);
1381
1382     const bool know_pluses = _know_pluses(weap, desc, ident, ignore_flags);
1383     const bool know_ego =    _know_ego(weap, desc, ident, ignore_flags);
1384
1385     const string curse_prefix = !dbname && !terse && weap.cursed() ? "cursed " : "";
1386     const string plus_text = know_pluses ? _plus_prefix(weap) : "";
1387
1388     if (is_artefact(weap) && !dbname)
1389     {
1390         const string long_name = curse_prefix + plus_text
1391                                  + get_artefact_name(weap, ident);
1392
1393         // crop long artefact names when not controlled by webtiles -
1394         // webtiles displays weapon names across multiple lines
1395 #ifdef USE_TILE_WEB
1396         if (!tiles.is_controlled_from_web())
1397 #endif
1398         {
1399             const bool has_inscript = desc != DESC_BASENAME
1400                                    && desc != DESC_DBNAME
1401                                    && inscr;
1402             const string inscription = _item_inscription(weap);
1403
1404             const int total_length = long_name.size()
1405                                      + (has_inscript ? inscription.size() : 0);
1406             const string inv_slot_text = "x) ";
1407             const int max_length = crawl_view.hudsz.x - inv_slot_text.size();
1408             if (!terse || total_length <= max_length)
1409                 return long_name;
1410         }
1411 #ifdef USE_TILE_WEB
1412         else
1413             return long_name;
1414 #endif
1415
1416         // special case: these two shouldn't ever have their base name revealed
1417         // (since showing 'eudaemon blade' is unhelpful in the former case, and
1418         // showing 'broad axe' is misleading in the latter)
1419         // could be a flag, but doesn't seem worthwhile for only two items
1420         if (is_unrandom_artefact(weap, UNRAND_ZEALOT_SWORD)
1421             || is_unrandom_artefact(weap, UNRAND_DEMON_AXE))
1422         {
1423             return long_name;
1424         }
1425
1426         const string short_name
1427             = curse_prefix + plus_text + get_artefact_base_name(weap, true);
1428         return short_name;
1429     }
1430
1431     const bool show_cosmetic = !basename && !qualname && !dbname
1432                                && !know_pluses && !know_ego
1433                                && !terse
1434                                && !(ignore_flags & ISFLAG_COSMETIC_MASK);
1435
1436     const string cosmetic_text
1437         = show_cosmetic ? _cosmetic_text(weap, ignore_flags) : "";
1438     const string base_name = item_base_name(weap);
1439     const string name_with_ego
1440         = know_ego ? weapon_brand_desc(base_name.c_str(), weap, terse)
1441         : base_name;
1442     const string curse_suffix
1443         = weap.cursed() && terse && !dbname && !qualname ? " (curse)" :  "";
1444     return curse_prefix + plus_text + cosmetic_text
1445            + name_with_ego + curse_suffix;
1446 }
1447
1448 // Note that "terse" is only currently used for the "in hand" listing on
1449 // the game screen.
1450 string item_def::name_aux(description_level_type desc, bool terse, bool ident,
1451                           bool with_inscription, iflags_t ignore_flags) const
1452 {
1453     // Shortcuts
1454     const int item_typ   = sub_type;
1455
1456     const bool know_type = ident || item_type_known(*this);
1457
1458     const bool dbname   = (desc == DESC_DBNAME);
1459     const bool basename = _use_basename(*this, desc, ident);
1460     const bool qualname = (desc == DESC_QUALNAME);
1461
1462     const bool know_pluses = _know_pluses(*this, desc, ident, ignore_flags);
1463     const bool know_brand =  _know_ego(*this, desc, ident, ignore_flags);
1464
1465     const bool know_ego = know_brand;
1466
1467     // Display runed/glowing/embroidered etc?
1468     // Only display this if brand is unknown.
1469     const bool show_cosmetic = !know_pluses && !know_brand
1470                                && !basename && !qualname && !dbname
1471                                && !terse
1472                                && !(ignore_flags & ISFLAG_COSMETIC_MASK);
1473
1474     const bool need_plural = !basename && !dbname;
1475
1476     ostringstream buff;
1477
1478     switch (base_type)
1479     {
1480     case OBJ_WEAPONS:
1481         buff << _name_weapon(*this, desc, terse, ident, with_inscription,
1482                              ignore_flags);
1483         break;
1484
1485     case OBJ_MISSILES:
1486     {
1487         special_missile_type msl_brand = get_ammo_brand(*this);
1488
1489         if (!terse && !dbname && !basename)
1490         {
1491             if (props.exists(DAMNATION_BOLT_KEY)) // hack alert
1492                 buff << "damnation ";
1493             else if (_missile_brand_is_prefix(msl_brand)) // see below for postfix brands
1494                 buff << missile_brand_name(*this, MBN_NAME) << ' ';
1495         }
1496
1497         buff << ammo_name(static_cast<missile_type>(item_typ));
1498
1499         if (msl_brand != SPMSL_NORMAL
1500             && !basename && !dbname)
1501         {
1502             if (terse)
1503             {
1504                 if (props.exists(DAMNATION_BOLT_KEY)) // still a hack
1505                     buff << " (damnation)";
1506                 else
1507                     buff << " (" <<  missile_brand_name(*this, MBN_TERSE) << ")";
1508             }
1509             else if (_missile_brand_is_postfix(msl_brand)) // see above for prefix brands
1510                 buff << " of " << missile_brand_name(*this, MBN_NAME);
1511         }
1512
1513         break;
1514     }
1515     case OBJ_ARMOUR:
1516         if (!terse && cursed())
1517             buff << "cursed ";
1518
1519         // If we know enough to know it has *something* ('shiny' etc),
1520         // but we know it has no ego, it must have a plus. (or maybe a curse.)
1521         // If we don't know what the plus is, call it 'enchanted'.
1522         if (!terse && know_ego && get_armour_ego_type(*this) == SPARM_NORMAL &&
1523             !know_pluses && !is_artefact(*this) && get_equip_desc(*this))
1524         {
1525             buff << "enchanted ";
1526         }
1527
1528         // Don't list unenchantable armor as +0.
1529         if (know_pluses && armour_is_enchantable(*this))
1530             buff << make_stringf("%+d ", plus);
1531
1532         if (item_typ == ARM_GLOVES || item_typ == ARM_BOOTS)
1533             buff << "pair of ";
1534
1535         if (is_artefact(*this) && !dbname)
1536         {
1537             buff << get_artefact_name(*this, ident);
1538             break;
1539         }
1540
1541         if (show_cosmetic)
1542         {
1543             switch (get_equip_desc(*this))
1544             {
1545             case ISFLAG_EMBROIDERED_SHINY:
1546                 if (testbits(ignore_flags, ISFLAG_EMBROIDERED_SHINY))
1547                     break;
1548                 if (item_typ == ARM_ROBE || item_typ == ARM_CLOAK
1549                     || item_typ == ARM_GLOVES || item_typ == ARM_BOOTS
1550                     || item_typ == ARM_SCARF
1551                     || get_armour_slot(*this) == EQ_HELMET
1552                        && !is_hard_helmet(*this))
1553                 {
1554                     buff << "embroidered ";
1555                 }
1556                 else if (item_typ != ARM_LEATHER_ARMOUR
1557                          && item_typ != ARM_ANIMAL_SKIN)
1558                 {
1559                     buff << "shiny ";
1560                 }
1561                 else
1562                     buff << "dyed ";
1563                 break;
1564
1565             case ISFLAG_RUNED:
1566                 if (!testbits(ignore_flags, ISFLAG_RUNED))
1567                     buff << "runed ";
1568                 break;
1569
1570             case ISFLAG_GLOWING:
1571                 if (!testbits(ignore_flags, ISFLAG_GLOWING))
1572                     buff << "glowing ";
1573                 break;
1574             }
1575         }
1576
1577         buff << item_base_name(*this);
1578
1579         if (know_ego && !is_artefact(*this))
1580         {
1581             const special_armour_type sparm = get_armour_ego_type(*this);
1582
1583             if (sparm != SPARM_NORMAL)
1584             {
1585                 if (!terse)
1586                     buff << " of ";
1587                 else
1588                     buff << " {";
1589                 buff << armour_ego_name(*this, terse);
1590                 if (terse)
1591                     buff << "}";
1592             }
1593         }
1594
1595         if (cursed() && terse && !qualname)
1596             buff << " (curse)";
1597         break;
1598
1599     case OBJ_WANDS:
1600         if (basename)
1601         {
1602             buff << "wand";
1603             break;
1604         }
1605
1606         if (know_type)
1607             buff << "wand of " << _wand_type_name(item_typ);
1608         else
1609         {
1610             buff << wand_secondary_string(subtype_rnd / NDSC_WAND_PRI)
1611                  << wand_primary_string(subtype_rnd % NDSC_WAND_PRI)
1612                  << " wand";
1613         }
1614
1615         if (dbname)
1616             break;
1617
1618         if (know_type && charges > 0)
1619             buff << " (" << charges << ")";
1620
1621         break;
1622
1623     case OBJ_POTIONS:
1624         if (basename)
1625         {
1626             buff << "potion";
1627             break;
1628         }
1629
1630         if (know_type)
1631             buff << "potion of " << potion_type_name(item_typ);
1632         else
1633         {
1634             const int pqual   = PQUAL(subtype_rnd);
1635             const int pcolour = PCOLOUR(subtype_rnd);
1636
1637             static const char *potion_qualifiers[] =
1638             {
1639                 "",  "bubbling ", "fuming ", "fizzy ", "viscous ", "lumpy ",
1640                 "smoky ", "glowing ", "sedimented ", "metallic ", "murky ",
1641                 "gluggy ", "oily ", "slimy ", "emulsified ",
1642             };
1643             COMPILE_CHECK(ARRAYSZ(potion_qualifiers) == PDQ_NQUALS);
1644
1645             static const char *potion_colours[] =
1646             {
1647 #if TAG_MAJOR_VERSION == 34
1648                 "clear",
1649 #endif
1650                 "blue", "black", "silvery", "cyan", "purple", "orange",
1651                 "inky", "red", "yellow", "green", "brown", "ruby", "white",
1652                 "emerald", "grey", "pink", "coppery", "golden", "dark", "puce",
1653                 "amethyst", "sapphire",
1654             };
1655             COMPILE_CHECK(ARRAYSZ(potion_colours) == PDC_NCOLOURS);
1656
1657             const char *qualifier =
1658                 (pqual < 0 || pqual >= PDQ_NQUALS) ? "bug-filled "
1659                                     : potion_qualifiers[pqual];
1660
1661             const char *clr =  (pcolour < 0 || pcolour >= PDC_NCOLOURS) ?
1662                                    "bogus" : potion_colours[pcolour];
1663
1664             buff << qualifier << clr << " potion";
1665         }
1666         break;
1667
1668 #if TAG_MAJOR_VERSION == 34
1669     case OBJ_FOOD:
1670         buff << "removed food"; break;
1671         break;
1672 #endif
1673
1674     case OBJ_SCROLLS:
1675         buff << "scroll";
1676         if (basename)
1677             break;
1678         else
1679             buff << " ";
1680
1681         if (know_type)
1682             buff << "of " << scroll_type_name(item_typ);
1683         else
1684             buff << "labelled " << make_name(subtype_rnd, MNAME_SCROLL);
1685         break;
1686
1687     case OBJ_JEWELLERY:
1688     {
1689         if (basename)
1690         {
1691             if (jewellery_is_amulet(*this))
1692                 buff << "amulet";
1693             else
1694                 buff << "ring";
1695
1696             break;
1697         }
1698
1699         const bool is_randart = is_artefact(*this);
1700
1701         if (!terse && cursed())
1702             buff << "cursed ";
1703
1704         if (is_randart && !dbname)
1705         {
1706             buff << get_artefact_name(*this, ident);
1707             break;
1708         }
1709
1710         if (know_type)
1711         {
1712             if (know_pluses && jewellery_has_pluses(*this))
1713                 buff << make_stringf("%+d ", plus);
1714
1715             buff << jewellery_type_name(item_typ);
1716         }
1717         else
1718         {
1719             if (jewellery_is_amulet(*this))
1720             {
1721                 buff << amulet_secondary_string(subtype_rnd / NDSC_JEWEL_PRI)
1722                      << amulet_primary_string(subtype_rnd % NDSC_JEWEL_PRI)
1723                      << " amulet";
1724             }
1725             else  // i.e., a ring
1726             {
1727                 buff << ring_secondary_string(subtype_rnd / NDSC_JEWEL_PRI)
1728                      << ring_primary_string(subtype_rnd % NDSC_JEWEL_PRI)
1729                      << " ring";
1730             }
1731         }
1732         if (cursed() && terse && !qualname)
1733             buff << " (curse)";
1734         break;
1735     }
1736     case OBJ_MISCELLANY:
1737     {
1738         if (!dbname && item_typ == MISC_ZIGGURAT && you.zigs_completed > 0)
1739             buff << "+" << you.zigs_completed << " ";
1740
1741         buff << misc_type_name(item_typ);
1742
1743         if (is_xp_evoker(*this) && !dbname && !evoker_charges(sub_type))
1744             buff << " (inert)";
1745         else if (is_xp_evoker(*this) &&
1746                  !dbname && evoker_max_charges(sub_type) > 1)
1747         {
1748             buff << " (" << evoker_charges(sub_type) << "/"
1749                  << evoker_max_charges(sub_type) << ")";
1750         }
1751
1752         break;
1753     }
1754
1755     case OBJ_BOOKS:
1756         if (is_random_artefact(*this) && !dbname && !basename)
1757         {
1758             buff << get_artefact_name(*this, ident);
1759             if (!know_type)
1760                 buff << "book";
1761             break;
1762         }
1763         if (basename)
1764             buff << (item_typ == BOOK_MANUAL ? "manual" : "book");
1765         else if (!know_type)
1766         {
1767             buff << book_secondary_string(rnd)
1768                  << book_primary_string(rnd) << " "
1769                  << (item_typ == BOOK_MANUAL ? "manual" : "book");
1770         }
1771         else
1772             buff << sub_type_string(*this, !dbname);
1773         break;
1774
1775 #if TAG_MAJOR_VERSION == 34
1776     case OBJ_RODS:
1777         buff << "removed rod";
1778         break;
1779 #endif
1780
1781     case OBJ_STAVES:
1782         if (!terse && cursed())
1783             buff << "cursed ";
1784
1785         if (!know_type)
1786         {
1787             if (!basename)
1788             {
1789                 buff << staff_secondary_string(subtype_rnd / NDSC_STAVE_PRI)
1790                      << staff_primary_string(subtype_rnd % NDSC_STAVE_PRI);
1791             }
1792
1793             buff << "staff";
1794         }
1795         else
1796             buff << "staff of " << staff_type_name(item_typ);
1797
1798         if (cursed() && terse && !qualname)
1799             buff << " (curse)";
1800         break;
1801
1802     // rearranged 15 Apr 2000 {dlb}:
1803     case OBJ_ORBS:
1804         buff.str("Orb of Zot");
1805         break;
1806
1807     case OBJ_RUNES:
1808         if (!dbname)
1809             buff << rune_type_name(sub_type) << " ";
1810         buff << "rune of Zot";
1811         break;
1812
1813     case OBJ_GOLD:
1814         buff << "gold piece";
1815         break;
1816
1817     case OBJ_CORPSES:
1818     {
1819         if (dbname && item_typ == CORPSE_SKELETON)
1820             return "decaying skeleton";
1821
1822         monster_flags_t name_flags;
1823         const string _name = get_corpse_name(*this, &name_flags);
1824         const monster_flags_t name_type = name_flags & MF_NAME_MASK;
1825
1826         const bool shaped = starts_with(_name, "shaped ");
1827
1828         if (!_name.empty() && name_type == MF_NAME_ADJECTIVE)
1829             buff << _name << " ";
1830
1831         if ((name_flags & MF_NAME_SPECIES) && name_type == MF_NAME_REPLACE)
1832             buff << _name << " ";
1833         else if (!dbname && !starts_with(_name, "the "))
1834         {
1835             const monster_type mc = mon_type;
1836             if (!(mons_is_unique(mc) && mons_species(mc) == mc))
1837                 buff << mons_type_name(mc, DESC_PLAIN) << ' ';
1838
1839             if (!_name.empty() && shaped)
1840                 buff << _name << ' ';
1841         }
1842
1843         if (item_typ == CORPSE_BODY)
1844             buff << "corpse";
1845         else if (item_typ == CORPSE_SKELETON)
1846             buff << "skeleton";
1847         else
1848             buff << "corpse bug";
1849
1850         if (!_name.empty() && !shaped && name_type != MF_NAME_ADJECTIVE
1851             && !(name_flags & MF_NAME_SPECIES) && name_type != MF_NAME_SUFFIX
1852             && !dbname)
1853         {
1854             buff << " of " << _name;
1855         }
1856         break;
1857     }
1858
1859     default:
1860         buff << "!";
1861     }
1862
1863     // One plural to rule them all.
1864     if (need_plural && quantity > 1 && !basename && !qualname)
1865         buff.str(pluralise(buff.str()));
1866
1867     // debugging output -- oops, I probably block it above ... dang! {dlb}
1868     if (buff.str().length() < 3)
1869     {
1870         buff << "bad item (cl:" << static_cast<int>(base_type)
1871              << ",ty:" << item_typ << ",pl:" << plus
1872              << ",pl2:" << plus2 << ",sp:" << special
1873              << ",qu:" << quantity << ")";
1874     }
1875
1876     return buff.str();
1877 }
1878
1879 // WARNING: You can break save compatibility if you edit this without
1880 // amending tags.cc to properly marshall the change.
1881 bool item_type_has_ids(object_class_type base_type)
1882 {
1883     COMPILE_CHECK(NUM_WEAPONS    < MAX_SUBTYPES);
1884     COMPILE_CHECK(NUM_MISSILES   < MAX_SUBTYPES);
1885     COMPILE_CHECK(NUM_ARMOURS    < MAX_SUBTYPES);
1886     COMPILE_CHECK(NUM_WANDS      < MAX_SUBTYPES);
1887     COMPILE_CHECK(NUM_SCROLLS    < MAX_SUBTYPES);
1888     COMPILE_CHECK(NUM_JEWELLERY  < MAX_SUBTYPES);
1889     COMPILE_CHECK(NUM_POTIONS    < MAX_SUBTYPES);
1890     COMPILE_CHECK(NUM_BOOKS      < MAX_SUBTYPES);
1891     COMPILE_CHECK(NUM_STAVES     < MAX_SUBTYPES);
1892     COMPILE_CHECK(NUM_MISCELLANY < MAX_SUBTYPES);
1893 #if TAG_MAJOR_VERSION == 34
1894     COMPILE_CHECK(NUM_RODS       < MAX_SUBTYPES);
1895     COMPILE_CHECK(NUM_FOODS      < MAX_SUBTYPES);
1896 #endif
1897
1898     return base_type == OBJ_WANDS || base_type == OBJ_SCROLLS
1899         || base_type == OBJ_JEWELLERY || base_type == OBJ_POTIONS
1900         || base_type == OBJ_STAVES || base_type == OBJ_BOOKS;
1901 }
1902
1903 bool item_brand_known(const item_def& item)
1904 {
1905     return item_ident(item, ISFLAG_KNOW_TYPE)
1906            || is_artefact(item)
1907            && artefact_known_property(item, ARTP_BRAND);
1908 }
1909
1910 bool item_type_known(const item_def& item)
1911 {
1912     if (item_ident(item, ISFLAG_KNOW_TYPE))
1913         return true;
1914
1915     // Artefacts have different descriptions from other items,
1916     // so we can't use general item knowledge for them.
1917     if (is_artefact(item))
1918         return false;
1919
1920     if (item.base_type == OBJ_MISSILES)
1921         return true;
1922
1923     if (item.base_type == OBJ_MISCELLANY)
1924         return true;
1925
1926 #if TAG_MAJOR_VERSION == 34
1927     if (item.is_type(OBJ_BOOKS, BOOK_BUGGY_DESTRUCTION))
1928         return true;
1929 #endif
1930
1931     if (item.is_type(OBJ_BOOKS, BOOK_MANUAL))
1932         return false;
1933
1934     if (!item_type_has_ids(item.base_type))
1935         return false;
1936     return you.type_ids[item.base_type][item.sub_type];
1937 }
1938
1939 bool item_type_unknown(const item_def& item)
1940 {
1941     if (item_type_known(item))
1942         return false;
1943
1944     if (is_artefact(item))
1945         return true;
1946
1947     return item_type_has_ids(item.base_type);
1948 }
1949
1950 bool item_type_known(const object_class_type base_type, const int sub_type)
1951 {
1952     if (!item_type_has_ids(base_type))
1953         return false;
1954     return you.type_ids[base_type][sub_type];
1955 }
1956
1957 bool set_ident_type(item_def &item, bool identify)
1958 {
1959     if (is_artefact(item) || crawl_state.game_is_arena())
1960         return false;
1961
1962     if (!set_ident_type(item.base_type, item.sub_type, identify))
1963         return false;
1964
1965     if (in_inventory(item))
1966     {
1967         shopping_list.cull_identical_items(item);
1968         if (identify)
1969             item_skills(item, you.skills_to_show);
1970     }
1971
1972     if (identify && notes_are_active()
1973         && is_interesting_item(item)
1974         && !(item.flags & (ISFLAG_NOTED_ID | ISFLAG_NOTED_GET)))
1975     {
1976         // Make a note of it.
1977         take_note(Note(NOTE_ID_ITEM, 0, 0, item.name(DESC_A),
1978                        origin_desc(item)));
1979
1980         // Sometimes (e.g. shops) you can ID an item before you get it;
1981         // don't note twice in those cases.
1982         item.flags |= (ISFLAG_NOTED_ID | ISFLAG_NOTED_GET);
1983     }
1984
1985     return true;
1986 }
1987
1988 bool set_ident_type(object_class_type basetype, int subtype, bool identify)
1989 {
1990     if (!item_type_has_ids(basetype))
1991         return false;
1992
1993     if (you.type_ids[basetype][subtype] == identify)
1994         return false;
1995
1996     you.type_ids[basetype][subtype] = identify;
1997     request_autoinscribe();
1998
1999     // Our item knowledge changed in a way that could possibly affect shop
2000     // prices.
2001     shopping_list.item_type_identified(basetype, subtype);
2002
2003     // We identified something, maybe we identified other things by process of
2004     // elimination.
2005     if (identify && !(you.pending_revival || crawl_state.updating_scores))
2006         _maybe_identify_pack_item();
2007
2008     return true;
2009 }
2010
2011 void pack_item_identify_message(int base_type, int sub_type)
2012 {
2013     for (const auto &item : you.inv)
2014         if (item.defined() && item.is_type(base_type, sub_type))
2015             mprf_nocap("%s", item.name(DESC_INVENTORY_EQUIP).c_str());
2016 }
2017
2018 bool get_ident_type(const item_def &item)
2019 {
2020     if (is_artefact(item))
2021         return false;
2022
2023     return get_ident_type(item.base_type, item.sub_type);
2024 }
2025
2026 bool get_ident_type(object_class_type basetype, int subtype)
2027 {
2028     if (!item_type_has_ids(basetype))
2029         return false;
2030     ASSERT(subtype < MAX_SUBTYPES);
2031     return you.type_ids[basetype][subtype];
2032 }
2033
2034 static MenuEntry* _fixup_runeorb_entry(MenuEntry* me)
2035 {
2036     auto entry = static_cast<InvEntry*>(me);
2037     ASSERT(entry);
2038
2039     if (entry->item->base_type == OBJ_RUNES)
2040     {
2041         auto rune = static_cast<rune_type>(entry->item->sub_type);
2042         colour_t colour;
2043         // Make Gloorx's rune more distinguishable from uncollected runes.
2044         if (you.runes[rune])
2045         {
2046             colour = (rune == RUNE_GLOORX_VLOQ) ? colour_t{LIGHTGREY}
2047                                                 : rune_colour(rune);
2048         }
2049         else
2050             colour = DARKGREY;
2051
2052         string text = "<";
2053         text += colour_to_str(colour);
2054         text += ">";
2055         text += rune_type_name(rune);
2056         text += " rune of Zot";
2057         if (!you.runes[rune])
2058         {
2059             text += " (";
2060             text += branches[rune_location(rune)].longname;
2061             text += ")";
2062         }
2063         text += "</";
2064         text += colour_to_str(colour);
2065         text += ">";
2066         entry->text = text;
2067     }
2068     else if (entry->item->is_type(OBJ_ORBS, ORB_ZOT))
2069     {
2070         if (player_has_orb())
2071             entry->text = "<magenta>The Orb of Zot</magenta>";
2072         else
2073         {
2074             entry->text = "<darkgrey>The Orb of Zot"
2075                           " (the Realm of Zot)</darkgrey>";
2076         }
2077     }
2078
2079     return entry;
2080 }
2081
2082 void display_runes()
2083 {
2084     auto col = runes_in_pack() < ZOT_ENTRY_RUNES ?  "lightgrey" :
2085                runes_in_pack() < you.obtainable_runes ? "green" :
2086                                                    "lightgreen";
2087
2088     auto title = make_stringf("<white>Runes of Zot (</white>"
2089                               "<%s>%d</%s><white> collected) & Orbs of Power</white>",
2090                               col, runes_in_pack(), col);
2091
2092     InvMenu menu(MF_NOSELECT | MF_ALLOW_FORMATTING);
2093
2094     menu.set_title(title);
2095
2096     vector<item_def> items;
2097
2098     if (!crawl_state.game_is_sprint())
2099     {
2100         // Add the runes in order of challenge (semi-arbitrary).
2101         for (branch_iterator it(branch_iterator_type::danger); it; ++it)
2102         {
2103             const branch_type br = it->id;
2104             if (!connected_branch_can_exist(br))
2105                 continue;
2106
2107             for (auto rune : branches[br].runes)
2108             {
2109                 item_def item;
2110                 item.base_type = OBJ_RUNES;
2111                 item.sub_type = rune;
2112                 item.quantity = you.runes[rune] ? 1 : 0;
2113                 item_colour(item);
2114                 items.push_back(item);
2115             }
2116         }
2117     }
2118     else
2119     {
2120         // We don't know what runes are accessible in the sprint, so just show
2121         // the ones you have. We can't iterate over branches as above since the
2122         // elven rune and mossy rune may exist in sprint.
2123         for (int i = 0; i < NUM_RUNE_TYPES; ++i)
2124         {
2125             if (you.runes[i])
2126             {
2127                 item_def item;
2128                 item.base_type = OBJ_RUNES;
2129                 item.sub_type = i;
2130                 item.quantity = 1;
2131                 item_colour(item);
2132                 items.push_back(item);
2133             }
2134         }
2135     }
2136     item_def item;
2137     item.base_type = OBJ_ORBS;
2138     item.sub_type = ORB_ZOT;
2139     item.quantity = player_has_orb() ? 1 : 0;
2140     items.push_back(item);
2141
2142     // We've sorted this vector already, so disable menu sorting. Maybe we
2143     // could a menu entry comparator and modify InvMenu::load_items() to allow
2144     // passing this in instead of doing a sort ahead of time.
2145     menu.load_items(items, _fixup_runeorb_entry, 0, false);
2146
2147     menu.show();
2148 }
2149
2150 // Seed ranges for _random_consonant_set: (B)eginning and one-past-the-(E)nd
2151 // of the (B)eginning, (E)nding, and (M)iddle cluster ranges.
2152 const size_t RCS_BB = 0;
2153 const size_t RCS_EB = 27;
2154 const size_t RCS_BE = 14;
2155 const size_t RCS_EE = 56;
2156 const size_t RCS_BM = 0;
2157 const size_t RCS_EM = 67;
2158 const size_t RCS_END = RCS_EM;
2159
2160 #define ITEMNAME_SIZE 200
2161 /**
2162  * Make a random name from the given seed.
2163  *
2164  * Used for: Pandemonium demonlords, shopkeepers, scrolls, random artefacts.
2165  *
2166  * This function is insane, but that might be useful.
2167  *
2168  * @param seed      The seed to generate the name from.
2169  *                  The same seed will always generate the same name.
2170  *                  By default a random number from the current RNG.
2171  * @param name_type The type of name to be generated.
2172  *                  If MNAME_SCROLL, increase length by 6 and force to allcaps.
2173  *                  If MNAME_JIYVA, start with J, do not generate spaces,
2174  *                  recurse instead of ploggifying, and cap length at 8.
2175  *                  Otherwise, no special behaviour.
2176  * @return          A randomly generated name.
2177  *                  E.g. "Joiduir", "Jays Fya", ZEFOKY WECZYXE,
2178  *                  THE GIAGGOSTUONO, etc.
2179  */
2180 string make_name(uint32_t seed, makename_type name_type)
2181 {
2182     // use the seed to select sequence, rather than seed per se. This is
2183     // because it is not important that the sequence be randomly distributed
2184     // in uint64_t.
2185     rng::subgenerator subgen(you.game_seed, static_cast<uint64_t>(seed));
2186
2187     string name;
2188
2189     bool has_space  = false; // Keep track of whether the name contains a space.
2190
2191     size_t len = 3;
2192     len += random2(5);
2193     len += (random2(5) == 0) ? random2(6) : 1;
2194
2195     if (name_type == MNAME_SCROLL)   // scrolls have longer names
2196         len += 6;
2197
2198     const size_t maxlen = name_type == MNAME_JIYVA ? 8 : SIZE_MAX;
2199     len = min(len, maxlen);
2200
2201     ASSERT_RANGE(len, 1, ITEMNAME_SIZE + 1);
2202
2203     static const int MAX_ITERS = 150;
2204     for (int iters = 0; iters < MAX_ITERS && name.length() < len; ++iters)
2205     {
2206         const char prev_char = name.length() ? name[name.length() - 1]
2207                                               : '\0';
2208         const char penult_char = name.length() > 1 ? name[name.length() - 2]
2209                                                     : '\0';
2210         if (name.empty() && name_type == MNAME_JIYVA)
2211         {
2212             // Start the name with a predefined letter.
2213             name += 'j';
2214         }
2215         else if (name.empty() || prev_char == ' ')
2216         {
2217             // Start the word with any letter.
2218             name += 'a' + random2(26);
2219         }
2220         else if (!has_space && name_type != MNAME_JIYVA
2221                  && name.length() > 5 && name.length() < len - 4
2222                  && random2(5) != 0) // 4/5 chance
2223         {
2224              // Hand out a space.
2225             name += ' ';
2226         }
2227         else if (name.length()
2228                  && (_is_consonant(prev_char)
2229                      || (name.length() > 1
2230                          && !_is_consonant(prev_char)
2231                          && _is_consonant(penult_char)
2232                          && random2(5) <= 1))) // 2/5
2233         {
2234             // Place a vowel.
2235             const char vowel = _random_vowel();
2236
2237             if (vowel == ' ')
2238             {
2239                 if (len < 7
2240                          || name.length() <= 2 || name.length() >= len - 3
2241                          || prev_char == ' ' || penult_char == ' '
2242                          || name_type == MNAME_JIYVA
2243                          || name.length() > 2
2244                             && _is_consonant(prev_char)
2245                             && _is_consonant(penult_char))
2246                 {
2247                     // Replace the space with something else if ...
2248                     // * the name is really short
2249                     // * we're close to the start/end of the name
2250                     // * we just got a space
2251                     // * we're generating a jiyva name, or
2252                     // * the last two letters were consonants
2253                     continue;
2254                 }
2255             }
2256             else if (name.length() > 1
2257                      && vowel == prev_char
2258                      && (vowel == 'y' || vowel == 'i'
2259                          || random2(5) <= 1))
2260             {
2261                 // Replace the vowel with something else if the previous
2262                 // letter was the same, and it's a 'y', 'i' or with 2/5 chance.
2263                 continue;
2264             }
2265
2266             name += vowel;
2267         }
2268         else // We want a consonant.
2269         {
2270             // Are we at start or end of the (sub) name?
2271             const bool beg = (name.empty() || prev_char == ' ');
2272             const bool end = (name.length() >= len - 2);
2273
2274             // Use one of number of predefined letter combinations.
2275             if ((len > 3 || !name.empty())
2276                 && random2(7) <= 1 // 2/7 chance
2277                 && (!beg || !end))
2278             {
2279                 const int first = (beg ? RCS_BB : (end ? RCS_BE : RCS_BM));
2280                 const int last  = (beg ? RCS_EB : (end ? RCS_EE : RCS_EM));
2281
2282                 const int range = last - first;
2283
2284                 const int cons_seed = random2(range) + first;
2285
2286                 const string consonant_set = _random_consonant_set(cons_seed);
2287
2288                 ASSERT(consonant_set.size() > 1);
2289                 len += consonant_set.size() - 2; // triples increase len
2290                 name += consonant_set;
2291             }
2292             else // Place a single letter instead.
2293             {
2294                 // Pick a random consonant.
2295                 name += _random_cons();
2296             }
2297         }
2298
2299         if (name[name.length() - 1] == ' ')
2300         {
2301             ASSERT(name_type != MNAME_JIYVA);
2302             has_space = true;
2303         }
2304     }
2305
2306     // Catch early exit and try to give a final letter.
2307     const char last_char = name[name.length() - 1];
2308     if (!name.empty()
2309         && last_char != ' '
2310         && last_char != 'y'
2311         && !_is_consonant(name[name.length() - 1])
2312         && (name.length() < len    // early exit
2313             || (len < 8
2314                 && random2(3) != 0))) // 2/3 chance for other short names
2315     {
2316         // Specifically, add a consonant.
2317         name += _random_cons();
2318     }
2319
2320     if (maxlen != SIZE_MAX)
2321         name = chop_string(name, maxlen);
2322     trim_string_right(name);
2323
2324     // Fallback if the name was too short.
2325     if (name.length() < 4)
2326     {
2327         // convolute & recurse
2328         if (name_type == MNAME_JIYVA)
2329             return make_name(rng::get_uint32(), MNAME_JIYVA);
2330
2331         name = "plog";
2332     }
2333
2334     string uppercased_name;
2335     for (size_t i = 0; i < name.length(); i++)
2336     {
2337         if (name_type == MNAME_JIYVA)
2338             ASSERT(name[i] != ' ');
2339
2340         if (name_type == MNAME_SCROLL || i == 0 || name[i - 1] == ' ')
2341             uppercased_name += toupper_safe(name[i]);
2342         else
2343             uppercased_name += name[i];
2344     }
2345
2346     return uppercased_name;
2347 }
2348 #undef ITEMNAME_SIZE
2349
2350 /**
2351  * Is the given character a lower-case ascii consonant?
2352  *
2353  * For our purposes, y is not a consonant.
2354  */
2355 static bool _is_consonant(char let)
2356 {
2357     static const set<char> all_consonants = { 'b', 'c', 'd', 'f', 'g',
2358                                               'h', 'j', 'k', 'l', 'm',
2359                                               'n', 'p', 'q', 'r', 's',
2360                                               't', 'v', 'w', 'x', 'z' };
2361     return all_consonants.count(let);
2362 }
2363
2364 // Returns a random vowel (a, e, i, o, u with equal probability) or space
2365 // or 'y' with lower chances.
2366 static char _random_vowel()
2367 {
2368     static const char vowels[] = "aeiouaeiouaeiouy  ";
2369     return vowels[random2(sizeof(vowels) - 1)];
2370 }
2371
2372 // Returns a random consonant with not quite equal probability.
2373 // Does not include 'y'.
2374 static char _random_cons()
2375 {
2376     static const char consonants[] = "bcdfghjklmnpqrstvwxzcdfghlmnrstlmnrst";
2377     return consonants[random2(sizeof(consonants) - 1)];
2378 }
2379
2380 /**
2381  * Choose a random consonant tuple/triple, based on the given seed.
2382  *
2383  * @param seed  The index into the consonant array; different seed ranges are
2384  *              expected to correspond with the place in the name being
2385  *              generated where the consonants should be inserted.
2386  * @return      A random length 2 or 3 consonant set; e.g. "kl", "str", etc.
2387  *              If the seed is out of bounds, return "";
2388  */
2389 static string _random_consonant_set(size_t c)
2390 {
2391     // Pick a random combination of consonants from the set below.
2392     //   begin  -> [RCS_BB, RCS_EB) = [ 0, 27)
2393     //   middle -> [RCS_BM, RCS_EM) = [ 0, 67)
2394     //   end    -> [RCS_BE, RCS_EE) = [14, 56)
2395
2396     static const string consonant_sets[] = {
2397         // 0-13: start, middle
2398         "kl", "gr", "cl", "cr", "fr",
2399         "pr", "tr", "tw", "br", "pl",
2400         "bl", "str", "shr", "thr",
2401         // 14-26: start, middle, end
2402         "sm", "sh", "ch", "th", "ph",
2403         "pn", "kh", "gh", "mn", "ps",
2404         "st", "sk", "sch",
2405         // 27-55: middle, end
2406         "ts", "cs", "xt", "nt", "ll",
2407         "rr", "ss", "wk", "wn", "ng",
2408         "cw", "mp", "ck", "nk", "dd",
2409         "tt", "bb", "pp", "nn", "mm",
2410         "kk", "gg", "ff", "pt", "tz",
2411         "dgh", "rgh", "rph", "rch",
2412         // 56-66: middle only
2413         "cz", "xk", "zx", "xz", "cv",
2414         "vv", "nl", "rh", "dw", "nw",
2415         "khl",
2416     };
2417     COMPILE_CHECK(ARRAYSZ(consonant_sets) == RCS_END);
2418
2419     ASSERT_RANGE(c, 0, ARRAYSZ(consonant_sets));
2420
2421     return consonant_sets[c];
2422 }
2423
2424 /**
2425  * Write all possible scroll names to the given file.
2426  */
2427 static void _test_scroll_names(const string& fname)
2428 {
2429     FILE *f = fopen(fname.c_str(), "w");
2430     if (!f)
2431         sysfail("can't write test output");
2432
2433     string longest;
2434     for (int i = 0; i < 151; i++)
2435     {
2436         for (int j = 0; j < 151; j++)
2437         {
2438             const int seed = i | (j << 8) | (OBJ_SCROLLS << 16);
2439             const string name = make_name(seed, MNAME_SCROLL);
2440             if (name.length() > longest.length())
2441                 longest = name;
2442             fprintf(f, "%s\n", name.c_str());
2443         }
2444     }
2445
2446     fprintf(f, "\nLongest: %s (%d)\n", longest.c_str(), (int)longest.length());
2447
2448     fclose(f);
2449 }
2450
2451 /**
2452  * Write one million random Jiyva names to the given file.
2453  */
2454 static void _test_jiyva_names(const string& fname)
2455 {
2456     FILE *f = fopen(fname.c_str(), "w");
2457     if (!f)
2458         sysfail("can't write test output");
2459
2460     string longest;
2461     rng::seed(27);
2462     for (int i = 0; i < 1000000; i++)
2463     {
2464         const string name = make_name(rng::get_uint32(), MNAME_JIYVA);
2465         ASSERT(name[0] == 'J');
2466         if (name.length() > longest.length())
2467             longest = name;
2468         fprintf(f, "%s\n", name.c_str());
2469     }
2470
2471     fprintf(f, "\nLongest: %s (%d)\n", longest.c_str(), (int)longest.length());
2472
2473     fclose(f);
2474 }
2475
2476 /**
2477  * Test make_name().
2478  *
2479  * Currently just a stress test iterating over all possible scroll names.
2480  */
2481 void make_name_tests()
2482 {
2483     _test_jiyva_names("jiyva_names.out");
2484     _test_scroll_names("scroll_names.out");
2485
2486     rng::seed(27);
2487     for (int i = 0; i < 1000000; ++i)
2488         make_name();
2489 }
2490
2491 bool is_interesting_item(const item_def& item)
2492 {
2493     if (fully_identified(item) && is_artefact(item))
2494         return true;
2495
2496     const string iname = item_prefix(item, false) + " " + item.name(DESC_PLAIN);
2497     for (const text_pattern &pat : Options.note_items)
2498         if (pat.matches(iname))
2499             return true;
2500
2501     return false;
2502 }
2503
2504 /**
2505  * Is an item a potentially life-saving consumable in emergency situations?
2506  * Unlike similar functions, this one never takes temporary conditions into
2507  * account. It does, however, take religion and mutations into account.
2508  * Permanently unusable items are in general not considered emergency items.
2509  *
2510  * @param item The item being queried.
2511  * @return True if the item is known to be an emergency item.
2512  */
2513 bool is_emergency_item(const item_def &item)
2514 {
2515     if (!item_type_known(item))
2516         return false;
2517
2518     switch (item.base_type)
2519     {
2520     case OBJ_SCROLLS:
2521         switch (item.sub_type)
2522         {
2523         case SCR_TELEPORTATION:
2524         case SCR_BLINKING:
2525             return you.species != SP_FORMICID;
2526         case SCR_FEAR:
2527         case SCR_FOG:
2528             return true;
2529         default:
2530             return false;
2531         }
2532     case OBJ_POTIONS:
2533         if (you.species == SP_MUMMY)
2534             return false;
2535
2536         switch (item.sub_type)
2537         {
2538         case POT_HASTE:
2539             return !have_passive(passive_t::no_haste)
2540                 && you.species != SP_FORMICID;
2541         case POT_HEAL_WOUNDS:
2542             return you.can_potion_heal();
2543         case POT_CURING:
2544         case POT_RESISTANCE:
2545         case POT_MAGIC:
2546             return true;
2547         default:
2548             return false;
2549         }
2550     default:
2551         return false;
2552     }
2553 }
2554
2555 /**
2556  * Is an item a particularly good consumable? Unlike similar functions,
2557  * this one never takes temporary conditions into account. Permanently
2558  * unusable items are in general not considered good.
2559  *
2560  * @param item The item being queried.
2561  * @return True if the item is known to be good.
2562  */
2563 bool is_good_item(const item_def &item)
2564 {
2565     if (!item_type_known(item))
2566         return false;
2567
2568     if (is_emergency_item(item))
2569         return true;
2570
2571     switch (item.base_type)
2572     {
2573     case OBJ_SCROLLS:
2574         return item.sub_type == SCR_ACQUIREMENT;
2575     case OBJ_POTIONS:
2576         if (you.species == SP_MUMMY)
2577             return false;
2578         switch (item.sub_type)
2579         {
2580         case POT_EXPERIENCE:
2581             return true;
2582         default:
2583             return false;
2584         CASE_REMOVED_POTIONS(item.sub_type)
2585         }
2586     default:
2587         return false;
2588     }
2589 }
2590
2591 /**
2592  * Is an item strictly harmful?
2593  *
2594  * @param item The item being queried.
2595  * @return True if the item is known to have only harmful effects.
2596  */
2597 bool is_bad_item(const item_def &item)
2598 {
2599     if (!item_type_known(item))
2600         return false;
2601
2602     switch (item.base_type)
2603     {
2604     case OBJ_SCROLLS:
2605         switch (item.sub_type)
2606         {
2607 #if TAG_MAJOR_VERSION == 34
2608         case SCR_CURSE_ARMOUR:
2609         case SCR_CURSE_WEAPON:
2610             if (you.species == SP_FELID)
2611                 return false;
2612         case SCR_CURSE_JEWELLERY:
2613             return !have_passive(passive_t::want_curses);
2614 #endif
2615         case SCR_NOISE:
2616             return true;
2617         default:
2618             return false;
2619         }
2620     case OBJ_POTIONS:
2621         // Can't be bad if you can't use them.
2622         if (you.species == SP_MUMMY)
2623             return false;
2624
2625         switch (item.sub_type)
2626         {
2627         case POT_DEGENERATION:
2628             return true;
2629         default:
2630             return false;
2631         CASE_REMOVED_POTIONS(item.sub_type);
2632         }
2633     case OBJ_JEWELLERY:
2634         // Potentially useful. TODO: check the properties.
2635         if (is_artefact(item))
2636             return false;
2637
2638         switch (item.sub_type)
2639         {
2640         case RING_EVASION:
2641         case RING_PROTECTION:
2642         case RING_STRENGTH:
2643         case RING_DEXTERITY:
2644         case RING_INTELLIGENCE:
2645         case RING_SLAYING:
2646             return item_ident(item, ISFLAG_KNOW_PLUSES) && item.plus <= 0;
2647         default:
2648             return false;
2649         }
2650
2651     default:
2652         return false;
2653     }
2654 }
2655
2656 /**
2657  * Is an item dangerous but potentially worthwhile?
2658  *
2659  * @param item The item being queried.
2660  * @param temp Should temporary conditions such as transformations and
2661  *             vampire state be taken into account?  Religion (but
2662  *             not its absence) is considered to be permanent here.
2663  * @return True if using the item is known to be risky but occasionally
2664  *         worthwhile.
2665  */
2666 bool is_dangerous_item(const item_def &item, bool temp)
2667 {
2668     if (!item_type_known(item))
2669         return false;
2670
2671     // useless items can hardly be dangerous.
2672     if (is_useless_item(item, temp))
2673         return false;
2674
2675     switch (item.base_type)
2676     {
2677     case OBJ_SCROLLS:
2678         switch (item.sub_type)
2679         {
2680         case SCR_IMMOLATION:
2681         case SCR_VULNERABILITY:
2682             return true;
2683         case SCR_TORMENT:
2684             return !you.get_mutation_level(MUT_TORMENT_RESISTANCE)
2685                    || !temp && you.species == SP_VAMPIRE;
2686         case SCR_HOLY_WORD:
2687             return you.undead_or_demonic();
2688         default:
2689             return false;
2690         }
2691
2692     case OBJ_POTIONS:
2693         switch (item.sub_type)
2694         {
2695         case POT_MUTATION:
2696             if (have_passive(passive_t::cleanse_mut_potions))
2697                 return false;
2698             // intentional fallthrough
2699         case POT_LIGNIFY:
2700         case POT_ATTRACTION:
2701             return true;
2702         default:
2703             return false;
2704         }
2705
2706     case OBJ_MISCELLANY:
2707         // Tremorstones will blow you right up.
2708         return item.sub_type == MISC_TIN_OF_TREMORSTONES;
2709
2710     case OBJ_ARMOUR:
2711         if (you.get_mutation_level(MUT_NO_LOVE)
2712             && is_unrandom_artefact(item, UNRAND_RATSKIN_CLOAK))
2713         {
2714             // some people don't like being randomly attacked by rats.
2715             // weird but what can you do.
2716             return true;
2717         }
2718
2719         // Tilting at windmills can be dangerous.
2720         return get_armour_ego_type(item) == SPARM_RAMPAGING;
2721
2722     default:
2723         return false;
2724     }
2725 }
2726
2727 static bool _invisibility_is_useless(const bool temp)
2728 {
2729     // If you're Corona'd or a TSO-ite, this is always useless.
2730     return temp ? you.backlit()
2731                 : you.haloed() && will_have_passive(passive_t::halo);
2732 }
2733
2734 /**
2735  * Is an item (more or less) useless to the player? Uselessness includes
2736  * but is not limited to situations such as:
2737  * \li The item cannot be used.
2738  * \li Using the item would have no effect.
2739  * \li Using the item would have purely negative effects (<tt>is_bad_item</tt>).
2740  * \li Using the item is expected to produce no benefit for a player of their
2741  *     religious standing. For example, magic enhancers for Trog worshippers
2742  *     are "useless", even if the player knows a spell and therefore could
2743  *     benefit.
2744  *
2745  * @param item The item being queried.
2746  * @param temp Should temporary conditions such as transformations and
2747  *             vampire state be taken into account? Religion (but
2748  *             not its absence) is considered to be permanent here.
2749  * @param ident Should uselessness be checked as if the item were already
2750  *              identified?
2751  * @return True if the item is known to be useless.
2752  */
2753 bool is_useless_item(const item_def &item, bool temp, bool ident)
2754 {
2755     // During game startup, no item is useless. If someone re-glyphs an item
2756     // based on its uselessness, the glyph-to-item cache will use the useless
2757     // value even if your god or species can make use of it.
2758     if (you.species == SP_UNKNOWN)
2759         return false;
2760
2761     switch (item.base_type)
2762     {
2763     case OBJ_WEAPONS:
2764         if (you.species == SP_FELID)
2765             return true;
2766
2767         if (!you.could_wield(item, true, !temp)
2768             && !is_throwable(&you, item))
2769         {
2770             // Weapon is too large (or small) to be wielded and cannot
2771             // be thrown either.
2772             return true;
2773         }
2774
2775         if (you.undead_or_demonic() && is_holy_item(item, false))
2776         {
2777             if (!temp && you.form == transformation::lich
2778                 && you.species != SP_DEMONSPAWN)
2779             {
2780                 return false;
2781             }
2782             return true;
2783         }
2784
2785         return false;
2786
2787     case OBJ_MISSILES:
2788         if ((you.has_spell(SPELL_SANDBLAST)
2789                 || !you.num_turns && you.char_class == JOB_EARTH_ELEMENTALIST)
2790                 && item.sub_type == MI_STONE)
2791         {
2792             return false;
2793         }
2794
2795         // Save for the above spells, all missiles are useless for felids.
2796         if (you.species == SP_FELID)
2797             return true;
2798
2799         // These are the same checks as in is_throwable(), except that
2800         // we don't take launchers into account.
2801         switch (item.sub_type)
2802         {
2803         case MI_LARGE_ROCK:
2804             return !you.can_throw_large_rocks();
2805         case MI_JAVELIN:
2806             return you.body_size(PSIZE_BODY, !temp) < SIZE_MEDIUM
2807                    && !you.can_throw_large_rocks();
2808         }
2809
2810         return false;
2811
2812     case OBJ_ARMOUR:
2813         if (!can_wear_armour(item, false, true))
2814             return true;
2815
2816         if (is_shield(item) && you.get_mutation_level(MUT_MISSING_HAND))
2817             return true;
2818
2819         if (is_artefact(item))
2820             return false;
2821
2822         if (item.sub_type == ARM_SCARF && (ident || item_type_known(item)))
2823         {
2824             special_armour_type ego = get_armour_ego_type(item);
2825             switch (ego)
2826             {
2827             case SPARM_SPIRIT_SHIELD:
2828                 return you.spirit_shield(false, false);
2829             case SPARM_REPULSION:
2830                 return temp && have_passive(passive_t::upgraded_storm_shield)
2831                        || you.get_mutation_level(MUT_DISTORTION_FIELD) == 3;
2832             default:
2833                 return false;
2834             }
2835         }
2836         return false;
2837
2838     case OBJ_SCROLLS:
2839         if (temp && silenced(you.pos()))
2840             return true; // can't use scrolls while silenced
2841
2842         if (!ident && !item_type_known(item))
2843             return false;
2844
2845         // A bad item is always useless.
2846         if (is_bad_item(item))
2847             return true;
2848
2849         switch (item.sub_type)
2850         {
2851         case SCR_RANDOM_USELESSNESS:
2852             return true;
2853         case SCR_TELEPORTATION:
2854             return you.species == SP_FORMICID
2855                    || crawl_state.game_is_sprint()
2856                    || temp && player_in_branch(BRANCH_GAUNTLET);
2857         case SCR_BLINKING:
2858             return you.species == SP_FORMICID;
2859         case SCR_AMNESIA:
2860             return you_worship(GOD_TROG);
2861 #if TAG_MAJOR_VERSION == 34
2862         case SCR_CURSE_WEAPON: // for non-Ashenzari, already handled
2863         case SCR_CURSE_ARMOUR:
2864 #endif
2865         case SCR_ENCHANT_WEAPON:
2866         case SCR_ENCHANT_ARMOUR:
2867         case SCR_BRAND_WEAPON:
2868             return you.species == SP_FELID;
2869         case SCR_SUMMONING:
2870             return you.get_mutation_level(MUT_NO_LOVE) > 0;
2871         case SCR_FOG:
2872             return temp && (env.level_state & LSTATE_STILL_WINDS);
2873         case SCR_IDENTIFY:
2874             return you_worship(GOD_ASHENZARI);
2875         default:
2876             return false;
2877         }
2878
2879     case OBJ_WANDS:
2880         if (you.get_mutation_level(MUT_NO_ARTIFICE))
2881             return true;
2882
2883 #if TAG_MAJOR_VERSION == 34
2884         if (is_known_empty_wand(item))
2885             return true;
2886 #endif
2887         if (!ident && !item_type_known(item))
2888             return false;
2889
2890         if (item.sub_type == WAND_CHARMING)
2891             return you.get_mutation_level(MUT_NO_LOVE);
2892
2893         return false;
2894
2895     case OBJ_POTIONS:
2896     {
2897         // Mummies and liches can't use potions.
2898         if (you.undead_state(temp) == US_UNDEAD && you.species != SP_GHOUL)
2899             return true;
2900
2901         if (!ident && !item_type_known(item))
2902             return false;
2903
2904         // A bad item is always useless.
2905         if (is_bad_item(item))
2906             return true;
2907
2908         switch (item.sub_type)
2909         {
2910         case POT_BERSERK_RAGE:
2911             return !you.can_go_berserk(true, true, true, nullptr, temp);
2912         case POT_HASTE:
2913             return you.stasis();
2914         case POT_MUTATION:
2915             return !you.can_safely_mutate(temp);
2916
2917         case POT_LIGNIFY:
2918             return you.undead_state(temp)
2919                    && (you.species != SP_VAMPIRE
2920                        || temp && !you.vampire_alive);
2921
2922         case POT_FLIGHT:
2923             return you.permanent_flight()
2924                    || you.racial_permanent_flight();
2925         case POT_HEAL_WOUNDS:
2926             return !you.can_potion_heal();
2927         case POT_INVISIBILITY:
2928             return _invisibility_is_useless(temp);
2929         case POT_BRILLIANCE:
2930             return you_worship(GOD_TROG);
2931         case POT_ATTRACTION:
2932             return false;
2933         CASE_REMOVED_POTIONS(item.sub_type)
2934         }
2935
2936         return false;
2937     }
2938     case OBJ_JEWELLERY:
2939         if (!ident && !item_type_known(item))
2940             return false;
2941
2942         // Potentially useful. TODO: check the properties.
2943         if (is_artefact(item))
2944             return false;
2945
2946         if (is_bad_item(item))
2947             return true;
2948
2949         switch (item.sub_type)
2950         {
2951         case RING_RESIST_CORROSION:
2952             return you.res_corr(false, false);
2953
2954         case AMU_FAITH:
2955             return (you.species == SP_DEMIGOD && !you.religion)
2956                     || you_worship(GOD_GOZAG) || you_worship(GOD_ASHENZARI)
2957                     || (you_worship(GOD_RU) && you.piety == piety_breakpoint(5));
2958
2959         case AMU_GUARDIAN_SPIRIT:
2960             return you.spirit_shield(false, false);
2961
2962         case RING_LIFE_PROTECTION:
2963             return player_prot_life(false, temp, false) == 3;
2964
2965         case AMU_REGENERATION:
2966             return you.get_mutation_level(MUT_NO_REGENERATION) > 0
2967                    || (temp
2968                        && (you.get_mutation_level(MUT_INHIBITED_REGENERATION) > 0
2969                            || you.species == SP_VAMPIRE)
2970                        && regeneration_is_inhibited());
2971
2972 #if TAG_MAJOR_VERSION == 34
2973         case AMU_MANA_REGENERATION:
2974             return you_worship(GOD_PAKELLAS);
2975 #endif
2976
2977         case RING_SEE_INVISIBLE:
2978             return you.innate_sinv();
2979
2980         case RING_POISON_RESISTANCE:
2981             return player_res_poison(false, temp, false) > 0
2982                    && (temp || you.species != SP_VAMPIRE);
2983
2984         case RING_WIZARDRY:
2985             return you_worship(GOD_TROG);
2986
2987         case RING_FLIGHT:
2988             return you.permanent_flight()
2989                    || you.racial_permanent_flight()
2990                    || you.get_mutation_level(MUT_NO_ARTIFICE);
2991
2992         case RING_STEALTH:
2993             return you.get_mutation_level(MUT_NO_STEALTH);
2994
2995         default:
2996             return false;
2997         }
2998
2999 #if TAG_MAJOR_VERSION == 34
3000     case OBJ_RODS:
3001             return true;
3002 #endif
3003
3004     case OBJ_STAVES:
3005         if (you.species == SP_FELID)
3006             return true;
3007         if (!you.could_wield(item, true, !temp))
3008         {
3009             // Weapon is too large (or small) to be wielded and cannot
3010             // be thrown either.
3011             return true;
3012         }
3013         if (!ident && !item_type_known(item))
3014             return false;
3015
3016         return false;
3017
3018     case OBJ_CORPSES:
3019         if (you.has_spell(SPELL_ANIMATE_DEAD)
3020             || you.has_spell(SPELL_ANIMATE_SKELETON)
3021             || you.has_spell(SPELL_SIMULACRUM)
3022             || you_worship(GOD_YREDELEMNUL) && !you.penance[GOD_YREDELEMNUL]
3023                && you.piety >= piety_breakpoint(0))
3024         {
3025             return false;
3026         }
3027
3028         return true;
3029
3030     case OBJ_MISCELLANY:
3031         switch (item.sub_type)
3032         {
3033 #if TAG_MAJOR_VERSION == 34
3034         case MISC_BUGGY_EBONY_CASKET:
3035             return item_type_known(item);
3036 #endif
3037         // These can always be used.
3038 #if TAG_MAJOR_VERSION == 34
3039         case MISC_BUGGY_LANTERN_OF_SHADOWS:
3040 #endif
3041         case MISC_ZIGGURAT:
3042             return false;
3043
3044         // Purely summoning misc items don't work w/ sac love
3045         case MISC_BOX_OF_BEASTS:
3046         case MISC_HORN_OF_GERYON:
3047         case MISC_PHANTOM_MIRROR:
3048             return you.get_mutation_level(MUT_NO_LOVE)
3049                    || you.get_mutation_level(MUT_NO_ARTIFICE);
3050
3051         case MISC_CONDENSER_VANE:
3052             if (temp && (env.level_state & LSTATE_STILL_WINDS))
3053                 return true;
3054             // Intentional fallthrough to check artifice
3055
3056         default:
3057             return you.get_mutation_level(MUT_NO_ARTIFICE);
3058         }
3059
3060     case OBJ_BOOKS:
3061         if (!ident && !item_type_known(item))
3062             return false;
3063         if ((ident || item_type_known(item)) && item.sub_type != BOOK_MANUAL)
3064         {
3065             // Spellbooks are useless if all spells are either in the library
3066             // already or are uncastable.
3067             bool useless = true;
3068             for (spell_type st : spells_in_book(item))
3069                 if (!you.spell_library[st] && you_can_memorise(st))
3070                     useless = false;
3071             return useless;
3072         }
3073         // If we're here, it's a manual.
3074         if (you.skills[item.plus] >= 27)
3075             return true;
3076         return is_useless_skill((skill_type)item.plus);
3077
3078     default:
3079         return false;
3080     }
3081     return false;
3082 }
3083
3084 string item_prefix(const item_def &item, bool temp)
3085 {
3086     vector<const char *> prefixes;
3087
3088     if (!item.defined())
3089         return "";
3090
3091     if (fully_identified(item))
3092         prefixes.push_back("identified");
3093     else if (item_ident(item, ISFLAG_KNOW_TYPE)
3094              || get_ident_type(item))
3095     {
3096         prefixes.push_back("known");
3097     }
3098     else
3099         prefixes.push_back("unidentified");
3100
3101     if (god_hates_item(item))
3102     {
3103         prefixes.push_back("evil_item");
3104         prefixes.push_back("forbidden");
3105     }
3106
3107     if (is_emergency_item(item))
3108         prefixes.push_back("emergency_item");
3109     if (is_good_item(item))
3110         prefixes.push_back("good_item");
3111     if (is_dangerous_item(item, temp))
3112         prefixes.push_back("dangerous_item");
3113     if (is_bad_item(item))
3114         prefixes.push_back("bad_item");
3115     if (is_useless_item(item, temp))
3116         prefixes.push_back("useless_item");
3117
3118     if (item_is_stationary(item))
3119         prefixes.push_back("stationary");
3120
3121     if (!is_artefact(item) && (item.base_type == OBJ_WEAPONS
3122                                || item.base_type == OBJ_ARMOUR))
3123     {
3124         if (item_ident(item, ISFLAG_KNOW_PLUSES) && item.plus > 0)
3125             prefixes.push_back("enchanted");
3126         if (item_ident(item, ISFLAG_KNOW_TYPE) && item.brand)
3127             prefixes.push_back("ego");
3128     }
3129
3130     switch (item.base_type)
3131     {
3132     case OBJ_STAVES:
3133     case OBJ_WEAPONS:
3134         if (is_range_weapon(item))
3135             prefixes.push_back("ranged");
3136         else if (is_melee_weapon(item)) // currently redundant
3137             prefixes.push_back("melee");
3138         // fall through
3139
3140     case OBJ_ARMOUR:
3141     case OBJ_JEWELLERY:
3142         if (is_artefact(item))
3143             prefixes.push_back("artefact");
3144         // fall through
3145
3146     case OBJ_MISSILES:
3147         if (item_is_equipped(item, true))
3148             prefixes.push_back("equipped");
3149         break;
3150
3151     case OBJ_BOOKS:
3152         if (item.sub_type != BOOK_MANUAL && item.sub_type != NUM_BOOKS)
3153             prefixes.push_back("spellbook");
3154         break;
3155
3156     default:
3157         break;
3158     }
3159
3160     prefixes.push_back(item_class_name(item.base_type, true));
3161
3162     string result = comma_separated_line(prefixes.begin(), prefixes.end(),
3163                                          " ", " ");
3164
3165     return result;
3166 }
3167
3168 /**
3169  * Return an item's name surrounded by colour tags, using menu colouring
3170  *
3171  * @param item The item being queried
3172  * @param desc The description level to use for the name string
3173  * @return A string containing the item's name surrounded by colour tags
3174  */
3175 string menu_colour_item_name(const item_def &item, description_level_type desc)
3176 {
3177     const string cprf      = item_prefix(item);
3178     const string item_name = item.name(desc);
3179
3180     const int col = menu_colour(item_name, cprf, "pickup");
3181     if (col == -1)
3182         return item_name;
3183
3184     const string colour = colour_to_str(col);
3185     const char * const colour_z = colour.c_str();
3186     return make_stringf("<%s>%s</%s>", colour_z, item_name.c_str(), colour_z);
3187 }
3188
3189 typedef map<string, item_kind> item_names_map;
3190 static item_names_map item_names_cache;
3191
3192 typedef map<unsigned, vector<string> > item_names_by_glyph_map;
3193 static item_names_by_glyph_map item_names_by_glyph_cache;
3194
3195 void init_item_name_cache()
3196 {
3197     item_names_cache.clear();
3198     item_names_by_glyph_cache.clear();
3199
3200     for (int i = 0; i < NUM_OBJECT_CLASSES; i++)
3201     {
3202         const object_class_type base_type = static_cast<object_class_type>(i);
3203
3204         for (const auto sub_type : all_item_subtypes(base_type))
3205         {
3206             if (base_type == OBJ_BOOKS)
3207             {
3208                 if (sub_type == BOOK_RANDART_LEVEL
3209                     || sub_type == BOOK_RANDART_THEME)
3210                 {
3211                     // These are randart only and have no fixed names.
3212                     continue;
3213                 }
3214             }
3215
3216             int npluses = 0;
3217             if (base_type == OBJ_BOOKS && sub_type == BOOK_MANUAL)
3218                 npluses = NUM_SKILLS;
3219
3220             item_def item;
3221             item.base_type = base_type;
3222             item.sub_type = sub_type;
3223             for (int plus = 0; plus <= npluses; plus++)
3224             {
3225                 if (plus > 0)
3226                     item.plus = max(0, plus - 1);
3227                 string name = item.name(plus || item.base_type == OBJ_RUNES ? DESC_PLAIN : DESC_DBNAME,
3228                                         true, true);
3229                 lowercase(name);
3230                 cglyph_t g = get_item_glyph(item);
3231
3232                 if (base_type == OBJ_JEWELLERY && sub_type >= NUM_RINGS
3233                     && sub_type < AMU_FIRST_AMULET)
3234                 {
3235                     continue;
3236                 }
3237                 else if (name.find("buggy") != string::npos)
3238                 {
3239                     mprf(MSGCH_ERROR, "Bad name for item name cache: %s",
3240                                                                 name.c_str());
3241                     continue;
3242                 }
3243
3244                 if (!item_names_cache.count(name))
3245                 {
3246                     item_names_cache[name] = { base_type, (uint8_t)sub_type,
3247                                                (int8_t)item.plus, 0 };
3248                     if (g.ch)
3249                         item_names_by_glyph_cache[g.ch].push_back(name);
3250                 }
3251             }
3252         }
3253     }
3254
3255     ASSERT(!item_names_cache.empty());
3256 }
3257
3258 item_kind item_kind_by_name(const string &name)
3259 {
3260     return lookup(item_names_cache, lowercase_string(name),
3261                   { OBJ_UNASSIGNED, 0, 0, 0 });
3262 }
3263
3264 vector<string> item_name_list_for_glyph(char32_t glyph)
3265 {
3266     return lookup(item_names_by_glyph_cache, glyph, {});
3267 }
3268
3269 bool is_named_corpse(const item_def &corpse)
3270 {
3271     ASSERT(corpse.base_type == OBJ_CORPSES);
3272
3273     return corpse.props.exists(CORPSE_NAME_KEY);
3274 }
3275
3276 string get_corpse_name(const item_def &corpse, monster_flags_t *name_type)
3277 {
3278     ASSERT(corpse.base_type == OBJ_CORPSES);
3279
3280     if (!corpse.props.exists(CORPSE_NAME_KEY))
3281         return "";
3282
3283     if (name_type != nullptr)
3284         name_type->flags = corpse.props[CORPSE_NAME_TYPE_KEY].get_int64();
3285
3286     return corpse.props[CORPSE_NAME_KEY].get_string();
3287 }