ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.13
Committed: Wed Dec 20 13:07:12 2006 UTC (17 years, 5 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.12: +0 -3 lines
Log Message:
removed LIGHT_SOURCE, MONSTER and SPAWN_GENERATOR types.

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