ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.17
Committed: Wed Jan 3 02:30:51 2007 UTC (17 years, 4 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.16: +1 -1 lines
Log Message:
implemented proper support for empty treasures, which
sadly occur in empty treasure lists. fixing treasurelists
to have no entries at all would be even more complicated,
but even when this is fixed, the current changes only make the
server more crash robust to bad treasures.
Also removed the 'NONE' specialcase for treasure lists. Developers
should use 'none' instead now.

File Contents

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