ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/item.C
Revision: 1.38
Committed: Sun Jul 1 05:00:17 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.37: +11 -12 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

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