ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.93
Committed: Tue Jan 3 11:25:30 2012 UTC (12 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.92: +1 -1 lines
Log Message:
update copyrights to 2012

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.41 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.19 *
4 root 1.93 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.73 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992 Frank Tore Johansen
7 pippijn 1.19 *
8 root 1.58 * Deliantra is free software: you can redistribute it and/or modify it under
9     * the terms of the Affero GNU General Public License as published by the
10     * Free Software Foundation, either version 3 of the License, or (at your
11     * option) any later version.
12 pippijn 1.19 *
13 root 1.38 * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17 pippijn 1.19 *
18 root 1.58 * You should have received a copy of the Affero GNU General Public License
19     * and the GNU General Public License along with this program. If not, see
20     * <http://www.gnu.org/licenses/>.
21 root 1.36 *
22 root 1.41 * The authors can be reached via e-mail to <support@deliantra.net>
23 pippijn 1.19 */
24 elmex 1.1
25     #include <global.h>
26     #include <living.h>
27     #include <spells.h>
28    
29 root 1.42 const char *const coins[NUM_COINS + 1] = { "royalty", "platinacoin", "goldcoin", "silvercoin", 0 };
30    
31 elmex 1.1 /* the ordering of this is actually doesn't make a difference
32     * However, for ease of use, new entries should go at the end
33     * so those people that debug the code that get used to something
34     * being in the location 4 don't get confused.
35     *
36     * The ordering in save_name, use_name, nonuse_name.
37     * save_name is the name used to load/save it from files. It should
38     * match that of the doc/Developers/objects. The only
39     * real limitation is that it shouldn't have spaces or other characters
40     * that may mess up the match code. It must also start with body_
41     * use_name is how we describe the location if we can use it.
42     * nonuse_name is how we describe it if we can't use it. I think
43     * the values below will make it pretty clear how those work out
44     * They are basically there to make life a little easier - if a character
45     * examines an item and it says it goes on 'your arm', its pretty clear
46     * they can use it. See the last sample (commented out) for a dragon
47     * Note that using the term 'human' may not be very accurate, humanoid
48     * may be better.
49     * Basically, for the use/nonuse, the code does something like:
50     * "This item goes %s\n", with the use/nonuse values filling in the %s
51     */
52 root 1.77 // see include/object.h
53 elmex 1.1 Body_Locations body_locations[NUM_BODY_LOCATIONS] = {
54 root 1.90 # define def(name, use, nonuse) { # name, KW_body_ ## name, use, nonuse },
55     # include "slotinc.h"
56     # undef def
57 elmex 1.1 };
58    
59     static char numbers_10[10][20] = {
60 root 1.4 "zero", "ten", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy",
61     "eighty", "ninety"
62 elmex 1.1 };
63    
64 root 1.81 static char ordnumbers[21][20] = {
65 root 1.4 "zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
66 elmex 1.1 "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
67 root 1.81 "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth",
68     "nineteenth", "twentieth"
69 elmex 1.1 };
70    
71 root 1.81 static char ordnumbers_10[11][20] = {
72 root 1.4 "zeroth", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
73     "seventieth", "eightieth", "ninetieth"
74 elmex 1.1 };
75    
76     /* The following is a large table of item types, the fields are:
77     * item number, item name, item name (plural), and two numbers that are the skills
78     * used to identify them. Anytime a new item type is added or removed, this list
79     * should be altered to reflect that. The defines for the numerical values are in
80     * define.h
81     */
82     static const typedata item_types[] = {
83 root 1.4 {PLAYER, "player", "players", 0, 0},
84     {ROD, "rod", "rods", SK_THAUMATURGY, 0},
85     {TREASURE, "treasure", "treasure", 0, 0},
86     {POTION, "potion", "potions", SK_ALCHEMY, 0},
87     {FOOD, "food", "food", SK_WOODSMAN, 0},
88     {POISON, "poison", "poisons", SK_ALCHEMY, 0},
89     {BOOK, "book", "books", SK_LITERACY, 0},
90     {CLOCK, "clock", "clocks", 0, 0},
91     {ARROW, "arrow", "arrows", SK_BOWYER, 0},
92     {BOW, "bow", "bows", SK_BOWYER, 0},
93     {WEAPON, "weapon", "weapons", SK_SMITHERY, 0},
94     {ARMOUR, "armour", "armour", SK_SMITHERY, 0},
95     {PEDESTAL, "pedestal", "pedestals", 0, 0},
96     {ALTAR, "altar", "altars", 0, 0},
97     {LOCKED_DOOR, "locked door", "locked doors", 0, 0},
98     {SPECIAL_KEY, "special key", "special keys", 0, 0},
99     {MAP, "map", "maps", 0, 0},
100     {DOOR, "door", "doors", 0, 0},
101     {KEY, "key", "keys", 0, 0},
102     {TIMED_GATE, "timed_gate", "timed_gates", 0, 0},
103     {TRIGGER, "trigger", "triggers", 0, 0},
104     {GRIMREAPER, "grimreaper", "grimreapers", 0, 0},
105     {MAGIC_EAR, "magic ear", "magic ears", 0, 0},
106     {TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0},
107     {TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0},
108     {TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0},
109     {SHIELD, "shield", "shields", SK_SMITHERY, 0},
110     {HELMET, "helmet", "helmets", SK_SMITHERY, 0},
111     {HORN, "horn", "horns", SK_THAUMATURGY, 0},
112     {MONEY, "money", "money", 0, 0},
113     {CLASS, "class", "classes", 0, 0},
114     {GRAVESTONE, "gravestone", "gravestones", 0, 0},
115     {AMULET, "amulet", "amulets", SK_JEWELER, 0},
116     {PLAYERMOVER, "player mover", "player movers", 0, 0},
117     {TELEPORTER, "teleporter", "teleporters", 0, 0},
118     {CREATOR, "creator", "creators", 0, 0},
119     {SKILL, "skill", "skills", 0, 0},
120     {EARTHWALL, "earthwall", "earthwalls", 0, 0},
121     {GOLEM, "golem", "golems", 0, 0},
122     {THROWN_OBJ, "projectile", "projectiles", 0, 0},
123     {BLINDNESS, "blindness", "blindness", 0, 0},
124     {GOD, "god", "gods", 0, 0},
125     {DETECTOR, "detector", "detectors", 0, 0},
126     {TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0},
127     {DEAD_OBJECT, "dead object", "dead objects", 0, 0},
128     {DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY},
129     {MARKER, "marker", "markers", 0, 0},
130     {HOLY_ALTAR, "holy altar", "holy altars", 0, 0},
131     {PLAYER_CHANGER, "player changer", "player changers", 0, 0},
132     {BATTLEGROUND, "battleground", "battlegrounds", 0, 0},
133     {PEACEMAKER, "peacemaker", "peacemakers", 0, 0},
134     {GEM, "gem", "gems", SK_JEWELER, 0},
135     {FIREWALL, "firewall", "firewalls", 0, 0},
136     {ANVIL, "anvil", "anvils", 0, 0},
137     {CHECK_INV, "inventory checker", "inventory checkers", 0, 0},
138     {MOOD_FLOOR, "mood floor", "mood floors", 0, 0},
139     {EXIT, "exit", "exits", 0, 0},
140     {ENCOUNTER, "encounter", "encounters", 0, 0},
141     {SHOP_FLOOR, "shop floor", "shop floors", 0, 0},
142     {SHOP_MAT, "shop mat", "shop mats", 0, 0},
143     {RING, "ring", "rings", SK_JEWELER, 0},
144 root 1.82 // {FLOOR, "floor", "floors", 0, 0},
145 root 1.4 {FLESH, "flesh", "flesh", SK_WOODSMAN, 0},
146     {INORGANIC, "inorganic", "inorganics", SK_ALCHEMY, 0},
147     {SKILL_TOOL, "skill tool", "skill tools", 0, 0},
148     {LIGHTER, "lighter", "lighters", 0, 0},
149 elmex 1.12 {BUILDABLE_WALL, "buildable wall", "buildable walls", 0, 0},
150 root 1.4 {MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0},
151 root 1.92 {TORCH, "torch", "torches", 0, 0},
152 root 1.4 {LAMP, "lamp", "lamps", 0, 0},
153     {DUPLICATOR, "duplicator", "duplicators", 0, 0},
154     {SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0},
155     {CLOAK, "cloak", "cloaks", SK_SMITHERY, 0},
156     {SPINNER, "spinner", "spinners", 0, 0},
157     {GATE, "gate", "gates", 0, 0},
158     {BUTTON, "button", "buttons", 0, 0},
159 root 1.59 {T_HANDLE, "cf handle", "cf handles", 0, 0},
160 root 1.4 {HOLE, "hole", "holes", 0, 0},
161     {TRAPDOOR, "trapdoor", "trapdoors", 0, 0},
162     {SIGN, "sign", "signs", 0, 0},
163     {BOOTS, "boots", "boots", SK_SMITHERY, 0},
164     {GLOVES, "gloves", "gloves", SK_SMITHERY, 0},
165     {SPELL, "spell", "spells", 0, 0},
166     {SPELL_EFFECT, "spell effect", "spell effects", 0, 0},
167     {CONVERTER, "converter", "converters", 0, 0},
168     {BRACERS, "bracers", "bracers", SK_SMITHERY, 0},
169     {POISONING, "poisoning", "poisonings", 0, 0},
170     {SAVEBED, "savebed", "savebeds", 0, 0},
171     {WAND, "wand", "wands", SK_THAUMATURGY, 0},
172     {SCROLL, "scroll", "scrolls", SK_LITERACY, 0},
173     {DIRECTOR, "director", "directors", 0, 0},
174     {GIRDLE, "girdle", "girdles", SK_SMITHERY, 0},
175     {FORCE, "force", "forces", 0, 0},
176     {POTION_EFFECT, "potion effect", "potion effects", 0, 0},
177     {CLOSE_CON, "closed container", "closed container", 0, 0},
178     {CONTAINER, "container", "containers", SK_ALCHEMY, 0},
179     {ARMOUR_IMPROVER, "armour improver", "armour improvers", 0, 0},
180     {WEAPON_IMPROVER, "weapon improver", "weapon improvers", 0, 0},
181     {SKILLSCROLL, "skillscroll", "skillscrolls", 0, 0},
182     {DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0},
183     {IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0},
184     {MENU, "inventory list", "inventory lists", 0, 0},
185     {RUNE, "rune", "runes", 0, 0},
186     {TRAP, "trap", "traps", 0, 0},
187     {POWER_CRYSTAL, "power_crystal", "power_crystals", 0, 0},
188     {CORPSE, "corpse", "corpses", 0, 0},
189     {DISEASE, "disease", "diseases", 0, 0},
190     {SYMPTOM, "symptom", "symptoms", 0, 0},
191     {BUILDER, "item builder", "item builders", 0, 0},
192     {MATERIAL, "building material", "building materials", 0, 0},
193     {ITEM_TRANSFORMER, "item_transformer", "item_transformers", 0, 0},
194 elmex 1.1 };
195    
196 root 1.86 static const int item_types_size = array_length (item_types);
197 elmex 1.1
198     /* This curve may be too steep. But the point is that there should
199     * be tough choices - there is no real point to this if everyone can
200     * wear whatever they want with no worries. Perhaps having the steep
201     * curve is good (maybe even steeper), but allowing players to
202     * have 2 * level instead. Ideally, top level characters should only be
203     * able to use 2-3 of the most powerful items.
204     * note that this table is only really used for program generated items -
205     * custom objects can use whatever they want.
206     */
207     static int enc_to_item_power[21] = {
208 root 1.85 0,
209 root 1.86 0, 1, 2, 3, 4, // 5
210     5, 7, 9, 11, 13, // 10
211     15, 18, 21, 24, 27, // 15
212     30, 35, 40, 45, 50 // 20
213 elmex 1.1 };
214    
215 root 1.4 int
216     get_power_from_ench (int ench)
217 elmex 1.1 {
218 root 1.53 return enc_to_item_power [clamp (ench, 0, 20)];
219 elmex 1.1 }
220    
221 root 1.84 static const struct need_identify_types : typeset
222     {
223     need_identify_types ()
224     {
225     set (RING);
226     set (WAND);
227     set (ROD);
228     set (HORN);
229     set (SCROLL);
230     set (SKILL);
231     set (SKILLSCROLL);
232     set (SPELLBOOK);
233     set (FOOD);
234     set (POTION);
235     set (BOW);
236     set (ARROW);
237     set (WEAPON);
238     set (ARMOUR);
239     set (SHIELD);
240     set (HELMET);
241     set (AMULET);
242     set (BOOTS);
243     set (GLOVES);
244     set (BRACERS);
245     set (GIRDLE);
246     set (CONTAINER);
247     set (DRINK);
248     set (FLESH);
249     set (INORGANIC);
250     set (CLOSE_CON);
251     set (CLOAK);
252     set (GEM);
253     set (POWER_CRYSTAL);
254     set (POISON);
255     set (BOOK);
256     set (SKILL_TOOL);
257     }
258     } need_identify_types;
259    
260     bool
261     object::need_identify () const
262     {
263     return need_identify_types [type];
264     }
265    
266 elmex 1.1 /* This takes an object 'op' and figures out what its item_power
267     * rating should be. This should only really be used by the treasure
268     * generation code, and when loading legacy objects. It returns
269     * the item_power it calculates.
270     * If flag is 1, we return the number of enchantment, and not the
271     * the power. This is used in the treasure code.
272     */
273 root 1.4 int
274     calc_item_power (const object *op, int flag)
275 elmex 1.1 {
276 root 1.4 int i, tmp, enc;
277 elmex 1.1
278 root 1.4 enc = 0;
279     for (i = 0; i < NUM_STATS; i++)
280 root 1.33 enc += op->stats.stat (i);
281 root 1.4
282     /* This protection logic is pretty flawed. 20% fire resistance
283     * is much more valuable than 20% confusion, or 20% slow, or
284     * several others. Start at 1 - ignore physical - all that normal
285     * armour shouldn't be counted against
286     */
287     tmp = 0;
288     for (i = 1; i < NROFATTACKS; i++)
289     tmp += op->resist[i];
290    
291     /* Add/substract 10 so that the rounding works out right */
292     if (tmp > 0)
293     enc += (tmp + 10) / 20;
294     else if (tmp < 0)
295     enc += (tmp - 10) / 20;
296    
297     enc += op->magic;
298    
299     /* For each attacktype a weapon has, one more encantment. Start at 1 -
300     * physical doesn't count against total.
301     */
302     if (op->type == WEAPON)
303     {
304     for (i = 1; i < NROFATTACKS; i++)
305     if (op->attacktype & (1 << i))
306     enc++;
307 root 1.49
308 root 1.4 if (op->slaying)
309     enc += 2; /* What it slays is probably more relevent */
310     }
311 root 1.49
312 root 1.4 /* Items the player can equip */
313     if ((op->type == WEAPON) || (op->type == ARMOUR) || (op->type == HELMET) ||
314     (op->type == SHIELD) || (op->type == RING) ||
315     (op->type == BOOTS) || (op->type == GLOVES) ||
316     (op->type == AMULET) || (op->type == GIRDLE) || (op->type == BRACERS) || (op->type == CLOAK))
317     {
318     enc += op->stats.food; /* sustenance */
319     enc += op->stats.hp; /* hp regen */
320     enc += op->stats.sp; /* mana regen */
321     enc += op->stats.grace; /* grace regen */
322     enc += op->stats.exp; /* speed bonus */
323     }
324 root 1.49
325 root 1.4 enc += op->stats.luck;
326    
327     /* Do spell paths now */
328     for (i = 1; i < NRSPELLPATHS; i++)
329 root 1.66 if (op->path_attuned & (1 << i))
330     enc++;
331     else if (op->path_denied & (1 << i))
332     enc -= 2;
333     else if (op->path_repelled & (1 << i))
334     enc--;
335 root 1.4
336 root 1.55 if (op->flag [FLAG_LIFESAVE ]) enc += 5;
337     if (op->flag [FLAG_REFL_SPELL ]) enc += 3;
338     if (op->flag [FLAG_REFL_MISSILE]) enc += 2;
339     if (op->flag [FLAG_XRAYS ]) enc += 2;
340     if (op->flag [FLAG_STEALTH ]) enc += 1;
341     if (op->flag [FLAG_SEE_IN_DARK ]) enc += 1;
342     if (op->flag [FLAG_MAKE_INVIS ]) enc += 1;
343 elmex 1.1
344 root 1.4 return get_power_from_ench (enc);
345 elmex 1.1 }
346    
347 root 1.87 static const struct get_typedata
348     {
349     const typedata *data [NUM_TYPES];
350    
351     get_typedata ()
352     {
353     for (int i = 0; i < item_types_size; i++)
354     data [item_types[i].number] = &item_types [i];
355     }
356    
357     const typedata *operator ()(int itemtype) const
358     {
359     return data [itemtype];
360     }
361     } get_typedata_;
362    
363 elmex 1.1 /* returns the typedata that has a number equal to itemtype, if there
364     * isn't one, returns NULL */
365 root 1.4 const typedata *
366     get_typedata (int itemtype)
367     {
368 root 1.87 return get_typedata_ (itemtype);
369 elmex 1.1 }
370    
371     /* returns the typedata that has a name equal to itemtype, if there
372     * isn't one, return the plural name that matches, if there still isn't
373     * one return NULL */
374 root 1.4 const typedata *
375     get_typedata_by_name (const char *name)
376     {
377 root 1.55 for (int i = 0; i < item_types_size; i++)
378 root 1.4 if (!strcmp (item_types[i].name, name))
379     return &item_types[i];
380 root 1.49
381 root 1.55 for (int i = 0; i < item_types_size; i++)
382 root 1.4 if (!strcmp (item_types[i].name_pl, name))
383     {
384     LOG (llevInfo,
385 root 1.49 "get_typedata_by_name: I have been sent the plural %s, the singular form %s is prefered\n", name, item_types[i].name);
386 root 1.4 return &item_types[i];
387     }
388 root 1.49
389 root 1.55 return 0;
390 elmex 1.1 }
391 root 1.4
392 elmex 1.1 /* describe_resistance generates the visible naming for resistances.
393     * returns a static array of the description. This can return
394     * a big buffer.
395     * if newline is true, we don't put parens around the description
396     * but do put a newline at the end. Useful when dumping to files
397     */
398 root 1.25 const char *
399 root 1.4 describe_resistance (const object *op, int newline)
400 elmex 1.1 {
401 root 1.60 static dynbuf_text buf; buf.clear ();
402 root 1.4
403 root 1.60 for (int i = 0; i < NROFATTACKS; i++)
404     if (op->resist[i] && (op->type != FLESH || atnr_is_dragon_enabled (i) == 1))
405     buf.printf (newline ? "%s %d\n" : "(%s %+d)", resist_plus[i], op->resist[i]);
406 root 1.55
407 root 1.4 return buf;
408 elmex 1.1 }
409    
410     /*
411     * query_weight(object) returns a character pointer to a static buffer
412     * containing the text-representation of the weight of the given object.
413     * The buffer will be overwritten by the next call to query_weight().
414 root 1.55 *
415     * Seems to be used only by unimportant stuff. Remove?
416 elmex 1.1 */
417 root 1.25 const char *
418 root 1.4 query_weight (const object *op)
419     {
420 elmex 1.1 static char buf[10];
421 root 1.46 sint32 i = op->total_weight ();
422 elmex 1.1
423 root 1.4 if (op->weight < 0)
424 elmex 1.1 return " ";
425 root 1.25
426 root 1.4 if (i % 1000)
427     sprintf (buf, "%6.1f", i / 1000.0);
428 elmex 1.1 else
429 root 1.4 sprintf (buf, "%4d ", i / 1000);
430 root 1.25
431 elmex 1.1 return buf;
432     }
433    
434     /*
435     * Returns the pointer to a static buffer containing
436     * the number requested (of the form first, second, third...)
437     */
438 root 1.25 const char *
439 root 1.81 ordinal (int i)
440 root 1.4 {
441 root 1.81 if (i < 0)
442     return format ("minus %s", ordinal (-i));
443 root 1.4
444 root 1.81 if (i < 21)
445     return ordnumbers[i];
446 root 1.25
447 root 1.81 int digit = i % 10;
448 root 1.55
449 root 1.81 if (i >= 100)
450     return format (
451     digit == 1 ? "%dst"
452     : digit == 2 ? "%dnd"
453     : digit == 3 ? "%drd"
454     : "%dth",
455     i
456     );
457 root 1.25
458 root 1.81 if (digit == 0)
459     return ordnumbers_10[i / 10];
460     else
461     return format ("%s%s", numbers_10[i / 10], ordnumbers[i % 10]);
462 elmex 1.1 }
463    
464     /*
465     * Returns pointer to static buffer containing ring's or amulet's
466     * abilities
467     * These are taken from old query_name(), but it would work better
468     * if describle_item() would be called to get this information and
469     * caller would handle FULL_RING_DESCRIPTION definition.
470     * Or make FULL_RING_DESCRIPTION standard part of a game and let
471     * client handle names.
472     */
473 root 1.4
474 elmex 1.1 /* Aug 95 modified this slightly so that Skill tools don't have magic bonus
475     * from stats.sp - b.t.
476     */
477 root 1.63 static const char *
478 root 1.4 ring_desc (const object *op)
479 elmex 1.1 {
480 root 1.39 static dynbuf_text buf; buf.clear ();
481 root 1.4 int attr, val, len;
482 elmex 1.1
483 root 1.83 if (op->flag [FLAG_IDENTIFIED])
484 root 1.39 {
485     for (attr = 0; attr < NUM_STATS; attr++)
486     if ((val = op->stats.stat (attr)))
487     buf.printf ("(%s%+d)", short_stat_name[attr], val);
488 elmex 1.1
489 root 1.88 if (op->stats.exp) buf.printf ("(speed %+d)", (int)op->stats.exp);
490 root 1.39 if (op->stats.wc) buf.printf ("(wc%+d)", op->stats.wc);
491     if (op->stats.dam) buf.printf ("(dam%+d)", op->stats.dam);
492     if (op->stats.ac) buf.printf ("(ac%+d)", op->stats.ac);
493    
494     buf << describe_resistance (op, 0);
495    
496     if (op->stats.food) buf.printf ("(sustenance%+d)", op->stats.food);
497     if (op->stats.grace) buf.printf ("(grace%+d)", op->stats.grace);
498     if (op->stats.sp && op->type != SKILL) buf.printf ("(magic%+d)", op->stats.sp);
499     if (op->stats.hp) buf.printf ("(regeneration%+d)", op->stats.hp);
500     if (op->stats.luck) buf.printf ("(luck%+d)", op->stats.luck);
501    
502 root 1.83 if (op->flag [FLAG_LIFESAVE]) buf << "(lifesaving)";
503     if (op->flag [FLAG_REFL_SPELL]) buf << "(reflect spells)";
504     if (op->flag [FLAG_REFL_MISSILE]) buf << "(reflect missiles)";
505     if (op->flag [FLAG_STEALTH]) buf << "(stealth)";
506 root 1.39
507     buf.add_paths ("Attuned" , op->path_attuned);
508     buf.add_paths ("Repelled", op->path_repelled);
509     buf.add_paths ("Denied" , op->path_denied);
510 root 1.4
511 root 1.39 if (buf.empty ())
512     buf << "of adornment";
513 root 1.4 }
514 root 1.27
515 root 1.4 return buf;
516 elmex 1.1 }
517    
518     /*
519     * query_short_name(object) is similar to query_name, but doesn't
520     * contain any information about object status (worn/cursed/etc.)
521 root 1.55 *
522     * It is sometimes used when printing messages, so should fit well into a sentence.
523 elmex 1.1 */
524 root 1.4 const char *
525     query_short_name (const object *op)
526 elmex 1.1 {
527 root 1.52 if (!op->name)
528 root 1.4 return "(null)";
529 root 1.5
530 root 1.42 if (!op->nrof
531     && !op->weight
532     && !op->title
533     && !is_magical (op)
534     && op->slaying != shstr_money)
535 root 1.4 return op->name; /* To speed things up (or make things slower?) */
536    
537 root 1.42 static dynbuf_text buf; buf.clear ();
538    
539 root 1.39 buf << (op->nrof <= 1 ? op->name : op->name_pl);
540 root 1.4
541 root 1.83 if (op->title && op->flag [FLAG_IDENTIFIED])
542 root 1.39 buf << ' ' << op->title;
543 elmex 1.1
544 root 1.4 switch (op->type)
545     {
546 root 1.39 case SPELLBOOK:
547     case SCROLL:
548     case WAND:
549     case ROD:
550 root 1.83 if (op->flag [FLAG_IDENTIFIED] || op->flag [FLAG_BEEN_APPLIED])
551 root 1.39 {
552     if (!op->title)
553     buf << " of " << (op->inv ? &op->inv->name : "bug, please report");
554    
555     if (op->type != SPELLBOOK)
556     buf.printf (" (lvl %d)", op->level);
557     }
558     break;
559    
560 root 1.53 case ALTAR:
561     case TRIGGER_ALTAR:
562     case IDENTIFY_ALTAR:
563     case CONVERTER:
564     if (op->slaying == shstr_money)
565     {
566     bool wrap = !!buf.size ();
567 root 1.42
568 root 1.53 if (wrap) buf << " [";
569 root 1.42
570 root 1.53 archetype *coin = 0;
571 root 1.42
572 root 1.53 for (char const *const *c = coins; *coins; ++c)
573     if ((coin = archetype::find (*c)))
574     if (op->stats.food % coin->value == 0)
575     break;
576 root 1.42
577 root 1.53 sint32 coins = op->stats.food / coin->value;
578 root 1.42
579 root 1.53 buf.printf ("drop %d %s (or equivalent)", coins, coins == 1 ? &coin->name : &coin->name_pl);
580 root 1.42
581 root 1.53 if (wrap) buf << ']';
582     }
583     break;
584 root 1.42
585 root 1.39 case SKILL:
586     case AMULET:
587     case RING:
588     if (!op->title)
589     {
590     /* If ring has a title, full description isn't so useful */
591     const char *s = ring_desc (op);
592 elmex 1.1
593 root 1.39 if (s && *s)
594     buf << " " << s;
595     }
596     break;
597 root 1.42
598 root 1.39 default:
599 root 1.84 if (op->magic
600     && ((op->flag [FLAG_BEEN_APPLIED] && op->need_identify ())
601     || op->flag [FLAG_IDENTIFIED]))
602 root 1.39 buf.printf (" %+d", op->magic);
603 elmex 1.1 }
604 root 1.39
605 root 1.4 return buf;
606 elmex 1.1 }
607    
608     /*
609     * query_name(object) returns a character pointer pointing to a static
610     * buffer which contains a verbose textual representation of the name
611     * of the given object.
612     * cf 0.92.6: Put in 5 buffers that it will cycle through. In this way,
613     * you can make several calls to query_name before the bufs start getting
614     * overwritten. This may be a bad thing (it may be easier to assume the value
615     * returned is good forever.) However, it makes printing statements that
616     * use several names much easier (don't need to store them to temp variables.)
617     *
618 root 1.55 * It is used extensively within messages, so should return only a prose
619     * and short description of the item.
620 root 1.71 * It is also used by examine/ex and similar functions.
621 elmex 1.1 */
622 root 1.25 const char *
623 root 1.4 query_name (const object *op)
624     {
625 root 1.39 int len = 0;
626     static dynbuf_text bufs[5];
627 root 1.4 static int use_buf = 0;
628 elmex 1.1
629 root 1.4 use_buf++;
630     use_buf %= 5;
631 elmex 1.1
632 root 1.39 dynbuf_text &buf = bufs [use_buf];
633     buf.clear ();
634    
635 root 1.67 #if 0
636     if ((op->is_armor () || op->is_weapon ()) && op->material)
637     buf << op->material->description << ' ';
638     #endif
639 elmex 1.1
640 root 1.39 buf << query_short_name (op);
641 elmex 1.1
642 root 1.83 if (op->flag [FLAG_INV_LOCKED])
643 root 1.39 buf << " *";
644 root 1.61 if (op->is_open_container ())
645 root 1.39 buf << " (open)";
646 root 1.4
647 root 1.83 if (op->flag [FLAG_KNOWN_CURSED])
648 root 1.4 {
649 root 1.83 if (op->flag [FLAG_DAMNED])
650 root 1.39 buf << " (damned)";
651 root 1.83 else if (op->flag [FLAG_CURSED])
652 root 1.39 buf << " (cursed)";
653 root 1.4 }
654 root 1.23
655 root 1.4 /* Basically, if the object is known magical (detect magic spell on it),
656     * and it isn't identified, print out the fact that
657     * it is magical. Assume that the detect magical spell will only set
658     * KNOWN_MAGICAL if the item actually is magical.
659     *
660     * Changed in V 0.91.4 - still print that the object is magical even
661     * if it has been applied. Equipping an item does not tell full
662     * abilities, especially for artifact items.
663     */
664 root 1.83 if (op->flag [FLAG_KNOWN_MAGICAL] && !op->flag [FLAG_IDENTIFIED])
665 root 1.39 buf << " (magic)";
666 elmex 1.1
667     #if 0
668 root 1.55 /* item_power will be returned in describe_item - it shouldn't really
669 root 1.4 * be returned in the name.
670     */
671     if (op->item_power)
672     sprintf (buf[use_buf] + strlen (buf[use_buf]), "(item_power %+d)", op->item_power);
673 elmex 1.1
674     #endif
675    
676 root 1.83 if (op->flag [FLAG_APPLIED])
677 root 1.4 {
678     switch (op->type)
679     {
680 root 1.89 case RANGED:
681 root 1.23 case BOW:
682     case WAND:
683     case ROD:
684     case HORN:
685     case WEAPON:
686 root 1.77 buf << " (applied)";
687 root 1.23 break;
688     case ARMOUR:
689     case HELMET:
690     case SHIELD:
691     case RING:
692     case BOOTS:
693     case GLOVES:
694     case AMULET:
695     case GIRDLE:
696     case BRACERS:
697     case CLOAK:
698 root 1.39 buf << " (worn)";
699 root 1.23 break;
700     case CONTAINER:
701 root 1.39 buf << " (active)";
702 root 1.23 break;
703     case SKILL:
704     default:
705 root 1.39 buf << " (applied)";
706 root 1.2 }
707 elmex 1.1 }
708 root 1.23
709 elmex 1.54 switch (op->type)
710     {
711     case LAMP:
712     if (op->glow_radius)
713     buf << " (on)";
714     else if (op->stats.food <= 0)
715     buf << " (empty)";
716     else
717     buf << " (off)";
718     break;
719    
720     case TORCH:
721     if (op->glow_radius)
722     buf << " (burning)";
723     else if (op->stats.food <= 0)
724     buf << " (burned out)";
725     break;
726     }
727    
728 root 1.83 if (op->flag [FLAG_UNPAID])
729 root 1.39 buf << " (unpaid)";
730 elmex 1.1
731 root 1.39 return buf;
732 elmex 1.1 }
733    
734     /*
735     * query_base_name(object) returns a character pointer pointing to a static
736     * buffer which contains a verbose textual representation of the name
737     * of the given object. The buffer will be overwritten at the next
738     * call to query_base_name(). This is a lot like query_name, but we
739     * don't include the item count or item status. Used for inventory sorting
740     * and sending to client.
741     * If plural is set, we generate the plural name of this.
742 root 1.55 *
743     * It is sometimes used to display messages, and usually only used to match stuff,
744     * so maybe this function should be removed.
745 root 1.71 * It is also used for client-side inventory/item descriptions.
746 elmex 1.1 */
747 root 1.4 const char *
748     query_base_name (const object *op, int plural)
749     {
750     if ((!plural && !op->name) || (plural && !op->name_pl))
751     return "(null)";
752 elmex 1.1
753 root 1.71 if (!op->nrof && !op->weight && !op->title && !is_magical (op)
754     && op->type != EXIT)
755 root 1.4 return op->name; /* To speed things up (or make things slower?) */
756 elmex 1.1
757 root 1.39 static dynbuf_text buf; buf.clear ();
758    
759 root 1.67 #if 0
760     if ((op->is_armor () || op->is_weapon ()) && op->material)
761     if (op->arch->material != op->material)
762     buf << op->material->description << ' ';
763     #endif
764 root 1.20
765 root 1.39 buf << (plural ? op->name_pl : op->name);
766 elmex 1.1
767 root 1.83 if (op->title && op->flag [FLAG_IDENTIFIED])
768 root 1.39 buf << ' ' << op->title;
769 elmex 1.1
770 root 1.4 switch (op->type)
771     {
772 root 1.20 case SPELLBOOK:
773     case SCROLL:
774     case WAND:
775     case ROD:
776 root 1.83 if (op->flag [FLAG_IDENTIFIED] || op->flag [FLAG_BEEN_APPLIED])
777 root 1.20 {
778     if (!op->title)
779 root 1.39 buf << " of " << (op->inv ? &op->inv->name : "bug, please report");
780    
781 root 1.20 if (op->type != SPELLBOOK)
782 root 1.39 buf.printf (" (lvl %d)", op->level);
783 root 1.20 }
784     break;
785 elmex 1.1
786    
787 root 1.20 case SKILL:
788     case AMULET:
789     case RING:
790     if (!op->title)
791     {
792     /* If ring has a title, full description isn't so useful */
793 root 1.25 const char *s = ring_desc (op);
794 root 1.4
795 root 1.39 if (s && *s)
796     buf << ' ' << s;
797 root 1.20 }
798     break;
799 root 1.29
800 root 1.72 case EXIT:
801     // random map exits "unfortunately" get patched, so this only works before entering
802 root 1.76 if (EXIT_PATH (op) == shstr_random_map_exit)
803     buf << " (random map)";
804     else if (!EXIT_PATH (op))
805     buf << " (closed)";
806 root 1.72 break;
807    
808 root 1.20 default:
809 root 1.84 if (op->magic
810     && ((op->flag [FLAG_BEEN_APPLIED] && op->need_identify ())
811     || op->flag [FLAG_IDENTIFIED]))
812 root 1.39 buf.printf (" %+d", op->magic);
813 elmex 1.1 }
814 root 1.20
815 root 1.4 return buf;
816 elmex 1.1 }
817    
818     /* Break this off from describe_item - that function was way
819     * too long, making it difficult to read. This function deals
820     * with describing the monsters & players abilities. It should only
821     * be called with monster & player objects. Returns a description
822     * in a static buffer.
823     */
824 root 1.39 static const char *
825 root 1.4 describe_monster (const object *op)
826     {
827 root 1.39 static dynbuf_text buf; buf.clear ();
828 root 1.4
829     /* Note that the resolution this provides for players really isn't
830     * very good. Any player with a speed greater than .67 will
831     * fall into the 'lightning fast movement' category.
832     */
833 elmex 1.16 if (op->has_active_speed ())
834 root 1.68 switch ((int)(op->speed * 15.))
835 root 1.39 {
836     case 0:
837 root 1.51 buf << "(very slow movement)";
838 root 1.39 break;
839     case 1:
840     buf << "(slow movement)";
841     break;
842     case 2:
843     buf << "(normal movement)";
844     break;
845     case 3:
846     case 4:
847     buf << "(fast movement)";
848     break;
849     case 5:
850     case 6:
851     buf << "(very fast movement)";
852     break;
853     case 7:
854     case 8:
855     case 9:
856     case 10:
857     buf << "(extremely fast movement)";
858     break;
859     default:
860     buf << "(lightning fast movement)";
861     break;
862     }
863    
864 root 1.83 if (op->flag [FLAG_UNDEAD]) buf << "(undead)";
865     if (op->flag [FLAG_SEE_INVISIBLE]) buf << "(see invisible)";
866     if (op->flag [FLAG_USE_WEAPON]) buf << "(wield weapon)";
867     if (op->flag [FLAG_USE_BOW]) buf << "(archer)";
868     if (op->flag [FLAG_USE_ARMOUR]) buf << "(wear armour)";
869     if (op->flag [FLAG_USE_RING]) buf << "(wear ring)";
870     if (op->flag [FLAG_USE_SCROLL]) buf << "(read scroll)";
871     if (op->flag [FLAG_USE_RANGE]) buf << "(fires wand/rod/horn)";
872     if (op->flag [FLAG_CAN_USE_SKILL]) buf << "(skill user)";
873     if (op->flag [FLAG_CAST_SPELL]) buf << "(spellcaster)";
874     if (op->flag [FLAG_FRIENDLY]) buf << "(friendly)";
875     if (op->flag [FLAG_UNAGGRESSIVE]) buf << "(unaggressive)";
876     if (op->flag [FLAG_HITBACK]) buf << "(hitback)";
877     if (op->flag [FLAG_STEALTH]) buf << "(stealthy)";
878 root 1.39
879     if (op->randomitems)
880 root 1.4 {
881 root 1.39 bool first = 1;
882 root 1.4
883 root 1.39 for (treasure *t = op->randomitems->items; t; t = t->next)
884 root 1.37 if (t->item && t->item->type == SPELL)
885 root 1.4 {
886     if (first)
887 root 1.39 buf << "(Spell abilities:)";
888    
889     first = 0;
890    
891     buf << '(' << t->item->object::name << ')';
892 root 1.4 }
893     }
894 root 1.39
895 root 1.4 if (op->type == PLAYER)
896     {
897     if (op->contr->digestion)
898 root 1.39 buf.printf ("(sustenance%+d)", op->contr->digestion);
899    
900 root 1.4 if (op->contr->gen_grace)
901 root 1.39 buf.printf ("(grace%+d)", op->contr->gen_grace);
902    
903 root 1.4 if (op->contr->gen_sp)
904 root 1.39 buf.printf ("(magic%+d)", op->contr->gen_sp);
905    
906 root 1.4 if (op->contr->gen_hp)
907 root 1.39 buf.printf ("(regeneration%+d)", op->contr->gen_hp);
908    
909 root 1.4 if (op->stats.luck)
910 root 1.39 buf.printf ("(luck%+d)", op->stats.luck);
911 elmex 1.1 }
912 root 1.4
913     /* describe attacktypes */
914 root 1.69 if (op->is_dragon ())
915 root 1.4 {
916     /* for dragon players display the attacktypes from clawing skill
917     * Break apart the for loop - move the comparison checking down -
918     * this makes it more readable.
919     */
920     object *tmp;
921    
922 root 1.39 for (tmp = op->inv; tmp; tmp = tmp->below)
923     if (tmp->type == SKILL && tmp->name == shstr_clawing)
924 root 1.4 break;
925    
926 root 1.39 if (tmp && tmp->attacktype)
927     buf.add_abilities ("Claws", tmp->attacktype);
928 root 1.4 else
929 root 1.39 buf.add_abilities ("Attacks", op->attacktype);
930 elmex 1.1 }
931 root 1.4 else
932 root 1.39 buf.add_abilities ("Attacks", op->attacktype);
933 root 1.21
934 root 1.39 buf.add_paths ("Attuned" , op->path_attuned);
935     buf.add_paths ("Repelled", op->path_repelled);
936     buf.add_paths ("Denied" , op->path_denied);
937 root 1.22
938 root 1.39 for (int i = 0; i < NROFATTACKS; i++)
939 root 1.22 if (op->resist[i])
940 root 1.39 buf.printf ("(%s %+d)", resist_plus[i], op->resist[i]);
941 root 1.22
942 root 1.39 return buf;
943 elmex 1.1 }
944    
945     /*
946     * Returns a pointer to a static buffer which contains a
947     * description of the given object.
948     * If it is a monster, lots of information about its abilities
949     * will be returned.
950     * If it is an item, lots of information about which abilities
951     * will be gained about its user will be returned.
952     * If it is a player, it writes out the current abilities
953     * of the player, which is usually gained by the items applied.
954     * It would be really handy to actually pass another object
955     * pointer on who is examining this object. Then, you could reveal
956     * certain information depending on what the examiner knows, eg,
957     * wouldn't need to use the SEE_INVISIBLE flag to know it is
958     * a dragon player examining food. Could have things like
959     * a dwarven axe, in which the full abilities are only known to
960     * dwarves, etc.
961     *
962     * Add 'owner' who is the person examining this object.
963     * owner can be null if no one is being associated with this
964     * item (eg, debug dump or the like)
965     */
966 root 1.25 const char *
967 root 1.4 describe_item (const object *op, object *owner)
968     {
969 root 1.83 if (op->flag [FLAG_MONSTER] || op->type == PLAYER)
970 root 1.39 return describe_monster (op);
971    
972     static dynbuf_text buf; buf.clear ();
973 root 1.4 int identified, i;
974    
975     /* figure this out once, instead of making multiple calls to need_identify.
976     * also makes the code easier to read.
977     */
978 root 1.84 identified = !op->need_identify () || op->flag [FLAG_IDENTIFIED];
979 root 1.39 if (!identified)
980     buf << "(unidentified)";
981    
982 root 1.4 switch (op->type)
983     {
984 root 1.89 case RANGED:
985 root 1.39 case BOW:
986     case ARROW:
987     case WAND:
988     case ROD:
989     case HORN:
990     case WEAPON:
991     case ARMOUR:
992     case HELMET:
993     case SHIELD:
994     case BOOTS:
995     case GLOVES:
996     case GIRDLE:
997     case BRACERS:
998     case CLOAK:
999     case SKILL_TOOL:
1000     break; /* We have more information to do below this switch */
1001    
1002     case POWER_CRYSTAL:
1003     if (op->stats.maxsp > 1000)
1004     { /*higher capacity crystals */
1005     i = (op->stats.maxsp % 1000) / 100;
1006    
1007     if (i)
1008 root 1.78 buf.printf ("(capacity %d.%dk; it is ", op->stats.maxsp / 1000, i);
1009 root 1.39 else
1010 root 1.78 buf.printf ("(capacity %dk; it is ", op->stats.maxsp / 1000);
1011 root 1.39 }
1012     else
1013 root 1.78 buf.printf ("(capacity %d; it is ", op->stats.maxsp);
1014 root 1.39
1015     i = (op->stats.sp * 10) / op->stats.maxsp;
1016     if (op->stats.sp == 0)
1017 root 1.78 buf << "empty";
1018 root 1.39 else if (i == 0)
1019 root 1.78 buf << "almost empty";
1020 root 1.39 else if (i < 3)
1021 root 1.78 buf << "partially filled";
1022 root 1.39 else if (i < 6)
1023 root 1.78 buf << "half full";
1024 root 1.39 else if (i < 9)
1025 root 1.78 buf << "well charged";
1026 root 1.39 else if (op->stats.sp == op->stats.maxsp)
1027 root 1.78 buf << "fully charged";
1028 root 1.39 else
1029 root 1.78 buf << "almost full";
1030    
1031     buf << ')';
1032 root 1.39 break;
1033    
1034 elmex 1.54 case LAMP:
1035     {
1036     int percent = ((double) 100 / op->arch->stats.food) * op->stats.food;
1037     buf << "(fuel: ";
1038     if (percent == 0)
1039     buf << "empty";
1040     else if (percent < 10)
1041     buf << "very low";
1042     else if (percent < 25)
1043     buf << "low";
1044     else if (percent < 50)
1045     buf << "half empty";
1046     else if (percent < 75)
1047     buf << "half full";
1048     else if (percent < 95)
1049     buf << "well filled";
1050     else if (percent <= 100)
1051     buf << "full";
1052     buf << ")";
1053     }
1054     break;
1055    
1056 root 1.39 case FOOD:
1057     case FLESH:
1058     case DRINK:
1059 root 1.83 if (identified || op->flag [FLAG_BEEN_APPLIED])
1060 root 1.39 {
1061     buf.printf ("(food+%d)", op->stats.food);
1062    
1063     if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled (op->last_eat))
1064     buf.printf ("(%s metabolism)", change_resist_msg[op->last_eat]);
1065    
1066 root 1.83 if (!op->flag [FLAG_CURSED])
1067 root 1.39 {
1068     if (op->stats.hp) buf << "(heals)";
1069     if (op->stats.sp) buf << "(spellpoint regen)";
1070     }
1071     else
1072     {
1073     if (op->stats.hp) buf << "(damages)";
1074     if (op->stats.sp) buf << "(spellpoint depletion)";
1075     }
1076     }
1077     break;
1078    
1079     case SKILL:
1080     case RING:
1081     case AMULET:
1082     if (op->item_power)
1083     buf.printf ("(item_power %+d)", op->item_power);
1084 root 1.2
1085 root 1.39 if (op->title)
1086     buf << ring_desc (op);
1087 root 1.2
1088 root 1.39 return buf;
1089 elmex 1.1
1090 root 1.39 default:
1091     return buf;
1092 elmex 1.1 }
1093    
1094 root 1.4 /* Down here, we more further describe equipment type items.
1095     * only describe them if they have been identified or the like.
1096     */
1097 root 1.83 if (identified || op->flag [FLAG_BEEN_APPLIED])
1098 root 1.4 {
1099 root 1.89 for (int attr = 0; attr < NUM_STATS; attr++)
1100     if (int val = op->stats.stat (attr))
1101 root 1.39 buf.printf ("(%s%+d)", short_stat_name[attr], val);
1102 root 1.2
1103 root 1.4 if (op->stats.exp)
1104 root 1.39 buf.printf ("(speed %+lld)", (long long) op->stats.exp);
1105    
1106     switch (op->type)
1107 root 1.4 {
1108 root 1.89 case RANGED:
1109 root 1.39 case BOW:
1110     case ARROW:
1111     case GIRDLE:
1112     case HELMET:
1113     case SHIELD:
1114     case BOOTS:
1115     case GLOVES:
1116     case WEAPON:
1117     case SKILL:
1118     case RING:
1119     case AMULET:
1120     case ARMOUR:
1121     case BRACERS:
1122     case FORCE:
1123     case CLOAK:
1124     if (op->stats.wc) buf.printf ("(wc%+d)", op->stats.wc);
1125     if (op->stats.dam) buf.printf ("(dam%+d)", op->stats.dam);
1126     if (op->stats.ac) buf.printf ("(ac%+d)", op->stats.ac);
1127 root 1.2
1128 root 1.39 if ((op->type == WEAPON || op->type == BOW) && op->level > 0)
1129     buf.printf ("(improved %d/%d)", op->last_eat, op->level);
1130 root 1.2
1131 root 1.39 break;
1132 root 1.2
1133 root 1.39 default:
1134     break;
1135 root 1.2 }
1136 root 1.39
1137 root 1.83 if (op->flag [FLAG_XRAYS]) buf << "(xray-vision)";
1138     if (op->flag [FLAG_SEE_IN_DARK]) buf << "(infravision)";
1139 root 1.4
1140     /* levitate was what is was before, so we'll keep it */
1141 root 1.39 if (op->move_type & MOVE_FLY_LOW) buf << "(levitate)";
1142     if (op->move_type & MOVE_FLY_HIGH) buf << "(fly)";
1143     if (op->move_type & MOVE_SWIM) buf << "(swim)";
1144 root 1.4
1145     /* walking is presumed as 'normal', so doesn't need mentioning */
1146    
1147     if (op->item_power)
1148 root 1.39 buf.printf ("(item_power %+d)", op->item_power);
1149 root 1.4 } /* End if identified or applied */
1150    
1151     /* This blocks only deals with fully identified object.
1152     * it is intentional that this is not an 'else' from a above -
1153     * in this way, information is added.
1154     */
1155     if (identified)
1156     {
1157     int more_info = 0;
1158    
1159     switch (op->type)
1160     {
1161 root 1.89 case RANGED:
1162 root 1.39 case ROD: /* These use stats.sp for spell selection and stats.food */
1163     case HORN: /* and stats.hp for spell-point regeneration... */
1164     case BOW:
1165     case ARROW:
1166     case WAND:
1167     case FOOD:
1168     case FLESH:
1169     case DRINK:
1170     more_info = 0;
1171     break;
1172    
1173     /* Armor type objects */
1174     case ARMOUR:
1175     case HELMET:
1176     case SHIELD:
1177     case BOOTS:
1178     case GLOVES:
1179     case GIRDLE:
1180     case BRACERS:
1181     case CLOAK:
1182     if (ARMOUR_SPEED (op)) buf.printf ("(Max speed %1.2f)", ARMOUR_SPEED (op) / 10.0);
1183     if (ARMOUR_SPELLS (op)) buf.printf ("(Spell regen penalty %d)", ARMOUR_SPELLS (op));
1184     more_info = 1;
1185     break;
1186 root 1.4
1187 root 1.39 case WEAPON:
1188     /* Calculate it the same way fix_player does so the results
1189     * make sense.
1190     */
1191     i = (WEAPON_SPEED (op) * 2 - op->magic) / 2;
1192     if (i < 0)
1193     i = 0;
1194    
1195     buf.printf ("(weapon speed %d)", i);
1196     more_info = 1;
1197     break;
1198 root 1.4 }
1199 root 1.39
1200 root 1.4 if (more_info)
1201     {
1202 root 1.39 if (op->stats.food) buf.printf ("(sustenance%+d)", op->stats.food);
1203     if (op->stats.grace) buf.printf ("(grace%+d)", op->stats.grace);
1204     if (op->stats.sp) buf.printf ("(magic%+d)", op->stats.sp);
1205     if (op->stats.hp) buf.printf ("(regeneration%+d)", op->stats.hp);
1206 root 1.2 }
1207    
1208 root 1.4 if (op->stats.luck)
1209 root 1.39 buf.printf ("(luck%+d)", op->stats.luck);
1210    
1211 root 1.83 if (op->flag [FLAG_LIFESAVE]) buf << "(lifesaving)";
1212     if (op->flag [FLAG_REFL_SPELL]) buf << "(reflect spells)";
1213     if (op->flag [FLAG_REFL_MISSILE]) buf << "(reflect missiles)";
1214     if (op->flag [FLAG_STEALTH]) buf << "(stealth)";
1215 root 1.39
1216     if (op->slaying && op->type != FOOD)
1217     buf.printf ("(slay %s)", &op->slaying);
1218    
1219 root 1.57 if (op->type == SKILL_TOOL && op->skill)
1220     buf.printf ("(%s)", &op->skill);
1221 sf-marcmagus 1.56
1222 root 1.39 buf.add_abilities ("Attacks", op->attacktype);
1223 root 1.4 /* resistance on flesh is only visible for quetzals. If
1224     * non flesh, everyone can see its resistances
1225     */
1226 root 1.69 if (op->type != FLESH || (owner && owner->is_dragon ()))
1227 root 1.39 buf << describe_resistance (op, 0);
1228    
1229     buf.add_paths ("Attuned", op->path_attuned);
1230     buf.add_paths ("Repelled", op->path_repelled);
1231     buf.add_paths ("Denied", op->path_denied);
1232 elmex 1.1 }
1233    
1234 root 1.39 return buf;
1235 elmex 1.1 }
1236    
1237 root 1.26 std::string
1238     object::describe_item (object *who)
1239     {
1240     return std::string (::describe_item (this, who));
1241     }
1242    
1243 root 1.79 static void
1244     describe_dump_object (dynbuf &buf, object *ob)
1245     {
1246     char *txt = dump_object (ob);
1247     for (char *p = txt; *p; ++p) if (*p == '\n') *p = '\r';
1248     buf << "\n" << txt << "\n";
1249    
1250     if (!ob->is_arch ())
1251     describe_dump_object (buf, ob->arch);
1252     }
1253    
1254     std::string
1255     object::describe (object *who)
1256     {
1257     dynbuf_text buf (1024, 1024);
1258    
1259     buf.printf ("That is: %s.\r", long_desc (who).c_str ());
1260    
1261     if (custom_name)
1262     buf.printf ("You call it %s.\r", &custom_name);
1263    
1264     switch (type)
1265     {
1266     case SPELLBOOK:
1267     if (flag [FLAG_IDENTIFIED] && inv)
1268 root 1.81 buf.printf ("%s is a %s level %s spell.\r", &inv->name, ordinal (inv->level), &inv->skill);
1269 root 1.79 break;
1270    
1271     case BOOK:
1272     if (msg)
1273     buf << "Something is written in it.\r";
1274     break;
1275    
1276     case CONTAINER:
1277     if (race)
1278     {
1279     if (weight_limit && stats.Str < 100)
1280     buf.printf ("It can hold only %s and its weight limit is %.1f kg.\r",
1281     &race, weight_limit / (10.0 * (100 - stats.Str)));
1282     else
1283     buf.printf ("It can hold only %s.\r", &race);
1284     }
1285     else if (weight_limit && stats.Str < 100)
1286     buf.printf ("Its weight limit is %.1f kg.\r", weight_limit / (10.0 * (100 - stats.Str)));
1287     break;
1288    
1289     case WAND:
1290     if (flag [FLAG_IDENTIFIED])
1291     buf.printf ("It has %d %s left.\r", stats.food, stats.food == 1 ? "charge" : "charges");
1292     break;
1293     }
1294    
1295     if (material != MATERIAL_NULL && !msg)
1296     buf << (nrof > 1 ? "They are made of " : "It is made of ")
1297     << material->description
1298     << ".\r";
1299    
1300     if (who)
1301     /* Where to wear this item */
1302     for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1303     if (slot[i].info)
1304     {
1305     buf << (who->slot[i].info ? body_locations[i].use_name : body_locations[i].nonuse_name);
1306    
1307     if (slot[i].info < -1 && who->slot[i].info)
1308     buf.printf ("(%d)", -slot[i].info);
1309    
1310     buf << ".\r";
1311     }
1312    
1313     if (weight)
1314     buf.printf ("%s %3.3f kg.\r", nrof > 1 ? "They weigh" : "It weighs", weight * (nrof ? nrof : 1) / 1000.0);
1315    
1316     if (flag [FLAG_STARTEQUIP])
1317     buf << (nrof > 1 ? "They were" : "It was")
1318     << " given by a god and will vanish when dropped.\r";
1319    
1320     if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1321     {
1322     buf.printf ("You reckon %s worth %s.\r", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1323    
1324     if (who->is_in_shop ())
1325     {
1326     if (flag [FLAG_UNPAID])
1327     buf.printf ("%s would cost you %s.\r", nrof > 1 ? "They" : "It", query_cost_string (this, who, F_BUY | F_SHOP));
1328     else
1329     buf.printf ("You are offered %s for %s.\r", query_cost_string (this, who, F_SELL + F_SHOP), nrof > 1 ? "them" : "it");
1330     }
1331     }
1332    
1333     if (flag [FLAG_MONSTER])
1334     buf << describe_monster (who);
1335    
1336     /* Is this item buildable? */
1337     if (flag [FLAG_IS_BUILDABLE])
1338     buf << "This is a buildable item.\r";
1339    
1340     /* Does the object have a message? Don't show message for all object
1341     * types - especially if the first entry is a match
1342     */
1343     if (msg)
1344     {
1345     if (type != EXIT && type != BOOK && type != CORPSE && !move_on && !has_dialogue ())
1346     {
1347 root 1.84 if (!need_identify ())
1348     buf << '\r' << msg << '\n';
1349     else if (flag [FLAG_IDENTIFIED])
1350     buf << '\r' << "The object has a story:\r" << msg;
1351 root 1.79 }
1352     }
1353 root 1.84 else if (inv
1354     && inv->msg
1355     && inv->type == SPELL
1356     && flag [FLAG_IDENTIFIED]
1357 root 1.79 && (type == SPELLBOOK || type == ROD || type == WAND
1358     || type == ROD || type == POTION || type == SCROLL))
1359     // for spellbooks and other stuff that contains spells, print the spell message,
1360     // unless the object has a custom message handled above.
1361     buf << '\r' << inv->msg << '\n';
1362    
1363     // try to display the duration for some potions and scrolls
1364     // this includes change ability potions and group spells,
1365     // but does not handle protection potions
1366     if (inv && inv->type == SPELL && flag [FLAG_IDENTIFIED]
1367     && (type == POTION || type == SCROLL))
1368     {
1369     object *spell = inv;
1370    
1371     if (spell->subtype == SP_PARTY_SPELL)
1372     spell = spell->other_arch;
1373    
1374     if (spell->subtype == SP_CHANGE_ABILITY)
1375     buf.printf ("\nH<The effect will last about %.10g seconds.>",
1376     TICK2TIME (change_ability_duration (spell, this)));
1377     }
1378    
1379 root 1.80 // some help text for skill tools
1380     if (type == SKILL_TOOL)
1381     buf << "\nH<This item is a skill tool: as long as you have this item applied "
1382     "you can use the " << &skill << " skill as if you had learned it.>";
1383    
1384 root 1.79 // Display a hint about inscribable items [empty books]
1385     // This includes the amount of text they can hold.
1386     if (type == INSCRIBABLE)
1387     {
1388     if (other_arch && other_arch->type == SCROLL)
1389     buf.printf ("\nH<You can use the inscription skill to inscribe a spell into it.>");
1390     else
1391     buf.printf ("\nH<You can use the inscription skill to inscribe text into it. It has room for up to %d characters.>",
1392     weight_limit);
1393     }
1394    
1395     buf << '\n';
1396    
1397     // the dungeon master additionally gets a complete dump
1398     if (who && who->flag [FLAG_WIZLOOK])
1399     {
1400     buf << "\nT<Object>\n";
1401     describe_dump_object (buf, this);
1402    
1403     if (inv)
1404     {
1405     buf << "\nT<Top Inventory>\n";
1406     describe_dump_object (buf, inv);
1407     }
1408     }
1409    
1410     return std::string (buf.linearise (), buf.size ());
1411     }
1412    
1413 root 1.40 void
1414     examine (object *op, object *tmp)
1415     {
1416 root 1.45 std::string info = tmp->describe (op);
1417 root 1.55
1418 root 1.45 op->contr->infobox (MSG_CHANNEL ("examine"), info.c_str ());
1419 root 1.40 }
1420    
1421     /*
1422     * inventory prints object's inventory. If inv==NULL then print player's
1423     * inventory.
1424     * [ Only items which are applied are showed. Tero.Haatanen@lut.fi ]
1425     */
1426     const char *
1427     object::query_inventory (object *who, const char *indent)
1428     {
1429     static dynbuf_text buf; buf.clear ();
1430    
1431     for (object *tmp = inv; tmp; tmp = tmp->below)
1432 root 1.83 if (who && who->flag [FLAG_WIZ])
1433 elmex 1.70 buf.printf ("%s- %-28.28s %-8s (%9d) %s\n", indent, tmp->query_name (), tmp->query_weight (), tmp->count, tmp->uuid.c_str ());
1434 root 1.83 else if (!tmp->invisible && (type == CONTAINER || tmp->flag [FLAG_APPLIED]))
1435 root 1.53 buf.printf ("%s- %-36.36s %-8s\n", indent, tmp->query_name (), tmp->query_weight ());
1436 root 1.40
1437     if (buf.size ())
1438 root 1.53 buf.printf ("%s(total weight: %s)\n", indent, query_weight ());
1439 root 1.40 else
1440     buf.printf ("%s(empty)\n", indent);
1441    
1442     return buf;
1443     }
1444    
1445 elmex 1.1 /* Return true if the item is magical. A magical item is one that
1446     * increases/decreases any abilities, provides a resistance,
1447     * has a generic magical bonus, or is an artifact.
1448     * This function is used by detect_magic to determine if an item
1449     * should be marked as magical.
1450     */
1451 root 1.4 int
1452     is_magical (const object *op)
1453     {
1454     int i;
1455 elmex 1.1
1456 root 1.4 /* living creatures are considered non magical */
1457 root 1.83 if (op->flag [FLAG_ALIVE])
1458 root 1.4 return 0;
1459 elmex 1.1
1460 root 1.4 /* This is a test for it being an artifact, as artifacts have titles */
1461     if (op->title != NULL)
1462     return 1;
1463    
1464     /* Handle rings and amulets specially. If they change any of these
1465     * values, it means they are magical.
1466     */
1467     if ((op->type == AMULET || op->type == RING) &&
1468     (op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam || op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
1469     return 1;
1470    
1471     /* Check for stealty, speed, flying, or just plain magic in the boots */
1472     /* Presume any boots that hvae a move_type are special. */
1473 root 1.83 if (op->type == BOOTS && ((op->flag [FLAG_STEALTH] || op->move_type || op->stats.exp)))
1474 root 1.4 return 1;
1475    
1476     /* Take care of amulet/shield that reflects spells/missiles */
1477 root 1.83 if ((op->type == AMULET || op->type == SHIELD) && (op->flag [FLAG_REFL_SPELL] || op->flag [FLAG_REFL_MISSILE]))
1478 root 1.4 return 1;
1479    
1480     /* Take care of helmet of xrays */
1481 root 1.83 if (op->type == HELMET && op->flag [FLAG_XRAYS])
1482 root 1.4 return 1;
1483    
1484     /* Potions & rods are always magical. Wands/staves are also magical,
1485     * assuming they still have any charges left.
1486     */
1487     if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
1488     return 1;
1489    
1490     /* if something gives a protection, either positive or negative, its magical */
1491     /* This is really a pretty bad hack - as of now, ATNR_PHYSICAL is 0,
1492     * so this always works out fine.
1493     */
1494     for (i = ATNR_PHYSICAL + 1; i < NROFATTACKS; i++)
1495     if (op->resist[i])
1496     return 1;
1497    
1498     /* Physical protection is expected on some item types, so they should
1499     * not be considered magical.
1500     */
1501     if (op->resist[ATNR_PHYSICAL] && op->type != HELMET && op->type != SHIELD &&
1502     op->type != BOOTS && op->type != GLOVES && op->type != ARMOUR)
1503     return 1;
1504    
1505     /* power crystal, spellbooks, and scrolls are always magical. */
1506     if (op->magic || op->type == POWER_CRYSTAL || op->type == SPELLBOOK || op->type == SCROLL || op->type == GIRDLE)
1507     return 1;
1508    
1509     /* Check to see if it increases/decreases any stats */
1510     for (i = 0; i < NUM_STATS; i++)
1511 root 1.33 if (op->stats.stat (i))
1512 root 1.4 return 1;
1513    
1514     /* If it doesn't fall into any of the above categories, must
1515     * be non magical.
1516     */
1517     return 0;
1518 elmex 1.1 }
1519    
1520     /*
1521     * Supposed to fix face-values as well here, but later.
1522     */
1523 root 1.4 void
1524     identify (object *op)
1525     {
1526 root 1.83 op->set_flag (FLAG_IDENTIFIED);
1527     op->clr_flag (FLAG_KNOWN_MAGICAL);
1528     op->clr_flag (FLAG_NO_SKILL_IDENT);
1529 root 1.4
1530     /*
1531     * We want autojoining of equal objects:
1532     */
1533 root 1.83 if (op->flag [FLAG_CURSED] || op->flag [FLAG_DAMNED])
1534     op->set_flag (FLAG_KNOWN_CURSED);
1535 root 1.4
1536     if (op->type == POTION)
1537     {
1538     if (op->inv && op->randomitems)
1539     op->title = op->inv->name;
1540     else if (op->arch)
1541     {
1542 root 1.48 op->name = op->arch->object::name;
1543 root 1.37 op->name_pl = op->arch->object::name_pl;
1544 root 1.4 }
1545 elmex 1.1 }
1546    
1547 root 1.4 /* If the object is on a map, make sure we update its face */
1548     if (op->map)
1549 root 1.24 update_object (op, UP_OBJ_CHANGE);
1550 root 1.50
1551     if (object *pl = op->visible_to ())
1552 root 1.48 /* A lot of the values can change from an update - might as well send
1553     * it all.
1554     */
1555     esrv_send_item (pl, op);
1556 elmex 1.1 }
1557 root 1.9