Bug 1889975: Fix randart rings of teleportation not getting
[crawl:crawl.git] / crawl-ref / source / randart.cc
1 /*
2  *  File:       randart.cc
3  *  Summary:    Random and unrandom artefact functions.
4  *  Written by: Linley Henzell
5  *
6  *  Modified for Crawl Reference by $Author$ on $Date$
7  *
8  *  Change History (most recent first):
9  *
10  *   <8>     19 Jun 99   GDL    added IBMCPP support
11  *   <7>     14/12/99    LRH    random2 -> random5
12  *   <6>     11/06/99    cdl    random4 -> random2
13  *
14  *   <1>     -/--/--     LRH    Created
15  */
16
17 #include "AppHdr.h"
18 #include "randart.h"
19
20 #include <cstdlib>
21 #include <climits>
22 #include <string.h>
23 #include <stdio.h>
24
25 #include "externs.h"
26 #include "itemname.h"
27 #include "itemprop.h"
28 #include "stuff.h"
29
30 #define KNOWN_PROPS_KEY "randart_known_props"
31
32 /*
33    The initial generation of a randart is very simple - it occurs
34    in dungeon.cc and consists of giving it a few random things - plus & plus2
35    mainly.
36 */
37 static const char *rand_wpn_names[] = {
38     " of Blood",
39     " of Death",
40     " of Bloody Death",
41     " of Pain",
42     " of Painful Death",
43     " of Pain & Death",
44     " of Infinite Pain",
45     " of Eternal Torment",
46     " of Power",
47     " of Wrath",
48 /* 10: */
49     " of Doom",
50     " of Tender Mercy",
51     " of the Apocalypse",
52     " of the Jester",
53     " of the Ring",
54     " of the Fool",
55     " of the Gods",
56     " of the Imperium",
57     " of Destruction",
58     " of Armageddon",
59 /* 20: */
60     " of Cruel Justice",
61     " of Righteous Anger",
62     " of Might",
63     " of the Orb",
64     " of Makhleb",
65     " of Trog",
66     " of Xom",
67     " of the Ancients",
68     " of Mana",
69     " of Nemelex Xobeh",
70 /* 30: */
71     " of the Magi",
72     " of the Archmagi",
73     " of the King",
74     " of the Queen",
75     " of the Spheres",
76     " of Circularity",
77     " of Linearity",
78     " of Conflict",
79     " of Battle",
80     " of Honour",
81 /* 40: */
82     " of the Butterfly",
83     " of the Wasp",
84     " of the Frog",
85     " of the Weasel",
86     " of the Troglodytes",
87     " of the Pill-Bug",
88     " of Sin",
89     " of Vengeance",
90     " of Execution",
91     " of Arbitration",
92 /* 50: */
93     " of the Seeker",
94     " of Truth",
95     " of Lies",
96     " of the Eggplant",
97     " of the Turnip",
98     " of Chance",
99     " of Curses",
100     " of Hell's Wrath",
101     " of the Undead",
102     " of Chaos",
103 /* 60: */
104     " of Law",
105     " of Life",
106     " of the Old World",
107     " of the New World",
108     " of the Middle World",
109     " of Crawl",
110     " of Unpleasantness",
111     " of Discomfort",
112     " of Brutal Revenge",
113     " of Triumph",
114 /* 70: */
115     " of Evisceration",
116     " of Dismemberment",
117     " of Terror",
118     " of Fear",
119     " of Pride",
120     " of the Volcano",
121     " of Blood-Lust",
122     " of Division",
123     " of Eternal Harmony",
124     " of Peace",
125 /* 80: */
126     " of Quick Death",
127     " of Instant Death",
128     " of Misery",
129     " of the Whale",
130     " of the Lobster",
131     " of the Whelk",
132     " of the Penguin",
133     " of the Puffin",
134     " of the Mushroom",
135     " of the Toadstool",
136 /* 90: */
137     " of the Little People",
138     " of the Puffball",
139     " of Spores",
140     " of Optimality",
141     " of Pareto-Optimality",
142     " of Greatest Utility",
143     " of Anarcho-Capitalism",
144     " of Ancient Evil",
145     " of the Revolution",
146     " of the People",
147 /* 100: */
148     " of the Elves",
149     " of the Dwarves",
150     " of the Orcs",
151     " of the Humans",
152     " of Sludge",
153     " of the Naga",
154     " of the Trolls",
155     " of the Ogres",
156     " of Equitable Redistribution",
157     " of Wealth",
158 /* 110: */
159     " of Poverty",
160     " of Reapportionment",
161     " of Fragile Peace",
162     " of Reinforcement",
163     " of Beauty",
164     " of the Slug",
165     " of the Snail",
166     " of the Gastropod",
167     " of Corporal Punishment",
168     " of Capital Punishment",
169 /* 120: */
170     " of the Beast",
171     " of Light",
172     " of Darkness",
173     " of Day",
174     " of the Day",
175     " of Night",
176     " of the Night",
177     " of Twilight",
178     " of the Twilight",
179     " of Dawn",
180 /* 130: */
181     " of the Dawn",
182     " of the Sun",
183     " of the Moon",
184     " of Distant Worlds",
185     " of the Unseen Realm",
186     " of Pandemonium",
187     " of the Abyss",
188     " of the Nexus",
189     " of the Gulag",
190     " of the Crusades",
191 /* 140: */
192     " of Proximity",
193     " of Wounding",
194     " of Peril",
195     " of the Eternal Warrior",
196     " of the Eternal War",
197     " of Evil",
198     " of Pounding",
199     " of Oozing Pus",
200     " of Pestilence",
201     " of Plague",
202 /* 150: */
203     " of Negation",
204     " of the Saviour",
205     " of Infection",
206     " of Defence",
207     " of Protection",
208     " of Defence by Offence",
209     " of Expedience",
210     " of Reason",
211     " of Unreason",
212     " of the Heart",
213 /* 160: */
214     " of Offence",
215     " of the Leaf",
216     " of Leaves",
217     " of Winter",
218     " of Summer",
219     " of Autumn",
220     " of Spring",
221     " of Midsummer",
222     " of Midwinter",
223     " of Eternal Night",
224 /* 170: */
225     " of Shrieking Terror",
226     " of the Lurker",
227     " of the Crawling Thing",
228     " of the Thing",
229     " \"Thing\"",
230     " of the Sea",
231     " of the Forest",
232     " of the Trees",
233     " of Earth",
234     " of the World",
235 /* 180: */
236     " of Bread",
237     " of Yeast",
238     " of the Amoeba",
239     " of Deformation",
240     " of Guilt",
241     " of Innocence",
242     " of Ascent",
243     " of Descent",
244     " of Music",
245     " of Brilliance",
246 /* 190: */
247     " of Disgust",
248     " of Feasting",
249     " of Sunlight",
250     " of Starshine",
251     " of the Stars",
252     " of Dust",
253     " of the Clouds",
254     " of the Sky",
255     " of Ash",
256     " of Slime",
257 /* 200: */
258     " of Clarity",
259     " of Eternal Vigilance",
260     " of Purpose",
261     " of the Moth",
262     " of the Goat",
263     " of Fortitude",
264     " of Equivalence",
265     " of Balance",
266     " of Unbalance",
267     " of Harmony",
268 /* 210: */
269     " of Disharmony",
270     " of the Inferno",
271     " of the Omega Point",
272     " of Inflation",
273     " of Deflation",
274     " of Supply",
275     " of Demand",
276     " of Gross Domestic Product",
277     " of Unjust Enrichment",
278     " of Detinue",
279 /* 220: */
280     " of Conversion",
281     " of Anton Piller",
282     " of Mandamus",
283     " of Frustration",
284     " of Breach",
285     " of Fundamental Breach",
286     " of Termination",
287     " of Extermination",
288     " of Satisfaction",
289     " of Res Nullius",
290 /* 230: */
291     " of Fee Simple",
292     " of Terra Nullius",
293     " of Context",
294     " of Prescription",
295     " of Freehold",
296     " of Tortfeasance",
297     " of Omission",
298     " of Negligence",
299     " of Pains",
300     " of Attainder",
301 /* 240: */
302     " of Action",
303     " of Inaction",
304     " of Truncation",
305     " of Defenestration",
306     " of Desertification",
307     " of the Wilderness",
308     " of Psychosis",
309     " of Neurosis",
310     " of Fixation",
311     " of the Open Hand",
312 /* 250: */
313     " of the Tooth",
314     " of Honesty",
315     " of Dishonesty",
316     " of Divine Compulsion",
317     " of the Invisible Hand",
318     " of Freedom",
319     " of Liberty",
320     " of Servitude",
321     " of Domination",
322     " of Tension",
323 /* 260: */
324     " of Monotheism",
325     " of Atheism",
326     " of Agnosticism",
327     " of Existentialism",
328     " of the Good",
329     " of Relativism",
330     " of Absolutism",
331     " of Absolution",
332     " of Abstinence",
333     " of Abomination",
334 /* 270: */
335     " of Mutilation",
336     " of Stasis",
337     " of Wonder",
338     " of Dullness",
339     " of Dim Light",
340     " of the Shining Light",
341     " of Immorality",
342     " of Amorality",
343     " of Precise Incision",
344     " of Orthodoxy",
345 /* 280: */
346     " of Faith",
347     " of Untruth",
348     " of the Augurer",
349     " of the Water Diviner",
350     " of the Soothsayer",
351     " of Punishment",
352     " of Amelioration",
353     " of Sulphur",
354     " of the Egg",
355     " of the Globe",
356 /* 290: */
357     " of the Candle",
358     " of the Candelabrum",
359     " of the Vampires",
360     " of the Orcs",
361     " of the Halflings",
362     " of World's End",
363     " of Blue Skies",
364     " of Red Skies",
365     " of Orange Skies",
366     " of Purple Skies",
367 /* 300: */
368     " of Articulation",
369     " of the Mind",
370     " of the Spider",
371     " of the Lamprey",
372     " of the Beginning",
373     " of the End",
374     " of Severance",
375     " of Sequestration",
376     " of Mourning",
377     " of Death's Door",
378 /* 310: */
379     " of the Key",
380     " of Earthquakes",
381     " of Failure",
382     " of Success",
383     " of Intimidation",
384     " of the Mosquito",
385     " of the Gnat",
386     " of the Blowfly",
387     " of the Turtle",
388     " of the Tortoise",
389 /* 320: */
390     " of the Pit",
391     " of the Grave",
392     " of Submission",
393     " of Dominance",
394     " of the Messenger",
395     " of Crystal",
396     " of Gravity",
397     " of Levity",
398     " of the Slorg",
399     " of Surprise",
400 /* 330: */
401     " of the Maze",
402     " of the Labyrinth",
403     " of Divine Intervention",
404     " of Rotation",
405     " of the Spinneret",
406     " of the Scorpion",
407     " of Demonkind",
408     " of the Genius",
409     " of Bloodstone",
410     " of Grontol",
411 /* 340: */
412     " \"Grim Tooth\"",
413     " \"Widowmaker\"",
414     " \"Widowermaker\"",
415     " \"Lifebane\"",
416     " \"Conservator\"",
417     " \"Banisher\"",
418     " \"Tormentor\"",
419     " \"Secret Weapon\"",
420     " \"String\"",
421     " \"Stringbean\"",
422 /* 350: */
423     " \"Blob\"",
424     " \"Globulus\"",
425     " \"Hulk\"",
426     " \"Raisin\"",
427     " \"Starlight\"",
428     " \"Giant's Toothpick\"",
429     " \"Pendulum\"",
430     " \"Backscratcher\"",
431     " \"Brush\"",
432     " \"Murmur\"",
433 /* 360: */
434     " \"Sarcophage\"",
435     " \"Concordance\"",
436     " \"Dragon's Tongue\"",
437     " \"Arbiter\"",
438     " \"Gram\"",
439     " \"Grom\"",
440     " \"Grim\"",
441     " \"Grum\"",
442     " \"Rummage\"",
443     " \"Omelette\"",
444 /* 370: */
445     " \"Egg\"",
446     " \"Aubergine\"",
447     " \"Z\"",
448     " \"X\"",
449     " \"Q\"",
450     " \"Ox\"",
451     " \"Death Rattle\"",
452     " \"Tattletale\"",
453     " \"Fish\"",
454     " \"Bung\"",
455 /* 380: */
456     " \"Arcanum\"",
457     " \"Mud Pie of Death\"",
458     " \"Transmigrator\"",
459     " \"Ultimatum\"",
460     " \"Earthworm\"",
461     " \"Worm\"",
462     " \"Worm's Wrath\"",
463     " \"Xom's Favour\"",
464     " \"Bingo\"",
465     " \"Leviticus\"",
466 /* 390: */
467     " of Joyful Slaughter"
468
469     // Lemuel's new names
470     " \"Eviscerator\"",
471     " \"Undertaker\"",
472     " \"Embalmer\"",
473     " of Sudden Death",
474     " of Slow Death",
475     " of Certain Death",
476     " of Uncertain Death",
477     " \"Trog's Wrath\"",
478     " \"Ogre's Foe\"",
479     " \"Dragon's Doom\"",
480     " \"Hellblazer\"",
481     " \"Hell-Harrower\"",
482     " of Hacking and Slashing",
483     " of Anger",
484     " of Fury",
485     " of Righteous Fury",
486     " of the Warrior",
487     " of the Doomed Warrior",
488     " of the Warrior-Mage",
489
490     // from the crawl.akrasiac.org patch
491     " of the Alphagorgon",
492     " \"Cookie Cutter\"",
493
494     " of the Nine Deaths",
495     " of Megalomania",
496     " of Egomania",
497     " of Pyrrhic Victory",
498     " of Irrepressible Laughter",
499     " of Impeachment",
500 };
501
502 static const char *rand_armour_names[] = {
503 /* 0: */
504     " of Shielding",
505     " of Grace",
506     " of Impermeability",
507     " of the Onion",
508     " of Life",
509     " of Defence",
510     " of Nonsense",
511     " of Eternal Vigilance",
512     " of Fun",
513     " of Joy",
514     " of Death's Door",
515     " of the Gate",
516     " of Watchfulness",
517     " of Integrity",
518     " of Bodily Harmony",
519     " of Harmony",
520     " of the Untouchables",
521     " of Grot",
522     " of Grottiness",
523     " of Filth",
524     " of Wonder",
525     " of Wondrous Power",
526     " of Power",
527     " of Vlad",
528     " of the Eternal Fruit",
529     " of Invincibility",
530     " of Hide-and-Seek",
531     " of the Mouse",
532     " of the Saviour",
533     " of Plasticity",
534     " of Baldness",
535     " of Terror",
536     " of the Arcane",
537     " of Resist Death",
538     " of Anaesthesia",
539     " of the Guardian",
540     " of Inviolability",
541     " of the Tortoise",
542     " of the Turtle",
543     " of the Armadillo",
544     " of the Echidna",
545     " of the Armoured One",
546     " of Weirdness",
547     " of Pathos",
548     " of Serendipity",
549     " of Loss",
550     " of Hedging",
551     " of Indemnity",
552     " of Limitation",
553     " of Exclusion",
554     " of Repulsion",
555     " of Untold Secrets",
556     " of the Earth",
557     " of the Turtledove",
558     " of Limited Liability",
559     " of Responsibility",
560     " of Hadjma",
561     " of Glory",
562     " of Preservation",
563     " of Conservation",
564     " of Protective Custody",
565     " of the Clam",
566     " of the Barnacle",
567     " of the Lobster",
568     " of Hairiness",
569     " of Supple Strength",
570     " of Space",
571     " of the Vacuum",
572     " of Compression",
573     " of Decompression",
574     " of the Loofah",
575
576     // Lemuel's new names
577     " of the Sun",
578     " of the Moon",
579     " of the Stars",
580     " of the Planets",
581     " of the Pleiades",
582     " of the Morning Star",
583     " of the Evening Star",
584     " of the Seven Stars",
585     " of the Seventy-Seven Stars",
586     " of Departure",
587     " of Arrival",
588     " of Change",
589     " of Stasis",
590     " of Doubt",
591     " of Uncertainty",
592     " of the Elephant",
593     " of the Donkey",
594     " of the Zebra",
595     " of the Hippo",
596     " of the Giraffe",
597     " of the Monkey",
598     " of the Monkey's Uncle",
599     " of Shadows and Fog",
600     " of Love and Death",
601     " of Crimes and Misdemeanours",
602     " of Courage",
603     " of Cowardice",
604     " of Valour",
605     " of the Extremes",
606     " of the Middle",
607     " of the Median",
608     " of Optimism",
609     " of Pessimism",
610     " of the Man with No Name",
611     " of Crawling",
612     " of Zot",
613     " of the Orb",
614     " of the Orb Guardian",
615     " of the Dragon",
616     " of the Komodo Dragon",
617     " of the Swamp",
618     " of the Islands",
619     " of the Lair",
620     " of the Beasts",
621     " of the Vault",
622     " of the Hive",
623     " of the Beekeeper",
624     " of the Garden",
625     " of the Gardener",
626     " of the Assistant Gardener",
627     " of War",
628     " of Peace",
629     " of Xom",
630     " of Xom's Laughter",
631     " of Xom's Questionable Humour",
632     " of Zin's Displeasure",
633     " of the Gods",
634     " of Atheism",
635     " of Agnosticism",
636     " of Heresy",
637     " of the Nightingale",
638     " of the Meadowlark",
639     " of Analysis",
640     " of the Ego",
641     " of the Id",
642     " of the Empty Set",
643     " with No Name",
644     " with an Unpronounceable Name",
645     " with a Strange-Sounding Name",
646     " of Trumpets",
647     " of the Kettle-Drum",
648     " of the Accordion",
649     " of the Hangman",
650     " of the Hanged Man",
651     " of Insatiable Hunger",
652     " of the Devil",
653     " of Demons",
654     " of Lesser Demons",
655     " of Greater Demons",
656     " of the Iron Devil",
657     " of Terror",
658     " of Annoyance",
659     " of Minor Irritation",
660     " of Boredom",
661     " of Ennui",
662     " of the Springtime",
663     " of Midsummer",
664     " of the Harvest",
665     " of First Snow",
666     " of Boiling Hail",
667     " of Perpetual Drought",
668     " of the Poles",
669     " of the Tropics",
670     " of the Equator",
671     " of the Flat Earth",
672     " of Premature Burial",
673     " of False Imprisonment",
674     " of Moderation",
675     " of Extremism",
676     " of Fun and Games",
677     " of the Great Game",
678     " of the Game of Life",
679     " of the King",
680     " of the Queen",
681     " of Royalty",
682     " of Nobility",
683     " of the Republic",
684     " of the Empire",
685     " of Commoners",
686     " of Peasants",
687     " of Townfolk",
688     " of the City",
689     " of the Country",
690     " of the Suburbs",
691     " \"Hero's Friend\"",
692     " of Calculation",
693     " of Instinct",
694     " of Intuition",
695     " of Magic",
696     " of Sorcery",
697     " of Hedge Wizardry",
698     " of Doom",
699     " of Pride",
700     " of Honour",
701     " of Dishonour",
702     " of Shame",
703     " of Embarrassment",
704     " of Abstract Expressionism",
705     " of Free Expression",
706     " of the Guilds",
707     " of the Guild-Master",
708     " of the Apprentice",
709     " of the Blacksmith",
710     " of the Carpenter",
711     " of the Wheelwright",
712     " of the Cooper",
713     " of the Fisher",
714     " of the Hunter",
715     " of the Ditch-Digger",
716     " of Patience",
717     " of Impatience",
718     " of Anxiety",
719     " of Urgency",
720     " \"Forget-Me-Not\"",
721     " of Lilacs",
722     " of Daffodils",
723     " of the Rose",
724
725     // from the crawl.akrasiac.org patch.
726     " of the Hot Ocelot",
727     " of Eight Boll Weevils",
728
729     " of Internal Strife",
730     " of Paranoia",
731     " of Claustrophobia",
732     " of Agoraphobia",
733     " of Dyspraxia",
734     " of Mental Paralysis"
735 };
736
737 static const char *randart_weapon_appearance[] = {
738     "brightly glowing ", "iridescent ", "smoking ", "bloodstained ", "twisted ",
739     "shimmering ", "warped ", "crystal ", "jewelled ", "transparent ",
740     "encrusted ", "pitted ", "slimy ", "polished ", "fine ", "crude ",
741     "ancient ", "ichor-stained ", "faintly glowing ", "steaming ", "shiny "
742 };
743
744 static const char *randart_armour_appearance[] = {
745     "brightly glowing ", "faintly humming ", "smoking ", "bloodstained ",
746     "twisted ", "shimmering ", "warped ", "heavily runed ", "jewelled ",
747     "transparent ", "encrusted ", "pitted ", "slimy ", "polished ", "fine ",
748     "crude ", "ancient ", "ichor-stained ", "faintly glowing ",
749     "steaming ", "shiny ", "distressingly furry "
750 };
751
752 static const char *randart_jewellery_appearance[] = {
753     "brightly glowing", "runed", "smoking", "ruby", "twisted",
754     "shimmering", "warped", "crystal", "diamond", "transparent",
755     "encrusted", "pitted", "slimy", "polished", "fine", "crude",
756     "ancient", "emerald", "faintly glowing", "steaming", "shiny",
757     "scintillating", "sparkling", "flickering", "glittering"
758 };
759
760 // Remember: disallow unrandart creation in abyss/pan
761
762 /*
763    The following unrandart bits were taken from $pellbinder's mon-util code
764    (see mon-util.h & mon-util.cc) and modified (LRH). They're in randart.cc and
765    not randart.h because they're only used in this code module.
766 */
767
768 struct unrandart_entry
769 {
770     const char *name;        // true name of unrandart (max 31 chars)
771     const char *unid_name;   // un-id'd name of unrandart (max 31 chars)
772
773     object_class_type ura_cl;        // class of ura
774     int ura_ty;        // type of ura
775     int ura_pl;        // plus of ura
776     int ura_pl2;       // plus2 of ura
777     int ura_col;       // colour of ura
778     short prpty[RA_PROPERTIES];
779
780     // special description added to 'v' command output (max 31 chars)
781     const char *spec_descrip1;
782     // special description added to 'v' command output (max 31 chars)
783     const char *spec_descrip2;
784     // special description added to 'v' command output (max 31 chars)
785     const char *spec_descrip3;
786 };
787
788 static unrandart_entry unranddata[] = {
789 #include "unrand.h"
790 };
791
792 static FixedVector < bool, NO_UNRANDARTS > unrandart_exist;
793
794 static unrandart_entry *seekunrandart( const item_def &item );
795
796 void set_unrandart_exist(int whun, bool is_exist)
797 {
798     unrandart_exist[whun] = is_exist;
799 }
800
801 bool does_unrandart_exist(int whun)
802 {
803     return (unrandart_exist[whun]);
804 }
805
806 bool is_artefact( const item_def &item )
807 {
808     return (is_random_artefact(item) || is_fixed_artefact(item));
809 }
810
811 // returns true is item is a pure randart or an unrandart
812 bool is_random_artefact( const item_def &item )
813 {
814     return (item.flags & ISFLAG_ARTEFACT_MASK);
815 }
816
817 // returns true if item in an unrandart
818 bool is_unrandom_artefact( const item_def &item )
819 {
820     return (item.flags & ISFLAG_UNRANDART);
821 }
822
823 // returns true if item is one of the original fixed artefacts
824 bool is_fixed_artefact( const item_def &item )
825 {
826     if (!is_random_artefact( item )
827         && item.base_type == OBJ_WEAPONS 
828         && item.special >= SPWPN_START_FIXEDARTS)
829     {
830         return (true);
831     }
832
833     return (false);
834 }
835
836 unique_item_status_type get_unique_item_status( object_class_type base_type,
837                                                 int art )
838 {
839     if (base_type == OBJ_WEAPONS
840         && art >= SPWPN_START_FIXEDARTS && art < SPWPN_START_NOGEN_FIXEDARTS)
841     {
842         return (you.unique_items[art - SPWPN_START_FIXEDARTS]);
843     }
844     else
845         return (UNIQ_NOT_EXISTS);
846 }
847
848 void set_unique_item_status( object_class_type base_type, int art,
849                              unique_item_status_type status )
850 {
851     if (base_type == OBJ_WEAPONS
852         && art >= SPWPN_START_FIXEDARTS && art < SPWPN_START_NOGEN_FIXEDARTS)
853     {
854         you.unique_items[art - SPWPN_START_FIXEDARTS] = status;
855     }
856 }
857
858 static long calc_seed( const item_def &item )
859 {
860     return (item.special & RANDART_SEED_MASK);
861 }
862
863 void randart_desc_properties( const item_def &item, 
864                               randart_properties_t &proprt,
865                               randart_known_props_t &known,
866                               bool force_fake_props)
867 {
868     randart_wpn_properties( item, proprt, known);
869
870     if ( !force_fake_props && item_ident( item, ISFLAG_KNOW_PROPERTIES ) )
871         return;
872
873     if (item.base_type != OBJ_JEWELLERY)
874         return;
875
876     randart_prop_type fake_rap  = RAP_NUM_PROPERTIES;
877     int               fake_plus = 1;
878
879     // The base jewellery type is one whose property is revealed by
880     // wearing it, but whose property isn't revealed by having
881     // ISFLAG_KNOW_PLUSES set.  For a randart with a base type of, for
882     // example, a ring of strength, wearing it sets
883     // ISFLAG_KNOW_PLUSES, which reveals the ring's strength plus.
884     switch (item.sub_type)
885     {
886     case RING_INVISIBILITY:
887         fake_rap = RAP_INVISIBLE;
888         break;
889
890     case RING_TELEPORTATION:
891         fake_rap = RAP_CAUSE_TELEPORTATION;
892         break;
893
894     case RING_MAGICAL_POWER:
895         fake_rap  = RAP_MAGICAL_POWER;
896         fake_plus = 9;
897         break;
898
899     case RING_LEVITATION:
900         fake_rap = RAP_LEVITATE;
901         break;
902
903     case AMU_RAGE:
904         fake_rap = RAP_BERSERK;
905         break;
906     }
907
908     if (fake_rap != RAP_NUM_PROPERTIES)
909     {
910         proprt[fake_rap] += fake_plus;
911
912         if (item_ident( item, ISFLAG_KNOW_PROPERTIES )
913             || item_ident( item, ISFLAG_KNOW_TYPE ))
914         {
915             known[fake_rap] = true;
916         }
917
918         return;
919     }
920
921     if (!force_fake_props)
922         return;
923
924     // For auto-inscribing randart jewellery, force_fake_props folds as
925     // much info about the base type as possible into the randarts
926     // property struct.
927
928     randart_prop_type fake_rap2  = RAP_NUM_PROPERTIES;
929     int               fake_plus2 = 1;
930
931     switch (item.sub_type)
932     {
933     case RING_PROTECTION:
934         fake_rap  = RAP_AC;
935         fake_plus = item.plus;
936         break;
937
938     case RING_PROTECTION_FROM_FIRE:
939         fake_rap = RAP_FIRE;
940         break;
941
942     case RING_POISON_RESISTANCE:
943         fake_rap = RAP_POISON;
944         break;
945
946     case RING_PROTECTION_FROM_COLD:
947         fake_rap = RAP_COLD;
948         break;
949
950     case RING_STRENGTH:
951         fake_rap = RAP_STRENGTH;
952         break;
953
954     case RING_SLAYING:
955         fake_rap   = RAP_ACCURACY;
956         fake_plus  = item.plus;
957         fake_rap2  = RAP_DAMAGE;
958         fake_plus2 = item.plus2;
959         break;
960
961     case RING_SEE_INVISIBLE:
962         fake_rap = RAP_EYESIGHT;
963         break;
964
965     case RING_HUNGER:
966         fake_rap = RAP_METABOLISM;
967         break;
968
969     case RING_EVASION:
970         fake_rap  = RAP_EVASION;
971         fake_plus = item.plus;
972         break;
973
974     case RING_DEXTERITY:
975         fake_rap  = RAP_DEXTERITY;
976         fake_plus = item.plus;
977         break;
978
979     case RING_INTELLIGENCE:
980         fake_rap  = RAP_INTELLIGENCE;
981         fake_plus = item.plus;
982         break;
983
984     case RING_LIFE_PROTECTION:
985         fake_rap = RAP_NEGATIVE_ENERGY;
986         break;
987
988     case RING_PROTECTION_FROM_MAGIC:
989         fake_rap = RAP_MAGIC;
990         break;
991
992     case RING_FIRE:
993         fake_rap   = RAP_FIRE;
994         fake_rap2  = RAP_COLD;
995         fake_plus2 = -1;
996         break;
997
998     case RING_ICE:
999         fake_rap   = RAP_COLD;
1000         fake_rap2  = RAP_FIRE;
1001         fake_plus2 = -1;
1002         break;
1003
1004     case AMU_INACCURACY:
1005         fake_rap  = RAP_ACCURACY;
1006         fake_plus = -5;
1007         break;
1008     }
1009
1010     if (fake_rap != RAP_NUM_PROPERTIES)
1011         proprt[fake_rap] += fake_plus;
1012
1013     if (fake_rap2 != RAP_NUM_PROPERTIES)
1014         proprt[fake_rap2] += fake_plus2;
1015
1016     if (item_ident( item, ISFLAG_KNOW_PROPERTIES )
1017         || item_ident( item, ISFLAG_KNOW_TYPE ))
1018     {
1019         if (fake_rap != RAP_NUM_PROPERTIES && proprt[fake_rap] != 0)
1020             known[fake_rap] = true;
1021
1022         if (fake_rap2 != RAP_NUM_PROPERTIES && proprt[fake_rap2] != 0)
1023             known[fake_rap2] = true;
1024     }
1025 }
1026
1027 static int randart_add_one_property( const item_def &item,
1028                                      randart_properties_t &proprt )
1029 {
1030     // This function assumes that no properties have been added to this
1031     // randart yet.
1032
1033     const object_class_type cl = item.base_type;
1034     const int ty = item.sub_type;
1035
1036     // 0 - ac, 1 - ev, 2 - str, 3 - int, 4 - dex
1037     int prop;
1038     int skip = -1;
1039
1040     // Determine if we need to skip any of the above.
1041     if (cl == OBJ_ARMOUR || (cl == OBJ_JEWELLERY && ty == RING_PROTECTION))
1042         skip = 0;
1043     else if (cl == OBJ_JEWELLERY && ty == RING_EVASION)
1044         skip = 1;
1045     else if (cl == OBJ_JEWELLERY && ty == RING_STRENGTH)
1046         skip = 2;
1047     else if (cl == OBJ_JEWELLERY && ty == RING_INTELLIGENCE)
1048         skip = 3;
1049     else if (cl == OBJ_JEWELLERY && ty == RING_DEXTERITY)
1050         skip = 4;
1051
1052     // Pick a random enchantment, taking into account the skipped index.
1053     if (skip >= 0)
1054     {
1055         prop = random2(4);
1056         if (prop >= skip)
1057             prop++;
1058     }
1059     else
1060     {
1061         prop = random2(5);
1062     }
1063
1064     const bool negench = one_chance_in(4);
1065
1066     switch(prop)
1067     {
1068     default:
1069     case 0:
1070         if (negench)
1071             proprt[RAP_AC] -= 1 + random2(3) + random2(3) + random2(3);
1072         else
1073             proprt[RAP_AC] = 1 + random2(3) + random2(3) + random2(3);
1074         break;
1075     case 1:
1076         if (negench)
1077             proprt[RAP_EVASION] -= 1 + random2(3) + random2(3) + random2(3);
1078         else
1079             proprt[RAP_EVASION] = 1 + random2(3) + random2(3) + random2(3);
1080         break;
1081     case 2:
1082         if (negench)
1083             proprt[RAP_STRENGTH] -= 1 + random2(3) + random2(3) 
1084                 + random2(3);
1085         else
1086             proprt[RAP_STRENGTH] = 1 + random2(3) + random2(2);
1087         break;
1088     case 3:
1089         if (negench)
1090             proprt[RAP_INTELLIGENCE] -= 1 + random2(3) + random2(3)
1091                 + random2(3);
1092         else
1093             proprt[RAP_INTELLIGENCE] = 1 + random2(3) + random2(2);
1094         break;
1095     case 4:
1096         if (negench)
1097             proprt[RAP_DEXTERITY] -= 1 + random2(3) + random2(3)
1098                 + random2(3);
1099         else
1100             proprt[RAP_DEXTERITY] = 1 + random2(3) + random2(2);
1101         break;
1102     }
1103
1104     return negench ? 0 : 1;
1105 }
1106
1107 void randart_wpn_properties( const item_def &item, 
1108                              randart_properties_t &proprt,
1109                              randart_known_props_t &known)
1110 {
1111     ASSERT( is_random_artefact( item ) ); 
1112     ASSERT( item.props.exists( KNOWN_PROPS_KEY ) );
1113     const CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1114     ASSERT( _val.get_type() == SV_VEC );
1115     const CrawlVector &known_vec = _val.get_vector();
1116     ASSERT( known_vec.get_type()     == SV_BOOL );
1117     ASSERT( known_vec.size()         == RA_PROPERTIES);
1118     ASSERT( known_vec.get_max_size() == RA_PROPERTIES);
1119
1120     if ( item_ident( item, ISFLAG_KNOW_PROPERTIES ) )
1121     {
1122         for (vec_size i = 0; i < RA_PROPERTIES; i++)
1123             known[i] = (bool) true;
1124     }
1125     else
1126     {
1127         for (vec_size i = 0; i < RA_PROPERTIES; i++)
1128             known[i] = known_vec[i];
1129     }
1130
1131     const object_class_type aclass = item.base_type;
1132     const int atype = item.sub_type;
1133
1134     int power_level = 0;
1135
1136     if (is_unrandom_artefact( item ))
1137     {
1138         const unrandart_entry *unrand = seekunrandart( item );
1139
1140         for (int i = 0; i < RA_PROPERTIES; i++)
1141             proprt[i] = unrand->prpty[i];
1142
1143         return;
1144     }
1145
1146     const long seed = calc_seed( item );
1147
1148     rng_save_excursion exc;
1149     seed_rng( seed );
1150
1151     if (aclass == OBJ_ARMOUR)
1152         power_level = item.plus / 2 + 2;
1153     else if (aclass == OBJ_JEWELLERY)
1154         power_level = 1 + random2(3) + random2(2);
1155     else // OBJ_WEAPON
1156         power_level = item.plus / 3 + item.plus2 / 3;
1157
1158     if (power_level < 0)
1159         power_level = 0;
1160
1161     proprt.init(0);
1162
1163     if (aclass == OBJ_WEAPONS)  /* Only weapons get brands, of course */
1164     {
1165         proprt[RAP_BRAND] = SPWPN_FLAMING + random2(15);        /* brand */
1166
1167         if (one_chance_in(6))
1168             proprt[RAP_BRAND] = SPWPN_FLAMING + random2(2);
1169
1170         if (one_chance_in(6))
1171             proprt[RAP_BRAND] = SPWPN_ORC_SLAYING + random2(5);
1172
1173         if (proprt[RAP_BRAND] == SPWPN_DRAGON_SLAYING
1174             && weapon_skill(item) != SK_POLEARMS)
1175         {
1176             proprt[RAP_BRAND] = 0;      /* missile wpns */
1177         }
1178
1179         if (one_chance_in(6))
1180             proprt[RAP_BRAND] = SPWPN_VORPAL;
1181
1182         if (proprt[RAP_BRAND] == SPWPN_FLAME
1183             || proprt[RAP_BRAND] == SPWPN_FROST)
1184         {
1185             proprt[RAP_BRAND] = 0;      /* missile wpns */
1186         }
1187
1188         if (proprt[RAP_BRAND] == SPWPN_PROTECTION)
1189             proprt[RAP_BRAND] = 0;      /* no protection */
1190
1191         // if this happens, things might get broken -- bwr
1192         if (proprt[RAP_BRAND] == SPWPN_SPEED && atype == WPN_QUICK_BLADE)
1193             proprt[RAP_BRAND] = SPWPN_NORMAL;
1194
1195         if (is_range_weapon(item))
1196         {
1197             proprt[RAP_BRAND] = SPWPN_NORMAL;
1198
1199             if (one_chance_in(3))
1200             {
1201                 int tmp = random2(20);
1202
1203                 proprt[RAP_BRAND] = (tmp >= 18) ? SPWPN_SPEED :
1204                                     (tmp >= 14) ? SPWPN_PROTECTION :
1205                                     (tmp >= 10) ? SPWPN_VENOM                   
1206                                                 : SPWPN_VORPAL + random2(3);
1207                 if (atype == WPN_BLOWGUN
1208                     && (proprt[RAP_BRAND] == SPWPN_VORPAL
1209                         || proprt[RAP_BRAND] == SPWPN_VENOM))
1210                 {
1211                     proprt[RAP_BRAND] = SPWPN_NORMAL;
1212                 }
1213             }
1214         }
1215
1216         if (is_demonic(item))
1217         {
1218             switch (random2(9))
1219             {
1220             case 0:
1221                 proprt[RAP_BRAND] = SPWPN_DRAINING;
1222                 break;
1223             case 1:
1224                 proprt[RAP_BRAND] = SPWPN_FLAMING;
1225                 break;
1226             case 2:
1227                 proprt[RAP_BRAND] = SPWPN_FREEZING;
1228                 break;
1229             case 3:
1230                 proprt[RAP_BRAND] = SPWPN_ELECTROCUTION;
1231                 break;
1232             case 4:
1233                 proprt[RAP_BRAND] = SPWPN_VAMPIRICISM;
1234                 break;
1235             case 5:
1236                 proprt[RAP_BRAND] = SPWPN_PAIN;
1237                 break;
1238             case 6:
1239                 proprt[RAP_BRAND] = SPWPN_VENOM;
1240                 break;
1241             default:
1242                 power_level -= 2;
1243             }
1244             power_level += 2;
1245         }
1246         else if (one_chance_in(3))
1247             proprt[RAP_BRAND] = SPWPN_NORMAL;
1248         else
1249             power_level++;
1250     }
1251
1252     if (!one_chance_in(5))
1253     {
1254         /* AC mod - not for armours or rings of protection */
1255         if (one_chance_in(4 + power_level)
1256             && aclass != OBJ_ARMOUR
1257             && (aclass != OBJ_JEWELLERY || atype != RING_PROTECTION))
1258         {
1259             proprt[RAP_AC] = 1 + random2(3) + random2(3) + random2(3);
1260             power_level++;
1261             if (one_chance_in(4))
1262             {
1263                 proprt[RAP_AC] -= 1 + random2(3) + random2(3) + random2(3);
1264                 power_level--;
1265             }
1266         }
1267
1268         /* ev mod - not for rings of evasion */
1269         if (one_chance_in(4 + power_level)
1270             && (aclass != OBJ_JEWELLERY || atype != RING_EVASION))
1271         {
1272             proprt[RAP_EVASION] = 1 + random2(3) + random2(3) + random2(3);
1273             power_level++;
1274             if (one_chance_in(4))
1275             {
1276                 proprt[RAP_EVASION] -= 1 + random2(3) + random2(3)
1277                     + random2(3);
1278                 power_level--;
1279             }
1280         }
1281
1282         /* str mod - not for rings of strength */
1283         if (one_chance_in(4 + power_level)
1284             && (aclass != OBJ_JEWELLERY || atype != RING_STRENGTH))
1285         {
1286             proprt[RAP_STRENGTH] = 1 + random2(3) + random2(2);
1287             power_level++;
1288             if (one_chance_in(4))
1289             {
1290                 proprt[RAP_STRENGTH] -= 1 + random2(3) + random2(3)
1291                     + random2(3);
1292                 power_level--;
1293             }
1294         }
1295
1296         /* int mod - not for rings of intelligence */
1297         if (one_chance_in(4 + power_level)
1298             && (aclass != OBJ_JEWELLERY || atype != RING_INTELLIGENCE))
1299         {
1300             proprt[RAP_INTELLIGENCE] = 1 + random2(3) + random2(2);
1301             power_level++;
1302             if (one_chance_in(4))
1303             {
1304                 proprt[RAP_INTELLIGENCE] -= 1 + random2(3) + random2(3)
1305                     + random2(3);
1306                 power_level--;
1307             }
1308         }
1309
1310         /* dex mod - not for rings of dexterity */
1311         if (one_chance_in(4 + power_level)
1312             && (aclass != OBJ_JEWELLERY || atype != RING_DEXTERITY))
1313         {
1314             proprt[RAP_DEXTERITY] = 1 + random2(3) + random2(2);
1315             power_level++;
1316             if (one_chance_in(4))
1317             {
1318                 proprt[RAP_DEXTERITY] -= 1 + random2(3) + random2(3)
1319                     + random2(3);
1320                 power_level--;
1321             }
1322         }
1323     }
1324
1325     if (random2(15) >= power_level && aclass != OBJ_WEAPONS &&
1326         (aclass != OBJ_JEWELLERY || atype != RING_SLAYING))
1327     {
1328         /* Weapons and rings of slaying can't get these */
1329         if (one_chance_in(4 + power_level))  /* to-hit */
1330         {
1331             proprt[RAP_ACCURACY] = 1 + random2(3) + random2(2);
1332             power_level++;
1333             if (one_chance_in(4))
1334             {
1335                 proprt[RAP_ACCURACY] -= 1 + random2(3) + random2(3) +
1336                     random2(3);
1337                 power_level--;
1338             }
1339         }
1340
1341         if (one_chance_in(4 + power_level))  /* to-dam */
1342         {
1343             proprt[RAP_DAMAGE] = 1 + random2(3) + random2(2);
1344             power_level++;
1345             if (one_chance_in(4))
1346             {
1347                 proprt[RAP_DAMAGE] -= 1 + random2(3) + random2(3) + random2(3);
1348                 power_level--;
1349             }
1350         }
1351     }
1352
1353     bool done_powers = (random2(12 < power_level));
1354
1355     /* res_fire */
1356     if (!done_powers
1357         && one_chance_in(4 + power_level)
1358         && (aclass != OBJ_JEWELLERY
1359             || (atype != RING_PROTECTION_FROM_FIRE
1360                 && atype != RING_FIRE
1361                 && atype != RING_ICE))
1362         && (aclass != OBJ_ARMOUR
1363             || (atype != ARM_DRAGON_ARMOUR
1364                 && atype != ARM_ICE_DRAGON_ARMOUR
1365                 && atype != ARM_GOLD_DRAGON_ARMOUR)))
1366     {
1367         proprt[RAP_FIRE] = 1;
1368         if (one_chance_in(5))
1369             proprt[RAP_FIRE]++;
1370         power_level++;
1371     }
1372
1373     /* res_cold */
1374     if (!done_powers
1375         && one_chance_in(4 + power_level)
1376         && (aclass != OBJ_JEWELLERY
1377             || (atype != RING_PROTECTION_FROM_COLD
1378                 && atype != RING_FIRE
1379                 && atype != RING_ICE))
1380         && (aclass != OBJ_ARMOUR
1381             || (atype != ARM_DRAGON_ARMOUR
1382                 && atype != ARM_ICE_DRAGON_ARMOUR
1383                 && atype != ARM_GOLD_DRAGON_ARMOUR)))
1384     {
1385         proprt[RAP_COLD] = 1;
1386         if (one_chance_in(5))
1387             proprt[RAP_COLD]++;
1388         power_level++;
1389     }
1390
1391     if (random2(12) < power_level || power_level > 7)
1392         done_powers = true;
1393
1394     /* res_elec */
1395     if (!done_powers
1396         && one_chance_in(4 + power_level)
1397         && (aclass != OBJ_ARMOUR || atype != ARM_STORM_DRAGON_ARMOUR))
1398     {
1399         proprt[RAP_ELECTRICITY] = 1;
1400         power_level++;
1401     }
1402
1403     /* res_poison */
1404     if (!done_powers
1405         && one_chance_in(5 + power_level)
1406         && (aclass != OBJ_JEWELLERY || atype != RING_POISON_RESISTANCE)
1407         && (aclass != OBJ_ARMOUR
1408             || atype != ARM_GOLD_DRAGON_ARMOUR
1409             || atype != ARM_SWAMP_DRAGON_ARMOUR))
1410     {
1411         proprt[RAP_POISON] = 1;
1412         power_level++;
1413     }
1414
1415     /* prot_life - no necromantic brands on weapons allowed */
1416     if (!done_powers
1417         && one_chance_in(4 + power_level)
1418         && (aclass != OBJ_JEWELLERY || atype != RING_LIFE_PROTECTION)
1419         && proprt[RAP_BRAND] != SPWPN_DRAINING
1420         && proprt[RAP_BRAND] != SPWPN_VAMPIRICISM
1421         && proprt[RAP_BRAND] != SPWPN_PAIN)
1422     {
1423         proprt[RAP_NEGATIVE_ENERGY] = 1;
1424         power_level++;
1425     }
1426
1427     /* res magic */
1428     if (!done_powers
1429         && one_chance_in(4 + power_level)
1430         && (aclass != OBJ_JEWELLERY || atype != RING_PROTECTION_FROM_MAGIC))
1431     {
1432         proprt[RAP_MAGIC] = 35 + random2(65);
1433         power_level++;
1434     }
1435
1436     /* see_invis */
1437     if (!done_powers
1438         && one_chance_in(4 + power_level)
1439         && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY))
1440     {
1441         proprt[RAP_EYESIGHT] = 1;
1442         power_level++;
1443     }
1444
1445     if (random2(12) < power_level || power_level > 10)
1446         done_powers = true;
1447
1448     /* turn invis */
1449     if (!done_powers
1450         && one_chance_in(10)
1451         && (aclass != OBJ_JEWELLERY || atype != RING_INVISIBILITY))
1452     {
1453         proprt[RAP_INVISIBLE] = 1;
1454         power_level++;
1455     }
1456
1457     /* levitate */
1458     if (!done_powers
1459         && one_chance_in(10)
1460         && (aclass != OBJ_JEWELLERY || atype != RING_LEVITATION))
1461     {
1462         proprt[RAP_LEVITATE] = 1;
1463         power_level++;
1464     }
1465
1466     if (!done_powers && one_chance_in(10))       /* blink */
1467     {
1468         proprt[RAP_BLINK] = 1;
1469         power_level++;
1470     }
1471
1472     /* teleport */
1473     if (!done_powers
1474         && one_chance_in(10)
1475         && (aclass != OBJ_JEWELLERY || atype != RING_TELEPORTATION))
1476     {
1477         proprt[RAP_CAN_TELEPORT] = 1;
1478         power_level++;
1479     }
1480
1481     /* go berserk */
1482     if (!done_powers
1483         && one_chance_in(10)
1484         && (aclass != OBJ_JEWELLERY || atype != AMU_RAGE))
1485     {
1486         proprt[RAP_BERSERK] = 1;
1487         power_level++;
1488     }
1489
1490     if (!done_powers && one_chance_in(10))       /* sense surr */
1491     {
1492         proprt[RAP_MAPPING] = 1;
1493         power_level++;
1494     }
1495
1496     /* Armours get less powers, and are also less likely to be
1497        cursed that wpns */
1498     if (aclass == OBJ_ARMOUR)
1499         power_level -= 4;
1500
1501     if (power_level >= 2 && random2(17) < power_level)
1502     {
1503         switch (random2(9))
1504         {
1505         case 0:                     /* makes noise */
1506             if (aclass != OBJ_WEAPONS)
1507                 break;
1508             proprt[RAP_NOISES] = 1 + random2(4);
1509             break;
1510         case 1:                     /* no magic */
1511             proprt[RAP_PREVENT_SPELLCASTING] = 1;
1512             break;
1513         case 2:                     /* random teleport */
1514             if (aclass != OBJ_WEAPONS)
1515                 break;
1516             proprt[RAP_CAUSE_TELEPORTATION] = 5 + random2(15);
1517             break;
1518         case 3:   /* no teleport - doesn't affect some instantaneous
1519                    * teleports */
1520             if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORTATION)
1521                 break;              /* already is a ring of tport */
1522             if (aclass == OBJ_JEWELLERY && atype == RING_TELEPORT_CONTROL)
1523                 break;              /* already is a ring of tport ctrl */
1524             proprt[RAP_BLINK] = 0;
1525             proprt[RAP_CAN_TELEPORT] = 0;
1526             proprt[RAP_PREVENT_TELEPORTATION] = 1;
1527             break;
1528         case 4:                     /* berserk on attack */
1529             if (aclass != OBJ_WEAPONS)
1530                 break;
1531             proprt[RAP_ANGRY] = 1 + random2(8);
1532             break;
1533         case 5:                     /* susceptible to fire */
1534             if (aclass == OBJ_JEWELLERY
1535                 && (atype == RING_PROTECTION_FROM_FIRE || atype == RING_FIRE
1536                     || atype == RING_ICE))
1537                 break;              /* already does this or something */
1538             if (aclass == OBJ_ARMOUR
1539                 && (atype == ARM_DRAGON_ARMOUR || atype == ARM_ICE_DRAGON_ARMOUR
1540                     || atype == ARM_GOLD_DRAGON_ARMOUR))
1541                 break;
1542             proprt[RAP_FIRE] = -1;
1543             break;
1544         case 6:                     /* susceptible to cold */
1545             if (aclass == OBJ_JEWELLERY
1546                 && (atype == RING_PROTECTION_FROM_COLD || atype == RING_FIRE
1547                     || atype == RING_ICE))
1548                 break;              /* already does this or something */
1549             if (aclass == OBJ_ARMOUR
1550                 && (atype == ARM_DRAGON_ARMOUR || atype == ARM_ICE_DRAGON_ARMOUR
1551                     || atype == ARM_GOLD_DRAGON_ARMOUR))
1552                 break;
1553             proprt[RAP_COLD] = -1;
1554             break;
1555         case 7:                     /* speed metabolism */
1556             if (aclass == OBJ_JEWELLERY && atype == RING_HUNGER)
1557                 break;              /* already is a ring of hunger */
1558             if (aclass == OBJ_JEWELLERY && atype == RING_SUSTENANCE)
1559                 break;              /* already is a ring of sustenance */
1560             proprt[RAP_METABOLISM] = 1 + random2(3);
1561             break;
1562         case 8:
1563             /* emits mutagenic radiation - increases
1564                magic_contamination.  property is chance (1 in ...) of
1565                increasing magic_contamination */
1566             proprt[RAP_MUTAGENIC] = 2 + random2(4);
1567             break;
1568         }
1569     }
1570
1571     if (one_chance_in(10) 
1572         && (aclass != OBJ_ARMOUR 
1573             || atype != ARM_CLOAK 
1574             || get_equip_race(item) != ISFLAG_ELVEN)
1575         && (aclass != OBJ_ARMOUR 
1576             || atype != ARM_BOOTS 
1577             || get_equip_race(item) != ISFLAG_ELVEN)
1578         && get_armour_ego_type( item ) != SPARM_STEALTH)
1579     {
1580         power_level++;
1581         proprt[RAP_STEALTH] = 10 + random2(70);
1582
1583         if (one_chance_in(4))
1584         {
1585             proprt[RAP_STEALTH] = -proprt[RAP_STEALTH] - random2(20);    
1586             power_level--;
1587         }
1588     }
1589
1590     if (randart_wpn_num_props(proprt) == 0)
1591         power_level += randart_add_one_property(item, proprt);
1592
1593     if ((power_level < 2 && one_chance_in(5)) || one_chance_in(30))
1594         proprt[RAP_CURSED] = 1;
1595 }
1596
1597 void randart_wpn_properties( const item_def &item, 
1598                              randart_properties_t &proprt )
1599 {
1600     randart_known_props_t known;
1601
1602     randart_wpn_properties(item, proprt, known);
1603 }
1604
1605 int randart_wpn_property( const item_def &item, randart_prop_type prop,
1606                           bool &_known )
1607 {
1608     randart_properties_t  proprt;
1609     randart_known_props_t known;
1610
1611     randart_wpn_properties( item, proprt, known );
1612
1613     _known = known[prop];
1614
1615     return ( proprt[prop] );
1616 }
1617
1618 int randart_wpn_property( const item_def &item, randart_prop_type prop )
1619 {
1620     bool known;
1621
1622     return randart_wpn_property( item, prop, known );
1623 }
1624
1625 int randart_known_wpn_property( const item_def &item, randart_prop_type prop )
1626 {
1627     randart_properties_t  proprt;
1628     randart_known_props_t known;
1629
1630     randart_wpn_properties( item, proprt, known );
1631
1632     if (known[prop])
1633         return ( proprt[prop] );
1634     else
1635         return (0);
1636 }
1637
1638
1639 int randart_wpn_num_props( const item_def &item )
1640 {
1641     randart_properties_t proprt;
1642     randart_wpn_properties( item, proprt );
1643
1644     return randart_wpn_num_props( proprt );
1645 }
1646
1647 int randart_wpn_num_props( const randart_properties_t &proprt )
1648 {
1649     int num = 0;
1650
1651     for (int i = 0; i < RAP_NUM_PROPERTIES; i++)
1652         if (proprt[i] != 0)
1653             num++;
1654
1655     return num;
1656 }
1657
1658 void randart_wpn_learn_prop( item_def &item, randart_prop_type prop )
1659 {
1660     ASSERT( is_random_artefact( item ) ); 
1661     ASSERT( item.props.exists( KNOWN_PROPS_KEY ) );
1662     CrawlStoreValue &_val = item.props[KNOWN_PROPS_KEY];
1663     ASSERT( _val.get_type() == SV_VEC );
1664     CrawlVector &known_vec = _val.get_vector();
1665     ASSERT( known_vec.get_type()     == SV_BOOL );
1666     ASSERT( known_vec.size()         == RA_PROPERTIES);
1667     ASSERT( known_vec.get_max_size() == RA_PROPERTIES);
1668
1669     if ( item_ident( item, ISFLAG_KNOW_PROPERTIES ) )
1670         return;
1671     else
1672         known_vec[prop] = (bool) true;
1673 }
1674
1675 bool randart_wpn_known_prop( const item_def &item, randart_prop_type prop )
1676 {
1677     bool known;
1678     randart_wpn_property( item, prop, known );
1679     return known;
1680 }
1681
1682 std::string randart_name( const item_def &item )
1683 {
1684     ASSERT( item.base_type == OBJ_WEAPONS );
1685
1686     if (is_unrandom_artefact( item ))
1687     {
1688         const unrandart_entry *unrand = seekunrandart( item );
1689         return (item_type_known(item) ? unrand->name : unrand->unid_name);
1690     }
1691
1692     const long seed = calc_seed( item );
1693
1694     rng_save_excursion rng_state;
1695     seed_rng( seed );
1696     
1697     std::string result;
1698     
1699     if (!item_type_known(item))
1700     {
1701         result += RANDOM_ELEMENT(randart_weapon_appearance);
1702         result += item_base_name(item);
1703         return result;
1704     }
1705
1706     if (coinflip())
1707     {
1708         result += item_base_name(item);
1709         result += RANDOM_ELEMENT(rand_wpn_names);
1710     }
1711     else
1712     {
1713         const std::string st_p = make_name(random_int(), false);
1714         result += item_base_name(item);
1715
1716         if (one_chance_in(3))
1717         {
1718             result += " of ";
1719             result += st_p;
1720         }
1721         else
1722         {
1723             result += " \"";
1724             result += st_p;
1725             result += "\"";
1726         }
1727     }
1728
1729     return result;
1730 }
1731
1732 std::string randart_armour_name( const item_def &item )
1733 {
1734     ASSERT( item.base_type == OBJ_ARMOUR );
1735
1736     if (is_unrandom_artefact( item ))
1737     {
1738         const unrandart_entry *unrand = seekunrandart( item );
1739         return (item_type_known(item) ? unrand->name : unrand->unid_name);
1740     }
1741
1742     const long seed = calc_seed( item );
1743
1744     rng_save_excursion exc;
1745     seed_rng( seed );
1746
1747     std::string result;
1748
1749     if (!item_type_known(item))
1750     {
1751         result += RANDOM_ELEMENT(randart_armour_appearance);
1752         result += item_base_name(item);
1753         return result;
1754     }
1755     
1756     if (coinflip())
1757     {
1758         result += item_base_name(item);
1759         result += RANDOM_ELEMENT(rand_armour_names);
1760     }
1761     else
1762     {
1763         const std::string st_p = make_name(random_int(), false);
1764         result += item_base_name(item);
1765         if (one_chance_in(3))
1766         {
1767             result += " of ";
1768             result += st_p;
1769         }
1770         else
1771         {
1772             result += " \"";
1773             result += st_p;
1774             result += "\"";
1775         }
1776     }
1777
1778     return result;
1779 }
1780
1781 std::string randart_jewellery_name( const item_def &item )
1782 {
1783     ASSERT( item.base_type == OBJ_JEWELLERY );
1784
1785
1786     if (is_unrandom_artefact( item ))
1787     {
1788         const unrandart_entry *unrand = seekunrandart( item );
1789         return (item_type_known(item) ? unrand->name : unrand->unid_name);
1790     }
1791
1792     const long seed = calc_seed( item );
1793
1794     rng_save_excursion exc;
1795     seed_rng( seed );
1796
1797     std::string result;
1798
1799     if (!item_type_known(item))
1800     {
1801         result += RANDOM_ELEMENT(randart_jewellery_appearance);
1802         result += " ";
1803         result += (jewellery_is_amulet(item) ? "amulet" : "ring");
1804
1805         return result;
1806     }
1807
1808     if (one_chance_in(5))
1809     {
1810         result += (jewellery_is_amulet(item) ? "amulet" : "ring");
1811         result += RANDOM_ELEMENT(rand_armour_names);
1812     }
1813     else
1814     {
1815         const std::string st_p = make_name(random_int(), false);
1816         result += (jewellery_is_amulet(item) ? "amulet" : "ring");
1817
1818         if (one_chance_in(3))
1819         {
1820             result += " of ";
1821             result += st_p;
1822         }
1823         else
1824         {
1825             result += " \"";
1826             result += st_p;
1827             result += "\"";
1828         }
1829     }
1830
1831     return result;
1832 }
1833
1834 int find_unrandart_index(const item_def& artefact)
1835 {
1836     for (int i=0; i < NO_UNRANDARTS; i++)
1837     {
1838         const unrandart_entry& candidate = unranddata[i];
1839         if (candidate.ura_cl == artefact.base_type
1840             && candidate.ura_ty == artefact.sub_type
1841             && candidate.ura_pl == artefact.plus
1842             && candidate.ura_pl2 == artefact.plus2
1843             && candidate.ura_col == artefact.colour)
1844         {
1845             return i;
1846         }
1847     }
1848
1849     return (-1);
1850 }
1851
1852 static unrandart_entry *seekunrandart( const item_def &item )
1853 {
1854     const int idx = find_unrandart_index(item);
1855     if ( idx == -1 )
1856         return &unranddata[0];  // dummy unrandart
1857     else
1858         return &unranddata[idx];
1859 }
1860
1861 int find_unrandart_index(int item_number)
1862 {
1863     return find_unrandart_index(mitm[item_number]);
1864 }
1865
1866 int find_okay_unrandart(unsigned char aclass, unsigned char atype)
1867 {
1868     int ret = -1;
1869
1870     // Pick randomly among not-yet-existing unrandarts with the proper
1871     // base_type and sub_type.
1872     for (int i = 0, count = 0; i < NO_UNRANDARTS; i++)
1873     {
1874         if (unranddata[i].ura_cl == aclass 
1875             && !does_unrandart_exist(i)
1876             && (atype == OBJ_RANDOM || unranddata[i].ura_ty == atype))
1877         {
1878             count++;
1879
1880             if (one_chance_in(count))
1881                 ret = i;
1882         }
1883     }
1884
1885     return (ret);
1886 }
1887
1888 // which == 0 (default) gives random fixed artefact.
1889 // Returns true if successful.
1890 bool make_item_fixed_artefact( item_def &item, bool in_abyss, int which )
1891 {
1892     const bool force = (which != 0);
1893
1894     if (!force)
1895     {
1896         which = SPWPN_START_FIXEDARTS +
1897             random2(SPWPN_START_NOGEN_FIXEDARTS - SPWPN_START_FIXEDARTS);
1898     }
1899
1900     const unique_item_status_type status =
1901         get_unique_item_status( OBJ_WEAPONS, which );
1902
1903     if ((status == UNIQ_EXISTS 
1904             || (in_abyss && status == UNIQ_NOT_EXISTS)
1905             || (!in_abyss && status == UNIQ_LOST_IN_ABYSS))
1906         && !force)
1907     {
1908         return (false);
1909     }
1910
1911     switch (which)
1912     {
1913     case SPWPN_SINGING_SWORD:
1914         item.base_type = OBJ_WEAPONS;
1915         item.sub_type = WPN_LONG_SWORD;
1916         item.plus  = 7;
1917         item.plus2 = 6;
1918         break;
1919
1920     case SPWPN_WRATH_OF_TROG:
1921         item.base_type = OBJ_WEAPONS;
1922         item.sub_type = WPN_BATTLEAXE;
1923         item.plus  = 3;
1924         item.plus2 = 11;
1925         break;
1926
1927     case SPWPN_SCYTHE_OF_CURSES:
1928         item.base_type = OBJ_WEAPONS;
1929         item.sub_type = WPN_SCYTHE;
1930         item.plus  = 13;
1931         item.plus2 = 13;
1932         break;
1933
1934     case SPWPN_MACE_OF_VARIABILITY:
1935         item.base_type = OBJ_WEAPONS;
1936         item.sub_type = WPN_MACE;
1937         item.plus  = random2(16) - 4;
1938         item.plus2 = random2(16) - 4;
1939         break;
1940
1941     case SPWPN_GLAIVE_OF_PRUNE:
1942         item.base_type = OBJ_WEAPONS;
1943         item.sub_type = WPN_GLAIVE;
1944         item.plus  = 0;
1945         item.plus2 = 12;
1946         break;
1947
1948     case SPWPN_SCEPTRE_OF_TORMENT:
1949         item.base_type = OBJ_WEAPONS;
1950         item.sub_type = WPN_MACE;
1951         item.plus  = 7;
1952         item.plus2 = 6;
1953         break;
1954
1955     case SPWPN_SWORD_OF_ZONGULDROK:
1956         item.base_type = OBJ_WEAPONS;
1957         item.sub_type = WPN_LONG_SWORD;
1958         item.plus  = 9;
1959         item.plus2 = 9;
1960         break;
1961
1962     case SPWPN_SWORD_OF_POWER:
1963         item.base_type = OBJ_WEAPONS;
1964         item.sub_type = WPN_GREAT_SWORD;
1965         item.plus  = 0; // set on wield
1966         item.plus2 = 0; // set on wield
1967         break;
1968
1969     case SPWPN_KNIFE_OF_ACCURACY:
1970         item.base_type = OBJ_WEAPONS;
1971         item.sub_type = WPN_DAGGER;
1972         item.plus  = 27;
1973         item.plus2 = -1;
1974         break;
1975
1976     case SPWPN_STAFF_OF_OLGREB:
1977         item.base_type = OBJ_WEAPONS;
1978         item.sub_type = WPN_QUARTERSTAFF;
1979         item.plus  = 0; // set on wield
1980         item.plus2 = 0; // set on wield
1981         break;
1982
1983     case SPWPN_VAMPIRES_TOOTH:
1984         item.base_type = OBJ_WEAPONS;
1985         item.sub_type = WPN_DAGGER;
1986         item.plus  = 3;
1987         item.plus2 = 4;
1988         break;
1989
1990     case SPWPN_STAFF_OF_WUCAD_MU:
1991         item.base_type = OBJ_WEAPONS;
1992         item.sub_type = WPN_QUARTERSTAFF;
1993         item.plus  = 0; // set on wield
1994         item.plus2 = 0; // set on wield
1995         break;
1996
1997     case SPWPN_SWORD_OF_CEREBOV:
1998         item.base_type = OBJ_WEAPONS;
1999         item.sub_type = WPN_GREAT_SWORD;
2000         item.plus  = 6;
2001         item.plus2 = 6;
2002         item.colour = YELLOW;
2003         do_curse_item( item );
2004         break;
2005
2006     case SPWPN_STAFF_OF_DISPATER:
2007         item.base_type = OBJ_WEAPONS;
2008         item.sub_type = WPN_QUARTERSTAFF;
2009         item.plus  = 4;
2010         item.plus2 = 4;
2011         item.colour = YELLOW;
2012         break;
2013
2014     case SPWPN_SCEPTRE_OF_ASMODEUS:
2015         item.base_type = OBJ_WEAPONS;
2016         item.sub_type = WPN_QUARTERSTAFF;
2017         item.plus  = 7;
2018         item.plus2 = 7;
2019         item.colour = RED;
2020         break;
2021
2022     default:
2023         DEBUGSTR( "Trying to create illegal fixed artefact!" );
2024         return (false);
2025     }
2026
2027     // If we get here, we've made the artefact
2028     item.special = which;
2029     item.quantity = 1;
2030
2031     // Items originally generated in the abyss and not found will be
2032     // shifted to "lost in abyss", and will only be found there. -- bwr
2033     set_unique_item_status( OBJ_WEAPONS, which, UNIQ_EXISTS );
2034
2035     return (true);
2036 }
2037
2038 static bool randart_is_redundant( const item_def &item,
2039                                   randart_properties_t &proprt )
2040 {
2041     if (item.base_type != OBJ_JEWELLERY)
2042         return false;
2043
2044     randart_prop_type provides  = RAP_NUM_PROPERTIES;
2045     randart_prop_type provides2 = RAP_NUM_PROPERTIES;
2046
2047     switch (item.sub_type)
2048     {
2049     case RING_PROTECTION:
2050         provides = RAP_AC;
2051         break;
2052
2053     case RING_FIRE:
2054     case RING_PROTECTION_FROM_FIRE:
2055         provides = RAP_FIRE;
2056         break;
2057
2058     case RING_POISON_RESISTANCE:
2059         provides = RAP_POISON;
2060         break;
2061
2062     case RING_ICE:
2063     case RING_PROTECTION_FROM_COLD:
2064         provides = RAP_COLD;
2065         break;
2066
2067     case RING_STRENGTH:
2068         provides = RAP_STRENGTH;
2069         break;
2070
2071     case RING_SLAYING:
2072         provides  = RAP_DAMAGE;
2073         provides2 = RAP_ACCURACY;
2074         break;
2075
2076     case RING_SEE_INVISIBLE:
2077         provides = RAP_ACCURACY;
2078         break;
2079
2080     case RING_INVISIBILITY:
2081         provides = RAP_INVISIBLE;
2082         break;
2083
2084     case RING_HUNGER:
2085         provides = RAP_METABOLISM;
2086         break;
2087
2088     case RING_TELEPORTATION:
2089         provides = RAP_CAN_TELEPORT;
2090         provides = RAP_CAUSE_TELEPORTATION;
2091         break;
2092
2093     case RING_EVASION:
2094         provides = RAP_EVASION;
2095         break;
2096
2097     case RING_DEXTERITY:
2098         provides = RAP_DEXTERITY;
2099         break;
2100
2101     case RING_INTELLIGENCE:
2102         provides = RAP_INTELLIGENCE;
2103         break;
2104
2105     case RING_MAGICAL_POWER:
2106         provides = RAP_MAGICAL_POWER;
2107         break;
2108
2109     case RING_LEVITATION:
2110         provides = RAP_LEVITATE;
2111         break;
2112
2113     case RING_LIFE_PROTECTION:
2114         provides = RAP_AC;
2115         break;
2116
2117     case RING_PROTECTION_FROM_MAGIC:
2118         provides = RAP_MAGIC;
2119         break;
2120
2121     case AMU_RAGE:
2122         provides = RAP_BERSERK;
2123         break;
2124
2125     case AMU_INACCURACY:
2126         provides = RAP_ACCURACY;
2127         break;
2128     }
2129
2130     if (provides == RAP_NUM_PROPERTIES)
2131         return false;
2132
2133     if (proprt[provides] != 0)
2134         return true;
2135
2136     if (provides2 == RAP_NUM_PROPERTIES)
2137         return false;
2138
2139     if (proprt[provides2] != 0)
2140         return true;
2141     
2142     return false;
2143 }
2144
2145 static bool randart_is_conflicting( const item_def &item,
2146                                     randart_properties_t &proprt )
2147 {
2148     if (item.base_type != OBJ_JEWELLERY)
2149         return false;
2150
2151     randart_prop_type conflicts = RAP_NUM_PROPERTIES;
2152
2153     switch (item.sub_type)
2154     {
2155     case RING_SUSTENANCE:
2156         conflicts = RAP_METABOLISM;
2157         break;
2158
2159     case RING_FIRE:
2160     case RING_ICE:
2161     case RING_WIZARDRY:
2162     case RING_MAGICAL_POWER:
2163         conflicts = RAP_PREVENT_SPELLCASTING;
2164         break;
2165
2166     case RING_TELEPORTATION:
2167     case RING_TELEPORT_CONTROL:
2168         conflicts = RAP_PREVENT_TELEPORTATION;
2169         break;
2170
2171     case AMU_RESIST_MUTATION:
2172         conflicts = RAP_MUTAGENIC;
2173         break;
2174
2175     case AMU_RAGE:
2176         conflicts = RAP_STEALTH;
2177         break;
2178     }        
2179
2180     if (conflicts == RAP_NUM_PROPERTIES)
2181         return false;
2182
2183     if (proprt[conflicts] != 0)
2184         return true;
2185
2186     return false;
2187 }
2188
2189 bool randart_is_bad( const item_def &item, randart_properties_t &proprt )
2190 {
2191     if (randart_wpn_num_props( proprt ) == 0)
2192         return true;
2193
2194     return ( randart_is_redundant( item, proprt ) || 
2195              randart_is_conflicting( item, proprt ) );
2196 }
2197
2198 bool randart_is_bad( const item_def &item )
2199 {
2200     randart_properties_t proprt;
2201     randart_wpn_properties( item, proprt );
2202
2203     return randart_is_bad( item, proprt);
2204 }
2205
2206 bool make_item_randart( item_def &item )
2207 {
2208     if (item.base_type != OBJ_WEAPONS 
2209         && item.base_type != OBJ_ARMOUR
2210         && item.base_type != OBJ_JEWELLERY)
2211     {
2212         return (false);
2213     }
2214
2215     if (item.flags & ISFLAG_RANDART)
2216         return (true);
2217
2218     if (item.flags & ISFLAG_UNRANDART)
2219         return (false);
2220
2221     ASSERT(!item.props.exists( KNOWN_PROPS_KEY ));
2222     item.props[KNOWN_PROPS_KEY].new_vector(SV_BOOL).resize(RA_PROPERTIES);
2223     CrawlVector &known = item.props[KNOWN_PROPS_KEY];
2224     known.set_max_size(RA_PROPERTIES);
2225     for (vec_size i = 0; i < RA_PROPERTIES; i++)
2226         known[i] = (bool) false;
2227
2228     item.flags |= ISFLAG_RANDART;
2229     do
2230     {
2231         item.special = (random_int() & RANDART_SEED_MASK);
2232     } while (randart_is_bad( item ));
2233
2234     return (true);
2235 }
2236
2237 bool make_item_unrandart( item_def &item, int unrand_index )
2238 {
2239     if (!item.props.exists( KNOWN_PROPS_KEY ))
2240     {
2241         item.props[KNOWN_PROPS_KEY].new_vector(SV_BOOL).resize(RA_PROPERTIES);
2242         CrawlVector &known = item.props[KNOWN_PROPS_KEY];
2243         known.set_max_size(RA_PROPERTIES);
2244         for (vec_size i = 0; i < RA_PROPERTIES; i++)
2245             known[i] = (bool) false;
2246     }
2247
2248     item.base_type = unranddata[unrand_index].ura_cl;
2249     item.sub_type  = unranddata[unrand_index].ura_ty;
2250     item.plus      = unranddata[unrand_index].ura_pl;
2251     item.plus2     = unranddata[unrand_index].ura_pl2;
2252     item.colour    = unranddata[unrand_index].ura_col;
2253
2254     item.flags |= ISFLAG_UNRANDART; 
2255     item.special = unranddata[ unrand_index ].prpty[ RAP_BRAND ];
2256
2257     if (unranddata[ unrand_index ].prpty[ RAP_CURSED ])
2258         do_curse_item( item );
2259
2260     set_unrandart_exist( unrand_index, true );
2261
2262     return (true);
2263 }                               // end make_item_unrandart()
2264
2265 const char *unrandart_descrip( int which_descrip, const item_def &item )
2266 {
2267 /* Eventually it would be great to have randomly generated descriptions for
2268    randarts. */
2269     const unrandart_entry *unrand = seekunrandart( item );
2270
2271     return ((which_descrip == 0) ? unrand->spec_descrip1 :
2272             (which_descrip == 1) ? unrand->spec_descrip2 :
2273             (which_descrip == 2) ? unrand->spec_descrip3 : "Unknown.");
2274 }