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