ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.24
Committed: Wed Mar 14 04:12:27 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.23: +1 -1 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

File Contents

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