ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.6
Committed: Thu Sep 14 22:33:58 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.5: +1 -7 lines
Log Message:
indent

File Contents

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