ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.84
Committed: Thu Apr 15 02:51:39 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.83: +60 -67 lines
Log Message:
better need_identify

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