1 /* File: obj-info.c */
2
3 /*
4 * Copyright (c) 2002 Andrew Sidwell, Robert Ruehlmann
5 *
6 * This software may be copied and distributed for educational, research,
7 * and not for profit purposes provided that this copyright and statement
8 * are included in all such copies. Other copyrights may also apply.
9 */
10
11 #include "mangband.h"
12
13 /*
14 * This part came from angband's use-obj.c
15 */
16 static cptr act_description[ACT_MAX] =
17 {
18 "illumination",
19 "magic mapping",
20 "clairvoyance",
21 "protection from evil",
22 "dispel evil (x5)",
23 "heal (500)",
24 "heal (1000)",
25 "cure wounds (4d8)",
26 "haste self (20+d20 turns)",
27 "haste self (75+d75 turns)",
28 "fire bolt (9d8)",
29 "fire ball (72)",
30 "large fire ball (120)",
31 "frost bolt (6d8)",
32 "frost ball (48)",
33 "frost ball (100)",
34 "frost bolt (12d8)",
35 "large frost ball (200)",
36 "acid bolt (5d8)",
37 "recharge item I",
38 "sleep II",
39 "lightning bolt (4d8)",
40 "large lightning ball (250)",
41 "banishment",
42 "mass banishment",
43 "identify",
44 "drain life (90)",
45 "drain life (120)",
46 "bizarre things",
47 "star ball (150)",
48 "berserk rage, bless, and resistance",
49 "phase door",
50 "door and trap destruction",
51 "detection",
52 "resistance (20+d20 turns)",
53 "teleport",
54 "restore life levels",
55 "magic missile (2d6)",
56 "a magical arrow (150)",
57 "remove fear and cure poison",
58 "stinking cloud (12)",
59 "stone to mud",
60 "teleport away",
61 "word of recall",
62 "confuse monster",
63 "probing",
64 "fire branding of bolts",
65 "starlight (10d8)",
66 "mana bolt (12d8)",
67 "berserk rage (50+d50 turns)"
68 };
69
70 /* Hack -- forward compatibility with V320 */
71 #define textblock_append(TB, STR) text_out(STR)
72
describe_origin(const player_type * p_ptr,const object_type * o_ptr)73 bool describe_origin(const player_type *p_ptr, const object_type *o_ptr)
74 {
75 char *original_owner = NULL;
76 bool changed_hands = FALSE;
77 char origin_text[80];
78
79 if (o_ptr->origin_depth)
80 {
81 if (p_ptr == NULL)
82 strnfmt(origin_text, sizeof(origin_text), "%d feet (level %d)",
83 o_ptr->origin_depth * 50, o_ptr->origin_depth);
84 else if (option_p(p_ptr,DEPTH_IN_FEET))
85 strnfmt(origin_text, sizeof(origin_text), "%d feet",
86 o_ptr->origin_depth * 50);
87 else
88 strnfmt(origin_text, sizeof(origin_text), "level %d",
89 o_ptr->origin_depth);
90 }
91 else
92 my_strcpy(origin_text, "town", sizeof(origin_text));
93
94 if (p_ptr && o_ptr->origin_player)
95 {
96 original_owner = (char*)quark_str(o_ptr->origin_player);
97 if (streq(original_owner, p_ptr->name)) original_owner = NULL;
98 else if (o_ptr->owner_name != o_ptr->origin_player)
99 {
100 changed_hands = TRUE;
101 }
102 }
103
104 /* Hack -- add extra space :( */
105 if (o_ptr->origin != ORIGIN_NONE &&
106 o_ptr->origin != ORIGIN_MIXED) text_out(" ");
107
108 /* MAngband-specific: different player origin */
109 if (o_ptr->origin != ORIGIN_NONE &&
110 o_ptr->origin != ORIGIN_MIXED &&
111 o_ptr->origin != ORIGIN_BIRTH &&
112 changed_hands
113 ) textblock_append(tb, format("Obtained from %s. Rumored to be ", original_owner));
114
115 switch (o_ptr->origin)
116 {
117 case ORIGIN_NONE:
118 case ORIGIN_MIXED:
119 return FALSE;
120
121 case ORIGIN_BIRTH:
122
123 if (original_owner)
124 textblock_append(tb, format("An inheritance from %s's family.\n", original_owner));
125 else
126
127 textblock_append(tb, "An inheritance from your family.\n");
128 break;
129
130 case ORIGIN_STORE:
131 textblock_append(tb, "Bought from a store.\n");
132 break;
133
134 case ORIGIN_FLOOR:
135 textblock_append(tb, format("Found lying on the floor %s %s.\n",
136 (o_ptr->origin_depth ? "at" : "in"),
137 origin_text));
138 break;
139
140 case ORIGIN_DROP:
141 {
142 const char *name = r_name + r_info[o_ptr->origin_xtra].name;
143
144 textblock_append(tb, "Dropped by ");
145
146 if (r_info[o_ptr->origin_xtra].flags1 & RF1_UNIQUE)
147 textblock_append(tb, format("%s", name));
148 else
149 textblock_append(tb,format( "%s%s",
150 is_a_vowel(name[0]) ? "an " : "a ", name));
151
152 textblock_append(tb, format(" %s %s.\n",
153 (o_ptr->origin_depth ? "at" : "in"),
154 origin_text));
155 break;
156 }
157
158 case ORIGIN_DROP_UNKNOWN:
159 textblock_append(tb, format("Dropped by an unknown monster %s %s.\n",
160 (o_ptr->origin_depth ? "at" : "in"),
161 origin_text));
162 break;
163
164 case ORIGIN_ACQUIRE:
165 textblock_append(tb, format("Conjured forth by magic %s %s.\n",
166 (o_ptr->origin_depth ? "at" : "in"),
167 origin_text));
168 break;
169
170 case ORIGIN_CHEAT:
171 textblock_append(tb, format("Created by debug option.\n"));
172 break;
173
174 case ORIGIN_CHEST:
175 textblock_append(tb, format("Found in a chest from %s.\n",
176 origin_text));
177 break;
178
179 /* MAngband-specific origins */
180 case ORIGIN_WILD_DWELLING:
181 textblock_append(tb, format("Found in the abandoned house at %s.\n",
182 origin_text));
183 break;
184 }
185
186
187 //textblock_append(tb, "\n");
188
189 return TRUE;
190 }
191
192
193 /* MAngband-specific. Math sourced from cmd6.c and use-obj.c
194 * Give the player an idea of their odds of successfully activating
195 * a wand, staff, rod, or item. - Avenger */
describe_activation_chance(const object_type * o_ptr)196 void describe_activation_chance(const object_type *o_ptr)
197 {
198 int chance, lev;
199 player_type *p_ptr = player_textout;
200 u32b f1, f2, f3;
201
202 /* Extract the flags */
203 object_flags(o_ptr, &f1, &f2, &f3);
204
205 /* Verify that this is a magic device or other item than can be activated */
206 if (o_ptr->tval == TV_STAFF || o_ptr->tval == TV_WAND || o_ptr->tval == TV_ROD || (f3 & TR3_ACTIVATE))
207 {
208 /* Base chance of success */
209 chance = p_ptr->skill_dev;
210
211 /* Extract the item level */
212 lev = k_info[o_ptr->k_idx].level;
213
214 /* Confusion hurts skill */
215 if (p_ptr->confused) chance = chance / 2;
216
217 /* High level objects are harder */
218 chance = chance - ((lev > 50) ? 50 : lev);
219
220 /* Set the descriptive mask.
221 *
222 * Because activation failure has a constant minimum threshhold regardless of the value
223 * of chance, this is not a strict percentage. Instead, I use a Fibonacci sequence to
224 * sort the masks into approximate tiers. */
225 if (chance < 1) /* Caps at 5% when chance is 0, approaches zero very quickly as chance drops below 0 */
226 text_out("\n\n You have almost no chance to successfully use this item.");
227 else if (chance < USE_DEVICE) /* ~6 to 8% */
228 text_out("\n\n You have a negligible chance to successfully use this item.");
229 else if (chance == USE_DEVICE) /* 25% */
230 text_out("\n\n You have a very low chance to successfully use this item.");
231 else if (chance < 5) /* 40% */
232 text_out("\n\n You have a low chance to successfully use this item.");
233 else if (chance < 8) /* 50 - 62.5% */
234 text_out("\n\n You have a moderate chance to successfully use this item.");
235 else if (chance < 13) /* ~67 - 70% */
236 text_out("\n\n You have a fair chance to successfully use this item.");
237 else if (chance < 21) /* ~78 - 85% */
238 text_out("\n\n You have a good chance to successfully use this item.");
239 else if (chance < 34) /* ~86 - 91% */
240 text_out("\n\n You have an very good chance to successfully use this item.");
241 else if (chance < 55) /* ~91 - 94% */
242 text_out("\n\n You have an excellent chance to successfully use this item.");
243 else if (chance < 89) /* ~95 - 96% */
244 text_out("\n\n You have a superb chance to successfully use this item.");
245 else /* > 96.667% */
246 text_out("\n\n You have an almost certain chance to successfully use this item.");
247 }
248 return;
249 }
250 /*
251 * Determine the "Activation" (if any) for an artifact
252 */
describe_item_activation(const object_type * o_ptr)253 void describe_item_activation(const object_type *o_ptr)
254 {
255 u32b f1, f2, f3;
256
257 /* Extract the flags */
258 object_flags(o_ptr, &f1, &f2, &f3);
259
260 /* Require activation ability */
261 if (!(f3 & TR3_ACTIVATE)) return;
262
263 /* Artifact activations */
264 if (artifact_p(o_ptr))
265 {
266 artifact_type *a_ptr = artifact_ptr(o_ptr);
267
268 if (!a_ptr->time && !a_ptr->randtime) text_out("[ERROR: missing `A:` line in artifact.txt] ");
269
270 /* Paranoia */
271 if (a_ptr->activation >= ACT_MAX) return;
272
273 /* Some artifacts can be activated */
274 text_out(act_description[a_ptr->activation]);
275
276 /* Output the number of turns */
277
278 if (a_ptr->time && a_ptr->randtime)
279 text_out(format(" every %d+d%d turns", a_ptr->time, a_ptr->randtime));
280 else if (a_ptr->time)
281 text_out(format(" every %d turns", a_ptr->time));
282 else if (a_ptr->randtime)
283 text_out(format(" every d%d turns", a_ptr->randtime));
284
285
286 return;
287 }
288
289 /* MAngband-specific hack: Some ego items can be activated */
290 switch (o_ptr->name2)
291 {
292 case EGO_CLOAK_LORDLY_RES:
293 {
294 text_out("resistance every 150+d50 turns");
295 }
296 }
297
298 /* MAngband-specific hack: The amulet of the moon can be activated for sleep */
299 if ((o_ptr->tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_THE_MOON))
300 text_out("sleep monsters every 100+d100 turns");
301
302 /* Ring activations */
303 if (o_ptr->tval == TV_RING)
304 {
305 /* Branch on the sub-type */
306 switch (o_ptr->sval)
307 {
308 case SV_RING_ACID:
309 {
310 text_out("acid resistance (20+d20 turns) and acid ball (70) every 50+d50 turns");
311 break;
312 }
313 case SV_RING_FLAMES:
314 {
315 text_out("fire resistance (20+d20 turns) and fire ball (80) every 50+d50 turns");
316 break;
317 }
318 case SV_RING_ICE:
319 {
320 text_out("cold resistance (20+d20 turns) and cold ball (75) every 50+d50 turns");
321 break;
322 }
323
324 case SV_RING_LIGHTNING:
325 {
326 text_out("electricity resistance (20+d20 turns) and electricity ball (85) every 50+d50 turns");
327 break;
328 }
329 }
330
331 return;
332 }
333
334 /* Require dragon scale mail */
335 if (o_ptr->tval != TV_DRAG_ARMOR) return;
336
337 /* Branch on the sub-type */
338 switch (o_ptr->sval)
339 {
340 case SV_DRAGON_BLUE:
341 {
342 text_out("breathe lightning (100) every 450+d450 turns");
343 break;
344 }
345 case SV_DRAGON_WHITE:
346 {
347 text_out("breathe frost (110) every 450+d450 turns");
348 break;
349 }
350 case SV_DRAGON_BLACK:
351 {
352 text_out("breathe acid (130) every 450+d450 turns");
353 break;
354 }
355 case SV_DRAGON_GREEN:
356 {
357 text_out("breathe poison gas (150) every 450+d450 turns");
358 break;
359 }
360 case SV_DRAGON_RED:
361 {
362 text_out("breathe fire (200) every 450+d450 turns");
363 break;
364 }
365 case SV_DRAGON_MULTIHUED:
366 {
367 text_out("breathe multi-hued (250) every 225+d225 turns");
368 break;
369 }
370 case SV_DRAGON_BRONZE:
371 {
372 text_out("breathe confusion (120) every 450+d450 turns");
373 break;
374 }
375 case SV_DRAGON_GOLD:
376 {
377 text_out("breathe sound (130) every 450+d450 turns");
378 break;
379 }
380 case SV_DRAGON_CHAOS:
381 {
382 text_out("breathe chaos/disenchant (220) every 300+d300 turns");
383 break;
384 }
385 case SV_DRAGON_LAW:
386 {
387 text_out("breathe sound/shards (230) every 300+d300 turns");
388 break;
389 }
390 case SV_DRAGON_BALANCE:
391 {
392 text_out("breathe balance (250) every 300+d300 turns");
393 break;
394 }
395 case SV_DRAGON_SHINING:
396 {
397 text_out("breathe light/darkness (200) every 300+d300 turns");
398 break;
399 }
400 case SV_DRAGON_POWER:
401 {
402 text_out("breathe the elements (300) every 300+d300 turns");
403 break;
404 }
405 }
406 }
407
408 /* use-obj.c end */
409
410 /* TRUE if a paragraph break should be output before next p_text_out() */
411 static bool new_paragraph = FALSE;
412
413
p_text_out(cptr str)414 static void p_text_out(cptr str)
415 {
416 if (new_paragraph)
417 {
418 text_out("\n\n ");
419 new_paragraph = FALSE;
420 }
421
422 text_out(str);
423 }
424
425
output_list(cptr list[],int n)426 static void output_list(cptr list[], int n)
427 {
428 int i;
429
430 cptr conjunction = "and ";
431
432 if (n < 0)
433 {
434 n = -n;
435 conjunction = "or ";
436 }
437
438 for (i = 0; i < n; i++)
439 {
440 if (i != 0)
441 {
442 p_text_out((i == 1 && i == n - 1) ? " " : ", ");
443
444 if (i == n - 1) p_text_out(conjunction);
445 }
446
447 p_text_out(list[i]);
448 }
449 }
450
451
output_desc_list(cptr intro,cptr list[],int n)452 static void output_desc_list(cptr intro, cptr list[], int n)
453 {
454 if (n != 0)
455 {
456 /* Output intro */
457 p_text_out(intro);
458
459 /* Output list */
460 output_list(list, n);
461
462 /* Output end */
463 p_text_out(". ");
464 }
465 }
466
467
468 /*
469 * Describe stat modifications.
470 * This function is HACKed to handle MAngband-specific bpval (bonus value)
471 * Handles each stat separately!
472 */
describe_stats(const object_type * o_ptr,u32b f1,u32b fH)473 static bool describe_stats(const object_type *o_ptr, u32b f1, u32b fH)
474 {
475 cptr descs[A_MAX];
476 int pval[A_MAX];
477 bool noted[A_MAX], found = FALSE;
478 int cnt = 0;
479 int i, j;
480
481 /* First pass - collect flags */
482 for (i = 0; i < A_MAX; i++)
483 {
484 noted[i] = FALSE;
485 pval[i] = 0;
486 if ((fH & (TR1_STR << i)) && !randart_p(o_ptr))
487 pval[i] += o_ptr->bpval;
488 if (f1 & (TR1_STR << i) )
489 pval[i] += o_ptr->pval;
490 }
491 /* Second pass - report all similar stats */
492 for (j = 0; j < A_MAX; j++)
493 {
494 cnt = 0;
495 WIPE(descs, cptr);
496 /* Found a suitable flag to report */
497 if (pval[j] != 0 && noted[j] == FALSE)
498 {
499 /* Report it and all similar to it */
500 for (i = j; i < A_MAX; i++)
501 {
502 if (pval[i] == pval[j])
503 {
504 /* Store flag for report */
505 descs[cnt++] = stat_names_full[i];
506
507 /* Do not report this again */
508 noted[i] = TRUE;
509 }
510 }
511 }
512 /* Report all stored flags */
513 if (cnt != 0)
514 {
515 /* Shorten to "all stats", if appropriate. */
516 if (cnt == A_MAX)
517 {
518 p_text_out(format("It %s all your stats", (pval[j] > 0 ? "increases" : "decreases")));
519 }
520 else
521 {
522 p_text_out(format("It %s your ", (pval[j] > 0 ? "increases" : "decreases")));
523
524 /* Output list */
525 output_list(descs, cnt);
526 }
527
528 /* Output end */
529 p_text_out(format(" by %i. ", (pval[j] > 0 ? pval[j] : -pval[j]) ));
530 found = TRUE;
531 }
532 }
533 /* We found something */
534 return (found);
535 #if 0
536 int pval = (o_ptr->pval > 0 ? o_ptr->pval : -o_ptr->pval);
537
538 /* Abort if the pval is zero */
539 if (!pval) return (FALSE);
540
541 /* Collect stat bonuses */
542 if (f1 & (TR1_STR)) descs[cnt++] = stat_names_full[A_STR];
543 if (f1 & (TR1_INT)) descs[cnt++] = stat_names_full[A_INT];
544 if (f1 & (TR1_WIS)) descs[cnt++] = stat_names_full[A_WIS];
545 if (f1 & (TR1_DEX)) descs[cnt++] = stat_names_full[A_DEX];
546 if (f1 & (TR1_CON)) descs[cnt++] = stat_names_full[A_CON];
547 if (f1 & (TR1_CHR)) descs[cnt++] = stat_names_full[A_CHR];
548
549 /* Skip */
550 if (cnt == 0) return (FALSE);
551
552 /* Shorten to "all stats", if appropriate. */
553 if (cnt == A_MAX)
554 {
555 p_text_out(format("It %s all your stats", (o_ptr->pval > 0 ? "increases" : "decreases")));
556 }
557 else
558 {
559 p_text_out(format("It %s your ", (o_ptr->pval > 0 ? "increases" : "decreases")));
560
561 /* Output list */
562 output_list(descs, cnt);
563 }
564
565 /* Output end */
566 p_text_out(format(" by %i. ", pval));
567
568 /* We found something */
569 return (TRUE);
570 #endif
571 }
572 /* Should probably put it into tables.c */
573 cptr secondary_names[8] =
574 {
575 "stealth", "searching", "infravision", "tunneling", "speed", "attack speed", "shooting speed", "shooting power"
576 };
577 /*
578 * Describe "secondary bonuses" of an item.
579 * This function is HACKed to handle MAngband-specific bpval (bonus value)
580 * == 6 || == 7 are special hacks for TR1_SHOT and TR1_MIGHT (grants 1 point)
581 */
describe_secondary(const object_type * o_ptr,u32b f1,u32b fH)582 static bool describe_secondary(const object_type *o_ptr, u32b f1, u32b fH)
583 {
584 cptr descs[8];
585 int cnt = 0;
586 int pval[8];
587 bool noted[8], found = FALSE;
588 int j, i;
589
590 /* First pass - collect flags */
591 for (i = 0; i < 8; i++)
592 {
593 noted[i] = FALSE;
594 pval[i] = 0;
595 /* Get 'base bonus' */
596 if ((fH & (TR1_STEALTH << i)) && !randart_p(o_ptr))
597 pval[i] += ( i == 6 || i == 7 ? 1 : o_ptr->bpval );
598 /* Get 'base' */
599 if (f1 & (TR1_STEALTH << i))
600 pval[i] += ( i == 6 || i == 7 ? 1 : o_ptr->pval );
601 }
602 /* Second pass - report all similar flags */
603 for (j = 0; j < 8; j++)
604 {
605 cnt = 0;
606 WIPE(descs, cptr);
607 /* Found a suitable flag to report */
608 if (pval[j] != 0 && noted[j] == FALSE)
609 {
610 /* Report it and all similar to it */
611 for (i = j; i < 8; i++)
612 {
613 if (pval[i] == pval[j])
614 {
615 /* Store flag for report */
616 descs[cnt++] = secondary_names[i];
617
618 /* Do not report this again */
619 noted[i] = TRUE;
620 }
621 }
622 }
623 /* Report all stored flags */
624 if (cnt != 0)
625 {
626 /* Start */
627 p_text_out(format("It %s your ", (pval[j] > 0 ? "increases" : "decreases")));
628
629 /* Output list */
630 output_list(descs, cnt);
631
632 /* Output end */
633 p_text_out(format(" by %i. ", (pval[j] > 0 ? pval[j] : -pval[j]) ));
634
635 found = TRUE;
636 }
637 }
638
639 return found;
640 #if 0
641 int pval = (o_ptr->pval > 0 ? o_ptr->pval : -o_ptr->pval);
642
643 /* Collect */
644 if (f1 & (TR1_STEALTH)) descs[cnt++] = "stealth";
645 if (f1 & (TR1_SEARCH)) descs[cnt++] = "searching";
646 if (f1 & (TR1_INFRA)) descs[cnt++] = "infravision";
647 if (f1 & (TR1_TUNNEL)) descs[cnt++] = "tunneling";
648 if (f1 & (TR1_SPEED)) descs[cnt++] = "speed";
649 if (f1 & (TR1_BLOWS)) descs[cnt++] = "attack speed";
650 if (f1 & (TR1_SHOTS)) descs[cnt++] = "shooting speed";
651 if (f1 & (TR1_MIGHT)) descs[cnt++] = "shooting power";
652
653 /* Skip */
654 if (!cnt) return (FALSE);
655
656 /* Start */
657 p_text_out(format("It %s your ", (o_ptr->pval > 0 ? "increases" : "decreases")));
658
659 /* Output list */
660 output_list(descs, cnt);
661
662 /* Output end */
663 p_text_out(format(" by %i. ", pval));
664
665 /* We found something */
666 return (TRUE);
667 #endif
668 }
669
670
671 /*
672 * Describe the special slays and executes of an item.
673 */
describe_slay(const object_type * o_ptr,u32b f1)674 static bool describe_slay(const object_type *o_ptr, u32b f1)
675 {
676 cptr slays[8], execs[3];
677 int slcnt = 0, excnt = 0;
678
679 /* Unused parameter */
680 (void)o_ptr;
681
682 /* Collect brands */
683 if (f1 & (TR1_SLAY_ANIMAL)) slays[slcnt++] = "animals";
684 if (f1 & (TR1_SLAY_ORC)) slays[slcnt++] = "orcs";
685 if (f1 & (TR1_SLAY_TROLL)) slays[slcnt++] = "trolls";
686 if (f1 & (TR1_SLAY_GIANT)) slays[slcnt++] = "giants";
687
688 /* Dragon slay/execute */
689 if (f1 & TR1_KILL_DRAGON)
690 execs[excnt++] = "dragons";
691 else if (f1 & TR1_SLAY_DRAGON)
692 slays[slcnt++] = "dragons";
693
694 /* Demon slay/execute */
695 if (f1 & TR1_KILL_DEMON)
696 execs[excnt++] = "demons";
697 else if (f1 & TR1_SLAY_DEMON)
698 slays[slcnt++] = "demons";
699
700 /* Undead slay/execute */
701 if (f1 & TR1_KILL_UNDEAD)
702 execs[excnt++] = "undead";
703 else if (f1 & TR1_SLAY_UNDEAD)
704 slays[slcnt++] = "undead";
705
706 if (f1 & (TR1_SLAY_EVIL)) slays[slcnt++] = "all evil creatures";
707
708 /* Describe */
709 if (slcnt)
710 {
711 /* Output intro */
712 p_text_out("It slays ");
713
714 /* Output list */
715 output_list(slays, slcnt);
716
717 /* Output end (if needed) */
718 if (!excnt) p_text_out(". ");
719 }
720
721 if (excnt)
722 {
723 /* Output intro */
724 if (slcnt) p_text_out(", and is especially deadly against ");
725 else p_text_out("It is especially deadly against ");
726
727 /* Output list */
728 output_list(execs, excnt);
729
730 /* Output end */
731 p_text_out(". ");
732 }
733
734 /* We are done here */
735 return ((excnt || slcnt) ? TRUE : FALSE);
736 }
737
738
739 /*
740 * Describe elemental brands.
741 */
describe_brand(const object_type * o_ptr,u32b f1)742 static bool describe_brand(const object_type *o_ptr, u32b f1)
743 {
744 cptr descs[5];
745 int cnt = 0;
746
747 /* Unused parameter */
748 (void)o_ptr;
749
750 /* Collect brands */
751 if (f1 & (TR1_BRAND_ACID)) descs[cnt++] = "acid";
752 if (f1 & (TR1_BRAND_ELEC)) descs[cnt++] = "electricity";
753 if (f1 & (TR1_BRAND_FIRE)) descs[cnt++] = "fire";
754 if (f1 & (TR1_BRAND_COLD)) descs[cnt++] = "frost";
755 if (f1 & (TR1_BRAND_POIS)) descs[cnt++] = "poison";
756
757 /* Describe brands */
758 output_desc_list("It is branded with ", descs, cnt);
759
760 /* We are done here */
761 return (cnt ? TRUE : FALSE);
762 }
763
764
765 /*
766 * Describe immunities granted by an object.
767 *
768 * ToDo - Merge intro describe_resist() below.
769 */
describe_immune(const object_type * o_ptr,u32b f2)770 static bool describe_immune(const object_type *o_ptr, u32b f2)
771 {
772 cptr descs[4];
773 int cnt = 0;
774
775 /* Unused parameter */
776 (void)o_ptr;
777
778 /* Collect immunities */
779 if (f2 & (TR2_IM_ACID)) descs[cnt++] = "acid";
780 if (f2 & (TR2_IM_ELEC)) descs[cnt++] = "lightning";
781 if (f2 & (TR2_IM_FIRE)) descs[cnt++] = "fire";
782 if (f2 & (TR2_IM_COLD)) descs[cnt++] = "cold";
783
784 /* Describe immunities */
785 output_desc_list("It provides immunity to ", descs, cnt);
786
787 /* We are done here */
788 return (cnt ? TRUE : FALSE);
789 }
790
791
792 /*
793 * Describe resistances granted by an object.
794 */
describe_resist(const object_type * o_ptr,u32b f2,u32b f3)795 static bool describe_resist(const object_type *o_ptr, u32b f2, u32b f3)
796 {
797 cptr vp[17];
798 int vn = 0;
799
800 /* Unused parameter */
801 (void)o_ptr;
802
803 /* Collect resistances */
804 if ((f2 & (TR2_RES_ACID)) && !(f2 & (TR2_IM_ACID)))
805 vp[vn++] = "acid";
806 if ((f2 & (TR2_RES_ELEC)) && !(f2 & (TR2_IM_ELEC)))
807 vp[vn++] = "lightning";
808 if ((f2 & (TR2_RES_FIRE)) && !(f2 & (TR2_IM_FIRE)))
809 vp[vn++] = "fire";
810 if ((f2 & (TR2_RES_COLD)) && !(f2 & (TR2_IM_COLD)))
811 vp[vn++] = "cold";
812
813 if (f2 & (TR2_RES_POIS)) vp[vn++] = "poison";
814 if (f2 & (TR2_RES_FEAR)) vp[vn++] = "fear";
815 if (f2 & (TR2_RES_LITE)) vp[vn++] = "light";
816 if (f2 & (TR2_RES_DARK)) vp[vn++] = "dark";
817 if (f2 & (TR2_RES_BLIND)) vp[vn++] = "blindness";
818 if (f2 & (TR2_RES_CONFU)) vp[vn++] = "confusion";
819 if (f2 & (TR2_RES_SOUND)) vp[vn++] = "sound";
820 if (f2 & (TR2_RES_SHARD)) vp[vn++] = "shards";
821 if (f2 & (TR2_RES_NEXUS)) vp[vn++] = "nexus" ;
822 if (f2 & (TR2_RES_NETHR)) vp[vn++] = "nether";
823 if (f2 & (TR2_RES_CHAOS)) vp[vn++] = "chaos";
824 if (f2 & (TR2_RES_DISEN)) vp[vn++] = "disenchantment";
825 if (f3 & (TR3_HOLD_LIFE)) vp[vn++] = "life draining";
826
827 /* Describe resistances */
828 output_desc_list("It provides resistance to ", vp, vn);
829
830 /* We are done here */
831 return (vn ? TRUE : FALSE);
832 }
833
834
835 /*
836 * Describe 'ignores' of an object.
837 */
describe_ignores(const object_type * o_ptr,u32b f3)838 static bool describe_ignores(const object_type *o_ptr, u32b f3)
839 {
840 cptr list[4];
841 int n = 0;
842
843 /* Unused parameter */
844 (void)o_ptr;
845
846 /* Collect the ignores */
847 if (f3 & (TR3_IGNORE_ACID)) list[n++] = "acid";
848 if (f3 & (TR3_IGNORE_ELEC)) list[n++] = "electricity";
849 if (f3 & (TR3_IGNORE_FIRE)) list[n++] = "fire";
850 if (f3 & (TR3_IGNORE_COLD)) list[n++] = "cold";
851
852 /* Describe ignores */
853 if (n == 4)
854 p_text_out("It cannot be harmed by the elements. ");
855 else
856 output_desc_list("It cannot be harmed by ", list, -n);
857
858 return ((n > 0) ? TRUE : FALSE);
859 }
860
861
862 /*
863 * Describe stat sustains.
864 */
describe_sustains(const object_type * o_ptr,u32b f2)865 static bool describe_sustains(const object_type *o_ptr, u32b f2)
866 {
867 cptr list[A_MAX];
868 int n = 0;
869
870 /* Unused parameter */
871 (void)o_ptr;
872
873 /* Collect the sustains */
874 if (f2 & (TR2_SUST_STR)) list[n++] = stat_names_full[A_STR];
875 if (f2 & (TR2_SUST_INT)) list[n++] = stat_names_full[A_INT];
876 if (f2 & (TR2_SUST_WIS)) list[n++] = stat_names_full[A_WIS];
877 if (f2 & (TR2_SUST_DEX)) list[n++] = stat_names_full[A_DEX];
878 if (f2 & (TR2_SUST_CON)) list[n++] = stat_names_full[A_CON];
879 if (f2 & (TR2_SUST_CHR)) list[n++] = stat_names_full[A_CHR];
880
881 /* Describe immunities */
882 if (n == A_MAX)
883 p_text_out("It sustains all your stats. ");
884 else
885 output_desc_list("It sustains your ", list, n);
886
887 /* We are done here */
888 return (n ? TRUE : FALSE);
889 }
890
891
892 /*
893 * Describe miscellaneous powers such as see invisible, free action,
894 * permanent light, etc; also note curses and penalties.
895 */
describe_misc_magic(const object_type * o_ptr,u32b f3)896 static bool describe_misc_magic(const object_type *o_ptr, u32b f3)
897 {
898 cptr good[6], bad[4];
899 int gc = 0, bc = 0;
900 bool something = FALSE;
901
902 /* Collect stuff which can't be categorized */
903 if (f3 & (TR3_BLESSED)) good[gc++] = "is blessed by the gods";
904 if (f3 & (TR3_IMPACT)) good[gc++] = "creates earthquakes on impact";
905 if (f3 & (TR3_SLOW_DIGEST)) good[gc++] = "slows your metabolism";
906 if (f3 & (TR3_FEATHER)) good[gc++] = "makes you fall like a feather";
907 if (((o_ptr->tval == TV_LITE) && artifact_p(o_ptr)) || (f3 & (TR3_LITE)))
908 good[gc++] = "lights the dungeon around you";
909 if (f3 & (TR3_REGEN)) good[gc++] = "speeds your regeneration";
910
911 /* Describe */
912 output_desc_list("It ", good, gc);
913
914 /* Set "something" */
915 if (gc) something = TRUE;
916
917 /* Collect granted powers */
918 gc = 0;
919 if (f3 & (TR3_FREE_ACT)) good[gc++] = "immunity to paralysis";
920 if (f3 & (TR3_TELEPATHY)) good[gc++] = "the power of telepathy";
921 if (f3 & (TR3_SEE_INVIS)) good[gc++] = "the ability to see invisible things";
922
923 /* Collect penalties */
924 if (f3 & (TR3_AGGRAVATE)) bad[bc++] = "aggravates creatures around you";
925 if (f3 & (TR3_DRAIN_EXP)) bad[bc++] = "drains experience";
926 if (f3 & (TR3_TELEPORT)) bad[bc++] = "induces random teleportation";
927
928 /* Deal with cursed stuff */
929 if (cursed_p(o_ptr))
930 {
931 if (f3 & (TR3_PERMA_CURSE)) bad[bc++] = "is permanently cursed";
932 else if (f3 & (TR3_HEAVY_CURSE)) bad[bc++] = "is heavily cursed";
933 else if (object_known_p(player_textout, o_ptr)) bad[bc++] = "is cursed";
934 }
935
936 /* Describe */
937 if (gc)
938 {
939 /* Output intro */
940 p_text_out("It grants you ");
941
942 /* Output list */
943 output_list(good, gc);
944
945 /* Output end (if needed) */
946 if (!bc) p_text_out(". ");
947 }
948
949 if (bc)
950 {
951 /* Output intro */
952 if (gc) p_text_out(", but it also ");
953 else p_text_out("It ");
954
955 /* Output list */
956 output_list(bad, bc);
957
958 /* Output end */
959 p_text_out(". ");
960 }
961
962 /* Set "something" */
963 if (gc || bc) something = TRUE;
964
965 /* Return "something" */
966 return (something);
967 }
968
969
970 /*
971 * Describe an object's activation, if any.
972 */
describe_activation(const object_type * o_ptr,u32b f3)973 static bool describe_activation(const object_type *o_ptr, u32b f3)
974 {
975 /* Check for the activation flag */
976 if (f3 & TR3_ACTIVATE)
977 {
978 p_text_out("It activates for ");
979 describe_item_activation(o_ptr);
980 p_text_out(". ");
981
982 return (TRUE);
983 }
984
985 /* No activation */
986 return (FALSE);
987 }
988
989
990 /*
991 * Output object information
992 */
993
object_info_out(const object_type * o_ptr)994 bool object_info_out(const object_type *o_ptr)
995 {
996 object_kind *k_ptr = &k_info[o_ptr->k_idx];
997 ego_item_type *e_ptr = &e_info[o_ptr->name2];
998 u32b f1, f2, f3, fH;
999 bool something = FALSE;
1000
1001 f1 = f2 = f3 = fH = 0;
1002
1003 /* Grab the object flags */
1004 object_flags_known(player_textout, o_ptr, &f1, &f2, &f3);
1005
1006 /* Hack -- set bonus flags */
1007 if ( (k_ptr->flags1 & TR1_PVAL_MASK) && object_known_p(player_textout, o_ptr) )
1008 fH = k_ptr->flags1;
1009 /* Hack -- clear out any pval bonuses that are in the base item */
1010 if (o_ptr->name2)
1011 f1 &= ~(k_ptr->flags1 & TR1_PVAL_MASK & ~e_ptr->flags1);
1012
1013 /* Describe the object */
1014 if (describe_stats(o_ptr, f1, fH)) something = TRUE;
1015 if (describe_secondary(o_ptr, f1, fH)) something = TRUE;
1016 if (describe_slay(o_ptr, f1)) something = TRUE;
1017 if (describe_brand(o_ptr, f1)) something = TRUE;
1018 if (describe_immune(o_ptr, f2)) something = TRUE;
1019 if (describe_resist(o_ptr, f2, f3)) something = TRUE;
1020 if (describe_sustains(o_ptr, f2)) something = TRUE;
1021 if (describe_misc_magic(o_ptr, f3)) something = TRUE;
1022 if (describe_activation(o_ptr, f3)) something = TRUE;
1023 if (describe_ignores(o_ptr, f3)) something = TRUE;
1024
1025 /* Describe boring bits */
1026 if ((o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION) &&
1027 o_ptr->pval)
1028 {
1029 text_out(" It provides nourishment for about ");
1030 text_out/*_c(*TERM_L_GREEN,*/(format("%d ", o_ptr->pval / 2));
1031 text_out("turns under normal conditions.\n");
1032 something = TRUE;
1033 }
1034
1035 /* Unknown extra powers (ego-item with random extras or artifact) */
1036 if (object_known_p(player_textout, o_ptr) && (!(o_ptr->ident & ID_MENTAL)) &&
1037 ((o_ptr->xtra1) || artifact_p(o_ptr)))
1038 {
1039 /* Hack -- Put this in a separate paragraph if screen dump */
1040 //if (text_out_hook == text_out_to_screen)
1041 // new_paragraph = TRUE;
1042
1043 p_text_out("It might have hidden powers.");
1044 something = TRUE;
1045 }
1046
1047 /* We are done. */
1048 return something;
1049 }
1050
1051
1052 /*
1053 * Header for additional information when printing to screen.
1054 *
1055 * Return TRUE if an object description was displayed.
1056 */
screen_out_head(const object_type * o_ptr)1057 static bool screen_out_head(const object_type *o_ptr)
1058 {
1059 player_type *p_ptr = player_textout;
1060 //char *o_name;
1061 //int name_size = 80;//Term->wid;
1062 bool has_description = FALSE;
1063
1064 /* Allocate memory to the size of the screen */
1065 //o_name = C_RNEW(name_size, char);
1066 char o_name[80];
1067
1068 /* Description */
1069 object_desc(player_textout, o_name, sizeof(o_name), o_ptr, TRUE, 3);
1070
1071
1072 /* Print, in colour */
1073 //text_out_c(TERM_YELLOW, format("%^s", o_name));
1074
1075 /* Free up the memory */
1076 //FREE(o_name);
1077
1078 /* Display the known artifact description */
1079 //!adult_rand_artifacts
1080 if (true_artifact_p(o_ptr) &&
1081 object_known_p(player_textout, o_ptr) && a_info[o_ptr->name1].text)
1082 {
1083 p_text_out("\n\n ");
1084 p_text_out(a_text + a_info[o_ptr->name1].text);
1085 has_description = TRUE;
1086 }
1087
1088 /* Display the known object description */
1089 else if (object_aware_p(p_ptr, o_ptr) || object_known_p(player_textout, o_ptr))
1090 {
1091 if (k_info[o_ptr->k_idx].text)
1092 {
1093 p_text_out("\n\n ");
1094 p_text_out(k_text + k_info[o_ptr->k_idx].text);
1095 has_description = TRUE;
1096 }
1097
1098 /* Display an additional ego-item description */
1099 if (o_ptr->name2 && object_known_p(player_textout, o_ptr) && e_info[o_ptr->name2].text)
1100 {
1101 p_text_out("\n\n ");
1102 p_text_out(e_text + e_info[o_ptr->name2].text);
1103 has_description = TRUE;
1104 }
1105 }
1106 return has_description;
1107 }
1108
1109
1110 /*
1111 * Place an item description on the screen.
1112 */
object_info_screen(const object_type * o_ptr)1113 void object_info_screen(const object_type *o_ptr)
1114 {
1115 bool has_description, has_info;
1116
1117 /* Redirect output to the screen */
1118 //text_out_hook = text_out_to_screen;
1119
1120 /* Save the screen */
1121 //screen_save();
1122
1123 has_description = screen_out_head(o_ptr);
1124
1125 //object_info_out_flags = object_flags_known;
1126
1127 /* Dump the info */
1128 new_paragraph = TRUE;
1129 has_info = object_info_out(o_ptr);
1130 new_paragraph = FALSE;
1131
1132 if (!object_known_p(player_textout, o_ptr))
1133 p_text_out("\n\n This item has not been identified.");
1134 else if (!has_description && !has_info)
1135 p_text_out("\n\n This item does not seem to possess any special abilities.");
1136 else
1137 describe_activation_chance(o_ptr);
1138
1139 /*if (subjective)*/ describe_origin(player_textout, o_ptr);
1140
1141 //text_out_c(TERM_L_BLUE, "\n\n[Press any key to continue]\n");
1142
1143 /* Wait for input */
1144 //(void)inkey();
1145
1146 /* Load the screen */
1147 //screen_load();
1148
1149 /* Hack -- Browse book, then prompt for a command */
1150 /*
1151 if (o_ptr->tval == cp_ptr->cp_ptr->spell_book)
1152 {
1153 // Call the aux function
1154 do_cmd_browse_aux(o_ptr);
1155 }
1156 */
1157 }
1158
1159