ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.82
Committed: Tue Apr 6 04:24:29 2010 UTC (14 years, 1 month ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.81: +1 -1 lines
Log Message:
*** empty log message ***

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