ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.99
Committed: Sun Jan 29 02:47:04 2017 UTC (7 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.98: +8 -8 lines
Log Message:
remove eol whitespace

File Contents

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