3 * Summary: Random and unrandom artefact functions.
4 * Written by: Linley Henzell
37 #include "view.h" // Elemental colours for unrandarts
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 &
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
)
50 // Jellies can't eat artefacts, so their god won't make any.
51 if (which_god
== GOD_JIYVA
)
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;
60 // Peaceful healer god: no weapons, no berserking.
61 if (item
.base_type
== OBJ_WEAPONS
)
64 if (item
.base_type
== OBJ_JEWELLERY
&& item
.sub_type
== AMU_RAGE
)
69 // Precision fighter god: no inaccuracy.
70 if (item
.base_type
== OBJ_JEWELLERY
&& item
.sub_type
== AMU_INACCURACY
)
75 // Lawful god: no increased hunger.
76 if (item
.base_type
== OBJ_JEWELLERY
&& item
.sub_type
== RING_HUNGER
)
81 case GOD_KIKUBAAQUDGHA
:
83 // The magic gods: no weapons, no preventing spellcasting.
84 if (item
.base_type
== OBJ_WEAPONS
)
89 // Anti-magic god: no spell use, no enhancing magic.
90 if (item
.base_type
== OBJ_BOOKS
)
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
))
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
)
106 if (item
.base_type
== OBJ_JEWELLERY
&& item
.sub_type
== AMU_RAGE
)
114 if (type_bad
&& !name_check_only
)
116 die("%s attempting to gift invalid type of item.",
117 god_name(which_god
).c_str());
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
)
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
133 || artefact_wpn_property(item
, ARTP_CURSED
) != 0))
141 // Orc god: no orc slaying.
142 if (brand
== SPWPN_ORC_SLAYING
)
147 // Peaceful healer god: no berserking.
148 if (artefact_wpn_property(item
, ARTP_ANGRY
)
149 || artefact_wpn_property(item
, ARTP_BERSERK
))
156 // Lawful god: no mutagenics.
157 if (artefact_wpn_property(item
, ARTP_MUTAGENIC
))
161 case GOD_SHINING_ONE
:
162 // Crusader god: holiness, honourable combat.
163 if (item
.base_type
== OBJ_WEAPONS
&& brand
!= SPWPN_HOLY_WRATH
)
166 if (artefact_wpn_property(item
, ARTP_INVISIBLE
)
167 || artefact_wpn_property(item
, ARTP_STEALTH
) > 0)
174 // Abyss god: corruption.
175 if (item
.base_type
== OBJ_WEAPONS
&& brand
!= SPWPN_DISTORTION
)
180 case GOD_KIKUBAAQUDGHA
:
182 // The magic gods: no preventing spellcasting.
183 if (artefact_wpn_property(item
, ARTP_PREVENT_SPELLCASTING
))
188 // Anti-magic god: no spell use, no enhancing magic.
189 if (brand
== SPWPN_PAIN
) // Pain involves necromantic spell use.
192 if (artefact_wpn_property(item
, ARTP_MAGICAL_POWER
))
197 // Fedhas forbids necromancy involving corpses, only reaping
199 if (brand
== SPWPN_REAPING
)
203 case GOD_CHEIBRIADOS
:
204 // Slow god: no speed, no berserking.
205 if (brand
== SPWPN_SPEED
)
208 if (ego
== SPARM_RUNNING
)
211 if (artefact_wpn_property(item
, ARTP_ANGRY
)
212 || artefact_wpn_property(item
, ARTP_BERSERK
))
225 static std::string
_replace_name_parts(const std::string name_in
,
226 const item_def
& item
)
228 std::string name
= name_in
;
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@",
242 + getRandNameString("killer_name"));
243 name
= replace_all(name
, "@player_doom@",
245 + getRandNameString("death_or_doom"));
249 // Simply overwrite the name with one of type "God's Favour".
251 name
+= god_name(god_gift
, false);
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
)
264 if (one_chance_in(5))
275 place
= "Pandemonium";
279 place
= "the Realm of Zot";
282 place
= "the Labyrinth";
285 place
= "the Portal Chambers";
291 const branch_type branch
=
292 static_cast<branch_type
>(random2(BRANCH_TARTARUS
));
293 place
= place_name(get_packed_place(branch
, 1, LEVEL_DUNGEON
),
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
)
307 // God gifts will always get the gifting god's name.
308 if (god_gift
!= GOD_NO_GOD
)
309 which_god
= god_gift
;
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'");
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
))
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
)
412 artefact_wpn_properties(item
, proprt
, known
);
414 if (!force_fake_props
&& item_ident(item
, ISFLAG_KNOW_PROPERTIES
))
417 // Only jewellery need fake randart properties.
418 if (item
.base_type
!= OBJ_JEWELLERY
)
421 artefact_prop_type fake_rap
= ARTP_NUM_PROPERTIES
;
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
;
435 case RING_TELEPORTATION
:
436 fake_rap
= ARTP_CAUSE_TELEPORTATION
;
439 case RING_MAGICAL_POWER
:
440 fake_rap
= ARTP_MAGICAL_POWER
;
444 case RING_LEVITATION
:
445 fake_rap
= ARTP_LEVITATE
;
449 fake_rap
= ARTP_BERSERK
;
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;
466 if (!force_fake_props
)
469 // For auto-inscribing randart jewellery, force_fake_props folds as
470 // much info about the base type as possible into the randarts
473 artefact_prop_type fake_rap2
= ARTP_NUM_PROPERTIES
;
476 switch (item
.sub_type
)
478 case RING_PROTECTION
:
480 fake_plus
= item
.plus
;
483 case RING_PROTECTION_FROM_FIRE
:
484 fake_rap
= ARTP_FIRE
;
487 case RING_POISON_RESISTANCE
:
488 fake_rap
= ARTP_POISON
;
491 case RING_PROTECTION_FROM_COLD
:
492 fake_rap
= ARTP_COLD
;
496 fake_rap
= ARTP_ACCURACY
;
497 fake_plus
= item
.plus
;
498 fake_rap2
= ARTP_DAMAGE
;
499 fake_plus2
= item
.plus2
;
502 case RING_SEE_INVISIBLE
:
503 fake_rap
= ARTP_EYESIGHT
;
507 fake_rap
= ARTP_METABOLISM
;
511 fake_rap
= ARTP_EVASION
;
512 fake_plus
= item
.plus
;
516 fake_rap
= ARTP_STRENGTH
;
517 fake_plus
= item
.plus
;
520 case RING_INTELLIGENCE
:
521 fake_rap
= ARTP_INTELLIGENCE
;
522 fake_plus
= item
.plus
;
526 fake_rap
= ARTP_DEXTERITY
;
527 fake_plus
= item
.plus
;
530 case RING_LIFE_PROTECTION
:
531 fake_rap
= ARTP_NEGATIVE_ENERGY
;
534 case RING_PROTECTION_FROM_MAGIC
:
535 fake_rap
= ARTP_MAGIC
;
539 fake_rap
= ARTP_FIRE
;
540 fake_rap2
= ARTP_COLD
;
545 fake_rap
= ARTP_COLD
;
546 fake_rap2
= ARTP_FIRE
;
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
,
573 // This shouldn't be called with 0, else no property gets added after all.
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
,
592 int prop
= RANDOM_ELEMENT(artprops
);
594 if (proprt
[prop
] != 0)
600 if (cl
== OBJ_JEWELLERY
&& ty
== RING_STRENGTH
)
603 _randart_propset(proprt
, ARTP_STRENGTH
,
604 1 + random2(3) + random2(3),
608 case ARTP_INTELLIGENCE
:
609 if (cl
== OBJ_JEWELLERY
&& ty
== RING_INTELLIGENCE
)
612 _randart_propset(proprt
, ARTP_INTELLIGENCE
,
613 1 + random2(3) + random2(3),
618 if (cl
== OBJ_JEWELLERY
&& ty
== RING_DEXTERITY
)
621 _randart_propset(proprt
, ARTP_DEXTERITY
,
622 1 + random2(3) + random2(3),
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
)
640 for (int i
= 0; i
< ARTP_NUM_PROPERTIES
; i
++)
642 if (i
== ARTP_CURSED
)
648 if (i
>= ARTP_AC
&& i
<= ARTP_DEXTERITY
)
650 else if (i
>= ARTP_ACCURACY
&& i
<= ARTP_DAMAGE
)
656 num_stats
+= num_acc_dam
;
658 // If an artefact has no properties at all, something is wrong.
662 // Artefacts with two of more stat-only properties are fine.
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.)
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
;
681 const uint32_t seed
= _calc_seed(item
);
682 rng_save_excursion exc
;
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);
690 power_level
= item
.plus
/ 3 + item
.plus2
/ 3;
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
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
))
759 proprt
[ARTP_BRAND
] = SPWPN_DRAINING
;
762 proprt
[ARTP_BRAND
] = SPWPN_FLAMING
;
765 proprt
[ARTP_BRAND
] = SPWPN_FREEZING
;
768 proprt
[ARTP_BRAND
] = SPWPN_ELECTROCUTION
;
771 proprt
[ARTP_BRAND
] = SPWPN_VAMPIRICISM
;
774 proprt
[ARTP_BRAND
] = SPWPN_PAIN
;
777 proprt
[ARTP_BRAND
] = SPWPN_VENOM
;
784 else if (one_chance_in(3))
785 proprt
[ARTP_BRAND
] = SPWPN_NORMAL
;
789 if (!is_weapon_brand_ok(atype
, proprt
[ARTP_BRAND
], true))
791 proprt
[ARTP_BRAND
] = SPWPN_NORMAL
;
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);
806 if (one_chance_in(4))
808 proprt
[ARTP_STRENGTH
] -= 1 + random2(3) + random2(3)
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);
820 if (one_chance_in(4))
822 proprt
[ARTP_INTELLIGENCE
] -= 1 + random2(3) + random2(3)
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);
834 if (one_chance_in(4))
836 proprt
[ARTP_DEXTERITY
] -= 1 + random2(3) + random2(3)
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);
851 if (one_chance_in(4))
853 proprt
[ARTP_ACCURACY
] -= 1 + random2(3) + random2(3)
859 if (one_chance_in(4 + power_level
)) // to-dam
861 proprt
[ARTP_DAMAGE
] = 1 + random2(3) + random2(2);
863 if (one_chance_in(4))
865 proprt
[ARTP_DAMAGE
] -= 1 + random2(3) + random2(3)
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);
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))
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))
916 if (x_chance_in_y(power_level
, 12) || power_level
> 7)
921 && one_chance_in(4 + power_level
)
922 && (aclass
!= OBJ_ARMOUR
|| atype
!= ARM_STORM_DRAGON_ARMOUR
))
924 proprt
[ARTP_ELECTRICITY
] = 1;
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;
941 // prot_life - no necromantic brands on weapons allowed
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;
957 && one_chance_in(4 + power_level
)
958 && (aclass
!= OBJ_JEWELLERY
|| atype
!= RING_PROTECTION_FROM_MAGIC
))
960 proprt
[ARTP_MAGIC
] = 35 + random2(65);
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;
974 if (x_chance_in_y(power_level
, 12) || power_level
> 10)
980 && (aclass
!= OBJ_JEWELLERY
|| atype
!= RING_INVISIBILITY
))
982 proprt
[ARTP_INVISIBLE
] = 1;
989 && (aclass
!= OBJ_JEWELLERY
|| atype
!= RING_LEVITATION
))
991 proprt
[ARTP_LEVITATE
] = 1;
996 if (!done_powers
&& one_chance_in(10))
998 proprt
[ARTP_BLINK
] = 1;
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;
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
;
1019 // Armours get fewer powers, and are also less likely to be cursed
1021 if (aclass
== OBJ_ARMOUR
)
1024 if (power_level
>= 2 && x_chance_in_y(power_level
, 17))
1028 case 0: // makes noise
1029 if (aclass
!= OBJ_WEAPONS
)
1031 proprt
[ARTP_NOISES
] = 1 + random2(4);
1034 proprt
[ARTP_PREVENT_SPELLCASTING
] = 1;
1036 case 2: // random teleport
1037 if (aclass
!= OBJ_WEAPONS
)
1039 proprt
[ARTP_CAUSE_TELEPORTATION
] = 5 + random2(15);
1041 case 3: // no teleport - doesn't affect some instantaneous
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;
1050 case 4: // berserk on attack
1051 if (aclass
!= OBJ_WEAPONS
|| is_range_weapon(item
))
1053 proprt
[ARTP_ANGRY
] = 1 + random2(8);
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
))
1068 proprt
[ARTP_FIRE
] = -1;
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
))
1083 proprt
[ARTP_COLD
] = -1;
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);
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);
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
)
1111 proprt
[ARTP_STEALTH
] = 10 + random2(70);
1113 if (one_chance_in(4))
1115 proprt
[ARTP_STEALTH
] = -proprt
[ARTP_STEALTH
] - random2(20);
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);
1131 proprt
[ARTP_CURSED
] = -1;
1135 static bool _redo_book(item_def
&book
)
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
)
1148 if (!you
.seen_spell
[spell
])
1152 if (num_spells
<= 5 && num_unknown
== 0)
1154 else if (num_spells
> 5 && num_unknown
<= 1)
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);
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
;
1175 for (int i
= 0; i
< 4; i
++)
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
);
1184 book_good
= make_book_theme_randart(book
);
1189 if (redo
&& _redo_book(book
))
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
]);
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
);
1229 rap
[i
] = static_cast<short>(prop
[i
]);
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
))
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);
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
]);
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
,
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
)
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
);
1323 return (proprt
[prop
]);
1328 static int _artefact_num_props(const artefact_properties_t
&proprt
)
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)
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
))
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
)
1371 // Distinguish between amulets and rings only in appearance.
1375 if (jewellery_is_amulet(item
))
1384 static bool _pick_db_name(const item_def
&item
)
1386 switch (item
.base_type
)
1392 return one_chance_in(5);
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
);
1433 // Use prefix of gifting god, if applicable.
1434 bool god_gift
= false;
1438 // Divine gifts don't look special, so this is only necessary
1439 // for actually naming an item.
1440 item_orig
= item
.orig_monnum
;
1442 item_orig
= -item_orig
;
1446 if (item_orig
> GOD_NO_GOD
&& item_orig
< NUM_GODS
)
1448 lookup
+= god_name(static_cast<god_type
>(item_orig
), false) + " ";
1454 lookup
+= _get_artefact_type(item
, appearance
);
1456 rng_save_excursion rng_state
;
1461 std::string appear
= getRandNameString(lookup
, " appearance");
1464 appear
= getRandNameString("general appearance");
1465 if (appear
.empty()) // still nothing found?
1466 appear
= "non-descript";
1471 result
+= item_base_name(item
);
1475 if (_pick_db_name(item
))
1477 result
+= item_base_name(item
) + " ";
1483 (_artefact_name_lookup(name
, item
, lookup
)
1485 // If nothing found, try god name alone.
1487 && _artefact_name_lookup(name
, item
,
1489 static_cast<god_type
>(item_orig
),
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";
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))
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
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
)
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
)
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
)
1592 // Never randomly generated until lost in the abyss.
1593 if ((!in_abyss
|| status
!= UNIQ_LOST_IN_ABYSS
)
1594 && entry
->flags
& UNRAND_FLAG_NOGEN
)
1599 if (entry
->base_type
!= aclass
1600 || (atype
!= OBJ_RANDOM
&& entry
->sub_type
!= atype
))
1607 if (one_chance_in(count
))
1614 int get_unrandart_num(const char *name
)
1616 std::string 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
, "'", "");
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
)
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
:
1649 case RING_PROTECTION_FROM_FIRE
:
1650 provides
= ARTP_FIRE
;
1653 case RING_POISON_RESISTANCE
:
1654 provides
= ARTP_POISON
;
1658 case RING_PROTECTION_FROM_COLD
:
1659 provides
= ARTP_COLD
;
1663 provides
= ARTP_STRENGTH
;
1667 provides
= ARTP_DAMAGE
;
1668 provides2
= ARTP_ACCURACY
;
1671 case RING_SEE_INVISIBLE
:
1672 provides
= ARTP_EYESIGHT
;
1675 case RING_INVISIBILITY
:
1676 provides
= ARTP_INVISIBLE
;
1680 provides
= ARTP_METABOLISM
;
1683 case RING_TELEPORTATION
:
1684 provides
= ARTP_CAUSE_TELEPORTATION
;
1688 provides
= ARTP_EVASION
;
1691 case RING_DEXTERITY
:
1692 provides
= ARTP_DEXTERITY
;
1695 case RING_INTELLIGENCE
:
1696 provides
= ARTP_INTELLIGENCE
;
1699 case RING_MAGICAL_POWER
:
1700 provides
= ARTP_MAGICAL_POWER
;
1703 case RING_LEVITATION
:
1704 provides
= ARTP_LEVITATE
;
1707 case RING_LIFE_PROTECTION
:
1711 case RING_PROTECTION_FROM_MAGIC
:
1712 provides
= ARTP_MAGIC
;
1716 provides
= ARTP_BERSERK
;
1719 case AMU_INACCURACY
:
1720 provides
= ARTP_ACCURACY
;
1724 provides
= ARTP_PREVENT_TELEPORTATION
;
1728 if (provides
== ARTP_NUM_PROPERTIES
)
1731 if (proprt
[provides
] != 0)
1734 if (provides2
== ARTP_NUM_PROPERTIES
)
1737 if (proprt
[provides2
] != 0)
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))
1754 if (item
.base_type
!= OBJ_JEWELLERY
)
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))
1766 artefact_prop_type conflicts
= ARTP_NUM_PROPERTIES
;
1768 switch (item
.sub_type
)
1770 case RING_SUSTENANCE
:
1771 conflicts
= ARTP_METABOLISM
;
1777 case RING_MAGICAL_POWER
:
1778 conflicts
= ARTP_PREVENT_SPELLCASTING
;
1781 case RING_TELEPORTATION
:
1782 case RING_TELEPORT_CONTROL
:
1783 conflicts
= ARTP_PREVENT_TELEPORTATION
;
1786 case AMU_RESIST_MUTATION
:
1787 conflicts
= ARTP_MUTAGENIC
;
1791 conflicts
= ARTP_STEALTH
;
1795 if (conflicts
== ARTP_NUM_PROPERTIES
)
1798 if (proprt
[conflicts
] != 0)
1804 bool randart_is_bad(const item_def
&item
, artefact_properties_t
&proprt
)
1806 if (item
.base_type
== OBJ_BOOKS
)
1809 if (_artefact_num_props(proprt
) == 0)
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))
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
)
1867 if (item
.base_type
== OBJ_BOOKS
)
1869 if (item
.sub_type
!= BOOK_RANDART_LEVEL
1870 && item
.sub_type
!= BOOK_RANDART_THEME
)
1876 // This item already is a randart.
1877 if (item
.flags
& ISFLAG_RANDART
)
1880 // Not a truly random artefact.
1881 if (item
.flags
& ISFLAG_UNRANDART
)
1884 // Mundane items are much less likely to be artefacts.
1885 if (!force_mundane
&& item
.is_mundane() && !one_chance_in(5))
1888 _artefact_setup_prop_vectors(item
);
1889 item
.flags
|= ISFLAG_RANDART
;
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.
1904 item
.props
.erase(ARTEFACT_PROPS_KEY
);
1905 item
.props
.erase(KNOWN_PROPS_KEY
);
1906 item
.flags
&= ~ISFLAG_RANDART
;
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
);
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
);
1923 item
.props
[ARTEFACT_APPEAR_KEY
].get_string() =
1924 artefact_name(item
, true);
1929 static void _make_faerie_armour(item_def
&item
)
1932 for (int i
=0; i
<100; i
++)
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.
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
))
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
);
2008 const char *unrandart_descrip(int which_descrip
, const item_def
&item
)
2010 // Eventually it would be great to have randomly generated descriptions
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
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
];
2036 rap_vec
[i
].get_short() = value
;
2040 void artefact_set_property(item_def
&item
,
2041 artefact_prop_type prop
,
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(
2066 god_name(GOD_CHEIBRIADOS
) + " ponderous");
2067 set_artefact_name(item
, item_base_name(item
) + " " + suffix
);
2069 artefact_properties_t props
;
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
)
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);