1 /* File: flavor.c */
2
3 /* Purpose: Object flavor code */
4
5 /*
6 * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke
7 *
8 * This software may be copied and distributed for educational, research, and
9 * not for profit purposes provided that this copyright and statement are
10 * included in all such copies.
11 */
12
13 #include "angband.h"
14
15
16 /*
17 * Max sizes of the following arrays
18 */
19 #define MAX_ROCKS 68 /* Used with rings (min 55) */
20 #define MAX_AMULETS 30 /* Used with amulets (min 20) */
21 #define MAX_WOODS 40 /* Used with staffs (min 30) */
22 #define MAX_METALS 39 /* Used with wands/rods (min 30/29) */
23 #define MAX_COLORS 76 /* Used with potions (min 64) */
24 #define MAX_SHROOM 25 /* Used with mushrooms (min 20) */
25 #define MAX_TITLES 54 /* Used with scrolls (min 48) */
26 #define MAX_SYLLABLES 164 /* Used with scrolls (see below) */
27
28
29 /*
30 * Rings (adjectives and colors)
31 */
32
33 static cptr ring_adj[MAX_ROCKS] =
34 {
35 /* 0-9 */
36 "Alexandrite", "Amethyst", "Aquamarine", "Azurite", "Beryl",
37 "Bloodstone", "Calcite", "Carnelian", "Corundum", "Diamond",
38 /* 10-19 */
39 "Emerald", "Fluorite", "Garnet", "Granite", "Jade",
40 "Jasper", "Lapis Lazuli", "Malachite", "Marble", "Moonstone",
41 /* 20-29 */
42 "Onyx", "Opal", "Pearl", "Quartz", "Quartzite",
43 "Rhodonite", "Ruby", "Sapphire", "Tiger Eye", "Topaz",
44 /* 30-39 */
45 "Turquoise", "Zircon", "Platinum", "Bronze", "Gold",
46 "Obsidian", "Silver", "Tortoise Shell", "Mithril", "Jet",
47 /* 40-49 */
48 "Engagement", "Adamantite", "Wire", "Dilithium", "Bone",
49 "Wooden", "Iron", "Serpent", "Wedding", "Double",
50 /* 50-59 */
51 "Plain", "Brass", "Scarab", "Shining", "Rusty",
52 "Transparent", "Cat's-Eye", "Chrysoberyl", "Serpentine", "Spinel",
53 /* 60-67 */
54 "Topaz", "Morganite", "Heliodor", "Tourmaline", "Chalcedony",
55 "Peridot", "Hematite", "Coral"
56 };
57
58 static byte ring_col[MAX_ROCKS] =
59 {
60 /* 0-9 */
61 TERM_GREEN, TERM_VIOLET, TERM_L_BLUE, TERM_L_BLUE, TERM_L_GREEN,
62 TERM_RED, TERM_WHITE, TERM_RED, TERM_SLATE, TERM_WHITE,
63 /* 10-19 */
64 TERM_GREEN, TERM_L_GREEN, TERM_RED, TERM_L_DARK, TERM_L_GREEN,
65 TERM_UMBER, TERM_BLUE, TERM_GREEN, TERM_WHITE, TERM_L_WHITE,
66 /* 20-29 */
67 TERM_L_RED, TERM_L_WHITE, TERM_WHITE, TERM_L_WHITE, TERM_L_WHITE,
68 TERM_L_RED, TERM_RED, TERM_BLUE, TERM_YELLOW, TERM_YELLOW,
69 /* 30-39 */
70 TERM_L_BLUE, TERM_L_UMBER, TERM_WHITE, TERM_L_UMBER, TERM_YELLOW,
71 TERM_L_DARK, TERM_L_WHITE, TERM_GREEN, TERM_L_BLUE, TERM_L_DARK,
72 /* 40-49 */
73 TERM_YELLOW, TERM_VIOLET, TERM_UMBER, TERM_L_WHITE, TERM_WHITE,
74 TERM_UMBER, TERM_BLUE, TERM_GREEN, TERM_YELLOW, TERM_ORANGE,
75 /* 50-59 */
76 TERM_YELLOW, TERM_ORANGE, TERM_L_GREEN, TERM_YELLOW, TERM_RED,
77 TERM_WHITE, TERM_YELLOW, TERM_YELLOW, TERM_L_GREEN, TERM_RED,
78 /* 60-67 */
79 TERM_YELLOW, TERM_L_RED, TERM_YELLOW, TERM_GREEN, TERM_L_DARK,
80 TERM_L_GREEN, TERM_L_DARK, TERM_L_RED
81 };
82
83
84 /*
85 * Amulets (adjectives and colors)
86 */
87 static cptr amulet_adj[MAX_AMULETS] =
88 {
89 /* 0-9 */
90 "Amber", "Driftwood", "Coral", "Agate", "Ivory",
91 "Obsidian", "Bone", "Brass", "Bronze", "Pewter",
92 /* 10-19 */
93 "Tortoise Shell", "Golden", "Azure", "Crystal", "Silver",
94 "Copper", "Rosetted", "Spiral", "Star", "Square",
95 /* 20-29 */
96 "Hexagonal", "Steel", "Skull", "Platinum", "Electrum",
97 "Glass", "Cracked", "Heartwood", "Bark", "Mirrored"
98 };
99
100 static byte amulet_col[MAX_AMULETS] =
101 {
102 /* 0-9 */
103 TERM_YELLOW, TERM_L_UMBER, TERM_WHITE, TERM_L_WHITE, TERM_WHITE,
104 TERM_L_DARK, TERM_WHITE, TERM_L_UMBER, TERM_L_UMBER, TERM_SLATE,
105 /* 10-19 */
106 TERM_GREEN, TERM_YELLOW, TERM_L_BLUE, TERM_L_BLUE, TERM_L_WHITE,
107 TERM_L_UMBER, TERM_VIOLET, TERM_VIOLET, TERM_YELLOW, TERM_L_UMBER,
108 /* 20-29 */
109 TERM_L_DARK, TERM_WHITE, TERM_L_DARK, TERM_L_WHITE, TERM_WHITE,
110 TERM_L_RED, TERM_RED, TERM_UMBER, TERM_UMBER, TERM_WHITE
111 };
112
113
114 /*
115 * Staffs (adjectives and colors)
116 */
117 static cptr staff_adj[MAX_WOODS] =
118 {
119 /* 0-9 */
120 "Aspen", "Balsa", "Banyan", "Birch", "Cedar",
121 "Cottonwood", "Cypress", "Dogwood", "Elm", "Willow",
122 /* 10-19 */
123 "Hemlock", "Hickory", "Ironwood", "Locust", "Mahogany",
124 "Maple", "Mulberry", "Oak", "Pine", "Redwood",
125 /* 20-29 */
126 "Rosewood", "Spruce", "Sycamore", "Teak", "Walnut",
127 "Mistletoe", "Hawthorn", "Bamboo", "Silver", "Runed",
128 /* 30-39 */
129 "Golden", "Ashen", "Gnarled", "Ivory", "Sandalwood",
130 "Yew", "Thorned", "Charred", "Darkwood", "Flowering"
131 };
132
133 static byte staff_col[MAX_WOODS] =
134 {
135 /* 0-9 */
136 TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER,
137 TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER,
138 /* 10-19 */
139 TERM_L_UMBER, TERM_L_UMBER, TERM_UMBER, TERM_L_UMBER, TERM_UMBER,
140 TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_RED,
141 /* 20-29 */
142 TERM_RED, TERM_L_UMBER, TERM_L_UMBER, TERM_L_UMBER, TERM_UMBER,
143 TERM_GREEN, TERM_L_UMBER, TERM_L_UMBER, TERM_L_WHITE, TERM_UMBER,
144 /* 30-39 */
145 TERM_YELLOW, TERM_SLATE, TERM_UMBER, TERM_L_WHITE, TERM_YELLOW,
146 TERM_L_UMBER, TERM_L_UMBER, TERM_L_DARK, TERM_L_DARK, TERM_L_GREEN
147 };
148
149
150 /*
151 * Wands (adjectives and colors)
152 */
153 static cptr wand_adj[MAX_METALS] =
154 {
155 /* 0-9 */
156 "Aluminium", "Cast Iron", "Chromium", "Copper", "Gold",
157 "Iron", "Magnesium", "Molybdenum", "Nickel", "Rusty",
158 /* 10-19 */
159 "Silver", "Steel", "Tin", "Titanium", "Tungsten",
160 "Zirconium", "Zinc", "Aluminium-Plated", "Copper-Plated", "Gold-Plated",
161 /* 20-29 */
162 "Nickel-Plated", "Silver-Plated", "Steel-Plated", "Tin-Plated", "Zinc-Plated",
163 "Mithril-Plated", "Mithril", "Runed", "Bronze", "Brass",
164 /* 30-38 */
165 "Platinum", "Lead", "Lead-Plated", "Ivory", "Adamantite",
166 "Uridium", "Long", "Short", "Hexagonal"
167 };
168
169 static byte wand_col[MAX_METALS] =
170 {
171 /* 0-9 */
172 TERM_L_BLUE, TERM_L_DARK, TERM_WHITE, TERM_L_UMBER, TERM_YELLOW,
173 TERM_SLATE, TERM_L_WHITE, TERM_L_WHITE, TERM_L_UMBER, TERM_RED,
174 /* 10-19 */
175 TERM_L_WHITE, TERM_L_WHITE, TERM_L_WHITE, TERM_WHITE, TERM_WHITE,
176 TERM_L_WHITE, TERM_L_WHITE, TERM_L_BLUE, TERM_L_UMBER, TERM_YELLOW,
177 /* 20-29 */
178 TERM_L_UMBER, TERM_L_WHITE, TERM_L_WHITE, TERM_L_WHITE, TERM_L_WHITE,
179 TERM_L_BLUE, TERM_L_BLUE, TERM_UMBER, TERM_L_UMBER, TERM_L_UMBER,
180 /* 30-38 */
181 TERM_WHITE, TERM_SLATE, TERM_SLATE, TERM_WHITE, TERM_VIOLET,
182 TERM_L_RED, TERM_L_BLUE, TERM_BLUE, TERM_RED
183 };
184
185
186 /*
187 * Rods (adjectives and colors).
188 * Efficiency -- copied from wand arrays
189 */
190
191 static cptr rod_adj[MAX_METALS];
192
193 static byte rod_col[MAX_METALS];
194
195
196 /*
197 * Mushrooms (adjectives and colors)
198 */
199
200 static cptr food_adj[MAX_SHROOM] =
201 {
202 /* 0-9 */
203 "Blue", "Black", "Black Spotted", "Brown", "Dark Blue",
204 "Dark Green", "Dark Red", "Yellow", "Furry", "Green",
205 /* 10-19 */
206 "Grey", "Light Blue", "Light Green", "Violet", "Red",
207 "Slimy", "Tan", "White", "White Spotted", "Wrinkled",
208 /* 20-24 */
209 "Strange", "Silver", "Glowing", "Orange", "Dried",
210 };
211
212 static byte food_col[MAX_SHROOM] =
213 {
214 /* 0-9 */
215 TERM_BLUE, TERM_L_DARK, TERM_L_DARK, TERM_UMBER, TERM_BLUE,
216 TERM_GREEN, TERM_RED, TERM_YELLOW, TERM_L_WHITE, TERM_GREEN,
217 /* 10-19 */
218 TERM_SLATE, TERM_L_BLUE, TERM_L_GREEN, TERM_VIOLET, TERM_RED,
219 TERM_SLATE, TERM_L_UMBER, TERM_WHITE, TERM_WHITE, TERM_UMBER,
220 /* 20-24 */
221 TERM_L_BLUE, TERM_WHITE, TERM_YELLOW, TERM_ORANGE, TERM_UMBER,
222 };
223
224
225 /*
226 * Color adjectives and colors, for potions.
227 * Hack -- The first four entries are hard-coded.
228 * (water, apple juice, slime mold juice, something)
229 */
230
231 static cptr potion_adj[MAX_COLORS] =
232 {
233 /* Fixed colors */
234 "Clear", "Light Brown", "Icky Green", "xxx",
235 /* 4-9 */
236 "Azure",
237 "Blue", "Blue Speckled", "Black", "Brown", "Brown Speckled",
238 /* 10-19 */
239 "Bubbling", "Chartreuse", "Cloudy", "Copper Speckled", "Crimson",
240 "Cyan", "Dark Blue", "Dark Green", "Dark Red", "Gold Speckled",
241 /* 20-29 */
242 "Green", "Green Speckled", "Grey", "Grey Speckled", "Hazy",
243 "Indigo", "Light Blue", "Light Green", "Magenta", "Metallic Blue",
244 /* 30-39 */
245 "Metallic Red", "Metallic Green", "Metallic Purple", "Misty", "Orange",
246 "Orange Speckled", "Pink", "Pink Speckled", "Puce", "Purple",
247 /* 40-49 */
248 "Purple Speckled", "Red", "Red Speckled", "Silver Speckled", "Smoky",
249 "Tangerine", "Violet", "Vermilion", "White", "Yellow",
250 /* 50-59 */
251 "Violet Speckled", "Pungent", "Clotted Red", "Viscous Pink", "Oily Yellow",
252 "Gloopy Green", "Shimmering", "Coagulated Crimson", "Yellow Speckled",
253 /* 60-69 */
254 "Gold", "Manly", "Stinking", "Oily Black", "Ichor", "Ivory White",
255 "Sky Blue", "Bloody", "Inky Black", "Silver Flecked", "Red Flecked",
256 /* 70-75 */
257 "Green Flecked", "Sea Green", "Umber", "Layered", "Fizzy Yellow",
258 "Fizzy Green",
259 };
260
261 static byte potion_col[MAX_COLORS] =
262 {
263 /* Fixed colors */
264 TERM_WHITE, TERM_L_UMBER, TERM_GREEN, 0,
265 /* 4-9 */
266 TERM_L_BLUE,
267 TERM_BLUE, TERM_BLUE, TERM_L_DARK, TERM_UMBER, TERM_UMBER,
268 /* 10-19 */
269 TERM_L_WHITE, TERM_L_GREEN, TERM_WHITE, TERM_L_UMBER, TERM_RED,
270 TERM_L_BLUE, TERM_BLUE, TERM_GREEN, TERM_RED, TERM_YELLOW,
271 /* 20-29 */
272 TERM_GREEN, TERM_GREEN, TERM_SLATE, TERM_SLATE, TERM_L_WHITE,
273 TERM_VIOLET, TERM_L_BLUE, TERM_L_GREEN, TERM_RED, TERM_BLUE,
274 /* 30-39 */
275 TERM_RED, TERM_GREEN, TERM_VIOLET, TERM_L_WHITE, TERM_ORANGE,
276 TERM_ORANGE, TERM_L_RED, TERM_L_RED, TERM_VIOLET, TERM_VIOLET,
277 /* 40-49 */
278 TERM_VIOLET, TERM_RED, TERM_RED, TERM_L_WHITE, TERM_L_DARK,
279 TERM_ORANGE, TERM_VIOLET, TERM_RED, TERM_WHITE, TERM_YELLOW,
280 /* 50-59 */
281 TERM_VIOLET, TERM_L_RED, TERM_RED, TERM_L_RED, TERM_YELLOW,
282 TERM_GREEN, TERM_VIOLET, TERM_RED, TERM_YELLOW, TERM_YELLOW,
283 /* 60-69 */
284 TERM_L_UMBER, TERM_UMBER, TERM_L_DARK, TERM_RED, TERM_WHITE,
285 TERM_L_BLUE, TERM_RED, TERM_L_DARK, TERM_WHITE, TERM_RED,
286 /* 70-75 */
287 TERM_GREEN, TERM_L_GREEN, TERM_UMBER, TERM_L_BLUE, TERM_YELLOW,
288 TERM_L_GREEN,
289 };
290
291
292 /*
293 * Syllables for scrolls (must be 1-4 letters each)
294 */
295
296 static cptr syllables[MAX_SYLLABLES] =
297 {
298 "a", "ab", "ag", "aks", "ala", "an", "ankh", "app",
299 "arg", "arze", "ash", "aus", "ban", "bar", "bat", "bek",
300 "bie", "bin", "bit", "bjor", "blu", "bot", "bu",
301 "byt", "comp", "con", "cos", "cre", "dalf", "dan",
302 "den", "der", "doe", "dok", "eep", "el", "eng", "er", "ere", "erk",
303 "esh", "evs", "fa", "fid", "flit", "for", "fri", "fu", "gan",
304 "gar", "glen", "gop", "gre", "ha", "he", "hyd", "i",
305 "ing", "ion", "ip", "ish", "it", "ite", "iv", "jo",
306 "kho", "kli", "klis", "la", "lech", "man", "mar",
307 "me", "mi", "mic", "mik", "mon", "mung", "mur", "nag", "nej",
308 "nelg", "nep", "ner", "nes", "nis", "nih", "nin", "o",
309 "od", "ood", "org", "orn", "ox", "oxy", "pay", "pet",
310 "ple", "plu", "po", "pot", "prok", "re", "rea", "rhov",
311 "ri", "ro", "rog", "rok", "rol", "sa", "san", "sat",
312 "see", "sef", "seh", "shu", "ski", "sna", "sne", "snik",
313 "sno", "so", "sol", "sri", "sta", "sun", "ta", "tab",
314 "tem", "ther", "ti", "tox", "trol", "tue", "turs", "u",
315 "ulk", "um", "un", "uni", "ur", "val", "viv", "vly",
316 "vom", "wah", "wed", "werg", "wex", "whon", "wun", "xi",
317 "yerg", "yp", "zun", "tri", "blaa", "jah", "bul", "on",
318 "foo", "ju", "xuxu"
319 };
320
321
322 /*
323 * Hold the titles of scrolls, 6 to 14 characters each
324 * Also keep an array of scroll colors (always WHITE for now)
325 */
326 static char scroll_adj[MAX_TITLES][16];
327
328 static byte scroll_col[MAX_TITLES];
329
330
331 /*
332 * Certain items, if aware, are known instantly
333 * This function is used only by "flavor_init()"
334 */
object_easy_know(int i)335 static bool object_easy_know(int i)
336 {
337 object_kind *k_ptr = &k_info[i];
338
339 if (FLAG(k_ptr, TR_EASY_KNOW)) return (TRUE);
340
341 /* Nope */
342 return (FALSE);
343 }
344
345
346 /*
347 * Certain items have a flavor
348 * This function is used only by "flavor_init()"
349 */
object_flavor(int k_idx)350 static bool object_flavor(int k_idx)
351 {
352 object_kind *k_ptr = &k_info[k_idx];
353
354 /* Analyze the item */
355 switch (k_ptr->tval)
356 {
357 case TV_AMULET:
358 {
359 return (0x80 + amulet_col[k_ptr->sval]);
360 }
361
362 case TV_RING:
363 {
364 return (0x90 + ring_col[k_ptr->sval]);
365 }
366
367 case TV_STAFF:
368 {
369 return (0xA0 + staff_col[k_ptr->sval]);
370 }
371
372 case TV_WAND:
373 {
374 return (0xB0 + wand_col[k_ptr->sval]);
375 }
376
377 case TV_ROD:
378 {
379 return (0xC0 + rod_col[k_ptr->sval]);
380 }
381
382 case TV_SCROLL:
383 {
384 return (0xD0 + scroll_col[k_ptr->sval]);
385 }
386
387 case TV_POTION:
388 {
389 return (0xE0 + potion_col[k_ptr->sval]);
390 }
391
392 case TV_FOOD:
393 {
394 if (k_ptr->sval < SV_FOOD_MIN_FOOD)
395 {
396 return (0xF0 + food_col[k_ptr->sval]);
397 }
398
399 break;
400 }
401 }
402
403 /* No flavor */
404 return (0);
405 }
406
407
get_table_name(char * out_string,bool quotes)408 void get_table_name(char *out_string, bool quotes)
409 {
410 int testcounter = 2;
411
412 int len = 0;
413
414 /* Empty string */
415 out_string[0] = 0;
416
417 if (quotes)
418 {
419 strnfcat(out_string, 18, &len, "'");
420 }
421
422 if (one_in_(3))
423 {
424 while (testcounter--)
425 strnfcat(out_string, 18, &len, syllables[randint0(MAX_SYLLABLES)]);
426 }
427 else
428 {
429 char Syllable[80];
430
431 while (testcounter--)
432 {
433 (void)get_rnd_line("elvish.txt", 0, Syllable);
434 strnfcat(out_string, 18, &len, "%s", Syllable);
435 }
436 }
437
438 if (quotes)
439 {
440 out_string[1] = toupper(out_string[1]);
441 strnfcat(out_string, 18, &len, "'");
442 }
443 else
444 {
445 out_string[0] = toupper(out_string[0]);
446 }
447 }
448
449
450 /*
451 * Prepare the "variable" part of the "k_info" array.
452 *
453 * The "color"/"metal"/"type" of an item is its "flavor".
454 * For the most part, flavors are assigned randomly each game.
455 *
456 * Initialize descriptions for the "colored" objects, including:
457 * Rings, Amulets, Staffs, Wands, Rods, Food, Potions, Scrolls.
458 *
459 * The first 4 entries for potions are fixed (Water, Apple Juice,
460 * Slime Mold Juice, Unused Potion).
461 *
462 * Scroll titles are always between 6 and 14 letters long. This is
463 * ensured because every title is composed of whole words, where every
464 * word is from 1 to 8 letters long (one or two syllables of 1 to 4
465 * letters each), and that no scroll is finished until it attempts to
466 * grow beyond 15 letters. The first time this can happen is when the
467 * current title has 6 letters and the new word has 8 letters, which
468 * would result in a 6 letter scroll title.
469 *
470 * Duplicate titles are avoided by requiring that no two scrolls share
471 * the same first four letters (not the most efficient method, and not
472 * the least efficient method, but it will always work).
473 *
474 * Hack -- make sure everything stays the same for each saved game
475 * This is accomplished by the use of a saved "random seed", as in
476 * "town_gen()". Since no other functions are called while the special
477 * seed is in effect, so this function is pretty "safe".
478 *
479 * Note that the "hacked seed" may provide an RNG with alternating parity!
480 */
flavor_init(void)481 void flavor_init(void)
482 {
483 int i, j;
484
485 byte temp_col;
486
487 cptr temp_adj;
488
489
490 /* Hack -- Use the "simple" RNG */
491 Rand_quick = TRUE;
492
493 /* Hack -- Induce consistant flavors */
494 Rand_value = seed_flavor;
495
496
497 /* Efficiency -- Rods/Wands share initial array */
498 for (i = 0; i < MAX_METALS; i++)
499 {
500 rod_adj[i] = wand_adj[i];
501 rod_col[i] = wand_col[i];
502 }
503
504
505 /* Rings have "ring colors" */
506 for (i = 0; i < MAX_ROCKS; i++)
507 {
508 j = randint0(MAX_ROCKS);
509 temp_adj = ring_adj[i];
510 ring_adj[i] = ring_adj[j];
511 ring_adj[j] = temp_adj;
512 temp_col = ring_col[i];
513 ring_col[i] = ring_col[j];
514 ring_col[j] = temp_col;
515 }
516
517 /* Amulets have "amulet colors" */
518 for (i = 0; i < MAX_AMULETS; i++)
519 {
520 j = randint0(MAX_AMULETS);
521 temp_adj = amulet_adj[i];
522 amulet_adj[i] = amulet_adj[j];
523 amulet_adj[j] = temp_adj;
524 temp_col = amulet_col[i];
525 amulet_col[i] = amulet_col[j];
526 amulet_col[j] = temp_col;
527 }
528
529 /* Staffs */
530 for (i = 0; i < MAX_WOODS; i++)
531 {
532 j = randint0(MAX_WOODS);
533 temp_adj = staff_adj[i];
534 staff_adj[i] = staff_adj[j];
535 staff_adj[j] = temp_adj;
536 temp_col = staff_col[i];
537 staff_col[i] = staff_col[j];
538 staff_col[j] = temp_col;
539 }
540
541 /* Wands */
542 for (i = 0; i < MAX_METALS; i++)
543 {
544 j = randint0(MAX_METALS);
545 temp_adj = wand_adj[i];
546 wand_adj[i] = wand_adj[j];
547 wand_adj[j] = temp_adj;
548 temp_col = wand_col[i];
549 wand_col[i] = wand_col[j];
550 wand_col[j] = temp_col;
551 }
552
553 /* Rods */
554 for (i = 0; i < MAX_METALS; i++)
555 {
556 j = randint0(MAX_METALS);
557 temp_adj = rod_adj[i];
558 rod_adj[i] = rod_adj[j];
559 rod_adj[j] = temp_adj;
560 temp_col = rod_col[i];
561 rod_col[i] = rod_col[j];
562 rod_col[j] = temp_col;
563 }
564
565 /* Foods (Mushrooms) */
566 for (i = 0; i < MAX_SHROOM; i++)
567 {
568 j = randint0(MAX_SHROOM);
569 temp_adj = food_adj[i];
570 food_adj[i] = food_adj[j];
571 food_adj[j] = temp_adj;
572 temp_col = food_col[i];
573 food_col[i] = food_col[j];
574 food_col[j] = temp_col;
575 }
576
577 /* Potions */
578 for (i = 4; i < MAX_COLORS; i++)
579 {
580 j = rand_range(4, MAX_COLORS - 1);
581 temp_adj = potion_adj[i];
582 potion_adj[i] = potion_adj[j];
583 potion_adj[j] = temp_adj;
584 temp_col = potion_col[i];
585 potion_col[i] = potion_col[j];
586 potion_col[j] = temp_col;
587 }
588
589 /* Scrolls (random titles, always white) */
590 for (i = 0; i < MAX_TITLES; i++)
591 {
592 /* Get a new title */
593 while (TRUE)
594 {
595 char buf[80];
596
597 int buf_len = 0;
598
599 bool okay;
600
601 /* Start a new title */
602 buf[0] = '\0';
603
604 /* Collect words until done */
605 while (1)
606 {
607 int q, s;
608
609 char tmp[80];
610
611 int len = 0;
612
613 /* Start a new word */
614 tmp[0] = '\0';
615
616 /* Choose one or two syllables */
617 s = ((randint0(100) < 30) ? 1 : 2);
618
619 /* Add a one or two syllable word */
620 for (q = 0; q < s; q++)
621 {
622 /* Add the syllable */
623 strnfcat(tmp, 80, &len, syllables[randint0(MAX_SYLLABLES)]);
624 }
625
626 /* Stop before getting too long */
627 if (strlen(buf) + 1 + strlen(tmp) > 15) break;
628
629 /* Add a space + word */
630 strnfcat(buf, 80, &buf_len, " %s", tmp);
631 }
632
633 /* Save the title */
634 strcpy(scroll_adj[i], buf + 1);
635
636 /* Assume okay */
637 okay = TRUE;
638
639 /* Check for "duplicate" scroll titles */
640 for (j = 0; j < i; j++)
641 {
642 cptr hack1 = scroll_adj[j];
643 cptr hack2 = scroll_adj[i];
644
645 /* Compare first four characters */
646 if (*hack1++ != *hack2++) continue;
647 if (*hack1++ != *hack2++) continue;
648 if (*hack1++ != *hack2++) continue;
649 if (*hack1++ != *hack2++) continue;
650
651 /* Not okay */
652 okay = FALSE;
653
654 /* Stop looking */
655 break;
656 }
657
658 /* Break when done */
659 if (okay) break;
660 }
661
662 /* All scrolls are white */
663 scroll_col[i] = TERM_WHITE;
664 }
665
666
667 /* Hack -- Use the "complex" RNG */
668 Rand_quick = FALSE;
669
670 /* Analyze every object */
671 for (i = 1; i < z_info->k_max; i++)
672 {
673 object_kind *k_ptr = &k_info[i];
674
675 /* Skip "empty" objects */
676 if (!k_ptr->name) continue;
677
678 /* Extract "flavor" (if any) */
679 k_ptr->flavor = object_flavor(i);
680
681 /* No flavor yields aware */
682 if (!k_ptr->flavor) k_ptr->aware = TRUE;
683
684 /* Check for "easily known" */
685 k_ptr->easy_know = object_easy_know(i);
686 }
687 }
688
689
690 /*
691 * Creates a description of the item "o_ptr", and stores it in "out_val".
692 *
693 * One can choose the "verbosity" of the description, including whether
694 * or not the "number" of items should be described, and how much detail
695 * should be used when describing the item.
696 *
697 * The given "buf" must be 80 chars long to hold the longest possible
698 * description, which can get pretty long, including incriptions, such as:
699 * "no more Maces of Disruption (Defender) (+10,+10) [+5] (+3 to stealth)".
700 * Note that the inscription will be clipped to keep the total description
701 * under size - 1 chars (plus a terminator).
702 *
703 * Note the use of "object_desc_num()" and "object_desc_int()" as
704 * hyper-efficient, portable, versions of some common "sprintf()" commands.
705 *
706 * Note that all ego-items (when known) append an "Ego-Item Name", unless
707 * the item is also an artifact, which should NEVER happen.
708 *
709 * Note that all artifacts (when known) append an "Artifact Name", so we
710 * have special processing for "Specials" (artifact Lites, Rings, Amulets).
711 * The "Specials" never use "modifiers" if they are "known", since they
712 * have special "descriptions", such as "The Necklace of the Dwarves".
713 *
714 * Special Lite's use the "k_info" base-name (Phial, Star, or Arkenstone),
715 * plus the artifact name, just like any other artifact, if known.
716 *
717 * Special Ring's and Amulet's, if not "aware", use the same code as normal
718 * rings and amulets, and if "aware", use the "k_info" base-name (Ring or
719 * Amulet or Necklace). They will NEVER "append" the "k_info" name. But,
720 * they will append the artifact name, just like any artifact, if known.
721 *
722 * None of the Special Rings/Amulets are "EASY_KNOW", though they could be,
723 * at least, those which have no "pluses", such as the three artifact lites.
724 *
725 * Hack -- Display "The One Ring" as "a Plain Gold Ring" until aware.
726 *
727 * If "pref" then a "numeric" prefix will be pre-pended.
728 *
729 * Mode:
730 * 0 -- The Cloak of Death
731 * 1 -- The Cloak of Death [1,+3]
732 * 2 -- The Cloak of Death [1,+3] (+2 to Stealth)
733 * 3 -- The Cloak of Death [1,+3] (+2 to Stealth) {nifty}
734 */
object_desc(char * buf,const object_type * o_ptr,int pref,int mode,int max)735 void object_desc(char *buf, const object_type *o_ptr, int pref, int mode,
736 int max)
737 {
738 cptr basenm, modstr;
739 int power;
740
741 bool aware = FALSE;
742 bool known = FALSE;
743
744 bool append_name = FALSE;
745
746 bool show_weapon = FALSE;
747 bool show_armour = FALSE;
748
749 cptr s;
750
751 object_type *bow_ptr;
752
753 /* damage dice, damage sides, damage bonus, energy */
754 int dd, ds, db, energy_use;
755 int tmul;
756 long avgdam;
757
758 int len = 0;
759
760 object_kind *k_ptr = &k_info[o_ptr->k_idx];
761
762 monster_race *r_ptr = &r_info[o_ptr->pval];
763
764 /* See if the object is "aware" */
765 if (object_aware_p(o_ptr)) aware = TRUE;
766
767 /* See if the object is "known" */
768 if (object_known_p(o_ptr)) known = TRUE;
769
770 /* Artifacts are not "aware' unless "known" */
771 if ((FLAG(o_ptr, TR_INSTA_ART)) && !known) aware = FALSE;
772
773 /* Extract default "base" string */
774 basenm = get_object_name(o_ptr);
775
776 /* Assume no "modifier" string */
777 modstr = "";
778
779 /* Empty description */
780 buf[0] = '\0';
781
782 /* Analyze the object */
783 switch (o_ptr->tval)
784 {
785 case TV_SKELETON:
786 case TV_BOTTLE:
787 case TV_JUNK:
788 case TV_SPIKE:
789 case TV_FLASK:
790 case TV_CHEST:
791 {
792 /* Some objects are easy to describe */
793 break;
794 }
795
796 case TV_FIGURINE:
797 case TV_STATUE:
798 {
799 /* Figurines/Statues */
800 cptr tmp = mon_race_name(r_ptr);
801
802 char idol_name[512];
803
804 if (!FLAG(r_ptr, RF_UNIQUE))
805 {
806 strnfmt(idol_name, 512, "%s%s",
807 (is_a_vowel(*tmp) ? "an " : "a "), tmp);
808
809 modstr = idol_name;
810 }
811 else
812 {
813 modstr = tmp;
814 }
815
816 break;
817 }
818
819 case TV_SHOT:
820 case TV_BOLT:
821 case TV_ARROW:
822 case TV_BOW:
823 case TV_HAFTED:
824 case TV_POLEARM:
825 case TV_SWORD:
826 case TV_DIGGING:
827 {
828 /* Missiles/ Bows/ Weapons */
829 show_weapon = TRUE;
830 break;
831 }
832
833 case TV_BOOTS:
834 case TV_GLOVES:
835 case TV_CLOAK:
836 case TV_CROWN:
837 case TV_HELM:
838 case TV_SHIELD:
839 case TV_SOFT_ARMOR:
840 case TV_HARD_ARMOR:
841 case TV_DRAG_ARMOR:
842 {
843 /* Armour */
844 show_armour = TRUE;
845 break;
846 }
847
848 case TV_LITE:
849 {
850 /* Lites (including a few "Specials") */
851 break;
852 }
853
854 case TV_AMULET:
855 {
856 /* Amulets (including a few "Specials") */
857
858 /* Known artifacts */
859 if ((FLAG(k_ptr, TR_INSTA_ART)) && aware) break;
860
861 /* Color the object */
862 modstr = amulet_adj[o_ptr->sval];
863 if (aware) append_name = TRUE;
864
865 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
866 basenm = "& Amulet~";
867 else
868 basenm = "& # Amulet~";
869 break;
870 }
871
872 case TV_RING:
873 {
874 /* Rings (including a few "Specials") */
875
876 /* Known artifacts */
877 if ((FLAG(k_ptr, TR_INSTA_ART)) && aware) break;
878
879 /* Color the object */
880 modstr = ring_adj[o_ptr->sval];
881 if (aware) append_name = TRUE;
882
883 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
884 basenm = "& Ring~";
885 else
886 basenm = "& # Ring~";
887
888 /* Hack -- The One Ring */
889 if (!aware && (o_ptr->sval == SV_RING_POWER)) modstr = "Plain Gold";
890
891 break;
892 }
893
894 case TV_STAFF:
895 {
896 /* Color the object */
897 modstr = staff_adj[o_ptr->sval];
898 if (aware) append_name = TRUE;
899 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
900 basenm = "& Staff~";
901 else
902 basenm = "& # Staff~";
903 break;
904 }
905
906 case TV_WAND:
907 {
908 /* Color the object */
909 modstr = wand_adj[o_ptr->sval];
910 if (aware) append_name = TRUE;
911 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
912 basenm = "& Wand~";
913 else
914 basenm = "& # Wand~";
915 break;
916 }
917
918 case TV_ROD:
919 {
920 /* Color the object */
921 modstr = rod_adj[o_ptr->sval];
922 if (aware) append_name = TRUE;
923 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
924 basenm = "& Rod~";
925 else
926 basenm = "& # Rod~";
927 break;
928 }
929
930 case TV_SCROLL:
931 {
932 /* Color the object */
933 modstr = scroll_adj[o_ptr->sval];
934 if (aware) append_name = TRUE;
935 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
936 basenm = "& Scroll~";
937 else
938 basenm = "& Scroll~ titled \"#\"";
939 break;
940 }
941
942 case TV_POTION:
943 {
944 /* Color the object */
945 modstr = potion_adj[o_ptr->sval];
946 if (aware) append_name = TRUE;
947 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
948 basenm = "& Potion~";
949 else
950 basenm = "& # Potion~";
951 break;
952 }
953
954 case TV_FOOD:
955 {
956 /* Ordinary food is "boring" */
957 if (o_ptr->sval >= SV_FOOD_MIN_FOOD) break;
958
959 /* Color the object */
960 modstr = food_adj[o_ptr->sval];
961 if (aware) append_name = TRUE;
962 if (((plain_descriptions) && (aware)) || (o_ptr->info & OB_STOREB))
963 basenm = "& Mushroom~";
964 else
965 basenm = "& # Mushroom~";
966 break;
967 }
968
969 /*** Magic Books ***/
970
971 case TV_LIFE_BOOK:
972 {
973 modstr = basenm;
974 if (mp_ptr->spell_book == TV_LIFE_BOOK)
975 basenm = "& Book~ of Life Magic #";
976 else
977 basenm = "& Life Spellbook~ #";
978 break;
979 }
980
981 case TV_SORCERY_BOOK:
982 {
983 modstr = basenm;
984 if (mp_ptr->spell_book == TV_LIFE_BOOK)
985 basenm = "& Book~ of Sorcery #";
986 else
987 basenm = "& Sorcery Spellbook~ #";
988 break;
989 }
990
991 case TV_NATURE_BOOK:
992 {
993 modstr = basenm;
994 if (mp_ptr->spell_book == TV_LIFE_BOOK)
995 basenm = "& Book~ of Nature Magic #";
996 else
997 basenm = "& Nature Spellbook~ #";
998 break;
999 }
1000
1001 case TV_CHAOS_BOOK:
1002 {
1003 modstr = basenm;
1004 if (mp_ptr->spell_book == TV_LIFE_BOOK)
1005 basenm = "& Book~ of Chaos Magic #";
1006 else
1007 basenm = "& Chaos Spellbook~ #";
1008 break;
1009 }
1010
1011 case TV_DEATH_BOOK:
1012 {
1013 modstr = basenm;
1014 if (mp_ptr->spell_book == TV_LIFE_BOOK)
1015 basenm = "& Book~ of Death Magic #";
1016 else
1017 basenm = "& Death Spellbook~ #";
1018 break;
1019 }
1020
1021 case TV_TRUMP_BOOK:
1022 {
1023 modstr = basenm;
1024 if (mp_ptr->spell_book == TV_LIFE_BOOK)
1025 basenm = "& Book~ of Trump Magic #";
1026 else
1027 basenm = "& Trump Spellbook~ #";
1028 break;
1029 }
1030
1031 case TV_ARCANE_BOOK:
1032 {
1033 modstr = basenm;
1034 if (mp_ptr->spell_book == TV_LIFE_BOOK)
1035 basenm = "& Book~ of Arcane Magic #";
1036 else
1037 basenm = "& Arcane Spellbook~ #";
1038 break;
1039 }
1040
1041
1042 case TV_GOLD:
1043 {
1044 /* Hack -- Gold/Gems */
1045 strcpy(buf, basenm);
1046 return;
1047 }
1048
1049 default:
1050 {
1051 /* Used in the "inventory" routine */
1052 strcpy(buf, "(nothing)");
1053 return;
1054 }
1055 }
1056
1057 /* The object "expects" a "number" */
1058 if (basenm[0] == '&')
1059 {
1060 /* Skip the ampersand (and space) */
1061 s = basenm + 2;
1062
1063 /* No prefix */
1064 if (!pref)
1065 {
1066 /* Nothing */
1067 }
1068
1069 /* Hack -- None left */
1070 else if (o_ptr->number <= 0)
1071 {
1072 strnfcat(buf, max, &len, "no more ");
1073 }
1074
1075 /* Extract the number */
1076 else if (o_ptr->number > 1)
1077 {
1078 strnfcat(buf, max, &len, "%d ", o_ptr->number);
1079 }
1080
1081 /* Hack -- The only one of its kind */
1082 else if (known && (FLAG(o_ptr, TR_INSTA_ART)))
1083 {
1084 strnfcat(buf, max, &len, "The ");
1085 }
1086
1087 /* A single one, with a vowel in the modifier */
1088 else if ((*s == '#') && (is_a_vowel(modstr[0])))
1089 {
1090 strnfcat(buf, max, &len, "an ");
1091 }
1092
1093 /* A single one, with a vowel */
1094 else if (is_a_vowel(*s))
1095 {
1096 strnfcat(buf, max, &len, "an ");
1097 }
1098
1099 /* A single one, without a vowel */
1100 else
1101 {
1102 strnfcat(buf, max, &len, "a ");
1103 }
1104 }
1105
1106 /* Hack -- objects that "never" take an article */
1107 else
1108 {
1109 /* No ampersand */
1110 s = basenm;
1111
1112 /* No pref */
1113 if (!pref)
1114 {
1115 /* Nothing */
1116 }
1117
1118 /* Hack -- all gone */
1119 else if (o_ptr->number <= 0)
1120 {
1121 strnfcat(buf, max, &len, "no more ");
1122 }
1123
1124 /* Prefix a number if required */
1125 else if (o_ptr->number > 1)
1126 {
1127 strnfcat(buf, max, &len, "%d ", o_ptr->number);
1128 }
1129
1130 /* Hack -- The only one of its kind */
1131 else if (known && (FLAG(o_ptr, TR_INSTA_ART)))
1132 {
1133 strnfcat(buf, max, &len, "The ");
1134 }
1135
1136 /* Hack -- single items get no prefix */
1137 else
1138 {
1139 /* Nothing */
1140 }
1141 }
1142
1143 /* Copy the string */
1144 while (*s)
1145 {
1146 /* Pluralizer */
1147 if (*s == '~')
1148 {
1149 /* Add a plural if needed */
1150 if (o_ptr->number != 1)
1151 {
1152 /* Get previous character */
1153 char k = s[-1];
1154
1155 /* XXX XXX XXX Mega-Hack */
1156
1157 /* Hack -- "Cutlass-es" and "Torch-es" */
1158 if ((k == 's') || (k == 'h'))
1159 {
1160 strnfcat(buf, max, &len, "es");
1161 }
1162 else
1163 {
1164 /* Add an 's' */
1165 strnfcat(buf, max, &len, "s");
1166 }
1167 }
1168 }
1169
1170 /* Modifier */
1171 else if (*s == '#')
1172 {
1173 /* Insert the modifier */
1174 strnfcat(buf, max, &len, "%s", modstr);
1175 }
1176
1177 /* Normal */
1178 else
1179 {
1180 /* Copy character */
1181 strnfcat(buf, max, &len, "%c", *s);
1182 }
1183
1184 s++;
1185 }
1186
1187 /* Append the "kind name" to the "base name" */
1188 if (append_name)
1189 {
1190 strnfcat(buf, max, &len, " of %s", get_object_name(o_ptr));
1191 }
1192
1193
1194 /* Hack -- Append "Artifact" or "Special" names */
1195 if (known)
1196 {
1197 if (o_ptr->inscription && strchr(quark_str(o_ptr->inscription), '#'))
1198 {
1199 /* Find the '#' */
1200 cptr str = strchr(quark_str(o_ptr->inscription), '#');
1201
1202 /* Add the false name */
1203 strnfcat(buf, max, &len, " %s" CLR_DEFAULT, &str[1]);
1204 }
1205
1206 /* Is it a new artifact or ego item? */
1207 else if (o_ptr->xtra_name)
1208 {
1209 strnfcat(buf, max, &len, " %s", quark_str(o_ptr->xtra_name));
1210 }
1211 }
1212
1213 /* No more details wanted */
1214 if (mode < 1) return;
1215
1216 /* Hack -- Chests must be described in detail */
1217 if (o_ptr->tval == TV_CHEST)
1218 {
1219 /* Not searched yet */
1220 if (!known)
1221 {
1222 /* Nothing */
1223 }
1224
1225 /* May be "empty" */
1226 else if (!o_ptr->pval)
1227 {
1228 strnfcat(buf, max, &len, " (empty)");
1229 }
1230
1231 /* May be "disarmed" */
1232 else if (o_ptr->pval < 0)
1233 {
1234 if (chest_traps[0 - o_ptr->pval])
1235 {
1236 strnfcat(buf, max, &len, " (disarmed)");
1237 }
1238 else
1239 {
1240 strnfcat(buf, max, &len, " (unlocked)");
1241 }
1242 }
1243
1244 /* Describe the traps, if any */
1245 else
1246 {
1247 /* Describe the traps */
1248 switch (chest_traps[o_ptr->pval])
1249 {
1250 case 0:
1251 {
1252 strnfcat(buf, max, &len, " (Locked)");
1253 break;
1254 }
1255 case CHEST_LOSE_STR:
1256 {
1257 strnfcat(buf, max, &len, " (Poison Needle)");
1258 break;
1259 }
1260 case CHEST_LOSE_CON:
1261 {
1262 strnfcat(buf, max, &len, " (Poison Needle)");
1263 break;
1264 }
1265 case CHEST_POISON:
1266 {
1267 strnfcat(buf, max, &len, " (Gas Trap)");
1268 break;
1269 }
1270 case CHEST_PARALYZE:
1271 {
1272 strnfcat(buf, max, &len, " (Gas Trap)");
1273 break;
1274 }
1275 case CHEST_EXPLODE:
1276 {
1277 strnfcat(buf, max, &len, " (Explosion Device)");
1278 break;
1279 }
1280 case CHEST_SUMMON:
1281 {
1282 strnfcat(buf, max, &len, " (Summoning Runes)");
1283 break;
1284 }
1285 default:
1286 {
1287 strnfcat(buf, max, &len, " (Multiple Traps)");
1288 break;
1289 }
1290 }
1291 }
1292 }
1293
1294
1295 /* Display the item like a weapon */
1296 if (FLAG(o_ptr, TR_SHOW_MODS)) show_weapon = TRUE;
1297
1298 /* Display the item like a weapon */
1299 if (o_ptr->to_h && o_ptr->to_d) show_weapon = TRUE;
1300
1301 /* Display the item like armour */
1302 if ((o_ptr->ac) && (o_ptr->tval != TV_WAND)) show_armour = TRUE;
1303
1304 /* Dump base weapon info */
1305 switch (o_ptr->tval)
1306 {
1307 case TV_SHOT:
1308 case TV_BOLT:
1309 case TV_ARROW:
1310 case TV_HAFTED:
1311 case TV_POLEARM:
1312 case TV_SWORD:
1313 case TV_DIGGING:
1314 {
1315 /* Missiles and Weapons */
1316
1317 /* Append a "damage" string */
1318 strnfcat(buf, max, &len, " (%dd%d)", o_ptr->dd, o_ptr->ds);
1319
1320 /* All done */
1321 break;
1322 }
1323
1324 case TV_BOW:
1325 {
1326 /* Bows get a special "damage string" */
1327
1328 /* Extract the "base power" */
1329 switch (o_ptr->sval)
1330 {
1331 case SV_SLING:
1332 {
1333 power = 2;
1334 break;
1335 }
1336 case SV_SHORT_BOW:
1337 {
1338 power = 2;
1339 break;
1340 }
1341 case SV_LONG_BOW:
1342 {
1343 if (p_ptr->stat[A_STR].use >= 160)
1344 {
1345 power = 3;
1346 }
1347 else
1348 {
1349 /* hack- weak players cannot use a longbow well */
1350 power = 2;
1351 }
1352 break;
1353 }
1354 case SV_LIGHT_XBOW:
1355 {
1356 power = 4;
1357 break;
1358 }
1359 case SV_HEAVY_XBOW:
1360 {
1361 power = 5;
1362 break;
1363 }
1364 default:
1365 {
1366 msgf("Unknown firing multiplier.");
1367 power = 0;
1368 }
1369 }
1370
1371 /* Apply the "Extra Might" flag */
1372 if (FLAG(o_ptr, TR_XTRA_MIGHT)) power++;
1373
1374 /* Append a special "damage" string */
1375 strnfcat(buf, max, &len, " (x%d)", power);
1376
1377 /* All done */
1378 break;
1379 }
1380 }
1381
1382
1383 /* Add the weapon bonuses */
1384 if (known)
1385 {
1386 /* Show the tohit/todam on request */
1387 if (show_weapon)
1388 {
1389 strnfcat(buf, max, &len, " (%+d,%+d%%)", o_ptr->to_h,
1390 deadliness_calc(o_ptr->to_d) - 100);
1391 }
1392
1393 /* Show the tohit if needed */
1394 else if (o_ptr->to_h)
1395 {
1396 strnfcat(buf, max, &len, " (%+d)", o_ptr->to_h);
1397 }
1398
1399 /* Show the todam if needed */
1400 else if (o_ptr->to_d)
1401 {
1402 strnfcat(buf, max, &len, " (%+d%%)", o_ptr->to_d * 5);
1403 }
1404 }
1405
1406 bow_ptr = &p_ptr->equipment[EQUIP_BOW];
1407
1408 /* if have a firing weapon + ammo matches bow */
1409 if (bow_ptr->k_idx && (p_ptr->ammo_tval == o_ptr->tval))
1410 {
1411 /* See if the bow is "known" - then set damage bonus */
1412 if (object_known_p(bow_ptr))
1413 {
1414 db = bow_ptr->to_d;
1415 }
1416 else
1417 {
1418 db = 0;
1419 }
1420
1421 /* effect of player */
1422 db += p_ptr->dis_to_d;
1423
1424 /* effect of ammo */
1425 if (known) db += o_ptr->to_d;
1426
1427 dd = o_ptr->dd;
1428 ds = o_ptr->ds;
1429
1430 /* effect of damage dice x2 */
1431 avgdam = avg_dam(db, dd, ds);
1432
1433 /* Bow properties */
1434 energy_use = p_ptr->bow_energy;
1435 tmul = p_ptr->ammo_mult;
1436
1437 /* Get extra "power" from "extra might" */
1438 if (FLAG(p_ptr, TR_XTRA_MIGHT)) tmul++;
1439
1440 /* launcher multiplier */
1441 avgdam *= tmul;
1442
1443 /* display (shot damage/ avg damage) */
1444 strnfcat(buf, max, &len, " (%d/", avgdam / 200);
1445
1446 tmul = p_ptr->num_fire;
1447 if (tmul == 0)
1448 {
1449 strnfcat(buf, max, &len, "0)");
1450 }
1451 else
1452 {
1453 /* calc effects of energy x2 */
1454 avgdam *= (1 + p_ptr->num_fire);
1455
1456 /* rescale */
1457 avgdam /= 4 * energy_use;
1458 strnfcat(buf, max, &len, "%d)", avgdam);
1459 }
1460 }
1461
1462 /* Add the armor bonuses */
1463 if (known)
1464 {
1465 /* Show the armor class info */
1466 if (show_armour)
1467 {
1468 strnfcat(buf, max, &len, " [%d,%+d]", o_ptr->ac, o_ptr->to_a);
1469 }
1470
1471 /* No base armor, but does increase armor */
1472 else if (o_ptr->to_a)
1473 {
1474 strnfcat(buf, max, &len, " [%+d]", o_ptr->to_a);
1475 }
1476 }
1477
1478 /* Hack -- always show base armor */
1479 else if (show_armour)
1480 {
1481 strnfcat(buf, max, &len, " [%d]", o_ptr->ac);
1482 }
1483
1484
1485 /* No more details wanted */
1486 if (mode < 2) return;
1487
1488
1489 /*
1490 * Hack -- Wands and Staffs have charges. Make certain how many charges
1491 * a stack of staffs really has is clear. -LM-
1492 */
1493 if (known && ((o_ptr->tval == TV_STAFF) || (o_ptr->tval == TV_WAND)))
1494 {
1495 /* Dump " (N charges)" */
1496 strnfcat(buf, max, &len, " (");
1497
1498 /* Clear explaination for staffs. */
1499 if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1))
1500 {
1501 strnfcat(buf, max, &len, "%dx ", o_ptr->number);
1502 }
1503
1504 if (o_ptr->pval == 1)
1505 {
1506 strnfcat(buf, max, &len, "%d charge)", o_ptr->pval);
1507 }
1508 else
1509 {
1510 strnfcat(buf, max, &len, "%d charges)", o_ptr->pval);
1511 }
1512 }
1513 /* Hack -- Rods have a "charging" indicator. Now that stacks of rods may
1514 * be in any state of charge or discharge, this now includes a number. -LM-
1515 */
1516 else if (o_ptr->tval == TV_ROD)
1517 {
1518 /* Hack -- Dump " (# charging)" if relevant */
1519 if (o_ptr->timeout)
1520 {
1521 /* Stacks of rods display an exact count of charging rods. */
1522 if (o_ptr->number > 1)
1523 {
1524 /* Paranoia. */
1525 if (k_ptr->pval == 0) k_ptr->pval = 1;
1526
1527 /*
1528 * Find out how many rods are charging, by dividing
1529 * current timeout by each rod's maximum timeout.
1530 * Ensure that any remainder is rounded up. Display
1531 * very discharged stacks as merely fully discharged.
1532 */
1533 power = (o_ptr->timeout + (k_ptr->pval - 1)) / k_ptr->pval;
1534 if (power > o_ptr->number) power = o_ptr->number;
1535
1536 /* Display prettily. */
1537 strnfcat(buf, max, &len, " (%d charging)", power);
1538 }
1539
1540 /* "one Rod of Perception (1 charging)" would look tacky. */
1541 else
1542 {
1543 strnfcat(buf, max, &len, " (charging)");
1544 }
1545 }
1546 }
1547
1548 /* Hack -- Process Lanterns/Torches */
1549 else if (o_ptr->tval == TV_LITE)
1550 {
1551 if (FLAG(o_ptr, TR_LITE))
1552 {
1553 /* Hack - tell us when lites of everburning are "empty" */
1554 if ((o_ptr->sval <= SV_LITE_LANTERN) && !o_ptr->timeout)
1555 {
1556 strnfcat(buf, max, &len, " (empty)");
1557 }
1558 }
1559 else
1560 {
1561 /* Hack -- Turns of light for normal lites */
1562 strnfcat(buf, max, &len, " (with %d turns of light)", o_ptr->timeout);
1563 }
1564 }
1565
1566
1567 /* Dump "pval" flags for wearable items */
1568 if (known && (FLAG(o_ptr, TR_PVAL_MASK)))
1569 {
1570 /* Start the display */
1571 strnfcat(buf, max, &len, " (%+d", o_ptr->pval);
1572
1573 /* Do not display the "pval" flags */
1574 if (FLAG(o_ptr, TR_HIDE_TYPE))
1575 {
1576 /* Nothing */
1577 }
1578
1579 /* Speed */
1580 else if (FLAG(o_ptr, TR_SPEED))
1581 {
1582 /* Dump " to speed" */
1583 strnfcat(buf, max, &len, " to speed");
1584 }
1585
1586 /* Attack speed */
1587 else if (FLAG(o_ptr, TR_BLOWS))
1588 {
1589 if (ABS(o_ptr->pval) == 1)
1590 {
1591 /* Add " attack" */
1592 strnfcat(buf, max, &len, " attack");
1593 }
1594 else
1595 {
1596 /* Add "attacks" */
1597 strnfcat(buf, max, &len, " attacks");
1598 }
1599 }
1600
1601 /* Finish the display */
1602 strnfcat(buf, max, &len, ")");
1603 }
1604
1605 /* Indicate charging objects, but not rods. */
1606 if (known && o_ptr->timeout && (o_ptr->tval != TV_ROD)
1607 && (o_ptr->tval != TV_LITE))
1608 {
1609 /* Hack -- Dump " (charging)" if relevant */
1610 strnfcat(buf, max, &len, " (charging)");
1611 }
1612
1613
1614 /* No more details wanted */
1615 if (mode < 3) return;
1616
1617 /* Use the standard inscription if available */
1618 if (o_ptr->inscription)
1619 {
1620 cptr tmp = quark_str(o_ptr->inscription);
1621
1622 /* Append the inscription */
1623 strnfcat(buf, max, &len, " {");
1624
1625 /* Scan for the '#' character which marks a fake name. */
1626 while(*tmp && (*tmp != '#'))
1627 {
1628 strnfcat(buf, max, &len, "%c", *tmp);
1629
1630 tmp++;
1631 }
1632
1633 /* Finish the inscription */
1634 strnfcat(buf, max, &len, CLR_DEFAULT "}");
1635 }
1636
1637 /* Use the game-generated "feeling" otherwise, if available */
1638 else if (o_ptr->feeling)
1639 {
1640 /* Append the inscription */
1641 strnfcat(buf, max, &len, " {%s" CLR_DEFAULT "}", game_inscriptions[o_ptr->feeling]);
1642 }
1643
1644 /* Note "cursed" if the item is known to be cursed */
1645 else if (cursed_p(o_ptr) && (known || (o_ptr->info & (OB_SENSE))))
1646 {
1647 /* Append the inscription */
1648 strnfcat(buf, max, &len, " {cursed}");
1649 }
1650
1651 /* Mega-Hack -- note empty wands/staffs */
1652 else if (!known && (o_ptr->info & (OB_EMPTY)))
1653 {
1654 /* Append the inscription */
1655 strnfcat(buf, max, &len, " {empty}");
1656 }
1657
1658 /* Note "tried" if the object has been tested unsuccessfully */
1659 else if (!aware && object_tried_p(o_ptr))
1660 {
1661 /* Append the inscription */
1662 strnfcat(buf, max, &len, " {tried}");
1663 }
1664
1665 /* Note the discount, if any */
1666 else if (o_ptr->discount)
1667 {
1668 /* Append the inscription */
1669 strnfcat(buf, max, &len, " {%d%% off}", o_ptr->discount);
1670 }
1671 }
1672
1673 /*
1674 * Wrapper around object_desc() for the '%v'
1675 * format option. This allows object_desc() to be
1676 * called in a format string.
1677 *
1678 * The parameters are object_type (o_ptr), pref (int), mode(int).
1679 */
object_fmt(char * buf,uint max,cptr fmt,va_list * vp)1680 void object_fmt(char *buf, uint max, cptr fmt, va_list *vp)
1681 {
1682 const object_type *o_ptr;
1683 int pref;
1684 int mode;
1685
1686 /* Unused parameter */
1687 (void)fmt;
1688
1689 /* Get the object */
1690 o_ptr = va_arg(*vp, const object_type*);
1691
1692 /* Get the pref */
1693 pref = va_arg(*vp, int);
1694
1695 /* Get the mode */
1696 mode = va_arg(*vp, int);
1697
1698 object_desc(buf, o_ptr, pref, mode, max);
1699 }
1700
1701
1702 /*
1703 * Hack -- describe an item currently in a store's inventory
1704 * This allows an item to *look* like the player is "aware" of it
1705 */
object_desc_store(char * buf,const object_type * o_ptr,int pref,int mode,int size)1706 void object_desc_store(char *buf, const object_type *o_ptr, int pref,
1707 int mode, int size)
1708 {
1709 byte hack_flavor;
1710 bool hack_aware;
1711 byte info;
1712
1713 /* Hack - we will reset the object to exactly like it was */
1714 object_type *q_ptr = (object_type *)o_ptr;
1715
1716 /* Save the "flavor" */
1717 hack_flavor = k_info[o_ptr->k_idx].flavor;
1718
1719 /* Save the "aware" flag */
1720 hack_aware = k_info[o_ptr->k_idx].aware;
1721
1722 /* Save the "info" */
1723 info = o_ptr->info;
1724
1725 /* Clear the flavor */
1726 k_info[o_ptr->k_idx].flavor = FALSE;
1727
1728 /* If this is a shop item or in you are in wizard mode play with objects */
1729 if (q_ptr->info & OB_STOREB)
1730 {
1731 /* Make it known */
1732 q_ptr->info |= (OB_KNOWN);
1733
1734 /* Force "aware" for description */
1735 k_info[o_ptr->k_idx].aware = TRUE;
1736 }
1737
1738 /* Describe the object */
1739 object_desc(buf, q_ptr, pref, mode, size);
1740
1741 /* Restore "flavor" value */
1742 k_info[o_ptr->k_idx].flavor = hack_flavor;
1743
1744 /* Restore "aware" flag */
1745 k_info[o_ptr->k_idx].aware = hack_aware;
1746
1747 /* Restore the "info" */
1748 q_ptr->info = info;
1749 }
1750
1751 /*
1752 * Wrapper around object_desc_store() for the '%v'
1753 * format option. This allows object_desc() to be
1754 * called in a format string.
1755 *
1756 * The parameters are object_type (o_ptr), pref (int), mode(int).
1757 */
object_store_fmt(char * buf,uint max,cptr fmt,va_list * vp)1758 void object_store_fmt(char *buf, uint max, cptr fmt, va_list *vp)
1759 {
1760 const object_type *o_ptr;
1761 int pref;
1762 int mode;
1763
1764 /* Unused parameter */
1765 (void)fmt;
1766
1767 /* Get the object */
1768 o_ptr = va_arg(*vp, const object_type*);
1769
1770 /* Get the pref */
1771 pref = va_arg(*vp, int);
1772
1773 /* Get the mode */
1774 mode = va_arg(*vp, int);
1775
1776 object_desc_store(buf, o_ptr, pref, mode, max);
1777 }
1778
1779