1 /* File: describe.c */
2
3 /* Purpose: object recall */
4
5 /*
6 * Copyright (c) 1997-2001 Tim Baker
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 "tnb.h"
14
15 /*
16 * Like strcpy() but returns the length of the string copied
17 */
strcpy_len(char * s1,const char * s2)18 int strcpy_len(char *s1, const char *s2)
19 {
20 int len = 0;
21 while ((*s1++ = *s2++)) ++len;
22 return len;
23 }
24
25 /* Global pointer into output buffer */
26 static char *s_buffer;
27
28 /*
29 * Write a string to the output buffer, plus optional padding
30 */
roll_off(cptr str,bool pad)31 static void roll_off(cptr str, bool pad)
32 {
33 if (pad) s_buffer += strcpy_len(s_buffer, " ");
34 s_buffer += strcpy_len(s_buffer, str);
35 }
36
37 /*
38 * Remove characters from the output buffer
39 */
roll_back(int count)40 static void roll_back(int count)
41 {
42 s_buffer -= count;
43 }
44
45 /*
46 * Write array of strings to output buffer
47 */
roll_em(cptr * vp,int vn,cptr joiner,cptr finish)48 static void roll_em(cptr *vp, int vn, cptr joiner, cptr finish)
49 {
50 int i;
51
52 for (i = 0; i < vn; ++i)
53 {
54 roll_off(vp[i], FALSE);
55
56 if (i < vn - 2)
57 roll_off(", ", FALSE);
58 else if (i == vn - 2)
59 roll_off(joiner ? joiner : " and ", FALSE);
60 else
61 roll_off(finish ? finish : ".", FALSE);
62 }
63 }
64
65 #define TR0_STAT_MASK \
66 (TR0_STR | TR0_INT | TR0_WIS | TR0_DEX | \
67 TR0_CON | TR0_CHR)
68
69 #define TR1_SUST_MASK \
70 (TR1_SUST_STR | TR1_SUST_INT | TR1_SUST_WIS | TR1_SUST_DEX | \
71 TR1_SUST_CON | TR1_SUST_CHR)
72
73 #define TR_STAT_MASK 0, TR0_STAT_MASK
74 #define TR_SUST_MASK 1, TR1_SUST_MASK
75
76 /*
77 * Write object memory to a buffer
78 */
angtk_describe_object(object_type * o_ptr,char * buf,bool in_store)79 long angtk_describe_object(object_type *o_ptr, char *buf, bool in_store)
80 {
81 cptr vp[128];
82 int vn;
83
84 bool known = FALSE;
85 bool k = FALSE;
86 bool hack;
87
88 /* Set the global. See roll_off(). */
89 s_buffer = buf;
90
91 /* Null-terminate it anyhow */
92 s_buffer[0] = '\0';
93
94 /* See if the object is "known" */
95 if (object_known_p(o_ptr)) known = TRUE;
96
97 /* Mega-Hack -- describe activation */
98 if (FLAG(o_ptr, TR_ACTIVATE))
99 {
100 roll_off("It can be activated for ", k);
101 roll_off(item_activation(o_ptr), FALSE);
102 roll_off(" if it is being worn.", FALSE);
103
104 k = TRUE;
105 }
106
107 /* Figurines, a hack */
108 if (o_ptr->tval == TV_FIGURINE)
109 {
110 roll_off("It will transform into a pet when thrown.", k);
111 k = TRUE;
112 }
113
114 /* Bad things */
115 vn = 0;
116
117 hack = FALSE;
118
119 if (FLAG(o_ptr, TR_TY_CURSE)) vp[vn++] = "carries an ancient foul curse";
120
121 if (cursed_p(o_ptr))
122 {
123 if (FLAG(o_ptr, TR_PERMA_CURSE)) vp[vn++] = "is permanently cursed";
124 else if (FLAG(o_ptr, TR_HEAVY_CURSE)) vp[vn++] = "is heavily cursed";
125 else if (known || (o_ptr->info & OB_SENSE)) vp[vn++] = "is cursed";
126 }
127
128 if (FLAG(o_ptr, TR_DRAIN_EXP)) vp[vn++] = "drains experience";
129 if (FLAG(o_ptr, TR_TELEPORT)) vp[vn++] = "teleports randomly";
130 if (FLAG(o_ptr, TR_AGGRAVATE)) vp[vn++] = "aggravates monsters";
131 if (FLAG(o_ptr, TR_NO_MAGIC)) vp[vn++] = "disrupts magic";
132 if (FLAG(o_ptr, TR_NO_TELE)) vp[vn++] = "inhibits teleportation";
133
134 if (vn)
135 {
136 roll_off("Unfortunately it ", k);
137 roll_em(vp, vn, NULL, NULL);
138
139 k = TRUE;
140 hack = TRUE;
141 }
142
143 if ((FLAG(o_ptr, TR_STAT_MASK)) && o_ptr->pval)
144 {
145 if (hack && (o_ptr->pval < 0))
146 {
147 roll_back(1);
148 roll_off(",", FALSE);
149 }
150 else
151 {
152 if (k) roll_off(" ", FALSE);
153 k = TRUE;
154 }
155
156 roll_off((o_ptr->pval > 0) ? "Increases " : (hack ? " and it decreases " : "Decreases "), FALSE);
157
158 vn = 0;
159
160 if (FLAG(o_ptr, TR_STR)) vp[vn++] = "Strength";
161 if (FLAG(o_ptr, TR_INT)) vp[vn++] = "Intelligence";
162 if (FLAG(o_ptr, TR_WIS)) vp[vn++] = "Wisdom";
163 if (FLAG(o_ptr, TR_DEX)) vp[vn++] = "Dexterity";
164 if (FLAG(o_ptr, TR_CON)) vp[vn++] = "Constitution";
165 if (FLAG(o_ptr, TR_CHR)) vp[vn++] = "Charisma";
166
167 if (vn == 6)
168 {
169 roll_off("all stats.", FALSE);
170 }
171 else
172 {
173 roll_em(vp, vn, NULL, NULL);
174 }
175 }
176
177 /* Effects on skills */
178 if (o_ptr->pval)
179 {
180 vn = 0;
181
182 if (FLAG(o_ptr, TR_STEALTH)) vp[vn++] = "Stealth";
183 if (FLAG(o_ptr, TR_SEARCH)) vp[vn++] = "Searching";
184 if (FLAG(o_ptr, TR_INFRA)) vp[vn++] = "Infra-vision";
185 if (FLAG(o_ptr, TR_BLOWS)) vp[vn++] = "number of attacks";
186 if (FLAG(o_ptr, TR_SPEED)) vp[vn++] = "speed";
187
188 if (vn)
189 {
190 roll_off(o_ptr->pval > 0 ? "Improves " : "Hinders ", k);
191 roll_em(vp, vn, NULL, NULL);
192 k = TRUE;
193 }
194 }
195
196 /* Criticals */
197 vn = 0;
198
199 hack = FALSE;
200
201 if (FLAG(o_ptr, TR_BRAND_ACID)) vp[vn++] = "acid";
202 if (FLAG(o_ptr, TR_BRAND_ELEC)) vp[vn++] = "electricity";
203 if (FLAG(o_ptr, TR_BRAND_FIRE)) vp[vn++] = "fire";
204 if (FLAG(o_ptr, TR_BRAND_COLD)) vp[vn++] = "frost";
205 if (FLAG(o_ptr, TR_BRAND_POIS)) vp[vn++] = "poison";
206
207 if (vn)
208 {
209 roll_off("Does extra damage from ", k);
210 roll_em(vp, vn, NULL, NULL);
211
212 k = TRUE;
213 hack = TRUE;
214 }
215
216 if (FLAG(o_ptr, TR_THROW))
217 {
218 if (k) roll_off(" ", FALSE);
219 roll_off("It is perfectly balanced for throwing.", FALSE);
220
221 k = TRUE;
222 hack = TRUE;
223 }
224
225 /* Misc nastiness */
226 vn = 0;
227
228 if (FLAG(o_ptr, TR_CHAOTIC)) vp[vn++] = "produces chaotic effects";
229 if (FLAG(o_ptr, TR_VAMPIRIC)) vp[vn++] = "drains life from your foes";
230 if (FLAG(o_ptr, TR_IMPACT)) vp[vn++] = "causes earthquakes";
231 if (FLAG(o_ptr, TR_VORPAL)) vp[vn++] = "cuts with supernatural sharpness";
232
233 if (vn)
234 {
235 roll_off("It ", k);
236 roll_em(vp, vn, NULL, NULL);
237
238 k = TRUE;
239 hack = TRUE;
240 }
241
242 /* What does it slay? */
243 vn = 0;
244
245 if (FLAG(o_ptr, TR_KILL_DRAGON) || FLAG(o_ptr, TR_SLAY_DRAGON)) vp[vn++] = "dragons";
246 if (FLAG(o_ptr, TR_SLAY_ORC)) vp[vn++] = "orcs";
247 if (FLAG(o_ptr, TR_SLAY_TROLL)) vp[vn++] = "trolls";
248 if (FLAG(o_ptr, TR_SLAY_GIANT)) vp[vn++] = "giants";
249 if (FLAG(o_ptr, TR_SLAY_DEMON)) vp[vn++] = "demons";
250 if (FLAG(o_ptr, TR_SLAY_UNDEAD)) vp[vn++] = "undead";
251 if (FLAG(o_ptr, TR_SLAY_ANIMAL)) vp[vn++] = "animals";
252 if (FLAG(o_ptr, TR_SLAY_EVIL)) vp[vn++] = "evil";
253
254 if (vn)
255 {
256 roll_off("Especially deadly against ", k);
257 roll_em(vp, vn, NULL, NULL);
258 k = TRUE;
259 }
260
261 /* Sustain stats? */
262 if (FLAG(o_ptr, TR_SUST_MASK))
263 {
264 roll_off("Sustains ", k);
265
266 vn = 0;
267
268 if (FLAG(o_ptr, TR_SUST_STR)) vp[vn++] = "Strength";
269 if (FLAG(o_ptr, TR_SUST_INT)) vp[vn++] = "Intelligence";
270 if (FLAG(o_ptr, TR_SUST_WIS)) vp[vn++] = "Wisdom";
271 if (FLAG(o_ptr, TR_SUST_DEX)) vp[vn++] = "Dexterity";
272 if (FLAG(o_ptr, TR_SUST_CON)) vp[vn++] = "Constitution";
273 if (FLAG(o_ptr, TR_SUST_CHR)) vp[vn++] = "Charisma";
274
275 if (vn == 6)
276 {
277 roll_off("all stats.", FALSE);
278 }
279 else
280 {
281 roll_em(vp, vn, NULL, NULL);
282 }
283
284 k = TRUE;
285 }
286
287 /* Immunities */
288 vn = 0;
289
290 if (FLAG(o_ptr, TR_IM_ACID)) vp[vn++] = "acid";
291 if (FLAG(o_ptr, TR_IM_ELEC)) vp[vn++] = "electricity";
292 if (FLAG(o_ptr, TR_IM_FIRE)) vp[vn++] = "fire";
293 if (FLAG(o_ptr, TR_IM_COLD)) vp[vn++] = "cold";
294 if (FLAG(o_ptr, TR_RES_BLIND)) vp[vn++] = "blindness";
295 if (FLAG(o_ptr, TR_FREE_ACT)) vp[vn++] = "paralysis";
296 if (FLAG(o_ptr, TR_RES_FEAR)) vp[vn++] = "fear";
297
298 if (vn)
299 {
300 roll_off("Provides immunity to ", k);
301 k = TRUE;
302
303 roll_em(vp, vn, NULL, NULL);
304 }
305
306 /* Resistances */
307 vn = 0;
308
309 if (FLAG(o_ptr, TR_RES_ACID)) vp[vn++] = "acid";
310 if (FLAG(o_ptr, TR_RES_ELEC)) vp[vn++] = "electricity";
311 if (FLAG(o_ptr, TR_RES_FIRE)) vp[vn++] = "fire";
312 if (FLAG(o_ptr, TR_RES_COLD)) vp[vn++] = "cold";
313 if (FLAG(o_ptr, TR_RES_POIS)) vp[vn++] = "poison";
314
315 if (FLAG(o_ptr, TR_RES_LITE)) vp[vn++] = "light";
316 if (FLAG(o_ptr, TR_RES_DARK)) vp[vn++] = "dark";
317
318 if (FLAG(o_ptr, TR_RES_CONF)) vp[vn++] = "confusion";
319 if (FLAG(o_ptr, TR_RES_SOUND)) vp[vn++] = "sound";
320 if (FLAG(o_ptr, TR_RES_SHARDS)) vp[vn++] = "shards";
321
322 if (FLAG(o_ptr, TR_RES_NETHER)) vp[vn++] = "nether";
323 if (FLAG(o_ptr, TR_RES_NEXUS)) vp[vn++] = "nexus";
324 if (FLAG(o_ptr, TR_RES_CHAOS)) vp[vn++] = "chaos";
325 if (FLAG(o_ptr, TR_RES_DISEN)) vp[vn++] = "disenchantment";
326 if (FLAG(o_ptr, TR_HOLD_LIFE)) vp[vn++] = "life draining";
327
328 if (vn)
329 {
330 roll_off("Provides resistance to ", k);
331 roll_em(vp, vn, NULL, NULL);
332 k = TRUE;
333 }
334
335 /* What's cool? */
336 vn = 0;
337
338 if (FLAG(o_ptr, TR_FEATHER)) vp[vn++] = "feather falling";
339 if (FLAG(o_ptr, TR_SEE_INVIS)) vp[vn++] = "see invisible";
340 if (FLAG(o_ptr, TR_TELEPATHY)) vp[vn++] = "telepathy";
341 if (FLAG(o_ptr, TR_SLOW_DIGEST)) vp[vn++] = "slow digestion";
342 if (FLAG(o_ptr, TR_REGEN)) vp[vn++] = "regeneration";
343
344 if (vn)
345 {
346 roll_off("Enables ", k);
347 roll_em(vp, vn, NULL, NULL);
348 k = TRUE;
349 }
350
351 /* Cool too */
352 vn = 0;
353
354 if (FLAG(o_ptr, TR_REFLECT)) vp[vn++] = "reflects missiles";
355 if (FLAG(o_ptr, TR_SH_FIRE)) vp[vn++] = "radiates fire";
356 if (FLAG(o_ptr, TR_SH_ELEC)) vp[vn++] = "radiates electricity";
357
358 if (vn)
359 {
360 roll_off("It ", k);
361 roll_em(vp, vn, NULL, NULL);
362 k = TRUE;
363 }
364
365 /* Powerful bows */
366 vn = 0;
367
368 if (FLAG(o_ptr, TR_XTRA_MIGHT)) vp[vn++] = "with extra might";
369 if (FLAG(o_ptr, TR_XTRA_SHOTS)) vp[vn++] = "excessively fast";
370
371 if (vn)
372 {
373 roll_off("Fires missiles ", k);
374 roll_em(vp, vn, NULL, NULL);
375 k = TRUE;
376 }
377
378 /* Misc */
379 if (FLAG(o_ptr, TR_BLESSED))
380 {
381 roll_off("It has been blessed by the gods.", k);
382 k = TRUE;
383 }
384
385 /* Hack -- describe lite's */
386 if (o_ptr->tval == TV_LITE)
387 {
388 if (FLAG(o_ptr, TR_INSTA_ART))
389 {
390 roll_off("It provides light (radius 3) forever.", k);
391 }
392 else if (o_ptr->sval == SV_LITE_LANTERN)
393 {
394 roll_off("It provides light (radius 2) when fueled.", k);
395 }
396 else
397 {
398 roll_off("It provides light (radius 1) when fueled.", k);
399 }
400
401 k = TRUE;
402 }
403
404 /* Permanent light source */
405 if (FLAG(o_ptr, TR_LITE))
406 {
407 roll_off("It provides light (radius 1) forever.", k);
408 k = TRUE;
409 }
410
411 if (FLAG(o_ptr, TR_TUNNEL))
412 {
413 roll_off("It is ", k);
414 roll_off((o_ptr->pval >= 0) ? "an effective" : "a useless", FALSE);
415 roll_off(" digging tool.", FALSE);
416 k = TRUE;
417 }
418
419 /* What does the object resist? */
420 vn = 0;
421
422 if (FLAG(o_ptr, TR_IGNORE_ACID)) vp[vn++] = "acid";
423 if (FLAG(o_ptr, TR_IGNORE_ELEC)) vp[vn++] = "electricity";
424 if (FLAG(o_ptr, TR_IGNORE_FIRE)) vp[vn++] = "fire";
425 if (FLAG(o_ptr, TR_IGNORE_COLD)) vp[vn++] = "cold";
426
427 if (vn)
428 {
429 roll_off("It cannot be harmed by ", k);
430 roll_em(vp, vn, " or ", NULL);
431 k = TRUE;
432 }
433
434 /* Permanently identified? */
435 if (o_ptr->info & OB_MENTAL)
436 {
437 roll_off("It is permanently identified.", k);
438 k = TRUE;
439 }
440
441 /* Store bought */
442 if (!in_store && (o_ptr->info & OB_NO_EXP))
443 {
444 roll_off("It was purchased.", k);
445 k = TRUE;
446 }
447
448 return s_buffer - buf;
449 }
450
451
452 /*
453 * Set a field of a Tcl array variable
454 */
SetArrayValueChar(cptr varName,cptr field,char value)455 int SetArrayValueChar(cptr varName, cptr field, char value)
456 {
457 char string[20];
458
459 strnfmt(string, 20, "%c", value);
460 if (Tcl_SetVar2(g_interp, varName, field, string, TCL_LEAVE_ERR_MSG)
461 == NULL)
462 {
463 return TCL_ERROR;
464 }
465 return TCL_OK;
466 }
467
468 /*
469 * Set a field of a Tcl array variable
470 */
SetArrayValueLong(cptr varName,cptr field,long value)471 int SetArrayValueLong(cptr varName, cptr field, long value)
472 {
473 char string[20];
474
475 strnfmt(string, 20, "%ld", value);
476 if (Tcl_SetVar2(g_interp, varName, field, string, TCL_LEAVE_ERR_MSG)
477 == NULL)
478 {
479 return TCL_ERROR;
480 }
481 return TCL_OK;
482 }
483
484 /*
485 * Set a field of a Tcl array variable
486 */
SetArrayValueString(cptr varName,cptr field,cptr value)487 int SetArrayValueString(cptr varName, cptr field, cptr value)
488 {
489 if (Tcl_SetVar2(g_interp, varName, field, value, TCL_LEAVE_ERR_MSG)
490 == NULL)
491 {
492 return TCL_ERROR;
493 }
494 return TCL_OK;
495 }
496
497 /*
498 * Dump object info into a Tcl array variable
499 */
DumpObjectInfo(object_type * o_ptr,char * varName)500 static int DumpObjectInfo(object_type *o_ptr, char *varName)
501 {
502 int known;
503 cptr note;
504
505 /* Known? */
506 known = object_known_p(o_ptr) ? 1 : 0;
507
508 if (SetArrayValueLong(varName, "known", known) != TCL_OK)
509 {
510 return TCL_ERROR;
511 }
512
513 /* Some fields are returned only if the object is "known" */
514 if (known)
515 {
516 if (SetArrayValueLong(varName, "activate",
517 (FLAG(o_ptr, TR_ACTIVATE)) != 0) != TCL_OK)
518 {
519 return TCL_ERROR;
520 }
521 if (SetArrayValueLong(varName, "artifact", FLAG(o_ptr, TR_INSTA_ART))
522 != TCL_OK)
523 {
524 return TCL_ERROR;
525 }
526 if (SetArrayValueLong(varName, "pval", o_ptr->pval) != TCL_OK)
527 {
528 return TCL_ERROR;
529 }
530 if (SetArrayValueLong(varName, "to_a", o_ptr->to_a) != TCL_OK)
531 {
532 return TCL_ERROR;
533 }
534 if (SetArrayValueLong(varName, "to_d", o_ptr->to_d) != TCL_OK)
535 {
536 return TCL_ERROR;
537 }
538 if (SetArrayValueLong(varName, "to_h", o_ptr->to_h) != TCL_OK)
539 {
540 return TCL_ERROR;
541 }
542 if (SetArrayValueLong(varName, "timeout", o_ptr->timeout) != TCL_OK)
543 {
544 return TCL_ERROR;
545 }
546 }
547
548 if (SetArrayValueLong(varName, "ac", o_ptr->ac) != TCL_OK)
549 {
550 return TCL_ERROR;
551 }
552 if (SetArrayValueLong(varName, "dd", o_ptr->dd) != TCL_OK)
553 {
554 return TCL_ERROR;
555 }
556 if (SetArrayValueLong(varName, "ds", o_ptr->ds) != TCL_OK)
557 {
558 return TCL_ERROR;
559 }
560 if (SetArrayValueLong(varName, "k_idx", o_ptr->k_idx) != TCL_OK)
561 {
562 return TCL_ERROR;
563 }
564 if (SetArrayValueLong(varName, "number", o_ptr->number) != TCL_OK)
565 {
566 return TCL_ERROR;
567 }
568 if (SetArrayValueLong(varName, "sval", o_ptr->sval) != TCL_OK)
569 {
570 return TCL_ERROR;
571 }
572 if (SetArrayValueLong(varName, "tval", o_ptr->tval) != TCL_OK)
573 {
574 return TCL_ERROR;
575 }
576 if (SetArrayValueLong(varName, "weight", o_ptr->weight) != TCL_OK)
577 {
578 return TCL_ERROR;
579 }
580
581 note = "";
582 if (o_ptr->inscription)
583 {
584 note = quark_str(o_ptr->inscription);
585 }
586 if (ExtToUtf_SetArrayValueString(varName, "note", note) != TCL_OK)
587 {
588 return TCL_ERROR;
589 }
590
591 return TCL_OK;
592 }
593
594 /*
595 * Get verbose info for an inventory item. This should be combined
596 * with the "angband inventory" command. The main difference is it
597 * returns more info.
598 */
objcmd_inveninfo(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])599 int objcmd_inveninfo(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
600 {
601 CommandInfo *infoCmd = (CommandInfo *) clientData;
602 /* int objC = objc - infoCmd->depth; */
603 Tcl_Obj *CONST *objV = objv + infoCmd->depth;
604
605 int i_idx;
606 char *varName;
607 object_type *o_ptr;
608
609 /* Hack - ignore parameter */
610 (void) objc;
611
612 if (Tcl_GetIntFromObj(interp, objV[1], &i_idx) != TCL_OK)
613 {
614 return TCL_ERROR;
615 }
616
617 /*** Verify index, existing object ***/
618
619 /* Get the array variable name to dump results in */
620 varName = Tcl_GetStringFromObj(objV[2], NULL);
621
622 /* Grab the item */
623 o_ptr = get_list_item(p_ptr->inventory, i_idx);
624
625 return DumpObjectInfo(o_ptr, varName);
626 }
627
628 /* Textual name of each equipment slot */
629 cptr keyword_slot[] = {
630 "INVEN_WIELD", "INVEN_BOW", "INVEN_LEFT", "INVEN_RIGHT", "INVEN_NECK",
631 "INVEN_LITE", "INVEN_BODY", "INVEN_OUTER", "INVEN_ARM", "INVEN_HEAD",
632 "INVEN_HANDS", "INVEN_FEET",
633 NULL
634 };
635
636 /*
637 * Get verbose info for an equipment item. This should be combined
638 * with the "angband equipment" command. The main difference is it
639 * returns more info.
640 */
641 int
objcmd_equipinfo(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])642 objcmd_equipinfo(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
643 {
644 CommandInfo *infoCmd = (CommandInfo *) clientData;
645 /* int objC = objc - infoCmd->depth; */
646 Tcl_Obj *CONST *objV = objv + infoCmd->depth;
647
648 int i_idx;
649 char *varName;
650 object_type *o_ptr;
651
652 /* Hack - ignore parameter */
653 (void) objc;
654
655 /* Get a numerical index or slot name */
656 if (Tcl_GetIntFromObj(interp, objV[1], &i_idx) != TCL_OK)
657 {
658 Tcl_ResetResult(interp);
659 if (Tcl_GetIndexFromObj(interp, objV[1], keyword_slot,
660 "slot", 0, &i_idx) != TCL_OK)
661 {
662 return TCL_ERROR;
663 }
664 }
665
666 /*** Verify index, existing object ***/
667
668 /* Get the array variable name to dump results in */
669 varName = Tcl_GetStringFromObj(objV[2], NULL);
670
671 /* Grab the item */
672 o_ptr = &p_ptr->equipment[i_idx];
673
674 return DumpObjectInfo(o_ptr, varName);
675 }
676