4 * Copyright (c) 2002 Andrew Sidwell, Robert Ruehlmann
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.
14 /* TRUE if a paragraph break should be output before next p_text_out() */
15 static bool new_paragraph
= FALSE
;
18 static void p_text_out(cptr str
)
23 new_paragraph
= FALSE
;
30 static void output_list(cptr list
[], int n
)
34 cptr conjunction
= "and ";
42 for (i
= 0; i
< n
; i
++)
46 p_text_out((i
== 1 && i
== n
- 1) ? " " : ", ");
48 if (i
== n
- 1) p_text_out(conjunction
);
56 static void output_desc_list(cptr intro
, cptr list
[], int n
)
73 * Describe stat modifications.
75 static bool describe_stats(const object_type
*o_ptr
, u32b f1
)
79 int pval
= (o_ptr
->pval
> 0 ? o_ptr
->pval
: -o_ptr
->pval
);
81 /* Abort if the pval is zero */
82 if (!pval
) return (FALSE
);
84 /* Collect stat bonuses */
85 if (f1
& (TR1_STR
)) descs
[cnt
++] = stat_names_full
[A_STR
];
86 if (f1
& (TR1_INT
)) descs
[cnt
++] = stat_names_full
[A_INT
];
87 if (f1
& (TR1_WIS
)) descs
[cnt
++] = stat_names_full
[A_WIS
];
88 if (f1
& (TR1_DEX
)) descs
[cnt
++] = stat_names_full
[A_DEX
];
89 if (f1
& (TR1_CON
)) descs
[cnt
++] = stat_names_full
[A_CON
];
90 if (f1
& (TR1_CHR
)) descs
[cnt
++] = stat_names_full
[A_CHR
];
93 if (cnt
== 0) return (FALSE
);
95 /* Shorten to "all stats", if appropriate. */
98 p_text_out(format("It %s all your stats", (o_ptr
->pval
> 0 ? "increases" : "decreases")));
102 p_text_out(format("It %s your ", (o_ptr
->pval
> 0 ? "increases" : "decreases")));
105 output_list(descs
, cnt
);
109 p_text_out(format(" by %i. ", pval
));
111 /* We found something */
117 * Describe "secondary bonuses" of an item.
119 static bool describe_secondary(const object_type
*o_ptr
, u32b f1
)
123 int pval
= (o_ptr
->pval
> 0 ? o_ptr
->pval
: -o_ptr
->pval
);
126 if (f1
& (TR1_STEALTH
)) descs
[cnt
++] = "stealth";
127 if (f1
& (TR1_SEARCH
)) descs
[cnt
++] = "searching";
128 if (f1
& (TR1_INFRA
)) descs
[cnt
++] = "infravision";
129 if (f1
& (TR1_TUNNEL
)) descs
[cnt
++] = "tunneling";
130 if (f1
& (TR1_SPEED
)) descs
[cnt
++] = "speed";
131 if (f1
& (TR1_BLOWS
)) descs
[cnt
++] = "attack speed";
132 if (f1
& (TR1_SHOTS
)) descs
[cnt
++] = "shooting speed";
133 if (f1
& (TR1_MIGHT
)) descs
[cnt
++] = "shooting power";
136 if (!cnt
) return (FALSE
);
139 p_text_out(format("It %s your ", (o_ptr
->pval
> 0 ? "increases" : "decreases")));
142 output_list(descs
, cnt
);
145 p_text_out(format(" by %i. ", pval
));
147 /* We found something */
153 * Describe the special slays and executes of an item.
155 static bool describe_slay(const object_type
*o_ptr
, u32b f1
)
157 cptr slays
[8], execs
[3];
158 int slcnt
= 0, excnt
= 0;
160 /* Unused parameter */
164 if (f1
& (TR1_SLAY_ANIMAL
)) slays
[slcnt
++] = "animals";
165 if (f1
& (TR1_SLAY_ORC
)) slays
[slcnt
++] = "orcs";
166 if (f1
& (TR1_SLAY_TROLL
)) slays
[slcnt
++] = "trolls";
167 if (f1
& (TR1_SLAY_GIANT
)) slays
[slcnt
++] = "giants";
169 /* Dragon slay/execute */
170 if (f1
& TR1_KILL_DRAGON
)
171 execs
[excnt
++] = "dragons";
172 else if (f1
& TR1_SLAY_DRAGON
)
173 slays
[slcnt
++] = "dragons";
175 /* Demon slay/execute */
176 if (f1
& TR1_KILL_DEMON
)
177 execs
[excnt
++] = "demons";
178 else if (f1
& TR1_SLAY_DEMON
)
179 slays
[slcnt
++] = "demons";
181 /* Undead slay/execute */
182 if (f1
& TR1_KILL_UNDEAD
)
183 execs
[excnt
++] = "undead";
184 else if (f1
& TR1_SLAY_UNDEAD
)
185 slays
[slcnt
++] = "undead";
187 if (f1
& (TR1_SLAY_EVIL
)) slays
[slcnt
++] = "all evil creatures";
193 p_text_out("It slays ");
196 output_list(slays
, slcnt
);
198 /* Output end (if needed) */
199 if (!excnt
) p_text_out(". ");
205 if (slcnt
) p_text_out(", and is especially deadly against ");
206 else p_text_out("It is especially deadly against ");
209 output_list(execs
, excnt
);
215 /* We are done here */
216 return ((excnt
|| slcnt
) ? TRUE
: FALSE
);
221 * Describe elemental brands.
223 static bool describe_brand(const object_type
*o_ptr
, u32b f1
)
228 /* Unused parameter */
232 if (f1
& (TR1_BRAND_ACID
)) descs
[cnt
++] = "acid";
233 if (f1
& (TR1_BRAND_ELEC
)) descs
[cnt
++] = "electricity";
234 if (f1
& (TR1_BRAND_FIRE
)) descs
[cnt
++] = "fire";
235 if (f1
& (TR1_BRAND_COLD
)) descs
[cnt
++] = "frost";
236 if (f1
& (TR1_BRAND_POIS
)) descs
[cnt
++] = "poison";
238 /* Describe brands */
239 output_desc_list("It is branded with ", descs
, cnt
);
241 /* We are done here */
242 return (cnt
? TRUE
: FALSE
);
247 * Describe immunities granted by an object.
249 * ToDo - Merge intro describe_resist() below.
251 static bool describe_immune(const object_type
*o_ptr
, u32b f2
)
256 /* Unused parameter */
259 /* Collect immunities */
260 if (f2
& (TR2_IM_ACID
)) descs
[cnt
++] = "acid";
261 if (f2
& (TR2_IM_ELEC
)) descs
[cnt
++] = "lightning";
262 if (f2
& (TR2_IM_FIRE
)) descs
[cnt
++] = "fire";
263 if (f2
& (TR2_IM_COLD
)) descs
[cnt
++] = "cold";
265 /* Describe immunities */
266 output_desc_list("It provides immunity to ", descs
, cnt
);
268 /* We are done here */
269 return (cnt
? TRUE
: FALSE
);
274 * Describe resistances granted by an object.
276 static bool describe_resist(const object_type
*o_ptr
, u32b f2
, u32b f3
)
281 /* Unused parameter */
284 /* Collect resistances */
285 if ((f2
& (TR2_RES_ACID
)) && !(f2
& (TR2_IM_ACID
)))
287 if ((f2
& (TR2_RES_ELEC
)) && !(f2
& (TR2_IM_ELEC
)))
288 vp
[vn
++] = "lightning";
289 if ((f2
& (TR2_RES_FIRE
)) && !(f2
& (TR2_IM_FIRE
)))
291 if ((f2
& (TR2_RES_COLD
)) && !(f2
& (TR2_IM_COLD
)))
294 if (f2
& (TR2_RES_POIS
)) vp
[vn
++] = "poison";
295 if (f2
& (TR2_RES_FEAR
)) vp
[vn
++] = "fear";
296 if (f2
& (TR2_RES_LITE
)) vp
[vn
++] = "light";
297 if (f2
& (TR2_RES_DARK
)) vp
[vn
++] = "dark";
298 if (f2
& (TR2_RES_BLIND
)) vp
[vn
++] = "blindness";
299 if (f2
& (TR2_RES_CONFU
)) vp
[vn
++] = "confusion";
300 if (f2
& (TR2_RES_SOUND
)) vp
[vn
++] = "sound";
301 if (f2
& (TR2_RES_SHARD
)) vp
[vn
++] = "shards";
302 if (f2
& (TR2_RES_NEXUS
)) vp
[vn
++] = "nexus" ;
303 if (f2
& (TR2_RES_NETHR
)) vp
[vn
++] = "nether";
304 if (f2
& (TR2_RES_CHAOS
)) vp
[vn
++] = "chaos";
305 if (f2
& (TR2_RES_DISEN
)) vp
[vn
++] = "disenchantment";
306 if (f3
& (TR3_HOLD_LIFE
)) vp
[vn
++] = "life draining";
308 /* Describe resistances */
309 output_desc_list("It provides resistance to ", vp
, vn
);
311 /* We are done here */
312 return (vn
? TRUE
: FALSE
);
317 * Describe 'ignores' of an object.
319 static bool describe_ignores(const object_type
*o_ptr
, u32b f3
)
324 /* Unused parameter */
327 /* Collect the ignores */
328 if (f3
& (TR3_IGNORE_ACID
)) list
[n
++] = "acid";
329 if (f3
& (TR3_IGNORE_ELEC
)) list
[n
++] = "electricity";
330 if (f3
& (TR3_IGNORE_FIRE
)) list
[n
++] = "fire";
331 if (f3
& (TR3_IGNORE_COLD
)) list
[n
++] = "cold";
333 /* Describe ignores */
335 p_text_out("It cannot be harmed by the elements. ");
337 output_desc_list("It cannot be harmed by ", list
, -n
);
339 return ((n
> 0) ? TRUE
: FALSE
);
344 * Describe stat sustains.
346 static bool describe_sustains(const object_type
*o_ptr
, u32b f2
)
351 /* Unused parameter */
354 /* Collect the sustains */
355 if (f2
& (TR2_SUST_STR
)) list
[n
++] = stat_names_full
[A_STR
];
356 if (f2
& (TR2_SUST_INT
)) list
[n
++] = stat_names_full
[A_INT
];
357 if (f2
& (TR2_SUST_WIS
)) list
[n
++] = stat_names_full
[A_WIS
];
358 if (f2
& (TR2_SUST_DEX
)) list
[n
++] = stat_names_full
[A_DEX
];
359 if (f2
& (TR2_SUST_CON
)) list
[n
++] = stat_names_full
[A_CON
];
360 if (f2
& (TR2_SUST_CHR
)) list
[n
++] = stat_names_full
[A_CHR
];
362 /* Describe immunities */
364 p_text_out("It sustains all your stats. ");
366 output_desc_list("It sustains your ", list
, n
);
368 /* We are done here */
369 return (n
? TRUE
: FALSE
);
374 * Describe miscellaneous powers such as see invisible, free action,
375 * permanent light, etc; also note curses and penalties.
377 static bool describe_misc_magic(const object_type
*o_ptr
, u32b f3
)
379 cptr good
[6], bad
[4];
381 bool something
= FALSE
;
383 /* Describe lights */
384 if (o_ptr
->tval
== TV_LITE
|| (f3
& TR3_LITE
))
386 bool artifact
= artifact_p(o_ptr
);
387 bool no_fuel
= (f3
& TR3_NO_FUEL
) ? TRUE
: FALSE
;
392 else if (o_ptr
->tval
== TV_LITE
)
395 if (f3
& TR3_LITE
) rad
++;
397 p_text_out("It usually provides light of radius ");
398 text_out_c(TERM_L_GREEN
, format("%d", rad
));
399 if (no_fuel
&& !artifact
)
400 text_out(", and never needs refuelling");
401 else if (o_ptr
->tval
== TV_LITE
&& o_ptr
->sval
== SV_LITE_TORCH
)
402 text_out(", though this is reduced when running of out fuel");
408 /* Collect stuff which can't be categorized */
409 if (f3
& (TR3_BLESSED
)) good
[gc
++] = "is blessed by the gods";
410 if (f3
& (TR3_IMPACT
)) good
[gc
++] = "creates earthquakes on impact";
411 if (f3
& (TR3_SLOW_DIGEST
)) good
[gc
++] = "slows your metabolism";
412 if (f3
& (TR3_FEATHER
)) good
[gc
++] = "makes you fall like a feather";
413 if (f3
& (TR3_REGEN
)) good
[gc
++] = "speeds your regeneration";
416 output_desc_list("It ", good
, gc
);
418 /* Set "something" */
419 if (gc
) something
= TRUE
;
421 /* Collect granted powers */
423 if (f3
& (TR3_FREE_ACT
)) good
[gc
++] = "immunity to paralysis";
424 if (f3
& (TR3_TELEPATHY
)) good
[gc
++] = "the power of telepathy";
425 if (f3
& (TR3_SEE_INVIS
)) good
[gc
++] = "the ability to see invisible things";
427 /* Collect penalties */
428 if (f3
& (TR3_AGGRAVATE
)) bad
[bc
++] = "aggravates creatures around you";
429 if (f3
& (TR3_DRAIN_EXP
)) bad
[bc
++] = "drains experience";
430 if (f3
& (TR3_TELEPORT
)) bad
[bc
++] = "induces random teleportation";
432 /* Deal with cursed stuff */
435 if (f3
& (TR3_PERMA_CURSE
)) bad
[bc
++] = "is permanently cursed";
436 else if (f3
& (TR3_HEAVY_CURSE
)) bad
[bc
++] = "is heavily cursed";
437 else if (object_known_p(o_ptr
)) bad
[bc
++] = "is cursed";
444 p_text_out("It grants you ");
447 output_list(good
, gc
);
449 /* Output end (if needed) */
450 if (!bc
) p_text_out(". ");
456 if (gc
) p_text_out(", but it also ");
457 else p_text_out("It ");
460 output_list(bad
, bc
);
466 /* Set "something" */
467 if (gc
|| bc
) something
= TRUE
;
469 /* Return "something" */
475 * Describe an object's activation, if any.
477 static bool describe_activation(const object_type
*o_ptr
, u32b f3
)
479 /* Check for the activation flag */
480 if (f3
& TR3_ACTIVATE
)
482 p_text_out("It activates for ");
483 describe_item_activation(o_ptr
);
495 * Output object information
497 bool object_info_out(const object_type
*o_ptr
)
500 bool something
= FALSE
;
502 /* Grab the object flags */
503 object_info_out_flags(o_ptr
, &f1
, &f2
, &f3
);
505 /* Describe the object */
506 if (describe_stats(o_ptr
, f1
)) something
= TRUE
;
507 if (describe_secondary(o_ptr
, f1
)) something
= TRUE
;
508 if (describe_slay(o_ptr
, f1
)) something
= TRUE
;
509 if (describe_brand(o_ptr
, f1
)) something
= TRUE
;
510 if (describe_immune(o_ptr
, f2
)) something
= TRUE
;
511 if (describe_resist(o_ptr
, f2
, f3
)) something
= TRUE
;
512 if (describe_sustains(o_ptr
, f2
)) something
= TRUE
;
513 if (describe_misc_magic(o_ptr
, f3
)) something
= TRUE
;
514 if (describe_activation(o_ptr
, f3
)) something
= TRUE
;
515 if (describe_ignores(o_ptr
, f3
)) something
= TRUE
;
517 /* Unknown extra powers (ego-item with random extras or artifact) */
518 if (object_known_p(o_ptr
) && (!(o_ptr
->ident
& IDENT_MENTAL
)) &&
519 ((o_ptr
->xtra1
) || artifact_p(o_ptr
)))
521 /* Hack -- Put this in a separate paragraph if screen dump */
522 if (text_out_hook
== text_out_to_screen
)
523 new_paragraph
= TRUE
;
525 p_text_out("It might have hidden powers.");
535 * Header for additional information when printing to screen.
537 * Return TRUE if an object description was displayed.
539 static bool screen_out_head(const object_type
*o_ptr
)
542 int name_size
= Term
->wid
;
543 bool has_description
= FALSE
;
545 /* Allocate memory to the size of the screen */
546 o_name
= C_RNEW(name_size
, char);
549 object_desc(o_name
, name_size
, o_ptr
, TRUE
, 3);
551 /* Print, in colour */
552 text_out_c(TERM_YELLOW
, format("%^s", o_name
));
554 /* Free up the memory */
557 /* Display the known artifact description */
558 if (!adult_randarts
&& o_ptr
->name1
&&
559 object_known_p(o_ptr
) && a_info
[o_ptr
->name1
].text
)
562 p_text_out(a_text
+ a_info
[o_ptr
->name1
].text
);
563 has_description
= TRUE
;
566 /* Display the known object description */
567 else if (object_aware_p(o_ptr
) || object_known_p(o_ptr
))
569 if (k_info
[o_ptr
->k_idx
].text
)
572 p_text_out(k_text
+ k_info
[o_ptr
->k_idx
].text
);
573 has_description
= TRUE
;
576 /* Display an additional ego-item description */
577 if (o_ptr
->name2
&& object_known_p(o_ptr
) && e_info
[o_ptr
->name2
].text
)
580 p_text_out(e_text
+ e_info
[o_ptr
->name2
].text
);
581 has_description
= TRUE
;
585 return (has_description
);
590 * Place an item description on the screen.
592 void object_info_screen(const object_type
*o_ptr
)
594 bool has_description
, has_info
;
596 /* Redirect output to the screen */
597 text_out_hook
= text_out_to_screen
;
599 /* Save the screen */
602 has_description
= screen_out_head(o_ptr
);
604 object_info_out_flags
= object_flags_known
;
607 new_paragraph
= TRUE
;
608 has_info
= object_info_out(o_ptr
);
609 new_paragraph
= FALSE
;
611 if (!object_known_p(o_ptr
))
612 p_text_out("\n\n This item has not been identified.");
613 else if (!has_description
&& !has_info
)
614 p_text_out("\n\n This item does not seem to possess any special abilities.");
616 text_out_c(TERM_L_BLUE
, "\n\n[Press any key to continue]\n");
621 /* Load the screen */
624 /* Hack -- Browse book, then prompt for a command */
625 if (o_ptr
->tval
== cp_ptr
->spell_book
)
627 /* Call the aux function */
628 do_cmd_browse_aux(o_ptr
);