Give the faerie dragon armour a small chance of non-randart properties.
[crawl.git] / crawl-ref / source / artefact.cc
1 /**
2  * @file
3  * @brief Random and unrandom artefact functions.
4 **/
5
6 #include "AppHdr.h"
7
8 #include "artefact.h"
9
10 #include <cstdlib>
11 #include <climits>
12 #include <string.h>
13 #include <stdio.h>
14 #include <algorithm>
15
16 #include "externs.h"
17
18 #include "areas.h"
19 #include "branch.h"
20 #include "colour.h"
21 #include "coordit.h"
22 #include "database.h"
23 #include "describe.h"
24 #include "itemname.h"
25 #include "itemprop.h"
26 #include "items.h"
27 #include "libutil.h"
28 #include "makeitem.h"
29 #include "player.h"
30 #include "random.h"
31 #include "religion.h"
32 #include "shout.h"
33 #include "species.h"
34 #include "spl-book.h"
35 #include "stuff.h"
36
37 static bool _god_fits_artefact(const god_type which_god, const item_def &item,
38                                bool name_check_only = false)
39 {
40     if (which_god == GOD_NO_GOD)
41         return false;
42
43     // Jellies can't eat artefacts, so their god won't make any.
44     if (which_god == GOD_JIYVA)
45         return false;
46
47     // First check the item's base_type and sub_type, then check the
48     // item's brand and other randart properties.
49     bool type_bad = false;
50     switch (which_god)
51     {
52     case GOD_ELYVILON:
53         // Peaceful healer god: no weapons, no berserking.
54         if (item.base_type == OBJ_WEAPONS)
55             type_bad = true;
56
57         if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_RAGE)
58             type_bad = true;
59         break;
60
61     case GOD_OKAWARU:
62         // Precision fighter god: no inaccuracy.
63         if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_INACCURACY)
64             type_bad = true;
65         break;
66
67     case GOD_ZIN:
68         // Lawful god: no increased hunger.
69         if (item.base_type == OBJ_JEWELLERY && item.sub_type == RING_HUNGER)
70             type_bad = true;
71         break;
72
73     case GOD_SIF_MUNA:
74     case GOD_VEHUMET:
75         // The magic gods: no weapons, no preventing spellcasting.
76         if (item.base_type == OBJ_WEAPONS)
77             type_bad = true;
78         break;
79
80     case GOD_TROG:
81         // Anti-magic god: no spell use, no enhancing magic.
82         if (item.base_type == OBJ_BOOKS)
83             type_bad = true;
84
85         if (item.base_type == OBJ_JEWELLERY
86             && (item.sub_type == RING_WIZARDRY
87              || item.sub_type == RING_FIRE
88              || item.sub_type == RING_ICE
89              || item.sub_type == RING_MAGICAL_POWER))
90         {
91             type_bad = true;
92         }
93         break;
94
95     case GOD_CHEIBRIADOS:
96         // Slow god: no quick blades, no berserking.
97         if (item.base_type == OBJ_WEAPONS && item.sub_type == WPN_QUICK_BLADE)
98             type_bad = true;
99
100         if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_RAGE)
101             type_bad = true;
102         break;
103
104     default:
105         break;
106     }
107
108     if (type_bad && !name_check_only)
109     {
110         die("%s attempting to gift invalid type of item.",
111             god_name(which_god).c_str());
112     }
113
114     if (type_bad)
115         return false;
116
117     const int brand = get_weapon_brand(item);
118     const int ego   = get_armour_ego_type(item);
119
120     if (is_evil_god(which_god) && brand == SPWPN_HOLY_WRATH)
121         return false;
122     else if (is_good_god(which_god)
123              && (brand == SPWPN_DRAINING
124                  || brand == SPWPN_PAIN
125                  || brand == SPWPN_VAMPIRICISM
126                  || brand == SPWPN_REAPING
127                  || brand == SPWPN_CHAOS
128                  || is_demonic(item)
129                  || artefact_wpn_property(item, ARTP_CURSED) != 0))
130     {
131         return false;
132     }
133
134     switch (which_god)
135     {
136     case GOD_BEOGH:
137         // Orc god: no orc slaying.
138         if (brand == SPWPN_ORC_SLAYING)
139             return false;
140         break;
141
142     case GOD_ELYVILON:
143         // Peaceful healer god: no berserking.
144         if (artefact_wpn_property(item, ARTP_ANGRY)
145             || artefact_wpn_property(item, ARTP_BERSERK))
146         {
147             return false;
148         }
149         break;
150
151     case GOD_ZIN:
152         // Lawful god: no mutagenics.
153         if (artefact_wpn_property(item, ARTP_MUTAGENIC))
154             return false;
155         break;
156
157     case GOD_SHINING_ONE:
158         // Crusader god: holiness, honourable combat.
159         if (item.base_type == OBJ_WEAPONS && brand != SPWPN_HOLY_WRATH)
160             return false;
161
162         if (artefact_wpn_property(item, ARTP_INVISIBLE)
163             || artefact_wpn_property(item, ARTP_STEALTH) > 0)
164         {
165             return false;
166         }
167         break;
168
169     case GOD_LUGONU:
170         // Abyss god: corruption.
171         if (item.base_type == OBJ_WEAPONS && brand != SPWPN_DISTORTION)
172             return false;
173         break;
174
175     case GOD_KIKUBAAQUDGHA:
176         // Necromancy god.
177         if (item.base_type == OBJ_WEAPONS && brand != SPWPN_PAIN)
178             return false;
179     case GOD_SIF_MUNA:
180     case GOD_VEHUMET:
181         // The magic gods: no preventing spellcasting.
182         if (artefact_wpn_property(item, ARTP_PREVENT_SPELLCASTING))
183             return false;
184         break;
185
186     case GOD_TROG:
187         // Anti-magic god: no spell use, no enhancing magic.
188         if (brand == SPWPN_PAIN) // Pain involves necromantic spell use.
189             return false;
190
191         if (artefact_wpn_property(item, ARTP_MAGICAL_POWER))
192             return false;
193         break;
194
195     case GOD_FEDHAS:
196         // Fedhas forbids necromancy involving corpses, only reaping
197         // really applies.
198         if (brand == SPWPN_REAPING)
199             return false;
200         break;
201
202     case GOD_CHEIBRIADOS:
203         // Slow god: no speed, no berserking.
204         if (brand == SPWPN_SPEED)
205             return false;
206
207         if (ego == SPARM_RUNNING)
208             return false;
209
210         if (artefact_wpn_property(item, ARTP_ANGRY)
211             || artefact_wpn_property(item, ARTP_BERSERK))
212         {
213             return false;
214         }
215         break;
216
217     case GOD_ASHENZARI:
218         // Cursed god: no holy wrath (since that brand repels curses).
219         if (brand == SPWPN_HOLY_WRATH)
220             return false;
221         break;
222
223     default:
224         break;
225     }
226
227     return true;
228 }
229
230 std::string replace_name_parts(const std::string &name_in, const item_def& item)
231 {
232     std::string name = name_in;
233
234     god_type god_gift;
235     (void) origin_is_god_gift(item, &god_gift);
236
237     // Don't allow "player's Death" type names for god gifts (except
238     // for those from Xom).
239     if (name.find("@player_death@", 0) != std::string::npos
240         || name.find("@player_doom@", 0) != std::string::npos)
241     {
242         if (god_gift == GOD_NO_GOD || god_gift == GOD_XOM)
243         {
244             name = replace_all(name, "@player_death@",
245                                "@player_name@"
246                                + getRandNameString("killer_name"));
247             name = replace_all(name, "@player_doom@",
248                                "@player_name@'s "
249                                + getRandNameString("death_or_doom"));
250         }
251         else
252         {
253             // Simply overwrite the name with one of type "God's Favour".
254             name = "of ";
255             name += god_name(god_gift, false);
256             name += "'s ";
257             name += getRandNameString("divine_esteem");
258         }
259     }
260     name = replace_all(name, "@player_name@", you.your_name);
261
262     name = replace_all(name, "@player_species@",
263                  species_name(static_cast<species_type>(you.species), true));
264
265     if (name.find("@branch_name@", 0) != std::string::npos)
266     {
267         std::string place = branches[random2(NUM_BRANCHES)].longname;
268         if (!place.empty())
269             name = replace_all(name, "@branch_name@", place);
270     }
271
272     // Occasionally use long name for Xom (see religion.cc).
273     name = replace_all(name, "@xom_name@", god_name(GOD_XOM, coinflip()));
274
275     if (name.find("@god_name@", 0) != std::string::npos)
276     {
277         god_type which_god;
278
279         // God gifts will always get the gifting god's name.
280         if (god_gift != GOD_NO_GOD)
281             which_god = god_gift;
282         else
283         {
284             do
285                 which_god = random_god(false); // Fedhas in ZotDef only
286             while (!_god_fits_artefact(which_god, item, true));
287         }
288
289         name = replace_all(name, "@god_name@", god_name(which_god, false));
290     }
291
292     // copied from monster speech handling (mon-util.cc):
293     // The proper possessive for a word ending in an "s" is to
294     // put an apostrophe after the "s": "Chris" -> "Chris'",
295     // not "Chris" -> "Chris's".  Stupid English language...
296     name = replace_all(name, "s's", "s'");
297
298     return name;
299 }
300
301 // Remember: disallow unrandart creation in Abyss/Pan.
302
303 // Functions defined in art-func.h are referenced in art-data.h
304 #include "art-func.h"
305
306 static unrandart_entry unranddata[] = {
307 #include "art-data.h"
308 };
309
310 static unrandart_entry *_seekunrandart(const item_def &item);
311
312 bool is_known_artefact(const item_def &item)
313 {
314     if (!item_type_known(item))
315         return false;
316
317     return is_artefact(item);
318 }
319
320 bool is_artefact(const item_def &item)
321 {
322     return (item.flags & ISFLAG_ARTEFACT_MASK);
323 }
324
325 // returns true is item is a pure randart
326 bool is_random_artefact(const item_def &item)
327 {
328     return (item.flags & ISFLAG_RANDART);
329 }
330
331 // returns true if item in an unrandart
332 bool is_unrandom_artefact(const item_def &item)
333 {
334     return (item.flags & ISFLAG_UNRANDART);
335 }
336
337 bool is_special_unrandom_artefact(const item_def &item)
338 {
339     return (item.flags & ISFLAG_UNRANDART
340             && (_seekunrandart(item)->flags & UNRAND_FLAG_SPECIAL));
341 }
342
343 bool is_randapp_artefact(const item_def &item)
344 {
345     return (item.flags & ISFLAG_UNRANDART
346             && !(item.flags & ISFLAG_KNOW_TYPE)
347             && (_seekunrandart(item)->flags & UNRAND_FLAG_RANDAPP));
348 }
349
350 void autoid_unrand(item_def &item)
351 {
352     if (!(item.flags & ISFLAG_UNRANDART) || item.flags & ISFLAG_KNOW_TYPE)
353         return;
354     const uint16_t uflags = _seekunrandart(item)->flags;
355     if (uflags & UNRAND_FLAG_RANDAPP || uflags & UNRAND_FLAG_UNIDED)
356         return;
357
358     set_ident_flags(item, ISFLAG_IDENT_MASK | ISFLAG_NOTED_ID);
359     add_autoinscription(item);
360 }
361
362 unique_item_status_type get_unique_item_status(int art)
363 {
364     ASSERT(art > UNRAND_START && art < UNRAND_LAST);
365     return you.unique_items[art - UNRAND_START];
366 }
367
368 static void _set_unique_item_status(int art, unique_item_status_type status)
369 {
370     ASSERT(art > UNRAND_START && art < UNRAND_LAST);
371     you.unique_items[art - UNRAND_START] = status;
372 }
373
374 void set_unique_item_status(const item_def& item,
375                             unique_item_status_type status)
376 {
377     if (item.flags & ISFLAG_UNRANDART)
378         _set_unique_item_status(item.special, status);
379 }
380
381 void reveal_randapp_artefact(item_def &item)
382 {
383     ASSERT(is_unrandom_artefact(item));
384     const unrandart_entry *unrand = _seekunrandart(item);
385     ASSERT(unrand);
386     ASSERT(unrand->flags & UNRAND_FLAG_RANDAPP);
387     // name and tile update themselves
388     item.colour = unrand->colour;
389 }
390
391 void artefact_desc_properties(const item_def &item,
392                               artefact_properties_t &proprt,
393                               artefact_known_props_t &known,
394                               bool force_fake_props)
395 {
396     // Randart books have no randart properties.
397     if (item.base_type == OBJ_BOOKS)
398         return;
399
400     artefact_wpn_properties(item, proprt, known);
401
402     if (item.base_type == OBJ_ARMOUR)
403     {
404         switch (item.sub_type)
405         {
406         case ARM_SWAMP_DRAGON_ARMOUR:
407             ++proprt[ARTP_POISON];
408             break;
409         case ARM_FIRE_DRAGON_ARMOUR:
410             proprt[ARTP_FIRE] += 2;
411             --proprt[ARTP_COLD];
412             break;
413         case ARM_ICE_DRAGON_ARMOUR:
414             --proprt[ARTP_FIRE];
415             proprt[ARTP_COLD] += 2;
416             break;
417         case ARM_PEARL_DRAGON_ARMOUR:
418             ++proprt[ARTP_NEGATIVE_ENERGY];
419             break;
420         case ARM_STORM_DRAGON_ARMOUR:
421             ++proprt[ARTP_ELECTRICITY];
422             break;
423         case ARM_GOLD_DRAGON_ARMOUR:
424             ++proprt[ARTP_POISON];
425             ++proprt[ARTP_FIRE];
426             ++proprt[ARTP_COLD];
427             break;
428         }
429     }
430
431     if (!force_fake_props && item_ident(item, ISFLAG_KNOW_PROPERTIES))
432         return;
433
434     // Only jewellery need fake randart properties.
435     if (item.base_type != OBJ_JEWELLERY)
436         return;
437
438     artefact_prop_type fake_rap  = ARTP_NUM_PROPERTIES;
439     int               fake_plus = 1;
440
441     // The base jewellery type is one whose property is revealed by
442     // wearing it, but whose property isn't revealed by having
443     // ISFLAG_KNOW_PLUSES set.  For a randart with a base type of, for
444     // example, a ring of strength, wearing it sets
445     // ISFLAG_KNOW_PLUSES, which reveals the ring's strength plus.
446     switch (item.sub_type)
447     {
448     case RING_INVISIBILITY:
449         fake_rap = ARTP_INVISIBLE;
450         break;
451
452     case RING_MAGICAL_POWER:
453         fake_rap  = ARTP_MAGICAL_POWER;
454         fake_plus = 9;
455         break;
456
457     case RING_LEVITATION:
458         fake_rap = ARTP_LEVITATE;
459         break;
460
461     case AMU_RAGE:
462         fake_rap = ARTP_BERSERK;
463         break;
464     }
465
466     if (fake_rap != ARTP_NUM_PROPERTIES)
467     {
468         proprt[fake_rap] += fake_plus;
469
470         if (item_ident(item, ISFLAG_KNOW_PROPERTIES)
471             || item_ident(item, ISFLAG_KNOW_TYPE))
472         {
473             known[fake_rap] = true;
474         }
475
476         return;
477     }
478
479     if (!force_fake_props)
480         return;
481
482     // For auto-inscribing randart jewellery, force_fake_props folds as
483     // much info about the base type as possible into the randarts
484     // property struct.
485
486     artefact_prop_type fake_rap2  = ARTP_NUM_PROPERTIES;
487     int               fake_plus2 = 1;
488
489     switch (item.sub_type)
490     {
491     case RING_PROTECTION:
492         fake_rap  = ARTP_AC;
493         fake_plus = item.plus;
494         break;
495
496     case RING_PROTECTION_FROM_FIRE:
497         fake_rap = ARTP_FIRE;
498         break;
499
500     case RING_POISON_RESISTANCE:
501         fake_rap = ARTP_POISON;
502         break;
503
504     case RING_PROTECTION_FROM_COLD:
505         fake_rap = ARTP_COLD;
506         break;
507
508     case RING_SLAYING:
509         fake_rap   = ARTP_ACCURACY;
510         fake_plus  = item.plus;
511         fake_rap2  = ARTP_DAMAGE;
512         fake_plus2 = item.plus2;
513         break;
514
515     case RING_SEE_INVISIBLE:
516         fake_rap = ARTP_EYESIGHT;
517         break;
518
519     case RING_HUNGER:
520         fake_rap = ARTP_METABOLISM;
521         break;
522
523     case RING_EVASION:
524         fake_rap  = ARTP_EVASION;
525         fake_plus = item.plus;
526         break;
527
528     case RING_STRENGTH:
529         fake_rap  = ARTP_STRENGTH;
530         fake_plus = item.plus;
531         break;
532
533     case RING_INTELLIGENCE:
534         fake_rap  = ARTP_INTELLIGENCE;
535         fake_plus = item.plus;
536         break;
537
538     case RING_DEXTERITY:
539         fake_rap  = ARTP_DEXTERITY;
540         fake_plus = item.plus;
541         break;
542
543     case RING_LIFE_PROTECTION:
544         fake_rap = ARTP_NEGATIVE_ENERGY;
545         break;
546
547     case RING_PROTECTION_FROM_MAGIC:
548         fake_rap = ARTP_MAGIC;
549         break;
550
551     case RING_FIRE:
552         fake_rap   = ARTP_FIRE;
553         fake_rap2  = ARTP_COLD;
554         fake_plus2 = -1;
555         break;
556
557     case RING_ICE:
558         fake_rap   = ARTP_COLD;
559         fake_rap2  = ARTP_FIRE;
560         fake_plus2 = -1;
561         break;
562     }
563
564     if (fake_rap != ARTP_NUM_PROPERTIES && fake_plus != 0)
565         proprt[fake_rap] += fake_plus;
566
567     if (fake_rap2 != ARTP_NUM_PROPERTIES && fake_plus2 != 0)
568         proprt[fake_rap2] += fake_plus2;
569
570     if (item_ident(item, ISFLAG_KNOW_PROPERTIES)
571         || item_ident(item, ISFLAG_KNOW_TYPE))
572     {
573         if (fake_rap != ARTP_NUM_PROPERTIES && proprt[fake_rap] != 0)
574             known[fake_rap] = true;
575
576         if (fake_rap2 != ARTP_NUM_PROPERTIES && proprt[fake_rap2] != 0)
577             known[fake_rap2] = true;
578     }
579 }
580
581 static inline void _randart_propset(artefact_properties_t &p,
582                                      artefact_prop_type pt,
583                                      int value,
584                                      bool neg)
585 {
586     // This shouldn't be called with 0, else no property gets added after all.
587     ASSERT(value != 0);
588     p[pt] = (neg? -value : value);
589 }
590
591 static int _randart_add_one_property(const item_def &item,
592                                       artefact_properties_t &proprt)
593 {
594     // This function assumes that at least some properties are still possible.
595     const object_class_type cl = item.base_type;
596     const int               ty = item.sub_type;
597
598     const bool negench = one_chance_in(4);
599
600     const artefact_prop_type artprops[] = { ARTP_STRENGTH, ARTP_INTELLIGENCE,
601                                             ARTP_DEXTERITY };
602
603     do
604     {
605         int prop = RANDOM_ELEMENT(artprops);
606
607         if (proprt[prop] != 0)
608             continue;
609
610         switch (prop)
611         {
612         case ARTP_STRENGTH:
613             if (cl == OBJ_JEWELLERY && ty == RING_STRENGTH)
614                 continue;
615
616             _randart_propset(proprt, ARTP_STRENGTH,
617                              1 + random2(3) + random2(3),
618                              negench);
619             break;
620
621         case ARTP_INTELLIGENCE:
622             if (cl == OBJ_JEWELLERY && ty == RING_INTELLIGENCE)
623                 continue;
624
625             _randart_propset(proprt, ARTP_INTELLIGENCE,
626                              1 + random2(3) + random2(3),
627                              negench);
628             break;
629
630         case ARTP_DEXTERITY:
631             if (cl == OBJ_JEWELLERY && ty == RING_DEXTERITY)
632                 continue;
633
634             _randart_propset(proprt, ARTP_DEXTERITY,
635                              1 + random2(3) + random2(3),
636                              negench);
637             break;
638         }
639     }
640     while (false);
641
642     return (negench ? -1 : 1);
643 }
644
645 // An artefact will pass this check if it has any non-stat properties, and
646 // also if it has enough stat (Str, Dex, Int, Acc, Dam) properties.
647 // Returns how many (more) stat properties we need to add.
648 static int _need_bonus_stat_props(const artefact_properties_t &proprt)
649 {
650     int num_stats   = 0;
651     int num_acc_dam = 0;
652
653     for (int i = 0; i < ARTP_NUM_PROPERTIES; i++)
654     {
655         if (i == ARTP_CURSED)
656             continue;
657
658         if (proprt[i] == 0)
659             continue;
660
661         if (i >= ARTP_AC && i <= ARTP_DEXTERITY)
662             num_stats++;
663         else if (i >= ARTP_ACCURACY && i <= ARTP_DAMAGE)
664             num_acc_dam++;
665         else
666             return 0;
667     }
668
669     num_stats += num_acc_dam;
670
671     // If an artefact has no properties at all, something is wrong.
672     if (num_stats == 0)
673         return 2;
674
675     // Artefacts with two of more stat-only properties are fine.
676     if (num_stats >= 2)
677         return 0;
678
679     // If an artefact has exactly one stat property, we might want to add
680     // some more. (66% chance if it's Acc/Dam, else always.)
681     if (num_acc_dam > 0)
682         return random2(3);
683
684     return 1 + random2(2);
685 }
686
687 static void _get_randart_properties(const item_def &item,
688                                     artefact_properties_t &proprt)
689 {
690     const object_class_type aclass = item.base_type;
691     const int atype = item.sub_type;
692     int power_level = 0;
693
694     if (aclass == OBJ_ARMOUR)
695         power_level = item.plus * 2 / (armour_max_enchant(item) + 2) + 2;
696     else if (aclass == OBJ_JEWELLERY)
697         power_level = 1 + random2(3) + random2(2);
698     else // OBJ_WEAPON
699         power_level = item.plus / 3 + item.plus2 / 3;
700
701     if (power_level < 0)
702         power_level = 0;
703
704     proprt.init(0);
705
706     if (aclass == OBJ_WEAPONS) // Only weapons get brands, of course.
707     {
708         proprt[ARTP_BRAND] = SPWPN_FLAMING + random2(16);        // brand
709
710         if (one_chance_in(6))
711             proprt[ARTP_BRAND] = SPWPN_FLAMING + random2(2);
712
713         if (one_chance_in(6))
714             proprt[ARTP_BRAND] = SPWPN_ORC_SLAYING + random2(5);
715
716         if (one_chance_in(6))
717             proprt[ARTP_BRAND] = SPWPN_VORPAL;
718
719         if (proprt[ARTP_BRAND] == SPWPN_PROTECTION || proprt[ARTP_BRAND] == SPWPN_EVASION)
720             proprt[ARTP_BRAND] = SPWPN_NORMAL;      // no protection or evasion
721
722         if (is_range_weapon(item))
723         {
724             proprt[ARTP_BRAND] = random_choose_weighted(
725                 2, SPWPN_SPEED,
726                 4, SPWPN_VENOM,
727                 4, SPWPN_VORPAL,
728                 4, SPWPN_FLAME,
729                 4, SPWPN_FROST,
730                 0);
731
732             if (atype == WPN_BLOWGUN)
733                 proprt[ARTP_BRAND] = coinflip() ? SPWPN_SPEED : SPWPN_EVASION;
734             else if (atype == WPN_CROSSBOW)
735             {
736                 // Penetration and electrocution are only allowed on
737                 // crossbows.  This may change in future.
738                 if (one_chance_in(5))
739                     proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
740                 else if (one_chance_in(5))
741                     proprt[ARTP_BRAND] = SPWPN_PENETRATION;
742             }
743         }
744
745         // Quarter of the chance of distortion elsewhere.
746         if (!is_range_weapon(item) && one_chance_in(100))
747             proprt[ARTP_BRAND] = SPWPN_DISTORTION;
748         else if (is_demonic(item))
749         {
750             switch (random2(9))
751             {
752             case 0:
753                 proprt[ARTP_BRAND] = SPWPN_DRAINING;
754                 break;
755             case 1:
756                 proprt[ARTP_BRAND] = SPWPN_FLAMING;
757                 break;
758             case 2:
759                 proprt[ARTP_BRAND] = SPWPN_FREEZING;
760                 break;
761             case 3:
762                 proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
763                 break;
764             case 4:
765                 proprt[ARTP_BRAND] = SPWPN_VAMPIRICISM;
766                 break;
767             case 5:
768                 proprt[ARTP_BRAND] = SPWPN_PAIN;
769                 break;
770             case 6:
771                 proprt[ARTP_BRAND] = SPWPN_VENOM;
772                 break;
773             default:
774                 power_level -= 2;
775             }
776             power_level += 2;
777         }
778         else if (one_chance_in(3))
779             proprt[ARTP_BRAND] = SPWPN_NORMAL;
780         else
781             power_level++;
782
783         if (!is_weapon_brand_ok(atype, proprt[ARTP_BRAND], true))
784         {
785             proprt[ARTP_BRAND] = SPWPN_NORMAL;
786             power_level--;
787         }
788     }
789
790     if (!one_chance_in(5))
791     {
792         // TODO: compensate for the removal of +AC/+EV
793
794         // Str mod - not for rings of strength.
795         if (one_chance_in(4 + power_level)
796             && (aclass != OBJ_JEWELLERY || atype != RING_STRENGTH))
797         {
798             proprt[ARTP_STRENGTH] = 1 + random2(3) + random2(2);
799             power_level++;
800             if (one_chance_in(4))
801             {
802                 proprt[ARTP_STRENGTH] -= 1 + random2(3) + random2(3)
803                                            + random2(3);
804                 power_level--;
805             }
806         }
807
808         // Int mod - not for rings of intelligence.
809         if (one_chance_in(4 + power_level)
810             && (aclass != OBJ_JEWELLERY || atype != RING_INTELLIGENCE))
811         {
812             proprt[ARTP_INTELLIGENCE] = 1 + random2(3) + random2(2);
813             power_level++;
814             if (one_chance_in(4))
815             {
816                 proprt[ARTP_INTELLIGENCE] -= 1 + random2(3) + random2(3)
817                                                + random2(3);
818                 power_level--;
819             }
820         }
821
822         // Dex mod - not for rings of dexterity.
823         if (one_chance_in(4 + power_level)
824             && (aclass != OBJ_JEWELLERY || atype != RING_DEXTERITY))
825         {
826             proprt[ARTP_DEXTERITY] = 1 + random2(3) + random2(2);
827             power_level++;
828             if (one_chance_in(4))
829             {
830                 proprt[ARTP_DEXTERITY] -= 1 + random2(3) + random2(3)
831                                             + random2(3);
832                 power_level--;
833             }
834         }
835     }
836
837     if (random2(15) >= power_level && aclass != OBJ_WEAPONS
838         && (aclass != OBJ_JEWELLERY || atype != RING_SLAYING))
839     {
840         // Weapons and rings of slaying can't get these.
841         if (one_chance_in(4 + power_level))  // to-hit
842         {
843             proprt[ARTP_ACCURACY] = 2 + random2(3) + random2(3);
844             power_level++;
845             if (one_chance_in(4))
846             {
847                 proprt[ARTP_ACCURACY] -= 2 + random2(4) + random2(4)
848                                            + random2(3);
849                 power_level--;
850             }
851         }
852
853         if (one_chance_in(4 + power_level))  // to-dam
854         {
855             proprt[ARTP_DAMAGE] = 2 + random2(3) + random2(3);
856             power_level++;
857             if (one_chance_in(4))
858             {
859                 proprt[ARTP_DAMAGE] -= 2 + random2(4) + random2(4)
860                                          + random2(3);
861                 power_level--;
862             }
863         }
864     }
865
866     // This used to be: bool done_powers = (random2(12 < power_level));
867     // ... which can't be right. random2(boolean) == 0, always.
868     // So it's probably more along the lines of... (jpeg)
869 //    bool done_powers = (random2(12) < power_level);
870
871    // Try to improve items that still have a low power level.
872    bool done_powers = x_chance_in_y(power_level, 12);
873
874     // res_fire
875     if (!done_powers
876         && one_chance_in(4 + power_level)
877         && (aclass != OBJ_JEWELLERY
878             || (atype != RING_PROTECTION_FROM_FIRE
879                 && atype != RING_FIRE
880                 && atype != RING_ICE))
881         && (aclass != OBJ_ARMOUR
882             || (atype != ARM_FIRE_DRAGON_ARMOUR
883                 && atype != ARM_ICE_DRAGON_ARMOUR
884                 && atype != ARM_GOLD_DRAGON_ARMOUR)))
885     {
886         proprt[ARTP_FIRE] = 1;
887         if (one_chance_in(5))
888             proprt[ARTP_FIRE]++;
889         power_level++;
890     }
891
892     // res_cold
893     if (!done_powers
894         && one_chance_in(4 + power_level)
895         && (aclass != OBJ_JEWELLERY
896             || atype != RING_PROTECTION_FROM_COLD
897                && atype != RING_FIRE
898                && atype != RING_ICE)
899         && (aclass != OBJ_ARMOUR
900             || atype != ARM_FIRE_DRAGON_ARMOUR
901                && atype != ARM_ICE_DRAGON_ARMOUR
902                && atype != ARM_GOLD_DRAGON_ARMOUR))
903     {
904         proprt[ARTP_COLD] = 1;
905         if (one_chance_in(5))
906             proprt[ARTP_COLD]++;
907         power_level++;
908     }
909
910     if (x_chance_in_y(power_level, 12) || power_level > 7)
911         done_powers = true;
912
913     // res_elec
914     if (!done_powers
915         && one_chance_in(4 + power_level)
916         && (aclass != OBJ_ARMOUR || atype != ARM_STORM_DRAGON_ARMOUR))
917     {
918         proprt[ARTP_ELECTRICITY] = 1;
919         power_level++;
920     }
921
922     // res_poison
923     if (!done_powers
924         && one_chance_in(5 + power_level)
925         && (aclass != OBJ_JEWELLERY || atype != RING_POISON_RESISTANCE)
926         && (aclass != OBJ_ARMOUR
927             || atype != ARM_GOLD_DRAGON_ARMOUR
928                && atype != ARM_SWAMP_DRAGON_ARMOUR
929                && atype != ARM_NAGA_BARDING))
930     {
931         proprt[ARTP_POISON] = 1;
932         power_level++;
933     }
934
935     // prot_life
936     if (!done_powers
937         && one_chance_in(4 + power_level)
938         && (aclass != OBJ_JEWELLERY || atype != RING_LIFE_PROTECTION)
939         && (aclass != OBJ_ARMOUR || atype != ARM_PEARL_DRAGON_ARMOUR))
940     {
941         proprt[ARTP_NEGATIVE_ENERGY] = 1;
942         power_level++;
943     }
944
945     // res magic
946     if (!done_powers
947         && one_chance_in(4 + power_level)
948         && (aclass != OBJ_JEWELLERY || atype != RING_PROTECTION_FROM_MAGIC))
949     {
950         proprt[ARTP_MAGIC] = 35 + random2(65);
951         power_level++;
952     }
953
954     // see_invis
955     if (!done_powers
956         && one_chance_in(4 + power_level)
957         && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY)
958         && (aclass != OBJ_ARMOUR || atype != ARM_NAGA_BARDING))
959     {
960         proprt[ARTP_EYESIGHT] = 1;
961         power_level++;
962     }
963
964     if (x_chance_in_y(power_level, 12) || power_level > 10)
965         done_powers = true;
966
967     // turn invis
968     if (!done_powers
969         && one_chance_in(10)
970         && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY))
971     {
972         proprt[ARTP_INVISIBLE] = 1;
973         power_level++;
974     }
975
976     // levitate
977     if (!done_powers
978         && one_chance_in(10)
979         && (aclass != OBJ_JEWELLERY || atype != RING_LEVITATION))
980     {
981         proprt[ARTP_LEVITATE] = 1;
982         power_level++;
983     }
984
985     // blink
986     if (!done_powers && one_chance_in(10))
987     {
988         proprt[ARTP_BLINK] = 1;
989         power_level++;
990     }
991
992     // go berserk
993     if (!done_powers
994         && one_chance_in(10)
995         && (aclass != OBJ_WEAPONS || !is_range_weapon(item))
996         && (aclass != OBJ_JEWELLERY || atype != AMU_RAGE))
997     {
998         proprt[ARTP_BERSERK] = 1;
999         power_level++;
1000     }
1001
1002     if (!done_powers && one_chance_in(10) && aclass == OBJ_ARMOUR
1003         && (atype == ARM_CAP || atype == ARM_SHIELD))
1004     {
1005         proprt[ARTP_BRAND] = SPARM_SPIRIT_SHIELD;
1006         power_level++;
1007     }
1008
1009     // Armours get fewer powers, and are also less likely to be cursed
1010     // than weapons.
1011     if (aclass == OBJ_ARMOUR)
1012         power_level -= 4;
1013
1014     if (power_level >= 2 && x_chance_in_y(power_level, 17))
1015     {
1016         switch (random2(9))
1017         {
1018         case 0:                     // makes noise
1019             if (aclass != OBJ_WEAPONS)
1020                 break;
1021             proprt[ARTP_NOISES] = 1 + random2(4);
1022             break;
1023         case 1:                     // no magic
1024             proprt[ARTP_PREVENT_SPELLCASTING] = 1;
1025             break;
1026         case 2:                     // random teleport
1027             if (aclass != OBJ_WEAPONS || crawl_state.game_is_sprint())
1028                 break;
1029             proprt[ARTP_CAUSE_TELEPORTATION] = 5 + random2(15);
1030             break;
1031         case 3:   // no teleport - doesn't affect some instantaneous
1032                   // teleports
1033             if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORTATION)
1034                 break;              // already is a ring of tport
1035             if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORT_CONTROL)
1036                 break;              // already is a ring of tport ctrl
1037             proprt[ARTP_BLINK] = 0;
1038             proprt[ARTP_PREVENT_TELEPORTATION] = 1;
1039             break;
1040         case 4:                     // berserk on attack
1041             if (aclass != OBJ_WEAPONS || is_range_weapon(item))
1042                 break;
1043             proprt[ARTP_ANGRY] = 1 + random2(8);
1044             break;
1045         case 5:                     // susceptible to fire
1046             if (aclass == OBJ_JEWELLERY
1047                 && (atype == RING_PROTECTION_FROM_FIRE || atype == RING_FIRE
1048                     || atype == RING_ICE))
1049             {
1050                 break;              // already does this or something
1051             }
1052             if (aclass == OBJ_ARMOUR
1053                 && (atype == ARM_FIRE_DRAGON_ARMOUR
1054                     || atype == ARM_ICE_DRAGON_ARMOUR
1055                     || atype == ARM_GOLD_DRAGON_ARMOUR))
1056             {
1057                 break;
1058             }
1059             proprt[ARTP_FIRE] = -1;
1060             break;
1061         case 6:                     // susceptible to cold
1062             if (aclass == OBJ_JEWELLERY
1063                 && (atype == RING_PROTECTION_FROM_COLD || atype == RING_FIRE
1064                     || atype == RING_ICE))
1065             {
1066                 break;              // already does this or something
1067             }
1068             if (aclass == OBJ_ARMOUR
1069                 && (atype == ARM_FIRE_DRAGON_ARMOUR
1070                     || atype == ARM_ICE_DRAGON_ARMOUR
1071                     || atype == ARM_GOLD_DRAGON_ARMOUR))
1072             {
1073                 break;
1074             }
1075             proprt[ARTP_COLD] = -1;
1076             break;
1077         case 7:                     // speed metabolism
1078             if (aclass == OBJ_JEWELLERY && atype == RING_HUNGER)
1079                 break;              // already is a ring of hunger
1080             if (aclass == OBJ_JEWELLERY && atype == RING_SUSTENANCE)
1081                 break;              // already is a ring of sustenance
1082             proprt[ARTP_METABOLISM] = 1 + random2(3);
1083             break;
1084         case 8:
1085             // emits mutagenic radiation - increases
1086             // magic_contamination; property is chance (1 in ...) of
1087             // increasing magic_contamination
1088             proprt[ARTP_MUTAGENIC] = 2 + random2(4);
1089             break;
1090         }
1091     }
1092
1093     if (one_chance_in(10)
1094         && (aclass != OBJ_ARMOUR
1095             || atype != ARM_CLOAK
1096             || get_equip_race(item) != ISFLAG_ELVEN)
1097         && (aclass != OBJ_ARMOUR
1098             || atype != ARM_BOOTS
1099             || get_equip_race(item) != ISFLAG_ELVEN)
1100         && get_armour_ego_type(item) != SPARM_STEALTH)
1101     {
1102         power_level++;
1103         proprt[ARTP_STEALTH] = 10 + random2(70);
1104
1105         if (one_chance_in(4))
1106         {
1107             proprt[ARTP_STEALTH] = -proprt[ARTP_STEALTH] - random2(20);
1108             power_level--;
1109         }
1110     }
1111
1112     // "Boring" artefacts (no properties, or only one stat property)
1113     // get an additional property, or maybe two of them.
1114     int add_prop = _need_bonus_stat_props(proprt);
1115     while (0 < add_prop--)
1116         power_level += _randart_add_one_property(item, proprt);
1117
1118     if ((power_level < 2 && one_chance_in(5)) || one_chance_in(30))
1119     {
1120         if (one_chance_in(4))
1121             proprt[ARTP_CURSED] = 1 + random2(5);
1122         else
1123             proprt[ARTP_CURSED] = -1;
1124     }
1125 }
1126
1127 static bool _redo_book(item_def &book)
1128 {
1129     int num_spells  = 0;
1130     int num_unknown = 0;
1131
1132     for (int i = 0; i < SPELLBOOK_SIZE; i++)
1133     {
1134         spell_type spell = which_spell_in_book(book, i);
1135
1136         if (spell == SPELL_NO_SPELL)
1137             continue;
1138
1139         num_spells++;
1140         if (!you.seen_spell[spell])
1141             num_unknown++;
1142     }
1143
1144     if (num_spells <= 5 && num_unknown == 0)
1145         return true;
1146     else if (num_spells > 5 && num_unknown <= 1)
1147         return true;
1148
1149     return false;
1150 }
1151
1152 static bool _init_artefact_book(item_def &book)
1153 {
1154     ASSERT(book.sub_type == BOOK_RANDART_LEVEL
1155            || book.sub_type == BOOK_RANDART_THEME);
1156     ASSERT(book.plus != 0);
1157
1158     god_type god;
1159     bool redo = (!origin_is_god_gift(book, &god) || god != GOD_XOM);
1160
1161     // Plus and plus2 contain parameters to make_book_foo_randart(),
1162     // which might get changed after the book has been made into a
1163     // randart, so reset them on each iteration of the loop.
1164     int  plus  = book.plus;
1165     int  plus2 = book.plus2;
1166     bool book_good;
1167     for (int i = 0; i < 4; i++)
1168     {
1169         book.plus  = plus;
1170         book.plus2 = plus2;
1171
1172         if (book.sub_type == BOOK_RANDART_LEVEL)
1173         {
1174             // The parameters to this call are in book.plus and plus2.
1175             book_good = make_book_level_randart(book, book.plus);
1176         }
1177         else
1178             book_good = make_book_theme_randart(book);
1179
1180         if (!book_good)
1181             continue;
1182
1183         if (redo && _redo_book(book))
1184             continue;
1185
1186         break;
1187     }
1188
1189     return book_good;
1190 }
1191
1192 static bool _init_artefact_properties(item_def &item)
1193 {
1194     ASSERT(is_artefact(item));
1195
1196     CrawlVector &rap = item.props[ARTEFACT_PROPS_KEY].get_vector();
1197     for (vec_size i = 0; i < ART_PROPERTIES; i++)
1198         rap[i] = static_cast<short>(0);
1199
1200     if (is_unrandom_artefact(item))
1201     {
1202         const unrandart_entry *unrand = _seekunrandart(item);
1203
1204         for (int i = 0; i < ART_PROPERTIES; i++)
1205             rap[i] = static_cast<short>(unrand->prpty[i]);
1206
1207         return true;
1208     }
1209
1210     if (item.base_type == OBJ_BOOKS)
1211         return _init_artefact_book(item);
1212
1213     artefact_properties_t prop;
1214     _get_randart_properties(item, prop);
1215
1216     for (int i = 0; i < ART_PROPERTIES; i++)
1217     {
1218         if (i == ARTP_CURSED && prop[i] < 0)
1219         {
1220             do_curse_item(item);
1221             continue;
1222         }
1223         rap[i] = static_cast<short>(prop[i]);
1224     }
1225
1226     return true;
1227 }
1228
1229 void artefact_wpn_properties(const item_def &item,
1230                              artefact_properties_t  &proprt,
1231                              artefact_known_props_t &known)
1232 {
1233     ASSERT(is_artefact(item));
1234     if (!item.props.exists(KNOWN_PROPS_KEY))
1235         return;
1236
1237     const CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1238     ASSERT(_val.get_type() == SV_VEC);
1239     const CrawlVector &known_vec = _val.get_vector();
1240     ASSERT(known_vec.get_type()     == SV_BOOL);
1241     ASSERT(known_vec.size()         == ART_PROPERTIES);
1242     ASSERT(known_vec.get_max_size() == ART_PROPERTIES);
1243
1244     if (item_ident(item, ISFLAG_KNOW_PROPERTIES))
1245     {
1246         for (vec_size i = 0; i < ART_PROPERTIES; i++)
1247             known[i] = static_cast<bool>(true);
1248     }
1249     else
1250     {
1251         for (vec_size i = 0; i < ART_PROPERTIES; i++)
1252             known[i] = known_vec[i];
1253     }
1254
1255     if (item.props.exists(ARTEFACT_PROPS_KEY))
1256     {
1257         const CrawlVector &rap_vec =
1258             item.props[ARTEFACT_PROPS_KEY].get_vector();
1259         ASSERT(rap_vec.get_type()     == SV_SHORT);
1260         ASSERT(rap_vec.size()         == ART_PROPERTIES);
1261         ASSERT(rap_vec.get_max_size() == ART_PROPERTIES);
1262
1263         for (vec_size i = 0; i < ART_PROPERTIES; i++)
1264             proprt[i] = rap_vec[i].get_short();
1265     }
1266     else if (is_unrandom_artefact(item))
1267     {
1268         const unrandart_entry *unrand = _seekunrandart(item);
1269
1270         for (int i = 0; i < ART_PROPERTIES; i++)
1271             proprt[i] = static_cast<short>(unrand->prpty[i]);
1272     }
1273     else
1274         _get_randart_properties(item, proprt);
1275 }
1276
1277
1278 void artefact_wpn_properties(const item_def &item,
1279                               artefact_properties_t &proprt)
1280 {
1281     artefact_known_props_t known;
1282
1283     artefact_wpn_properties(item, proprt, known);
1284 }
1285
1286 int artefact_wpn_property(const item_def &item, artefact_prop_type prop,
1287                            bool &_known)
1288 {
1289     artefact_properties_t  proprt;
1290     artefact_known_props_t known;
1291     proprt.init(0);
1292     known.init(0);
1293
1294     artefact_wpn_properties(item, proprt, known);
1295
1296     _known = known[prop];
1297
1298     return proprt[prop];
1299 }
1300
1301 int artefact_wpn_property(const item_def &item, artefact_prop_type prop)
1302 {
1303     bool known;
1304
1305     return artefact_wpn_property(item, prop, known);
1306 }
1307
1308 int artefact_known_wpn_property(const item_def &item,
1309                                  artefact_prop_type prop)
1310 {
1311     artefact_properties_t  proprt;
1312     artefact_known_props_t known;
1313
1314     artefact_wpn_properties(item, proprt, known);
1315
1316     if (known[prop])
1317         return proprt[prop];
1318     else
1319         return 0;
1320 }
1321
1322 static int _artefact_num_props(const artefact_properties_t &proprt)
1323 {
1324     int num = 0;
1325
1326     // Count all properties, but exclude self-cursing.
1327     for (int i = 0; i < ARTP_NUM_PROPERTIES; ++i)
1328         if (i != ARTP_CURSED && proprt[i] != 0)
1329             num++;
1330
1331     return num;
1332 }
1333
1334 void artefact_wpn_learn_prop(item_def &item, artefact_prop_type prop)
1335 {
1336     ASSERT(is_artefact(item));
1337     ASSERT(item.props.exists(KNOWN_PROPS_KEY));
1338     CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1339     ASSERT(_val.get_type() == SV_VEC);
1340     CrawlVector &known_vec = _val.get_vector();
1341     ASSERT(known_vec.get_type()     == SV_BOOL);
1342     ASSERT(known_vec.size()         == ART_PROPERTIES);
1343     ASSERT(known_vec.get_max_size() == ART_PROPERTIES);
1344
1345     if (item_ident(item, ISFLAG_KNOW_PROPERTIES))
1346         return;
1347
1348     known_vec[prop] = static_cast<bool>(true);
1349     add_autoinscription(item);
1350 }
1351
1352 static std::string _get_artefact_type(const item_def &item,
1353                                       bool appear = false)
1354 {
1355     switch (item.base_type)
1356     {
1357     case OBJ_BOOKS:
1358         return "book";
1359     case OBJ_WEAPONS:
1360         return "weapon";
1361     case OBJ_ARMOUR:
1362         if (item.sub_type == ARM_ROBE)
1363             return "robe";
1364         if (get_item_slot(item) == EQ_BODY_ARMOUR)
1365             return "body armour";
1366         return "armour";
1367     case OBJ_JEWELLERY:
1368         // Distinguish between amulets and rings only in appearance.
1369         if (!appear)
1370             return "jewellery";
1371
1372         if (jewellery_is_amulet(item))
1373             return "amulet";
1374         else
1375             return "ring";
1376      default:
1377          return "artefact";
1378     }
1379 }
1380
1381 static bool _pick_db_name(const item_def &item)
1382 {
1383     switch (item.base_type)
1384     {
1385     case OBJ_WEAPONS:
1386     case OBJ_ARMOUR:
1387         return coinflip();
1388     case OBJ_JEWELLERY:
1389         return one_chance_in(5);
1390     default:
1391         return false;
1392     }
1393 }
1394
1395 static std::string _artefact_name_lookup(const item_def &item,
1396                                  const std::string &lookup)
1397 {
1398     const std::string name = getRandNameString(lookup);
1399     return name.empty() ? name : replace_name_parts(name, item);
1400 }
1401
1402 static bool _artefact_name_lookup(std::string &result,
1403                           const item_def &item,
1404                           const std::string &lookup)
1405 {
1406     result = _artefact_name_lookup(item, lookup);
1407     return !result.empty();
1408 }
1409
1410 std::string make_artefact_name(const item_def &item, bool appearance)
1411 {
1412     ASSERT(is_artefact(item));
1413
1414     ASSERT(item.base_type == OBJ_WEAPONS
1415            || item.base_type == OBJ_ARMOUR
1416            || item.base_type == OBJ_JEWELLERY
1417            || item.base_type == OBJ_BOOKS);
1418
1419     if (is_unrandom_artefact(item))
1420     {
1421         const unrandart_entry *unrand = _seekunrandart(item);
1422         if (!appearance)
1423             return unrand->name;
1424         if (!(unrand->flags & UNRAND_FLAG_RANDAPP))
1425             return unrand->unid_name;
1426     }
1427
1428     std::string lookup;
1429     std::string result;
1430
1431     // Use prefix of gifting god, if applicable.
1432     bool god_gift = false;
1433     int item_orig = 0;
1434     if (!appearance)
1435     {
1436         // Divine gifts don't look special, so this is only necessary
1437         // for actually naming an item.
1438         item_orig = item.orig_monnum;
1439         if (item_orig < 0)
1440             item_orig = -item_orig;
1441         else
1442             item_orig = 0;
1443
1444         if (item_orig > GOD_NO_GOD && item_orig < NUM_GODS)
1445         {
1446             lookup += god_name(static_cast<god_type>(item_orig), false) + " ";
1447             god_gift = true;
1448         }
1449     }
1450
1451     // get base type
1452     lookup += _get_artefact_type(item, appearance);
1453
1454     if (appearance)
1455     {
1456         std::string appear = getRandNameString(lookup, " appearance");
1457         if (appear.empty())
1458         {
1459             appear = getRandNameString("general appearance");
1460             if (appear.empty()) // still nothing found?
1461                 appear = "non-descript";
1462         }
1463
1464         result += appear;
1465         result += " ";
1466         result += item_base_name(item);
1467         return result;
1468     }
1469
1470     if (_pick_db_name(item))
1471     {
1472         result += item_base_name(item) + " ";
1473
1474         int tries = 100;
1475         std::string name;
1476         do
1477         {
1478             (_artefact_name_lookup(name, item, lookup)
1479
1480              // If nothing found, try god name alone.
1481              || (god_gift
1482                  && _artefact_name_lookup(name, item,
1483                                           god_name(
1484                                              static_cast<god_type>(item_orig),
1485                                              false)))
1486
1487              // If still nothing found, try base type alone.
1488              || _artefact_name_lookup(name, item, _get_artefact_type(item)));
1489         }
1490         while (--tries > 0 && strwidth(name) > 25);
1491
1492         if (name.empty()) // still nothing found?
1493             result += "of Bugginess";
1494         else
1495             result += name;
1496     }
1497     else
1498     {
1499         // construct a unique name
1500         const std::string st_p = make_name(random_int(), false);
1501         result += item_base_name(item);
1502
1503         if (one_chance_in(3))
1504         {
1505             result += " of ";
1506             result += st_p;
1507         }
1508         else
1509         {
1510             result += " \"";
1511             result += st_p;
1512             result += "\"";
1513         }
1514     }
1515
1516     return result;
1517 }
1518
1519 std::string get_artefact_name(const item_def &item, bool force_known)
1520 {
1521     ASSERT(is_artefact(item));
1522
1523     if (item_type_known(item) || force_known)
1524     {
1525         // print artefact's real name
1526         if (item.props.exists(ARTEFACT_NAME_KEY))
1527             return item.props[ARTEFACT_NAME_KEY].get_string();
1528         return make_artefact_name(item, false);
1529     }
1530     // print artefact appearance
1531     if (item.props.exists(ARTEFACT_APPEAR_KEY))
1532         return item.props[ARTEFACT_APPEAR_KEY].get_string();
1533     return make_artefact_name(item, true);
1534 }
1535
1536 void set_artefact_name(item_def &item, const std::string &name)
1537 {
1538     ASSERT(is_artefact(item));
1539     ASSERT(!name.empty());
1540     item.props[ARTEFACT_NAME_KEY].get_string() = name;
1541 }
1542
1543 int find_unrandart_index(const item_def& artefact)
1544 {
1545     return artefact.special;
1546 }
1547
1548 unrandart_entry* get_unrand_entry(int unrand_index)
1549 {
1550     unrand_index -= UNRAND_START;
1551
1552     if (unrand_index <= -1 || unrand_index >= NO_UNRANDARTS)
1553         return &unranddata[0];  // dummy unrandart
1554     else
1555         return &unranddata[unrand_index];
1556 }
1557
1558 static unrandart_entry *_seekunrandart(const item_def &item)
1559 {
1560     return get_unrand_entry(item.special);
1561 }
1562
1563 int find_okay_unrandart(uint8_t aclass, uint8_t atype, bool in_abyss)
1564 {
1565     int ret = -1;
1566
1567     // Pick randomly among not-yet-existing unrandarts with the proper
1568     // base_type and sub_type.
1569     for (int i = 0, count = 0; i < NO_UNRANDARTS; i++)
1570     {
1571         const int              index = i + UNRAND_START;
1572         const unrandart_entry* entry = &unranddata[i];
1573
1574         // Skip dummy entries.
1575         if (entry->base_type == OBJ_UNASSIGNED)
1576             continue;
1577
1578         const unique_item_status_type status =
1579             get_unique_item_status(index);
1580
1581         if (in_abyss && status != UNIQ_LOST_IN_ABYSS
1582             || !in_abyss && status != UNIQ_NOT_EXISTS)
1583         {
1584             continue;
1585         }
1586
1587         // Never randomly generated until lost in the abyss.
1588         if ((!in_abyss || status != UNIQ_LOST_IN_ABYSS)
1589             && entry->flags & UNRAND_FLAG_NOGEN)
1590         {
1591             continue;
1592         }
1593
1594         if (entry->base_type != aclass
1595             || atype != OBJ_RANDOM && entry->sub_type != atype
1596                // Acquirement.
1597                && (aclass != OBJ_WEAPONS
1598                    || weapon_skill(entry->base_type, atype) !=
1599                       weapon_skill(entry->base_type, entry->sub_type)
1600                    || hands_reqd(entry->base_type,
1601                                  atype,
1602                                  you.body_size()) !=
1603                       hands_reqd(entry->base_type,
1604                                  entry->sub_type,
1605                                  you.body_size())))
1606         {
1607             continue;
1608         }
1609
1610         count++;
1611
1612         if (one_chance_in(count))
1613             ret = index;
1614     }
1615
1616     return ret;
1617 }
1618
1619 int get_unrandart_num(const char *name)
1620 {
1621     std::string quoted = "\"";
1622     quoted += name;
1623     quoted += "\"";
1624     lowercase(quoted);
1625
1626     for (unsigned int i = 0; i < ARRAYSZ(unranddata); ++i)
1627     {
1628         std::string art = unranddata[i].name;
1629         art = replace_all(art, " ", "_");
1630         art = replace_all(art, "'", "");
1631         lowercase(art);
1632         if (art == name || art.find(quoted) != std::string::npos)
1633             return UNRAND_START + i;
1634     }
1635     return SPWPN_NORMAL;
1636 }
1637
1638 static bool _randart_is_redundant(const item_def &item,
1639                                    artefact_properties_t &proprt)
1640 {
1641     if (item.base_type != OBJ_JEWELLERY)
1642         return false;
1643
1644     artefact_prop_type provides  = ARTP_NUM_PROPERTIES;
1645     artefact_prop_type provides2 = ARTP_NUM_PROPERTIES;
1646
1647     switch (item.sub_type)
1648     {
1649     case RING_PROTECTION:
1650         provides = ARTP_AC;
1651         break;
1652
1653     case RING_FIRE:
1654     case RING_PROTECTION_FROM_FIRE:
1655         provides = ARTP_FIRE;
1656         break;
1657
1658     case RING_POISON_RESISTANCE:
1659         provides = ARTP_POISON;
1660         break;
1661
1662     case RING_ICE:
1663     case RING_PROTECTION_FROM_COLD:
1664         provides = ARTP_COLD;
1665         break;
1666
1667     case RING_STRENGTH:
1668         provides = ARTP_STRENGTH;
1669         break;
1670
1671     case RING_SLAYING:
1672         provides  = ARTP_DAMAGE;
1673         provides2 = ARTP_ACCURACY;
1674         break;
1675
1676     case RING_SEE_INVISIBLE:
1677         provides = ARTP_EYESIGHT;
1678         break;
1679
1680     case RING_INVISIBILITY:
1681         provides = ARTP_INVISIBLE;
1682         break;
1683
1684     case RING_HUNGER:
1685         provides = ARTP_METABOLISM;
1686         break;
1687
1688     case RING_TELEPORTATION:
1689         provides = ARTP_CAUSE_TELEPORTATION;
1690         break;
1691
1692     case RING_EVASION:
1693         provides = ARTP_EVASION;
1694         break;
1695
1696     case RING_DEXTERITY:
1697         provides = ARTP_DEXTERITY;
1698         break;
1699
1700     case RING_INTELLIGENCE:
1701         provides = ARTP_INTELLIGENCE;
1702         break;
1703
1704     case RING_MAGICAL_POWER:
1705         provides = ARTP_MAGICAL_POWER;
1706         break;
1707
1708     case RING_LEVITATION:
1709         provides = ARTP_LEVITATE;
1710         break;
1711
1712     case RING_LIFE_PROTECTION:
1713         provides = ARTP_AC;
1714         break;
1715
1716     case RING_PROTECTION_FROM_MAGIC:
1717         provides = ARTP_MAGIC;
1718         break;
1719
1720     case AMU_RAGE:
1721         provides = ARTP_BERSERK;
1722         break;
1723
1724     case AMU_INACCURACY:
1725         provides = ARTP_ACCURACY;
1726         break;
1727
1728     case AMU_STASIS:
1729         provides = ARTP_PREVENT_TELEPORTATION;
1730         break;
1731     }
1732
1733     if (provides == ARTP_NUM_PROPERTIES)
1734         return false;
1735
1736     if (proprt[provides] != 0)
1737         return true;
1738
1739     if (provides2 == ARTP_NUM_PROPERTIES)
1740         return false;
1741
1742     if (proprt[provides2] != 0)
1743         return true;
1744
1745     return false;
1746 }
1747
1748 static bool _randart_is_conflicting(const item_def &item,
1749                                      artefact_properties_t &proprt)
1750 {
1751     if (item.base_type == OBJ_WEAPONS
1752         && get_weapon_brand(item) == SPWPN_HOLY_WRATH
1753         && (is_demonic(item)
1754             || proprt[ARTP_CURSED] != 0))
1755     {
1756         return true;
1757     }
1758
1759     if (item.base_type != OBJ_JEWELLERY)
1760         return false;
1761
1762     if (item.sub_type == AMU_STASIS
1763         && (proprt[ARTP_BLINK] != 0
1764             || proprt[ARTP_CAUSE_TELEPORTATION] != 0
1765             || proprt[ARTP_ANGRY] != 0
1766             || proprt[ARTP_BERSERK] != 0))
1767     {
1768         return true;
1769     }
1770
1771     if (item.sub_type == RING_WIZARDRY && proprt[ARTP_INTELLIGENCE] < 0)
1772         return true;
1773
1774     artefact_prop_type conflicts = ARTP_NUM_PROPERTIES;
1775
1776     switch (item.sub_type)
1777     {
1778     case RING_SUSTENANCE:
1779         conflicts = ARTP_METABOLISM;
1780         break;
1781
1782     case RING_FIRE:
1783     case RING_ICE:
1784     case RING_WIZARDRY:
1785     case RING_MAGICAL_POWER:
1786         conflicts = ARTP_PREVENT_SPELLCASTING;
1787         break;
1788
1789     case RING_TELEPORTATION:
1790     case RING_TELEPORT_CONTROL:
1791         conflicts = ARTP_PREVENT_TELEPORTATION;
1792         break;
1793
1794     case AMU_RESIST_MUTATION:
1795         conflicts = ARTP_MUTAGENIC;
1796         break;
1797
1798     case AMU_RAGE:
1799         conflicts = ARTP_STEALTH;
1800         break;
1801     }
1802
1803     if (conflicts == ARTP_NUM_PROPERTIES)
1804         return false;
1805
1806     if (proprt[conflicts] != 0)
1807         return true;
1808
1809     return false;
1810 }
1811
1812 bool randart_is_bad(const item_def &item, artefact_properties_t &proprt)
1813 {
1814     if (item.base_type == OBJ_BOOKS)
1815         return false;
1816
1817     if (_artefact_num_props(proprt) == 0)
1818         return true;
1819
1820     // Weapons must have a brand and at least one other property.
1821     if (item.base_type == OBJ_WEAPONS
1822         && (proprt[ARTP_BRAND] == SPWPN_NORMAL
1823             || _artefact_num_props(proprt) < 2))
1824     {
1825         return true;
1826     }
1827
1828     return (_randart_is_redundant(item, proprt)
1829             || _randart_is_conflicting(item, proprt));
1830 }
1831
1832 bool randart_is_bad(const item_def &item)
1833 {
1834     artefact_properties_t proprt;
1835     artefact_wpn_properties(item, proprt);
1836
1837     return randart_is_bad(item, proprt);
1838 }
1839
1840 static void _artefact_setup_prop_vectors(item_def &item)
1841 {
1842     CrawlHashTable &props = item.props;
1843     if (!props.exists(ARTEFACT_PROPS_KEY))
1844         props[ARTEFACT_PROPS_KEY].new_vector(SV_SHORT).resize(ART_PROPERTIES);
1845
1846     CrawlVector &rap = props[ARTEFACT_PROPS_KEY].get_vector();
1847     rap.set_max_size(ART_PROPERTIES);
1848
1849     for (vec_size i = 0; i < ART_PROPERTIES; i++)
1850         rap[i].get_short() = 0;
1851
1852     if (!item.props.exists(KNOWN_PROPS_KEY))
1853     {
1854         props[KNOWN_PROPS_KEY].new_vector(SV_BOOL).resize(ART_PROPERTIES);
1855         CrawlVector &known = item.props[KNOWN_PROPS_KEY].get_vector();
1856         known.set_max_size(ART_PROPERTIES);
1857         for (vec_size i = 0; i < ART_PROPERTIES; i++)
1858             known[i] = static_cast<bool>(false);
1859     }
1860 }
1861
1862 // If force_mundane is true, normally mundane items are forced to
1863 // nevertheless become artefacts.
1864 bool make_item_randart(item_def &item, bool force_mundane)
1865 {
1866     if (item.base_type != OBJ_WEAPONS
1867         && item.base_type != OBJ_ARMOUR
1868         && item.base_type != OBJ_JEWELLERY
1869         && item.base_type != OBJ_BOOKS)
1870     {
1871         return false;
1872     }
1873
1874     if (item.base_type == OBJ_BOOKS)
1875     {
1876         if (item.sub_type != BOOK_RANDART_LEVEL
1877             && item.sub_type != BOOK_RANDART_THEME)
1878         {
1879             return false;
1880         }
1881     }
1882
1883     // This item already is a randart.
1884     if (item.flags & ISFLAG_RANDART)
1885         return true;
1886
1887     // Not a truly random artefact.
1888     if (item.flags & ISFLAG_UNRANDART)
1889         return false;
1890
1891     // Mundane items are much less likely to be artefacts.
1892     if (!force_mundane && item.is_mundane() && !one_chance_in(5))
1893         return false;
1894
1895     _artefact_setup_prop_vectors(item);
1896     item.flags |= ISFLAG_RANDART;
1897
1898     god_type god_gift;
1899     (void) origin_is_god_gift(item, &god_gift);
1900
1901     int randart_tries = 500;
1902     do
1903     {
1904         // Now that we found something, initialise the props array.
1905         if (--randart_tries <= 0 || !_init_artefact_properties(item))
1906         {
1907             // Something went wrong that no amount of rerolling will fix.
1908             item.special = 0;
1909             item.props.erase(ARTEFACT_PROPS_KEY);
1910             item.props.erase(KNOWN_PROPS_KEY);
1911             item.flags &= ~ISFLAG_RANDART;
1912             return false;
1913         }
1914     }
1915     while (randart_is_bad(item)
1916            || god_gift != GOD_NO_GOD && !_god_fits_artefact(god_gift, item));
1917
1918     // get true artefact name
1919     if (item.props.exists(ARTEFACT_NAME_KEY))
1920         ASSERT(item.props[ARTEFACT_NAME_KEY].get_type() == SV_STR);
1921     else
1922         set_artefact_name(item, make_artefact_name(item, false));
1923
1924     // get artefact appearance
1925     if (item.props.exists(ARTEFACT_APPEAR_KEY))
1926         ASSERT(item.props[ARTEFACT_APPEAR_KEY].get_type() == SV_STR);
1927     else
1928         item.props[ARTEFACT_APPEAR_KEY].get_string() =
1929             make_artefact_name(item, true);
1930
1931     return true;
1932 }
1933
1934 static void _make_faerie_armour(item_def &item)
1935 {
1936     item_def doodad;
1937     for (int i=0; i<100; i++)
1938     {
1939         doodad.clear();
1940         doodad.base_type = item.base_type;
1941         doodad.sub_type = item.sub_type;
1942         if (!make_item_randart(doodad))
1943         {
1944             i--; // Forbidden props are not absolute, artefactness is.
1945             continue;
1946         }
1947
1948         // These make little sense for a casting mon.
1949         if (artefact_wpn_property(doodad, ARTP_BERSERK)
1950             || artefact_wpn_property(doodad, ARTP_ANGRY)
1951             || artefact_wpn_property(doodad, ARTP_PREVENT_SPELLCASTING)
1952             || artefact_wpn_property(doodad, ARTP_CAUSE_TELEPORTATION)
1953             || artefact_wpn_property(doodad, ARTP_PREVENT_TELEPORTATION)
1954             || artefact_wpn_property(doodad, ARTP_MUTAGENIC))
1955         {
1956             continue;
1957         }
1958
1959         if (one_chance_in(20))
1960             artefact_set_property(doodad, ARTP_CLARITY, 1);
1961         if (one_chance_in(20))
1962             artefact_set_property(doodad, ARTP_MAGICAL_POWER, 1 + random2(10));
1963         if (one_chance_in(20))
1964             artefact_set_property(doodad, ARTP_HP, random2(21) - 10);
1965
1966         break;
1967     }
1968     ASSERT(is_artefact(doodad));
1969     ASSERT(doodad.sub_type == item.sub_type);
1970
1971     doodad.props[ARTEFACT_NAME_KEY].get_string()
1972         = item.props[ARTEFACT_NAME_KEY].get_string();
1973     doodad.props[ARTEFACT_APPEAR_KEY].get_string()
1974         = item.props[ARTEFACT_APPEAR_KEY].get_string();
1975     item.props = doodad.props;
1976     item.plus = 2 + random2(5);
1977 }
1978
1979 static jewellery_type octoring_types[8] =
1980 {
1981     RING_REGENERATION, RING_PROTECTION_FROM_FIRE, RING_PROTECTION_FROM_COLD,
1982     RING_SUSTAIN_ABILITIES, RING_SUSTENANCE, RING_WIZARDRY, RING_MAGICAL_POWER,
1983     RING_LIFE_PROTECTION
1984 };
1985
1986 static void _make_octoring(item_def &item)
1987 {
1988     if (you.octopus_king_rings == 255)
1989     {
1990         ASSERT(you.wizard);
1991         item.sub_type = octoring_types[random2(8)];
1992         return;
1993     }
1994
1995     int which = 0;
1996     do which = random2(8); while (you.octopus_king_rings & (1 << which));
1997
1998     item.sub_type = octoring_types[which];
1999
2000     // Save that we've found that particular type
2001     you.octopus_king_rings |= 1 << which;
2002
2003     // If there are any types left, unset the 'already found' flag
2004     if (you.octopus_king_rings != 255)
2005         _set_unique_item_status(UNRAND_OCTOPUS_KING_RING, UNIQ_NOT_EXISTS);
2006 }
2007
2008 bool make_item_unrandart(item_def &item, int unrand_index)
2009 {
2010     ASSERT(unrand_index > UNRAND_START);
2011     ASSERT(unrand_index < (UNRAND_START + NO_UNRANDARTS));
2012
2013     item.special = unrand_index;
2014
2015     const unrandart_entry *unrand = &unranddata[unrand_index - UNRAND_START];
2016     item.base_type = unrand->base_type;
2017     item.sub_type  = unrand->sub_type;
2018     item.plus      = unrand->plus;
2019     item.plus2     = unrand->plus2;
2020     item.colour    = unrand->colour;
2021
2022     item.flags |= ISFLAG_UNRANDART;
2023     _artefact_setup_prop_vectors(item);
2024     _init_artefact_properties(item);
2025
2026     if (unrand->prpty[ARTP_CURSED] != 0)
2027         do_curse_item(item);
2028
2029     // get true artefact name
2030     ASSERT(!item.props.exists(ARTEFACT_NAME_KEY));
2031     item.props[ARTEFACT_NAME_KEY].get_string() = unrand->name;
2032
2033     // get artefact appearance
2034     ASSERT(!item.props.exists(ARTEFACT_APPEAR_KEY));
2035     if (!(unrand->flags & UNRAND_FLAG_RANDAPP))
2036         item.props[ARTEFACT_APPEAR_KEY].get_string() = unrand->unid_name;
2037     else
2038     {
2039         item.props[ARTEFACT_APPEAR_KEY].get_string() = make_artefact_name(item, true);
2040         item_colour(item);
2041     }
2042
2043     _set_unique_item_status(unrand_index, UNIQ_EXISTS);
2044
2045     if (unrand_index == UNRAND_VARIABILITY)
2046     {
2047         item.plus  = random_range(-4, 16);
2048         item.plus2 = random_range(-4, 16);
2049     }
2050     else if (unrand_index == UNRAND_FAERIE)
2051         _make_faerie_armour(item);
2052     else if (unrand_index == UNRAND_OCTOPUS_KING_RING)
2053         _make_octoring(item);
2054
2055     if (!(unrand->flags & UNRAND_FLAG_RANDAPP)
2056         && !(unrand->flags & UNRAND_FLAG_UNIDED)
2057         && !strcmp(unrand->name, unrand->unid_name))
2058     {
2059         set_ident_flags(item, ISFLAG_IDENT_MASK | ISFLAG_NOTED_ID);
2060         add_autoinscription(item);
2061     }
2062
2063     return true;
2064 }
2065
2066 void unrand_reacts()
2067 {
2068     item_def*  weapon     = you.weapon();
2069     const int  old_plus   = weapon ? weapon->plus   : 0;
2070     const int  old_plus2  = weapon ? weapon->plus2  : 0;
2071
2072     for (int i = 0; i < NUM_EQUIP; i++)
2073     {
2074         if (you.unrand_reacts & (1 << i))
2075         {
2076             item_def&        item  = you.inv[you.equip[i]];
2077             unrandart_entry* entry = get_unrand_entry(item.special);
2078
2079             entry->world_reacts_func(&item);
2080         }
2081     }
2082
2083     if (weapon && (old_plus != weapon->plus || old_plus2 != weapon->plus2))
2084         you.wield_change = true;
2085 }
2086
2087 void artefact_set_property(item_def          &item,
2088                             artefact_prop_type prop,
2089                             int                val)
2090 {
2091     ASSERT(is_artefact(item));
2092     ASSERT(item.props.exists(ARTEFACT_PROPS_KEY));
2093
2094     CrawlVector &rap_vec = item.props[ARTEFACT_PROPS_KEY].get_vector();
2095     ASSERT(rap_vec.get_type()     == SV_SHORT);
2096     ASSERT(rap_vec.size()         == ART_PROPERTIES);
2097     ASSERT(rap_vec.get_max_size() == ART_PROPERTIES);
2098
2099     rap_vec[prop].get_short() = val;
2100 }
2101
2102 template<typename Z>
2103 static inline void artefact_pad_store_vector(CrawlVector &vec, Z value)
2104 {
2105     if (vec.get_max_size() < ART_PROPERTIES)
2106     {
2107         // Authentic tribal dance to propitiate the asserts in store.cc:
2108         const int old_size = vec.get_max_size();
2109         vec.set_max_size(VEC_MAX_SIZE);
2110         vec.resize(ART_PROPERTIES);
2111         vec.set_max_size(ART_PROPERTIES);
2112         for (int i = old_size; i < ART_PROPERTIES; ++i)
2113             vec[i] = value;
2114     }
2115 }
2116
2117 void artefact_fixup_props(item_def &item)
2118 {
2119     CrawlHashTable &props = item.props;
2120     if (props.exists(ARTEFACT_PROPS_KEY))
2121         artefact_pad_store_vector(props[ARTEFACT_PROPS_KEY], short(0));
2122
2123     if (props.exists(KNOWN_PROPS_KEY))
2124         artefact_pad_store_vector(props[KNOWN_PROPS_KEY], false);
2125 }