Apply the new ground_level method.
[crawl.git] / crawl-ref / source / artefact.cc
blob1a50b64da2fb9c97b9109270e79672db30c3a758
1 /*
2 * File: artefact.cc
3 * Summary: Random and unrandom artefact functions.
4 * Written by: Linley Henzell
5 */
7 #include "AppHdr.h"
9 #include "artefact.h"
11 #include <cstdlib>
12 #include <climits>
13 #include <string.h>
14 #include <stdio.h>
15 #include <algorithm>
17 #include "externs.h"
18 #include "options.h"
20 #include "areas.h"
21 #include "colour.h"
22 #include "coordit.h"
23 #include "database.h"
24 #include "describe.h"
25 #include "itemname.h"
26 #include "itemprop.h"
27 #include "items.h"
28 #include "libutil.h"
29 #include "makeitem.h"
30 #include "place.h"
31 #include "player.h"
32 #include "random.h"
33 #include "religion.h"
34 #include "species.h"
35 #include "spl-book.h"
36 #include "stuff.h"
37 #include "view.h" // Elemental colours for unrandarts
38 #include "shout.h"
40 // The initial generation of a randart is very simple - it occurs in
41 // dungeon.cc and consists of giving it a few random things - plus &
42 // plus2 mainly.
44 static bool _god_fits_artefact(const god_type which_god, const item_def &item,
45 bool name_check_only = false)
47 if (which_god == GOD_NO_GOD)
48 return (false);
50 // Jellies can't eat artefacts, so their god won't make any.
51 if (which_god == GOD_JIYVA)
52 return (false);
54 // First check the item's base_type and sub_type, then check the
55 // item's brand and other randart properties.
56 bool type_bad = false;
57 switch (which_god)
59 case GOD_ELYVILON:
60 // Peaceful healer god: no weapons, no berserking.
61 if (item.base_type == OBJ_WEAPONS)
62 type_bad = true;
64 if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_RAGE)
65 type_bad = true;
66 break;
68 case GOD_OKAWARU:
69 // Precision fighter god: no inaccuracy.
70 if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_INACCURACY)
71 type_bad = true;
72 break;
74 case GOD_ZIN:
75 // Lawful god: no increased hunger.
76 if (item.base_type == OBJ_JEWELLERY && item.sub_type == RING_HUNGER)
77 type_bad = true;
78 break;
80 case GOD_SIF_MUNA:
81 case GOD_KIKUBAAQUDGHA:
82 case GOD_VEHUMET:
83 // The magic gods: no weapons, no preventing spellcasting.
84 if (item.base_type == OBJ_WEAPONS)
85 type_bad = true;
86 break;
88 case GOD_TROG:
89 // Anti-magic god: no spell use, no enhancing magic.
90 if (item.base_type == OBJ_BOOKS)
91 type_bad = true;
93 if (item.base_type == OBJ_JEWELLERY && (item.sub_type == RING_WIZARDRY
94 || item.sub_type == RING_FIRE || item.sub_type == RING_ICE
95 || item.sub_type == RING_MAGICAL_POWER))
97 type_bad = true;
99 break;
101 case GOD_CHEIBRIADOS:
102 // Slow god: no quick blades, no berserking, no resist slowing.
103 if (item.base_type == OBJ_WEAPONS && item.sub_type == WPN_QUICK_BLADE)
104 type_bad = true;
106 if (item.base_type == OBJ_JEWELLERY && item.sub_type == AMU_RAGE)
107 type_bad = true;
108 break;
110 default:
111 break;
114 if (type_bad && !name_check_only)
116 die("%s attempting to gift invalid type of item.",
117 god_name(which_god).c_str());
120 if (type_bad)
121 return (false);
123 const int brand = get_weapon_brand(item);
124 const int ego = get_armour_ego_type(item);
126 if (is_evil_god(which_god) && brand == SPWPN_HOLY_WRATH)
127 return (false);
128 else if (is_good_god(which_god)
129 && (brand == SPWPN_DRAINING || brand == SPWPN_PAIN
130 || brand == SPWPN_VAMPIRICISM || brand == SPWPN_REAPING
131 || brand == SPWPN_CHAOS
132 || is_demonic(item)
133 || artefact_wpn_property(item, ARTP_CURSED) != 0))
135 return (false);
138 switch (which_god)
140 case GOD_BEOGH:
141 // Orc god: no orc slaying.
142 if (brand == SPWPN_ORC_SLAYING)
143 return (false);
144 break;
146 case GOD_ELYVILON:
147 // Peaceful healer god: no berserking.
148 if (artefact_wpn_property(item, ARTP_ANGRY)
149 || artefact_wpn_property(item, ARTP_BERSERK))
151 return (false);
153 break;
155 case GOD_ZIN:
156 // Lawful god: no mutagenics.
157 if (artefact_wpn_property(item, ARTP_MUTAGENIC))
158 return (false);
159 break;
161 case GOD_SHINING_ONE:
162 // Crusader god: holiness, honourable combat.
163 if (item.base_type == OBJ_WEAPONS && brand != SPWPN_HOLY_WRATH)
164 return (false);
166 if (artefact_wpn_property(item, ARTP_INVISIBLE)
167 || artefact_wpn_property(item, ARTP_STEALTH) > 0)
169 return (false);
171 break;
173 case GOD_LUGONU:
174 // Abyss god: corruption.
175 if (item.base_type == OBJ_WEAPONS && brand != SPWPN_DISTORTION)
176 return (false);
177 break;
179 case GOD_SIF_MUNA:
180 case GOD_KIKUBAAQUDGHA:
181 case GOD_VEHUMET:
182 // The magic gods: no preventing spellcasting.
183 if (artefact_wpn_property(item, ARTP_PREVENT_SPELLCASTING))
184 return (false);
185 break;
187 case GOD_TROG:
188 // Anti-magic god: no spell use, no enhancing magic.
189 if (brand == SPWPN_PAIN) // Pain involves necromantic spell use.
190 return (false);
192 if (artefact_wpn_property(item, ARTP_MAGICAL_POWER))
193 return (false);
194 break;
196 case GOD_FEDHAS:
197 // Fedhas forbids necromancy involving corpses, only reaping
198 // really applies.
199 if (brand == SPWPN_REAPING)
200 return (false);
201 break;
203 case GOD_CHEIBRIADOS:
204 // Slow god: no speed, no berserking.
205 if (brand == SPWPN_SPEED)
206 return (false);
208 if (ego == SPARM_RUNNING)
209 return (false);
211 if (artefact_wpn_property(item, ARTP_ANGRY)
212 || artefact_wpn_property(item, ARTP_BERSERK))
214 return (false);
216 break;
218 default:
219 break;
222 return (true);
225 static std::string _replace_name_parts(const std::string name_in,
226 const item_def& item)
228 std::string name = name_in;
230 god_type god_gift;
231 (void) origin_is_god_gift(item, &god_gift);
233 // Don't allow "player's Death" type names for god gifts (except
234 // for those from Xom).
235 if (name.find("@player_death@", 0) != std::string::npos
236 || name.find("@player_doom@", 0) != std::string::npos)
238 if (god_gift == GOD_NO_GOD || god_gift == GOD_XOM)
240 name = replace_all(name, "@player_death@",
241 "@player_name@"
242 + getRandNameString("killer_name"));
243 name = replace_all(name, "@player_doom@",
244 "@player_name@'s "
245 + getRandNameString("death_or_doom"));
247 else
249 // Simply overwrite the name with one of type "God's Favour".
250 name = "of ";
251 name += god_name(god_gift, false);
252 name += "'s ";
253 name += getRandNameString("divine_esteem");
256 name = replace_all(name, "@player_name@", you.your_name);
258 name = replace_all(name, "@player_species@",
259 species_name(static_cast<species_type>(you.species), true));
261 if (name.find("@branch_name@", 0) != std::string::npos)
263 std::string place;
264 if (one_chance_in(5))
266 switch (random2(8))
268 case 0:
269 case 1:
270 default:
271 place = "the Abyss";
272 break;
273 case 2:
274 case 3:
275 place = "Pandemonium";
276 break;
277 case 4:
278 case 5:
279 place = "the Realm of Zot";
280 break;
281 case 6:
282 place = "the Labyrinth";
283 break;
284 case 7:
285 place = "the Portal Chambers";
286 break;
289 else
291 const branch_type branch =
292 static_cast<branch_type>(random2(BRANCH_TARTARUS));
293 place = place_name(get_packed_place(branch, 1, LEVEL_DUNGEON),
294 true, false);
296 if (!place.empty())
297 name = replace_all(name, "@branch_name@", place);
300 // Occasionally use long name for Xom (see religion.cc).
301 name = replace_all(name, "@xom_name@", god_name(GOD_XOM, coinflip()));
303 if (name.find("@god_name@", 0) != std::string::npos)
305 god_type which_god;
307 // God gifts will always get the gifting god's name.
308 if (god_gift != GOD_NO_GOD)
309 which_god = god_gift;
310 else
313 which_god = static_cast<god_type>(random2(NUM_GODS - 1) + 1);
314 while (!_god_fits_artefact(which_god, item, true));
317 name = replace_all(name, "@god_name@", god_name(which_god, false));
320 // copied from monster speech handling (mon-util.cc):
321 // The proper possessive for a word ending in an "s" is to
322 // put an apostrophe after the "s": "Chris" -> "Chris'",
323 // not "Chris" -> "Chris's". Stupid English language...
324 name = replace_all(name, "s's", "s'");
326 return name;
329 // Remember: disallow unrandart creation in Abyss/Pan.
331 // Functions defined in art-func.h are referenced in art-data.h
332 #include "art-func.h"
334 static unrandart_entry unranddata[] = {
335 #include "art-data.h"
338 static unrandart_entry *_seekunrandart(const item_def &item);
340 bool is_known_artefact(const item_def &item)
342 if (!item_type_known(item))
343 return (false);
345 return (is_artefact(item));
348 bool is_artefact(const item_def &item)
350 return (item.flags & ISFLAG_ARTEFACT_MASK);
353 // returns true is item is a pure randart
354 bool is_random_artefact(const item_def &item)
356 return (item.flags & ISFLAG_RANDART);
359 // returns true if item in an unrandart
360 bool is_unrandom_artefact(const item_def &item)
362 return (item.flags & ISFLAG_UNRANDART);
365 bool is_special_unrandom_artefact(const item_def &item)
367 return (item.flags & ISFLAG_UNRANDART
368 && (_seekunrandart(item)->flags & UNRAND_FLAG_SPECIAL));
371 unique_item_status_type get_unique_item_status(const item_def& item)
373 if (item.flags & ISFLAG_UNRANDART)
374 return get_unique_item_status(item.special);
376 return (UNIQ_NOT_EXISTS);
379 unique_item_status_type get_unique_item_status(int art)
381 ASSERT(art > UNRAND_START && art < UNRAND_LAST);
382 return (you.unique_items[art - UNRAND_START]);
385 void set_unique_item_status(const item_def& item,
386 unique_item_status_type status)
388 if (item.flags & ISFLAG_UNRANDART)
389 set_unique_item_status(item.special, status);
392 void set_unique_item_status(int art, unique_item_status_type status)
394 ASSERT(art > UNRAND_START && art < UNRAND_LAST);
395 you.unique_items[art - UNRAND_START] = status;
398 static uint32_t _calc_seed(const item_def &item)
400 return (item.special & RANDART_SEED_MASK);
403 void artefact_desc_properties(const item_def &item,
404 artefact_properties_t &proprt,
405 artefact_known_props_t &known,
406 bool force_fake_props)
408 // Randart books have no randart properties.
409 if (item.base_type == OBJ_BOOKS)
410 return;
412 artefact_wpn_properties(item, proprt, known);
414 if (!force_fake_props && item_ident(item, ISFLAG_KNOW_PROPERTIES))
415 return;
417 // Only jewellery need fake randart properties.
418 if (item.base_type != OBJ_JEWELLERY)
419 return;
421 artefact_prop_type fake_rap = ARTP_NUM_PROPERTIES;
422 int fake_plus = 1;
424 // The base jewellery type is one whose property is revealed by
425 // wearing it, but whose property isn't revealed by having
426 // ISFLAG_KNOW_PLUSES set. For a randart with a base type of, for
427 // example, a ring of strength, wearing it sets
428 // ISFLAG_KNOW_PLUSES, which reveals the ring's strength plus.
429 switch (item.sub_type)
431 case RING_INVISIBILITY:
432 fake_rap = ARTP_INVISIBLE;
433 break;
435 case RING_TELEPORTATION:
436 fake_rap = ARTP_CAUSE_TELEPORTATION;
437 break;
439 case RING_MAGICAL_POWER:
440 fake_rap = ARTP_MAGICAL_POWER;
441 fake_plus = 9;
442 break;
444 case RING_LEVITATION:
445 fake_rap = ARTP_LEVITATE;
446 break;
448 case AMU_RAGE:
449 fake_rap = ARTP_BERSERK;
450 break;
453 if (fake_rap != ARTP_NUM_PROPERTIES)
455 proprt[fake_rap] += fake_plus;
457 if (item_ident(item, ISFLAG_KNOW_PROPERTIES)
458 || item_ident(item, ISFLAG_KNOW_TYPE))
460 known[fake_rap] = true;
463 return;
466 if (!force_fake_props)
467 return;
469 // For auto-inscribing randart jewellery, force_fake_props folds as
470 // much info about the base type as possible into the randarts
471 // property struct.
473 artefact_prop_type fake_rap2 = ARTP_NUM_PROPERTIES;
474 int fake_plus2 = 1;
476 switch (item.sub_type)
478 case RING_PROTECTION:
479 fake_rap = ARTP_AC;
480 fake_plus = item.plus;
481 break;
483 case RING_PROTECTION_FROM_FIRE:
484 fake_rap = ARTP_FIRE;
485 break;
487 case RING_POISON_RESISTANCE:
488 fake_rap = ARTP_POISON;
489 break;
491 case RING_PROTECTION_FROM_COLD:
492 fake_rap = ARTP_COLD;
493 break;
495 case RING_SLAYING:
496 fake_rap = ARTP_ACCURACY;
497 fake_plus = item.plus;
498 fake_rap2 = ARTP_DAMAGE;
499 fake_plus2 = item.plus2;
500 break;
502 case RING_SEE_INVISIBLE:
503 fake_rap = ARTP_EYESIGHT;
504 break;
506 case RING_HUNGER:
507 fake_rap = ARTP_METABOLISM;
508 break;
510 case RING_EVASION:
511 fake_rap = ARTP_EVASION;
512 fake_plus = item.plus;
513 break;
515 case RING_STRENGTH:
516 fake_rap = ARTP_STRENGTH;
517 fake_plus = item.plus;
518 break;
520 case RING_INTELLIGENCE:
521 fake_rap = ARTP_INTELLIGENCE;
522 fake_plus = item.plus;
523 break;
525 case RING_DEXTERITY:
526 fake_rap = ARTP_DEXTERITY;
527 fake_plus = item.plus;
528 break;
530 case RING_LIFE_PROTECTION:
531 fake_rap = ARTP_NEGATIVE_ENERGY;
532 break;
534 case RING_PROTECTION_FROM_MAGIC:
535 fake_rap = ARTP_MAGIC;
536 break;
538 case RING_FIRE:
539 fake_rap = ARTP_FIRE;
540 fake_rap2 = ARTP_COLD;
541 fake_plus2 = -1;
542 break;
544 case RING_ICE:
545 fake_rap = ARTP_COLD;
546 fake_rap2 = ARTP_FIRE;
547 fake_plus2 = -1;
548 break;
551 if (fake_rap != ARTP_NUM_PROPERTIES && fake_plus != 0)
552 proprt[fake_rap] += fake_plus;
554 if (fake_rap2 != ARTP_NUM_PROPERTIES && fake_plus2 != 0)
555 proprt[fake_rap2] += fake_plus2;
557 if (item_ident(item, ISFLAG_KNOW_PROPERTIES)
558 || item_ident(item, ISFLAG_KNOW_TYPE))
560 if (fake_rap != ARTP_NUM_PROPERTIES && proprt[fake_rap] != 0)
561 known[fake_rap] = true;
563 if (fake_rap2 != ARTP_NUM_PROPERTIES && proprt[fake_rap2] != 0)
564 known[fake_rap2] = true;
568 inline static void _randart_propset(artefact_properties_t &p,
569 artefact_prop_type pt,
570 int value,
571 bool neg)
573 // This shouldn't be called with 0, else no property gets added after all.
574 ASSERT(value != 0);
575 p[pt] = (neg? -value : value);
578 static int _randart_add_one_property(const item_def &item,
579 artefact_properties_t &proprt)
581 // This function assumes that at least some properties are still possible.
582 const object_class_type cl = item.base_type;
583 const int ty = item.sub_type;
585 const bool negench = one_chance_in(4);
587 const artefact_prop_type artprops[] = { ARTP_STRENGTH, ARTP_INTELLIGENCE,
588 ARTP_DEXTERITY };
592 int prop = RANDOM_ELEMENT(artprops);
594 if (proprt[prop] != 0)
595 continue;
597 switch (prop)
599 case ARTP_STRENGTH:
600 if (cl == OBJ_JEWELLERY && ty == RING_STRENGTH)
601 continue;
603 _randart_propset(proprt, ARTP_STRENGTH,
604 1 + random2(3) + random2(3),
605 negench);
606 break;
608 case ARTP_INTELLIGENCE:
609 if (cl == OBJ_JEWELLERY && ty == RING_INTELLIGENCE)
610 continue;
612 _randart_propset(proprt, ARTP_INTELLIGENCE,
613 1 + random2(3) + random2(3),
614 negench);
615 break;
617 case ARTP_DEXTERITY:
618 if (cl == OBJ_JEWELLERY && ty == RING_DEXTERITY)
619 continue;
621 _randart_propset(proprt, ARTP_DEXTERITY,
622 1 + random2(3) + random2(3),
623 negench);
624 break;
627 while (false);
629 return (negench ? -1 : 1);
632 // An artefact will pass this check if it has any non-stat properties, and
633 // also if it has enough stat (Str, Dex, Int, Acc, Dam) properties.
634 // Returns how many (more) stat properties we need to add.
635 static int _need_bonus_stat_props(const artefact_properties_t &proprt)
637 int num_stats = 0;
638 int num_acc_dam = 0;
640 for (int i = 0; i < ARTP_NUM_PROPERTIES; i++)
642 if (i == ARTP_CURSED)
643 continue;
645 if (proprt[i] == 0)
646 continue;
648 if (i >= ARTP_AC && i <= ARTP_DEXTERITY)
649 num_stats++;
650 else if (i >= ARTP_ACCURACY && i <= ARTP_DAMAGE)
651 num_acc_dam++;
652 else
653 return (0);
656 num_stats += num_acc_dam;
658 // If an artefact has no properties at all, something is wrong.
659 if (num_stats == 0)
660 return (2);
662 // Artefacts with two of more stat-only properties are fine.
663 if (num_stats >= 2)
664 return (0);
666 // If an artefact has exactly one stat property, we might want to add
667 // some more. (66% chance if it's Acc/Dam, else always.)
668 if (num_acc_dam > 0)
669 return (random2(3));
671 return (1 + random2(2));
674 void static _get_randart_properties(const item_def &item,
675 artefact_properties_t &proprt)
677 const object_class_type aclass = item.base_type;
678 const int atype = item.sub_type;
679 int power_level = 0;
681 const uint32_t seed = _calc_seed(item);
682 rng_save_excursion exc;
683 seed_rng(seed);
685 if (aclass == OBJ_ARMOUR)
686 power_level = item.plus / 2 + 2;
687 else if (aclass == OBJ_JEWELLERY)
688 power_level = 1 + random2(3) + random2(2);
689 else // OBJ_WEAPON
690 power_level = item.plus / 3 + item.plus2 / 3;
692 if (power_level < 0)
693 power_level = 0;
695 proprt.init(0);
697 if (aclass == OBJ_WEAPONS) // Only weapons get brands, of course.
699 proprt[ARTP_BRAND] = SPWPN_FLAMING + random2(16); // brand
701 if (one_chance_in(6))
702 proprt[ARTP_BRAND] = SPWPN_FLAMING + random2(2);
704 if (one_chance_in(6))
705 proprt[ARTP_BRAND] = SPWPN_ORC_SLAYING + random2(5);
707 if (one_chance_in(6))
708 proprt[ARTP_BRAND] = SPWPN_VORPAL;
710 if (proprt[ARTP_BRAND] == SPWPN_PROTECTION || proprt[ARTP_BRAND] == SPWPN_EVASION)
711 proprt[ARTP_BRAND] = SPWPN_NORMAL; // no protection or evasion
713 if (is_range_weapon(item))
715 proprt[ARTP_BRAND] = SPWPN_NORMAL;
717 if (one_chance_in(3))
719 int tmp = random2(20);
721 proprt[ARTP_BRAND] = (tmp >= 18) ? SPWPN_SPEED :
722 (tmp >= 14) ? SPWPN_PENETRATION :
723 (tmp >= 12) ? SPWPN_REAPING :
724 (tmp >= 8) ? SPWPN_VENOM
725 : SPWPN_VORPAL + random2(3);
727 if (atype == WPN_BLOWGUN
728 && proprt[ARTP_BRAND] != SPWPN_SPEED)
730 proprt[ARTP_BRAND] = SPWPN_NORMAL;
733 // Removed slings from getting the venom attribute: they can
734 // be branded with it now using Poison Weapon, and perma-branded
735 // via vorpalise weapon.
737 if (atype == WPN_CROSSBOW && one_chance_in(5))
738 proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
740 // XXX: Penetration is only allowed on crossbows. This may change
741 // in future.
742 if (atype != WPN_CROSSBOW && proprt[ARTP_BRAND] == SPWPN_PENETRATION)
743 proprt[ARTP_BRAND] = SPWPN_NORMAL;
745 // XXX: Only allow reaping brand on bows. This may change.
746 if (atype != WPN_BOW && atype != WPN_LONGBOW
747 && proprt[ARTP_BRAND] == SPWPN_REAPING)
749 proprt[ARTP_BRAND] = SPWPN_NORMAL;
754 if (is_demonic(item))
756 switch (random2(9))
758 case 0:
759 proprt[ARTP_BRAND] = SPWPN_DRAINING;
760 break;
761 case 1:
762 proprt[ARTP_BRAND] = SPWPN_FLAMING;
763 break;
764 case 2:
765 proprt[ARTP_BRAND] = SPWPN_FREEZING;
766 break;
767 case 3:
768 proprt[ARTP_BRAND] = SPWPN_ELECTROCUTION;
769 break;
770 case 4:
771 proprt[ARTP_BRAND] = SPWPN_VAMPIRICISM;
772 break;
773 case 5:
774 proprt[ARTP_BRAND] = SPWPN_PAIN;
775 break;
776 case 6:
777 proprt[ARTP_BRAND] = SPWPN_VENOM;
778 break;
779 default:
780 power_level -= 2;
782 power_level += 2;
784 else if (one_chance_in(3))
785 proprt[ARTP_BRAND] = SPWPN_NORMAL;
786 else
787 power_level++;
789 if (!is_weapon_brand_ok(atype, proprt[ARTP_BRAND], true))
791 proprt[ARTP_BRAND] = SPWPN_NORMAL;
792 power_level--;
796 if (!one_chance_in(5))
798 // TODO: compensate for the removal of +AC/+EV
800 // Str mod - not for rings of strength.
801 if (one_chance_in(4 + power_level)
802 && (aclass != OBJ_JEWELLERY || atype != RING_STRENGTH))
804 proprt[ARTP_STRENGTH] = 1 + random2(3) + random2(2);
805 power_level++;
806 if (one_chance_in(4))
808 proprt[ARTP_STRENGTH] -= 1 + random2(3) + random2(3)
809 + random2(3);
810 power_level--;
814 // Int mod - not for rings of intelligence.
815 if (one_chance_in(4 + power_level)
816 && (aclass != OBJ_JEWELLERY || atype != RING_INTELLIGENCE))
818 proprt[ARTP_INTELLIGENCE] = 1 + random2(3) + random2(2);
819 power_level++;
820 if (one_chance_in(4))
822 proprt[ARTP_INTELLIGENCE] -= 1 + random2(3) + random2(3)
823 + random2(3);
824 power_level--;
828 // Dex mod - not for rings of dexterity.
829 if (one_chance_in(4 + power_level)
830 && (aclass != OBJ_JEWELLERY || atype != RING_DEXTERITY))
832 proprt[ARTP_DEXTERITY] = 1 + random2(3) + random2(2);
833 power_level++;
834 if (one_chance_in(4))
836 proprt[ARTP_DEXTERITY] -= 1 + random2(3) + random2(3)
837 + random2(3);
838 power_level--;
843 if (random2(15) >= power_level && aclass != OBJ_WEAPONS
844 && (aclass != OBJ_JEWELLERY || atype != RING_SLAYING))
846 // Weapons and rings of slaying can't get these.
847 if (one_chance_in(4 + power_level)) // to-hit
849 proprt[ARTP_ACCURACY] = 1 + random2(3) + random2(2);
850 power_level++;
851 if (one_chance_in(4))
853 proprt[ARTP_ACCURACY] -= 1 + random2(3) + random2(3)
854 + random2(3);
855 power_level--;
859 if (one_chance_in(4 + power_level)) // to-dam
861 proprt[ARTP_DAMAGE] = 1 + random2(3) + random2(2);
862 power_level++;
863 if (one_chance_in(4))
865 proprt[ARTP_DAMAGE] -= 1 + random2(3) + random2(3)
866 + random2(3);
867 power_level--;
872 // This used to be: bool done_powers = (random2(12 < power_level));
873 // ... which can't be right. random2(boolean) == 0, always.
874 // So it's probably more along the lines of... (jpeg)
875 // bool done_powers = (random2(12) < power_level);
877 // Try to improve items that still have a low power level.
878 bool done_powers = x_chance_in_y(power_level, 12);
880 // res_fire
881 if (!done_powers
882 && one_chance_in(4 + power_level)
883 && (aclass != OBJ_JEWELLERY
884 || (atype != RING_PROTECTION_FROM_FIRE
885 && atype != RING_FIRE
886 && atype != RING_ICE))
887 && (aclass != OBJ_ARMOUR
888 || (atype != ARM_DRAGON_ARMOUR
889 && atype != ARM_ICE_DRAGON_ARMOUR
890 && atype != ARM_GOLD_DRAGON_ARMOUR)))
892 proprt[ARTP_FIRE] = 1;
893 if (one_chance_in(5))
894 proprt[ARTP_FIRE]++;
895 power_level++;
898 // res_cold
899 if (!done_powers
900 && one_chance_in(4 + power_level)
901 && (aclass != OBJ_JEWELLERY
902 || atype != RING_PROTECTION_FROM_COLD
903 && atype != RING_FIRE
904 && atype != RING_ICE)
905 && (aclass != OBJ_ARMOUR
906 || atype != ARM_DRAGON_ARMOUR
907 && atype != ARM_ICE_DRAGON_ARMOUR
908 && atype != ARM_GOLD_DRAGON_ARMOUR))
910 proprt[ARTP_COLD] = 1;
911 if (one_chance_in(5))
912 proprt[ARTP_COLD]++;
913 power_level++;
916 if (x_chance_in_y(power_level, 12) || power_level > 7)
917 done_powers = true;
919 // res_elec
920 if (!done_powers
921 && one_chance_in(4 + power_level)
922 && (aclass != OBJ_ARMOUR || atype != ARM_STORM_DRAGON_ARMOUR))
924 proprt[ARTP_ELECTRICITY] = 1;
925 power_level++;
928 // res_poison
929 if (!done_powers
930 && one_chance_in(5 + power_level)
931 && (aclass != OBJ_JEWELLERY || atype != RING_POISON_RESISTANCE)
932 && (aclass != OBJ_ARMOUR
933 || atype != ARM_GOLD_DRAGON_ARMOUR
934 && atype != ARM_SWAMP_DRAGON_ARMOUR
935 && atype != ARM_NAGA_BARDING))
937 proprt[ARTP_POISON] = 1;
938 power_level++;
941 // prot_life - no necromantic brands on weapons allowed
942 if (!done_powers
943 && one_chance_in(4 + power_level)
944 && (aclass != OBJ_JEWELLERY || atype != RING_LIFE_PROTECTION)
945 && (aclass != OBJ_ARMOUR || atype != ARM_PEARL_DRAGON_ARMOUR)
946 && proprt[ARTP_BRAND] != SPWPN_DRAINING
947 && proprt[ARTP_BRAND] != SPWPN_VAMPIRICISM
948 && proprt[ARTP_BRAND] != SPWPN_PAIN
949 && proprt[ARTP_BRAND] != SPWPN_REAPING)
951 proprt[ARTP_NEGATIVE_ENERGY] = 1;
952 power_level++;
955 // res magic
956 if (!done_powers
957 && one_chance_in(4 + power_level)
958 && (aclass != OBJ_JEWELLERY || atype != RING_PROTECTION_FROM_MAGIC))
960 proprt[ARTP_MAGIC] = 35 + random2(65);
961 power_level++;
964 // see_invis
965 if (!done_powers
966 && one_chance_in(4 + power_level)
967 && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY)
968 && (aclass != OBJ_ARMOUR || atype != ARM_NAGA_BARDING))
970 proprt[ARTP_EYESIGHT] = 1;
971 power_level++;
974 if (x_chance_in_y(power_level, 12) || power_level > 10)
975 done_powers = true;
977 // turn invis
978 if (!done_powers
979 && one_chance_in(10)
980 && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY))
982 proprt[ARTP_INVISIBLE] = 1;
983 power_level++;
986 // levitate
987 if (!done_powers
988 && one_chance_in(10)
989 && (aclass != OBJ_JEWELLERY || atype != RING_LEVITATION))
991 proprt[ARTP_LEVITATE] = 1;
992 power_level++;
995 // blink
996 if (!done_powers && one_chance_in(10))
998 proprt[ARTP_BLINK] = 1;
999 power_level++;
1002 // go berserk
1003 if (!done_powers
1004 && one_chance_in(10)
1005 && (aclass != OBJ_WEAPONS || !is_range_weapon(item))
1006 && (aclass != OBJ_JEWELLERY || atype != AMU_RAGE))
1008 proprt[ARTP_BERSERK] = 1;
1009 power_level++;
1012 if (!done_powers && one_chance_in(10) && aclass == OBJ_ARMOUR
1013 && (atype == ARM_CAP || atype == ARM_SHIELD))
1015 proprt[ARTP_BRAND] = SPARM_SPIRIT_SHIELD;
1016 power_level++;
1019 // Armours get fewer powers, and are also less likely to be cursed
1020 // than weapons.
1021 if (aclass == OBJ_ARMOUR)
1022 power_level -= 4;
1024 if (power_level >= 2 && x_chance_in_y(power_level, 17))
1026 switch (random2(9))
1028 case 0: // makes noise
1029 if (aclass != OBJ_WEAPONS)
1030 break;
1031 proprt[ARTP_NOISES] = 1 + random2(4);
1032 break;
1033 case 1: // no magic
1034 proprt[ARTP_PREVENT_SPELLCASTING] = 1;
1035 break;
1036 case 2: // random teleport
1037 if (aclass != OBJ_WEAPONS)
1038 break;
1039 proprt[ARTP_CAUSE_TELEPORTATION] = 5 + random2(15);
1040 break;
1041 case 3: // no teleport - doesn't affect some instantaneous
1042 // teleports
1043 if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORTATION)
1044 break; // already is a ring of tport
1045 if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORT_CONTROL)
1046 break; // already is a ring of tport ctrl
1047 proprt[ARTP_BLINK] = 0;
1048 proprt[ARTP_PREVENT_TELEPORTATION] = 1;
1049 break;
1050 case 4: // berserk on attack
1051 if (aclass != OBJ_WEAPONS || is_range_weapon(item))
1052 break;
1053 proprt[ARTP_ANGRY] = 1 + random2(8);
1054 break;
1055 case 5: // susceptible to fire
1056 if (aclass == OBJ_JEWELLERY
1057 && (atype == RING_PROTECTION_FROM_FIRE || atype == RING_FIRE
1058 || atype == RING_ICE))
1060 break; // already does this or something
1062 if (aclass == OBJ_ARMOUR
1063 && (atype == ARM_DRAGON_ARMOUR || atype == ARM_ICE_DRAGON_ARMOUR
1064 || atype == ARM_GOLD_DRAGON_ARMOUR))
1066 break;
1068 proprt[ARTP_FIRE] = -1;
1069 break;
1070 case 6: // susceptible to cold
1071 if (aclass == OBJ_JEWELLERY
1072 && (atype == RING_PROTECTION_FROM_COLD || atype == RING_FIRE
1073 || atype == RING_ICE))
1075 break; // already does this or something
1077 if (aclass == OBJ_ARMOUR
1078 && (atype == ARM_DRAGON_ARMOUR || atype == ARM_ICE_DRAGON_ARMOUR
1079 || atype == ARM_GOLD_DRAGON_ARMOUR))
1081 break;
1083 proprt[ARTP_COLD] = -1;
1084 break;
1085 case 7: // speed metabolism
1086 if (aclass == OBJ_JEWELLERY && atype == RING_HUNGER)
1087 break; // already is a ring of hunger
1088 if (aclass == OBJ_JEWELLERY && atype == RING_SUSTENANCE)
1089 break; // already is a ring of sustenance
1090 proprt[ARTP_METABOLISM] = 1 + random2(3);
1091 break;
1092 case 8:
1093 // emits mutagenic radiation - increases
1094 // magic_contamination; property is chance (1 in ...) of
1095 // increasing magic_contamination
1096 proprt[ARTP_MUTAGENIC] = 2 + random2(4);
1097 break;
1101 if (one_chance_in(10)
1102 && (aclass != OBJ_ARMOUR
1103 || atype != ARM_CLOAK
1104 || get_equip_race(item) != ISFLAG_ELVEN)
1105 && (aclass != OBJ_ARMOUR
1106 || atype != ARM_BOOTS
1107 || get_equip_race(item) != ISFLAG_ELVEN)
1108 && get_armour_ego_type(item) != SPARM_STEALTH)
1110 power_level++;
1111 proprt[ARTP_STEALTH] = 10 + random2(70);
1113 if (one_chance_in(4))
1115 proprt[ARTP_STEALTH] = -proprt[ARTP_STEALTH] - random2(20);
1116 power_level--;
1120 // "Boring" artefacts (no properties, or only one stat property)
1121 // get an additional property, or maybe two of them.
1122 int add_prop = _need_bonus_stat_props(proprt);
1123 while (0 < add_prop--)
1124 power_level += _randart_add_one_property(item, proprt);
1126 if ((power_level < 2 && one_chance_in(5)) || one_chance_in(30))
1128 if (one_chance_in(4))
1129 proprt[ARTP_CURSED] = 1 + random2(5);
1130 else
1131 proprt[ARTP_CURSED] = -1;
1135 static bool _redo_book(item_def &book)
1137 int num_spells = 0;
1138 int num_unknown = 0;
1140 for (int i = 0; i < SPELLBOOK_SIZE; i++)
1142 spell_type spell = which_spell_in_book(book, i);
1144 if (spell == SPELL_NO_SPELL)
1145 continue;
1147 num_spells++;
1148 if (!you.seen_spell[spell])
1149 num_unknown++;
1152 if (num_spells <= 5 && num_unknown == 0)
1153 return (true);
1154 else if (num_spells > 5 && num_unknown <= 1)
1155 return (true);
1157 return (false);
1160 static bool _init_artefact_book(item_def &book)
1162 ASSERT(book.sub_type == BOOK_RANDART_LEVEL
1163 || book.sub_type == BOOK_RANDART_THEME);
1164 ASSERT(book.plus != 0);
1166 god_type god;
1167 bool redo = (!origin_is_god_gift(book, &god) || god != GOD_XOM);
1169 // Plus and plus2 contain parameters to make_book_foo_randart(),
1170 // which might get changed after the book has been made into a
1171 // randart, so reset them on each iteration of the loop.
1172 int plus = book.plus;
1173 int plus2 = book.plus2;
1174 bool book_good;
1175 for (int i = 0; i < 4; i++)
1177 book.plus = plus;
1178 book.plus2 = plus2;
1180 if (book.sub_type == BOOK_RANDART_LEVEL)
1181 // The parameters to this call are in book.plus and plus2.
1182 book_good = make_book_level_randart(book, book.plus, book.plus2);
1183 else
1184 book_good = make_book_theme_randart(book);
1186 if (!book_good)
1187 continue;
1189 if (redo && _redo_book(book))
1190 continue;
1192 break;
1195 return (book_good);
1198 static bool _init_artefact_properties(item_def &item)
1200 ASSERT(is_artefact(item));
1202 CrawlVector &rap = item.props[ARTEFACT_PROPS_KEY].get_vector();
1203 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1204 rap[i] = static_cast<short>(0);
1206 if (is_unrandom_artefact(item))
1208 const unrandart_entry *unrand = _seekunrandart(item);
1210 for (int i = 0; i < ART_PROPERTIES; i++)
1211 rap[i] = static_cast<short>(unrand->prpty[i]);
1213 return (true);
1216 if (item.base_type == OBJ_BOOKS)
1217 return _init_artefact_book(item);
1219 artefact_properties_t prop;
1220 _get_randart_properties(item, prop);
1222 for (int i = 0; i < ART_PROPERTIES; i++)
1224 if (i == ARTP_CURSED && prop[i] < 0)
1226 do_curse_item(item);
1227 continue;
1229 rap[i] = static_cast<short>(prop[i]);
1232 return (true);
1235 void artefact_wpn_properties(const item_def &item,
1236 artefact_properties_t &proprt,
1237 artefact_known_props_t &known)
1239 ASSERT(is_artefact(item));
1240 if (!item.props.exists(KNOWN_PROPS_KEY))
1241 return;
1243 const CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1244 ASSERT(_val.get_type() == SV_VEC);
1245 const CrawlVector &known_vec = _val.get_vector();
1246 ASSERT(known_vec.get_type() == SV_BOOL);
1247 ASSERT(known_vec.size() == ART_PROPERTIES);
1248 ASSERT(known_vec.get_max_size() == ART_PROPERTIES);
1250 if (item_ident(item, ISFLAG_KNOW_PROPERTIES))
1252 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1253 known[i] = static_cast<bool>(true);
1255 else
1257 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1258 known[i] = known_vec[i];
1261 if (item.props.exists(ARTEFACT_PROPS_KEY))
1263 const CrawlVector &rap_vec =
1264 item.props[ARTEFACT_PROPS_KEY].get_vector();
1265 ASSERT(rap_vec.get_type() == SV_SHORT);
1266 ASSERT(rap_vec.size() == ART_PROPERTIES);
1267 ASSERT(rap_vec.get_max_size() == ART_PROPERTIES);
1269 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1270 proprt[i] = rap_vec[i].get_short();
1272 else if (is_unrandom_artefact(item))
1274 const unrandart_entry *unrand = _seekunrandart(item);
1276 for (int i = 0; i < ART_PROPERTIES; i++)
1277 proprt[i] = static_cast<short>(unrand->prpty[i]);
1279 else
1281 _get_randart_properties(item, proprt);
1286 void artefact_wpn_properties(const item_def &item,
1287 artefact_properties_t &proprt)
1289 artefact_known_props_t known;
1291 artefact_wpn_properties(item, proprt, known);
1294 int artefact_wpn_property(const item_def &item, artefact_prop_type prop,
1295 bool &_known)
1297 artefact_properties_t proprt;
1298 artefact_known_props_t known;
1300 artefact_wpn_properties(item, proprt, known);
1302 _known = known[prop];
1304 return (proprt[prop]);
1307 int artefact_wpn_property(const item_def &item, artefact_prop_type prop)
1309 bool known;
1311 return artefact_wpn_property(item, prop, known);
1314 int artefact_known_wpn_property(const item_def &item,
1315 artefact_prop_type prop)
1317 artefact_properties_t proprt;
1318 artefact_known_props_t known;
1320 artefact_wpn_properties(item, proprt, known);
1322 if (known[prop])
1323 return (proprt[prop]);
1324 else
1325 return (0);
1328 static int _artefact_num_props(const artefact_properties_t &proprt)
1330 int num = 0;
1332 // Count all properties, but exclude self-cursing.
1333 for (int i = 0; i < ARTP_NUM_PROPERTIES; ++i)
1334 if (i != ARTP_CURSED && proprt[i] != 0)
1335 num++;
1337 return num;
1340 void artefact_wpn_learn_prop(item_def &item, artefact_prop_type prop)
1342 ASSERT(is_artefact(item));
1343 ASSERT(item.props.exists(KNOWN_PROPS_KEY));
1344 CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1345 ASSERT(_val.get_type() == SV_VEC);
1346 CrawlVector &known_vec = _val.get_vector();
1347 ASSERT(known_vec.get_type() == SV_BOOL);
1348 ASSERT(known_vec.size() == ART_PROPERTIES);
1349 ASSERT(known_vec.get_max_size() == ART_PROPERTIES);
1351 if (item_ident(item, ISFLAG_KNOW_PROPERTIES))
1352 return;
1354 known_vec[prop] = static_cast<bool>(true);
1355 if (Options.autoinscribe_artefacts)
1356 add_autoinscription(item, artefact_auto_inscription(item));
1359 static std::string _get_artefact_type(const item_def &item,
1360 bool appear = false)
1362 switch (item.base_type)
1364 case OBJ_BOOKS:
1365 return "book";
1366 case OBJ_WEAPONS:
1367 return "weapon";
1368 case OBJ_ARMOUR:
1369 return "armour";
1370 case OBJ_JEWELLERY:
1371 // Distinguish between amulets and rings only in appearance.
1372 if (!appear)
1373 return "jewellery";
1375 if (jewellery_is_amulet(item))
1376 return "amulet";
1377 else
1378 return "ring";
1379 default:
1380 return "artefact";
1384 static bool _pick_db_name(const item_def &item)
1386 switch (item.base_type)
1388 case OBJ_WEAPONS:
1389 case OBJ_ARMOUR:
1390 return coinflip();
1391 case OBJ_JEWELLERY:
1392 return one_chance_in(5);
1393 default:
1394 return (false);
1398 static std::string _artefact_name_lookup(const item_def &item,
1399 const std::string &lookup)
1401 const std::string name = getRandNameString(lookup);
1402 return (!name.empty()? _replace_name_parts(name, item) : name);
1405 static bool _artefact_name_lookup(std::string &result,
1406 const item_def &item,
1407 const std::string &lookup)
1409 result = _artefact_name_lookup(item, lookup);
1410 return (!result.empty());
1413 std::string artefact_name(const item_def &item, bool appearance)
1415 ASSERT(is_artefact(item));
1417 ASSERT(item.base_type == OBJ_WEAPONS
1418 || item.base_type == OBJ_ARMOUR
1419 || item.base_type == OBJ_JEWELLERY
1420 || item.base_type == OBJ_BOOKS);
1422 if (is_unrandom_artefact(item))
1424 const unrandart_entry *unrand = _seekunrandart(item);
1425 return (item_type_known(item) ? unrand->name : unrand->unid_name);
1428 const uint32_t seed = _calc_seed(item);
1430 std::string lookup;
1431 std::string result;
1433 // Use prefix of gifting god, if applicable.
1434 bool god_gift = false;
1435 int item_orig = 0;
1436 if (!appearance)
1438 // Divine gifts don't look special, so this is only necessary
1439 // for actually naming an item.
1440 item_orig = item.orig_monnum;
1441 if (item_orig < 0)
1442 item_orig = -item_orig;
1443 else
1444 item_orig = 0;
1446 if (item_orig > GOD_NO_GOD && item_orig < NUM_GODS)
1448 lookup += god_name(static_cast<god_type>(item_orig), false) + " ";
1449 god_gift = true;
1453 // get base type
1454 lookup += _get_artefact_type(item, appearance);
1456 rng_save_excursion rng_state;
1457 seed_rng(seed);
1459 if (appearance)
1461 std::string appear = getRandNameString(lookup, " appearance");
1462 if (appear.empty())
1464 appear = getRandNameString("general appearance");
1465 if (appear.empty()) // still nothing found?
1466 appear = "non-descript";
1469 result += appear;
1470 result += " ";
1471 result += item_base_name(item);
1472 return (result);
1475 if (_pick_db_name(item))
1477 result += item_base_name(item) + " ";
1479 int tries = 100;
1480 std::string name;
1483 (_artefact_name_lookup(name, item, lookup)
1485 // If nothing found, try god name alone.
1486 || (god_gift
1487 && _artefact_name_lookup(name, item,
1488 god_name(
1489 static_cast<god_type>(item_orig),
1490 false)))
1492 // If still nothing found, try base type alone.
1493 || _artefact_name_lookup(name, item, _get_artefact_type(item)));
1495 while (--tries > 0 && name.length() > 25);
1497 if (name.empty()) // still nothing found?
1498 result += "of Bugginess";
1499 else
1500 result += name;
1502 else
1504 // construct a unique name
1505 const std::string st_p = make_name(random_int(), false);
1506 result += item_base_name(item);
1508 if (one_chance_in(3))
1510 result += " of ";
1511 result += st_p;
1513 else
1515 result += " \"";
1516 result += st_p;
1517 result += "\"";
1521 return result;
1524 std::string get_artefact_name(const item_def &item, bool force_known)
1526 ASSERT(is_artefact(item));
1528 if (item_type_known(item) || force_known)
1530 // print artefact's real name
1531 if (item.props.exists(ARTEFACT_NAME_KEY))
1532 return item.props[ARTEFACT_NAME_KEY].get_string();
1533 return artefact_name(item, false);
1535 // print artefact appearance
1536 if (item.props.exists(ARTEFACT_APPEAR_KEY))
1537 return item.props[ARTEFACT_APPEAR_KEY].get_string();
1538 return artefact_name(item, false);
1541 void set_artefact_name(item_def &item, const std::string &name)
1543 ASSERT(is_artefact(item));
1544 ASSERT(!name.empty());
1545 item.props[ARTEFACT_NAME_KEY].get_string() = name;
1548 int find_unrandart_index(const item_def& artefact)
1550 return (artefact.special);
1553 unrandart_entry* get_unrand_entry(int unrand_index)
1555 unrand_index -= UNRAND_START;
1557 if (unrand_index <= -1 || unrand_index >= NO_UNRANDARTS)
1558 return &unranddata[0]; // dummy unrandart
1559 else
1560 return &unranddata[unrand_index];
1563 static unrandart_entry *_seekunrandart(const item_def &item)
1565 return get_unrand_entry(item.special);
1568 int find_okay_unrandart(uint8_t aclass, uint8_t atype, bool in_abyss)
1570 int ret = -1;
1572 // Pick randomly among not-yet-existing unrandarts with the proper
1573 // base_type and sub_type.
1574 for (int i = 0, count = 0; i < NO_UNRANDARTS; i++)
1576 const int index = i + UNRAND_START;
1577 const unrandart_entry* entry = &unranddata[i];
1579 // Skip dummy entries.
1580 if (entry->base_type == OBJ_UNASSIGNED)
1581 continue;
1583 const unique_item_status_type status =
1584 get_unique_item_status(index);
1586 if (in_abyss && status != UNIQ_LOST_IN_ABYSS
1587 || !in_abyss && status != UNIQ_NOT_EXISTS)
1589 continue;
1592 // Never randomly generated until lost in the abyss.
1593 if ((!in_abyss || status != UNIQ_LOST_IN_ABYSS)
1594 && entry->flags & UNRAND_FLAG_NOGEN)
1596 continue;
1599 if (entry->base_type != aclass
1600 || (atype != OBJ_RANDOM && entry->sub_type != atype))
1602 continue;
1605 count++;
1607 if (one_chance_in(count))
1608 ret = index;
1611 return (ret);
1614 int get_unrandart_num(const char *name)
1616 std::string quoted = "\"";
1617 quoted += name;
1618 quoted += "\"";
1619 lowercase(quoted);
1621 for (unsigned int i = 0; i < ARRAYSZ(unranddata); ++i)
1623 std::string art = unranddata[i].name;
1624 art = replace_all(art, " ", "_");
1625 art = replace_all(art, "'", "");
1626 lowercase(art);
1627 if (art == name || art.find(quoted) != std::string::npos)
1628 return (UNRAND_START + i);
1630 return SPWPN_NORMAL;
1633 static bool _randart_is_redundant(const item_def &item,
1634 artefact_properties_t &proprt)
1636 if (item.base_type != OBJ_JEWELLERY)
1637 return (false);
1639 artefact_prop_type provides = ARTP_NUM_PROPERTIES;
1640 artefact_prop_type provides2 = ARTP_NUM_PROPERTIES;
1642 switch (item.sub_type)
1644 case RING_PROTECTION:
1645 provides = ARTP_AC;
1646 break;
1648 case RING_FIRE:
1649 case RING_PROTECTION_FROM_FIRE:
1650 provides = ARTP_FIRE;
1651 break;
1653 case RING_POISON_RESISTANCE:
1654 provides = ARTP_POISON;
1655 break;
1657 case RING_ICE:
1658 case RING_PROTECTION_FROM_COLD:
1659 provides = ARTP_COLD;
1660 break;
1662 case RING_STRENGTH:
1663 provides = ARTP_STRENGTH;
1664 break;
1666 case RING_SLAYING:
1667 provides = ARTP_DAMAGE;
1668 provides2 = ARTP_ACCURACY;
1669 break;
1671 case RING_SEE_INVISIBLE:
1672 provides = ARTP_EYESIGHT;
1673 break;
1675 case RING_INVISIBILITY:
1676 provides = ARTP_INVISIBLE;
1677 break;
1679 case RING_HUNGER:
1680 provides = ARTP_METABOLISM;
1681 break;
1683 case RING_TELEPORTATION:
1684 provides = ARTP_CAUSE_TELEPORTATION;
1685 break;
1687 case RING_EVASION:
1688 provides = ARTP_EVASION;
1689 break;
1691 case RING_DEXTERITY:
1692 provides = ARTP_DEXTERITY;
1693 break;
1695 case RING_INTELLIGENCE:
1696 provides = ARTP_INTELLIGENCE;
1697 break;
1699 case RING_MAGICAL_POWER:
1700 provides = ARTP_MAGICAL_POWER;
1701 break;
1703 case RING_LEVITATION:
1704 provides = ARTP_LEVITATE;
1705 break;
1707 case RING_LIFE_PROTECTION:
1708 provides = ARTP_AC;
1709 break;
1711 case RING_PROTECTION_FROM_MAGIC:
1712 provides = ARTP_MAGIC;
1713 break;
1715 case AMU_RAGE:
1716 provides = ARTP_BERSERK;
1717 break;
1719 case AMU_INACCURACY:
1720 provides = ARTP_ACCURACY;
1721 break;
1723 case AMU_STASIS:
1724 provides = ARTP_PREVENT_TELEPORTATION;
1725 break;
1728 if (provides == ARTP_NUM_PROPERTIES)
1729 return (false);
1731 if (proprt[provides] != 0)
1732 return (true);
1734 if (provides2 == ARTP_NUM_PROPERTIES)
1735 return (false);
1737 if (proprt[provides2] != 0)
1738 return (true);
1740 return (false);
1743 static bool _randart_is_conflicting(const item_def &item,
1744 artefact_properties_t &proprt)
1746 if (item.base_type == OBJ_WEAPONS
1747 && get_weapon_brand(item) == SPWPN_HOLY_WRATH
1748 && (is_demonic(item)
1749 || proprt[ARTP_CURSED] != 0))
1751 return (true);
1754 if (item.base_type != OBJ_JEWELLERY)
1755 return (false);
1757 if (item.sub_type == AMU_STASIS
1758 && (proprt[ARTP_BLINK] != 0
1759 || proprt[ARTP_CAUSE_TELEPORTATION] != 0
1760 || proprt[ARTP_ANGRY] != 0
1761 || proprt[ARTP_BERSERK] != 0))
1763 return (true);
1766 artefact_prop_type conflicts = ARTP_NUM_PROPERTIES;
1768 switch (item.sub_type)
1770 case RING_SUSTENANCE:
1771 conflicts = ARTP_METABOLISM;
1772 break;
1774 case RING_FIRE:
1775 case RING_ICE:
1776 case RING_WIZARDRY:
1777 case RING_MAGICAL_POWER:
1778 conflicts = ARTP_PREVENT_SPELLCASTING;
1779 break;
1781 case RING_TELEPORTATION:
1782 case RING_TELEPORT_CONTROL:
1783 conflicts = ARTP_PREVENT_TELEPORTATION;
1784 break;
1786 case AMU_RESIST_MUTATION:
1787 conflicts = ARTP_MUTAGENIC;
1788 break;
1790 case AMU_RAGE:
1791 conflicts = ARTP_STEALTH;
1792 break;
1795 if (conflicts == ARTP_NUM_PROPERTIES)
1796 return (false);
1798 if (proprt[conflicts] != 0)
1799 return (true);
1801 return (false);
1804 bool randart_is_bad(const item_def &item, artefact_properties_t &proprt)
1806 if (item.base_type == OBJ_BOOKS)
1807 return (false);
1809 if (_artefact_num_props(proprt) == 0)
1810 return (true);
1812 // Weapons must have a brand and at least one other property.
1813 if (item.base_type == OBJ_WEAPONS
1814 && (proprt[ARTP_BRAND] == SPWPN_NORMAL
1815 || _artefact_num_props(proprt) < 2))
1817 return (true);
1820 return (_randart_is_redundant(item, proprt)
1821 || _randart_is_conflicting(item, proprt));
1824 bool randart_is_bad(const item_def &item)
1826 artefact_properties_t proprt;
1827 artefact_wpn_properties(item, proprt);
1829 return randart_is_bad(item, proprt);
1832 static void _artefact_setup_prop_vectors(item_def &item)
1834 CrawlHashTable &props = item.props;
1835 if (!props.exists(ARTEFACT_PROPS_KEY))
1836 props[ARTEFACT_PROPS_KEY].new_vector(SV_SHORT)
1837 .resize(ART_PROPERTIES);
1839 CrawlVector &rap = props[ARTEFACT_PROPS_KEY].get_vector();
1840 rap.set_max_size(ART_PROPERTIES);
1842 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1843 rap[i].get_short() = 0;
1845 if (!item.props.exists(KNOWN_PROPS_KEY))
1847 props[KNOWN_PROPS_KEY].new_vector(SV_BOOL).resize(ART_PROPERTIES);
1848 CrawlVector &known = item.props[KNOWN_PROPS_KEY].get_vector();
1849 known.set_max_size(ART_PROPERTIES);
1850 for (vec_size i = 0; i < ART_PROPERTIES; i++)
1851 known[i] = static_cast<bool>(false);
1855 // If force_mundane is true, normally mundane items are forced to
1856 // nevertheless become artefacts.
1857 bool make_item_randart(item_def &item, bool force_mundane)
1859 if (item.base_type != OBJ_WEAPONS
1860 && item.base_type != OBJ_ARMOUR
1861 && item.base_type != OBJ_JEWELLERY
1862 && item.base_type != OBJ_BOOKS)
1864 return (false);
1867 if (item.base_type == OBJ_BOOKS)
1869 if (item.sub_type != BOOK_RANDART_LEVEL
1870 && item.sub_type != BOOK_RANDART_THEME)
1872 return (false);
1876 // This item already is a randart.
1877 if (item.flags & ISFLAG_RANDART)
1878 return (true);
1880 // Not a truly random artefact.
1881 if (item.flags & ISFLAG_UNRANDART)
1882 return (false);
1884 // Mundane items are much less likely to be artefacts.
1885 if (!force_mundane && item.is_mundane() && !one_chance_in(5))
1886 return (false);
1888 _artefact_setup_prop_vectors(item);
1889 item.flags |= ISFLAG_RANDART;
1891 god_type god_gift;
1892 (void) origin_is_god_gift(item, &god_gift);
1894 int randart_tries = 500;
1897 item.special = (random_int() & RANDART_SEED_MASK);
1898 // Now that we found something, initialise the props array.
1899 if (--randart_tries <= 0 || !_init_artefact_properties(item))
1901 // Something went wrong that no amount of changing
1902 // item.special will fix.
1903 item.special = 0;
1904 item.props.erase(ARTEFACT_PROPS_KEY);
1905 item.props.erase(KNOWN_PROPS_KEY);
1906 item.flags &= ~ISFLAG_RANDART;
1907 return (false);
1910 while (randart_is_bad(item)
1911 || god_gift != GOD_NO_GOD && !_god_fits_artefact(god_gift, item));
1913 // get true artefact name
1914 if (item.props.exists(ARTEFACT_NAME_KEY))
1915 ASSERT(item.props[ARTEFACT_NAME_KEY].get_type() == SV_STR);
1916 else
1917 set_artefact_name(item, artefact_name(item, false));
1919 // get artefact appearance
1920 if (item.props.exists(ARTEFACT_APPEAR_KEY))
1921 ASSERT(item.props[ARTEFACT_APPEAR_KEY].get_type() == SV_STR);
1922 else
1923 item.props[ARTEFACT_APPEAR_KEY].get_string() =
1924 artefact_name(item, true);
1926 return (true);
1929 static void _make_faerie_armour(item_def &item)
1931 item_def doodad;
1932 for (int i=0; i<100; i++)
1934 doodad.clear();
1935 doodad.base_type = item.base_type;
1936 doodad.sub_type = item.sub_type;
1937 if (!make_item_randart(doodad))
1939 i--; // Forbidden props are not absolute, artefactness is.
1940 continue;
1943 // These make little sense for a casting mon.
1944 if (artefact_wpn_property(doodad, ARTP_BERSERK)
1945 || artefact_wpn_property(doodad, ARTP_ANGRY)
1946 || artefact_wpn_property(doodad, ARTP_PREVENT_SPELLCASTING)
1947 || artefact_wpn_property(doodad, ARTP_CAUSE_TELEPORTATION)
1948 || artefact_wpn_property(doodad, ARTP_PREVENT_TELEPORTATION)
1949 || artefact_wpn_property(doodad, ARTP_MUTAGENIC)
1950 || artefact_wpn_property(doodad, ARTP_PONDEROUS))
1952 continue;
1955 ASSERT(is_artefact(doodad));
1956 ASSERT(doodad.sub_type == item.sub_type);
1958 doodad.props[ARTEFACT_NAME_KEY].get_string()
1959 = item.props[ARTEFACT_NAME_KEY].get_string();
1960 doodad.props[ARTEFACT_APPEAR_KEY].get_string()
1961 = item.props[ARTEFACT_APPEAR_KEY].get_string();
1962 item.props = doodad.props;
1963 item.plus = 2 + random2(5);
1966 bool make_item_unrandart(item_def &item, int unrand_index)
1968 ASSERT(unrand_index > UNRAND_START);
1969 ASSERT(unrand_index < (UNRAND_START + NO_UNRANDARTS));
1971 item.special = unrand_index;
1973 const unrandart_entry *unrand = &unranddata[unrand_index - UNRAND_START];
1974 item.base_type = unrand->base_type;
1975 item.sub_type = unrand->sub_type;
1976 item.plus = unrand->plus;
1977 item.plus2 = unrand->plus2;
1978 item.colour = unrand->colour;
1980 item.flags |= ISFLAG_UNRANDART;
1981 _artefact_setup_prop_vectors(item);
1982 _init_artefact_properties(item);
1984 if (unrand->prpty[ARTP_CURSED] != 0)
1985 do_curse_item(item);
1987 // get true artefact name
1988 ASSERT(!item.props.exists(ARTEFACT_NAME_KEY));
1989 item.props[ARTEFACT_NAME_KEY].get_string() = unrand->name;
1991 // get artefact appearance
1992 ASSERT(!item.props.exists(ARTEFACT_APPEAR_KEY));
1993 item.props[ARTEFACT_APPEAR_KEY].get_string() = unrand->unid_name;
1995 set_unique_item_status(unrand_index, UNIQ_EXISTS);
1997 if (unrand_index == UNRAND_VARIABILITY)
1999 item.plus = random_range(-4, 16);
2000 item.plus2 = random_range(-4, 16);
2002 else if (unrand_index == UNRAND_FAERIE)
2003 _make_faerie_armour(item);
2005 return (true);
2008 const char *unrandart_descrip(int which_descrip, const item_def &item)
2010 // Eventually it would be great to have randomly generated descriptions
2011 // for randarts.
2012 const unrandart_entry *unrand = _seekunrandart(item);
2014 return ((which_descrip == 0) ? unrand->desc :
2015 (which_descrip == 1) ? unrand->desc_id :
2016 (which_descrip == 2) ? unrand->desc_end
2017 : "Unknown.");
2020 // Set all non-zero properties in proprt on the randart supplied.
2021 static void _artefact_merge_properties(item_def &item,
2022 const artefact_properties_t &proprt)
2024 ASSERT(is_artefact(item));
2025 ASSERT(item.props.exists(ARTEFACT_PROPS_KEY));
2027 CrawlVector &rap_vec = item.props[ARTEFACT_PROPS_KEY].get_vector();
2028 ASSERT(rap_vec.get_type() == SV_SHORT);
2029 ASSERT(rap_vec.size() == ART_PROPERTIES);
2030 ASSERT(rap_vec.get_max_size() == ART_PROPERTIES);
2032 for (vec_size i = 0; i < ART_PROPERTIES; i++)
2034 const short value = proprt[i];
2035 if (value)
2036 rap_vec[i].get_short() = value;
2040 void artefact_set_property(item_def &item,
2041 artefact_prop_type prop,
2042 int val)
2044 ASSERT(is_artefact(item));
2045 ASSERT(item.props.exists(ARTEFACT_PROPS_KEY));
2047 CrawlVector &rap_vec = item.props[ARTEFACT_PROPS_KEY].get_vector();
2048 ASSERT(rap_vec.get_type() == SV_SHORT);
2049 ASSERT(rap_vec.size() == ART_PROPERTIES);
2050 ASSERT(rap_vec.get_max_size() == ART_PROPERTIES);
2052 rap_vec[prop].get_short() = val;
2055 void cheibriados_make_item_ponderous(item_def &item)
2057 ASSERT(item.base_type == OBJ_ARMOUR);
2058 const special_armour_type brand = get_armour_ego_type(item);
2059 if (!is_artefact(item))
2061 item.flags |= ISFLAG_RANDART;
2062 _artefact_setup_prop_vectors(item);
2063 const std::string suffix =
2064 _artefact_name_lookup(
2065 item,
2066 god_name(GOD_CHEIBRIADOS) + " ponderous");
2067 set_artefact_name(item, item_base_name(item) + " " + suffix);
2069 artefact_properties_t props;
2070 props.init(0);
2071 props[ARTP_PONDEROUS] = true;
2072 props[ARTP_BRAND] = brand;
2073 _artefact_merge_properties(item, props);
2075 if (Options.autoinscribe_artefacts)
2076 add_autoinscription(item, artefact_auto_inscription(item));
2079 template<typename Z>
2080 static inline void artefact_pad_store_vector(CrawlVector &vector, Z value)
2082 if (vector.get_max_size() < ART_PROPERTIES)
2084 // Authentic tribal dance to propitiate the asserts in store.cc:
2085 const int old_size = vector.get_max_size();
2086 vector.set_max_size(VEC_MAX_SIZE);
2087 vector.resize(ART_PROPERTIES);
2088 vector.set_max_size(ART_PROPERTIES);
2089 for (int i = old_size; i < ART_PROPERTIES; ++i)
2090 vector[i] = value;
2094 void artefact_fixup_props(item_def &item)
2096 CrawlHashTable &props = item.props;
2097 if (props.exists(ARTEFACT_PROPS_KEY))
2098 artefact_pad_store_vector(props[ARTEFACT_PROPS_KEY], short(0));
2100 if (props.exists(KNOWN_PROPS_KEY))
2101 artefact_pad_store_vector(props[KNOWN_PROPS_KEY], false);