00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00037 #include <stdio.h>
00038 #include <global.h>
00039 #include <living.h>
00040 #include <spells.h>
00041
00064 body_locations_struct body_locations[NUM_BODY_LOCATIONS] = {
00065 { "body_range", "in your range slot", "in a human's range slot" },
00066 { "body_arm", "on your arm", "on a human's arm" },
00067 { "body_torso", "on your body", "on a human's torso" },
00068 { "body_head", "on your head", "on a human's head" },
00069 { "body_neck", "around your neck", "around a humans neck" },
00070 { "body_skill", "in your skill slot", "in a human's skill slot" },
00071 { "body_finger", "on your finger", "on a human's finger" },
00072 { "body_shoulder", "around your shoulders", "around a human's shoulders" },
00073 { "body_foot", "on your feet", "on a human's feet" },
00074 { "body_hand", "on your hands", "on a human's hands" },
00075 { "body_wrist", "around your wrists", "around a human's wrist" },
00076 { "body_waist", "around your waist", "around a human's waist" },
00077 { "body_leg", "around your legs", "around a human's legs" },
00078
00079
00080 };
00081
00083 static const char numbers_10[10][20] = {
00084 "zero", "ten", "twenty", "thirty", "fourty", "fifty", "sixty", "seventy",
00085 "eighty", "ninety"
00086 };
00087
00089 static const char levelnumbers[21][20] = {
00090 "zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh",
00091 "eighth", "ninth", "tenth", "eleventh", "twelfth", "thirteenth",
00092 "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteen",
00093 "nineteen", "twentieth"
00094 };
00095
00097 static const char levelnumbers_10[11][20] = {
00098 "zeroth", "tenth", "twentieth", "thirtieth", "fortieth", "fiftieth", "sixtieth",
00099 "seventieth", "eightieth", "ninetieth"
00100 };
00101
00109 static const typedata item_types[] = {
00110 { PLAYER, "player", "players", 0, 0 },
00111 { ROD, "rod", "rods", SK_THAUMATURGY, 0 },
00112 { TREASURE, "treasure", "treasure", 0, 0 },
00113 { POTION, "potion", "potions", SK_ALCHEMY, 0 },
00114 { FOOD, "food", "food", SK_WOODSMAN, 0 },
00115 { POISON, "poison", "poisons", SK_ALCHEMY, 0 },
00116 { BOOK, "book", "books", SK_LITERACY, 0 },
00117 { CLOCK, "clock", "clocks", 0, 0 },
00118 { ARROW, "arrow", "arrows", SK_BOWYER, 0 },
00119 { BOW, "bow", "bows", SK_BOWYER, 0 },
00120 { WEAPON, "weapon", "weapons", SK_SMITHERY, 0 },
00121 { ARMOUR, "armour", "armour", SK_SMITHERY, 0 },
00122 { PEDESTAL, "pedestal", "pedestals", 0, 0 },
00123 { ALTAR, "altar", "altars", 0, 0 },
00124 { LOCKED_DOOR, "locked door", "locked doors", 0, 0 },
00125 { SPECIAL_KEY, "special key", "special keys", 0, 0 },
00126 { MAP, "map", "maps", 0, 0 },
00127 { DOOR, "door", "doors", 0, 0 },
00128 { KEY, "key", "keys", 0, 0 },
00129 { TIMED_GATE, "timed_gate", "timed_gates", 0, 0 },
00130 { TRIGGER, "trigger", "triggers", 0, 0 },
00131 { GRIMREAPER, "grimreaper", "grimreapers", 0, 0 },
00132 { MAGIC_EAR, "magic ear", "magic ears", 0, 0 },
00133 { TRIGGER_BUTTON, "trigger button", "trigger buttons", 0, 0 },
00134 { TRIGGER_ALTAR, "trigger altar", "trigger altars", 0, 0 },
00135 { TRIGGER_PEDESTAL, "trigger pedestal", "trigger pedestals", 0, 0 },
00136 { SHIELD, "shield", "shields", SK_SMITHERY, 0 },
00137 { HELMET, "helmet", "helmets", SK_SMITHERY, 0 },
00138 { HORN, "horn", "horns", SK_THAUMATURGY, 0 },
00139 { MONEY, "money", "money", 0, 0 },
00140 { CLASS, "class", "classes", 0, 0 },
00141 { AMULET, "amulet", "amulets", SK_JEWELER, 0 },
00142 { PLAYERMOVER, "player mover", "player movers", 0, 0 },
00143 { TELEPORTER, "teleporter", "teleporters", 0, 0 },
00144 { CREATOR, "creator", "creators", 0, 0 },
00145 { SKILL, "skill", "skills", 0, 0 },
00146 { EXPERIENCE, "experience", "experience", 0, 0 },
00147 { EARTHWALL, "earthwall", "earthwalls", 0, 0 },
00148 { GOLEM, "golem", "golems", 0, 0 },
00149 { THROWN_OBJ, "projectile", "projectiles", 0, 0 },
00150 { BLINDNESS, "blindness", "blindness", 0, 0 },
00151 { GOD, "god", "gods", 0, 0 },
00152 { DETECTOR, "detector", "detectors", 0, 0 },
00153 { TRIGGER_MARKER, "trigger marker", "trigger markers", 0, 0 },
00154 { DEAD_OBJECT, "dead object", "dead objects", 0, 0 },
00155 { DRINK, "drink", "drinks", SK_WOODSMAN, SK_ALCHEMY },
00156 { MARKER, "marker", "markers", 0, 0 },
00157 { HOLY_ALTAR, "holy altar", "holy altars", 0, 0 },
00158 { PLAYER_CHANGER, "player changer", "player changers", 0, 0 },
00159 { BATTLEGROUND, "battleground", "battlegrounds", 0, 0 },
00160 { PEACEMAKER, "peacemaker", "peacemakers", 0, 0 },
00161 { GEM, "gem", "gems", SK_JEWELER, 0 },
00162 { FIREWALL, "firewall", "firewalls", 0, 0 },
00163 { CHECK_INV, "inventory checker", "inventory checkers", 0, 0 },
00164 { MOOD_FLOOR, "mood floor", "mood floors", 0, 0 },
00165 { EXIT, "exit", "exits", 0, 0 },
00166 { ENCOUNTER, "encounter", "encounters", 0, 0 },
00167 { SHOP_FLOOR, "shop floor", "shop floors", 0, 0 },
00168 { SHOP_MAT, "shop mat", "shop mats", 0, 0 },
00169 { RING, "ring", "rings", SK_JEWELER, 0 },
00170 { FLOOR, "floor", "floors", 0, 0 },
00171 { FLESH, "flesh", "flesh", SK_WOODSMAN, 0 },
00172 { INORGANIC, "inorganic", "inorganics", SK_ALCHEMY, 0 },
00173 { SKILL_TOOL, "skill tool", "skill tools", 0, 0 },
00174 { LIGHTER, "lighter", "lighters", 0, 0 },
00175 { WALL, "wall", "walls", 0, 0 },
00176 { MISC_OBJECT, "bric-a-brac", "bric-a-brac", 0, 0 },
00177 { MONSTER, "monster", "monsters", 0, 0 },
00178 { LAMP, "lamp", "lamps", 0, 0 },
00179 { DUPLICATOR, "duplicator", "duplicators", 0, 0 },
00180 { SPELLBOOK, "spellbook", "spellbooks", SK_LITERACY, 0 },
00181 { CLOAK, "cloak", "cloaks", SK_SMITHERY, 0 },
00182 { SPINNER, "spinner", "spinners", 0, 0 },
00183 { GATE, "gate", "gates", 0, 0 },
00184 { BUTTON, "button", "buttons", 0, 0 },
00185 { CF_HANDLE, "cf handle", "cf handles", 0, 0 },
00186 { HOLE, "hole", "holes", 0, 0 },
00187 { TRAPDOOR, "trapdoor", "trapdoors", 0, 0 },
00188 { SIGN, "sign", "signs", 0, 0 },
00189 { BOOTS, "boots", "boots", SK_SMITHERY, 0 },
00190 { GLOVES, "gloves", "gloves", SK_SMITHERY, 0 },
00191 { SPELL, "spell", "spells", 0, 0 },
00192 { SPELL_EFFECT, "spell effect", "spell effects", 0, 0 },
00193 { CONVERTER, "converter", "converters", 0, 0 },
00194 { BRACERS, "bracers", "bracers", SK_SMITHERY, 0 },
00195 { POISONING, "poisoning", "poisonings", 0, 0 },
00196 { SAVEBED, "savebed", "savebeds", 0, 0 },
00197 { WAND, "wand", "wands", SK_THAUMATURGY, 0 },
00198 { SCROLL, "scroll", "scrolls", SK_LITERACY, 0 },
00199 { DIRECTOR, "director", "directors", 0, 0 },
00200 { GIRDLE, "girdle", "girdles", SK_SMITHERY, 0 },
00201 { FORCE, "force", "forces", 0, 0 },
00202 { POTION_EFFECT, "potion effect", "potion effects", 0, 0 },
00203 { CLOSE_CON, "closed container", "closed container", 0, 0 },
00204 { CONTAINER, "container", "containers", SK_ALCHEMY, 0 },
00205 { ARMOUR_IMPROVER, "armour improver", "armour improvers", 0, 0 },
00206 { WEAPON_IMPROVER, "weapon improver", "weapon improvers", 0, 0 },
00207 { SKILLSCROLL, "skillscroll", "skillscrolls", 0, 0 },
00208 { DEEP_SWAMP, "deep swamp", "deep swamps", 0, 0 },
00209 { IDENTIFY_ALTAR, "identify altar", "identify altars", 0, 0 },
00210 { SHOP_INVENTORY, "inventory list", "inventory lists", 0, 0 },
00211 { RUNE, "rune", "runes", 0, 0 },
00212 { TRAP, "trap", "traps", 0, 0 },
00213 { POWER_CRYSTAL, "power_crystal", "power_crystals", 0, 0 },
00214 { CORPSE, "corpse", "corpses", 0, 0 },
00215 { DISEASE, "disease", "diseases", 0, 0 },
00216 { SYMPTOM, "symptom", "symptoms", 0, 0 },
00217 { BUILDER, "item builder", "item builders", 0, 0 },
00218 { MATERIAL, "building material", "building materials", 0, 0 },
00219 };
00220
00222 static const int item_types_size = sizeof(item_types)/sizeof(*item_types);
00223
00233 static const int enc_to_item_power[21] = {
00234 0, 0, 1, 2, 3, 4,
00235 5, 7, 9, 11, 13,
00236 15, 18, 21, 24, 27,
00237 30, 35, 40, 45, 50
00238 };
00239
00240 int get_power_from_ench(int ench) {
00241 if (ench < 0)
00242 ench = 0;
00243 if (ench > 20)
00244 ench = 20;
00245 return enc_to_item_power[ench];
00246 }
00247
00264 int calc_item_power(const object *op, int flag) {
00265 int i, tmp, enc;
00266
00267 enc = 0;
00268 for (i = 0; i < NUM_STATS; i++)
00269 enc += get_attr_value(&op->stats, i);
00270
00271
00272
00273
00274
00275
00276 tmp = 0;
00277 for (i = 1; i < NROFATTACKS; i++)
00278 tmp += op->resist[i];
00279
00280
00281 if (tmp > 0)
00282 enc += (tmp+10)/20;
00283 else if (tmp < 0)
00284 enc += (tmp-10)/20;
00285
00286 enc += op->magic;
00287
00288
00289
00290
00291 if (op->type == WEAPON) {
00292 for (i = 1; i < NROFATTACKS; i++)
00293 if (op->attacktype&(1<<i))
00294 enc++;
00295 if (op->slaying)
00296 enc += 2;
00297 }
00298
00299 if ((op->type == WEAPON)
00300 || (op->type == ARMOUR)
00301 || (op->type == HELMET)
00302 || (op->type == SHIELD)
00303 || (op->type == RING)
00304 || (op->type == BOOTS)
00305 || (op->type == GLOVES)
00306 || (op->type == AMULET)
00307 || (op->type == GIRDLE)
00308 || (op->type == BRACERS)
00309 || (op->type == CLOAK)) {
00310 enc += op->stats.food;
00311 enc += op->stats.hp;
00312 enc += op->stats.sp;
00313 enc += op->stats.grace;
00314 enc += op->stats.exp;
00315 }
00316 enc += op->stats.luck;
00317
00318
00319 for (i = 1; i < NRSPELLPATHS; i++) {
00320 if (op->path_attuned&(1<<i))
00321 enc++;
00322 else if (op->path_denied&(1<<i))
00323 enc -= 2;
00324 else if (op->path_repelled&(1<<i))
00325 enc--;
00326 }
00327
00328 if (QUERY_FLAG(op, FLAG_LIFESAVE))
00329 enc += 5;
00330 if (QUERY_FLAG(op, FLAG_REFL_SPELL))
00331 enc += 3;
00332 if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
00333 enc += 2;
00334 if (QUERY_FLAG(op, FLAG_STEALTH))
00335 enc += 1;
00336 if (QUERY_FLAG(op, FLAG_XRAYS))
00337 enc += 2;
00338 if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
00339 enc += 1;
00340 if (QUERY_FLAG(op, FLAG_MAKE_INVIS))
00341 enc += 1;
00342
00343 return get_power_from_ench(enc);
00344 }
00345
00352 const typedata *get_typedata(int itemtype) {
00353 int i;
00354
00355 for (i = 0; i < item_types_size; i++)
00356 if (item_types[i].number == itemtype)
00357 return &item_types[i];
00358 return NULL;
00359 }
00360
00372 const typedata *get_typedata_by_name(const char *name) {
00373 int i;
00374
00375 for (i = 0; i < item_types_size; i++)
00376 if (!strcmp(item_types[i].name, name))
00377 return &item_types[i];
00378 for (i = 0; i < item_types_size; i++)
00379 if (!strcmp(item_types[i].name_pl, name)) {
00380 LOG(llevInfo, "get_typedata_by_name: I have been sent the plural %s, the singular form %s is preffered\n", name, item_types[i].name);
00381 return &item_types[i];
00382 }
00383 return NULL;
00384 }
00385
00399 void describe_resistance(const object *op, int newline, char *buf, size_t size) {
00400 char *p;
00401 int tmpvar;
00402
00403 p = buf;
00404 for (tmpvar = 0; tmpvar < NROFATTACKS; tmpvar++) {
00405 if (op->resist[tmpvar] && (op->type != FLESH || atnr_is_dragon_enabled(tmpvar) == 1)) {
00406 if (!newline)
00407 snprintf(p, buf+size-p, "(%s %+d)", resist_plus[tmpvar], op->resist[tmpvar]);
00408 else
00409 snprintf(p, buf+size-p, "%s %d\n", resist_plus[tmpvar], op->resist[tmpvar]);
00410 p = strchr(p, '\0');
00411 }
00412 }
00413 }
00414
00424 void query_weight(const object *op, char *buf, size_t size) {
00425 sint32 i = (op->nrof ? op->nrof : 1)*op->weight+op->carrying;
00426
00427 if (op->weight < 0)
00428 snprintf(buf, size, " ");
00429 else if (i%1000)
00430 snprintf(buf, size, "%6.1f", i/1000.0);
00431 else
00432 snprintf(buf, size, "%4d ", i/1000);
00433 }
00434
00444 void get_levelnumber(int i, char *buf, size_t size) {
00445 if (i > 99 || i < 0) {
00446 snprintf(buf, size, "%d.", i);
00447 return;
00448 }
00449 if (i < 21) {
00450 snprintf(buf, size, "%s", levelnumbers[i]);
00451 return;
00452 }
00453 if (!(i%10)) {
00454 snprintf(buf, size, "%s", levelnumbers_10[i/10]);
00455 return;
00456 }
00457 snprintf(buf, size, "%s%s", numbers_10[i/10], levelnumbers[i%10]);
00458 return;
00459 }
00460
00483 static void ring_desc(const object *op, char *buf, size_t size) {
00484 int attr, val;
00485 size_t len;
00486
00487 buf[0] = 0;
00488
00489 if (!QUERY_FLAG(op, FLAG_IDENTIFIED))
00490 return;
00491
00492 for (attr = 0; attr < NUM_STATS; attr++) {
00493 if ((val = get_attr_value(&(op->stats), attr)) != 0) {
00494 snprintf(buf+strlen(buf), size-strlen(buf), "(%s%+d)", short_stat_name[attr], val);
00495 }
00496 }
00497 if (op->stats.exp)
00498 snprintf(buf+strlen(buf), size-strlen(buf), "(speed %+"FMT64")", op->stats.exp);
00499 if (op->stats.wc)
00500 snprintf(buf+strlen(buf), size-strlen(buf), "(wc%+d)", op->stats.wc);
00501 if (op->stats.dam)
00502 snprintf(buf+strlen(buf), size-strlen(buf), "(dam%+d)", op->stats.dam);
00503 if (op->stats.ac)
00504 snprintf(buf+strlen(buf), size-strlen(buf), "(ac%+d)", op->stats.ac);
00505
00506 describe_resistance(op, 0, buf+strlen(buf), size-strlen(buf));
00507
00508 if (op->stats.food != 0)
00509 snprintf(buf+strlen(buf), size-strlen(buf), "(sustenance%+d)", op->stats.food);
00510
00511
00512 if (op->stats.grace)
00513 snprintf(buf+strlen(buf), size-strlen(buf), "(grace%+d)", op->stats.grace);
00514 if (op->stats.sp && op->type != SKILL)
00515 snprintf(buf+strlen(buf), size-strlen(buf), "(magic%+d)", op->stats.sp);
00516 if (op->stats.hp)
00517 snprintf(buf+strlen(buf), size-strlen(buf), "(regeneration%+d)", op->stats.hp);
00518 if (op->stats.luck)
00519 snprintf(buf+strlen(buf), size-strlen(buf), "(luck%+d)", op->stats.luck);
00520 if (QUERY_FLAG(op, FLAG_LIFESAVE))
00521 snprintf(buf+strlen(buf), size-strlen(buf), "(lifesaving)");
00522 if (QUERY_FLAG(op, FLAG_REFL_SPELL))
00523 snprintf(buf+strlen(buf), size-strlen(buf), "(reflect spells)");
00524 if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
00525 snprintf(buf+strlen(buf), size-strlen(buf), "(reflect missiles)");
00526 if (QUERY_FLAG(op, FLAG_STEALTH))
00527 snprintf(buf+strlen(buf), size-strlen(buf), "(stealth)");
00528
00529 len = strlen(buf);
00530 DESCRIBE_PATH_SAFE(buf, op->path_attuned, "Attuned", &len, size);
00531 DESCRIBE_PATH_SAFE(buf, op->path_repelled, "Repelled", &len, size);
00532 DESCRIBE_PATH_SAFE(buf, op->path_denied, "Denied", &len, size);
00533
00534
00535
00536 if (buf[0] == 0 && op->type != SKILL)
00537 snprintf(buf, size, "of adornment");
00538 }
00539
00551 void query_short_name(const object *op, char *buf, size_t size) {
00552 size_t len = 0;
00553
00554 if (op->name == NULL) {
00555 snprintf(buf, size, "(null)");
00556 return;
00557 }
00558 if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
00559 snprintf(buf, size, "%s", op->name);
00560 return;
00561 }
00562 buf[0] = '\0';
00563
00564 if (op->nrof <= 1)
00565 safe_strcat(buf, op->name, &len, size);
00566 else
00567 safe_strcat(buf, op->name_pl, &len, size);
00568
00569 if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
00570 safe_strcat(buf, " ", &len, size);
00571 safe_strcat(buf, op->title, &len, size);
00572 }
00573
00574 switch (op->type) {
00575 case SPELLBOOK:
00576 case SCROLL:
00577 case WAND:
00578 case ROD:
00579 if (QUERY_FLAG(op, FLAG_IDENTIFIED)||QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
00580 if (!op->title) {
00581 safe_strcat(buf, " of ", &len, size);
00582 if (op->inv)
00583 safe_strcat(buf, op->inv->name, &len, size);
00584 else
00585 LOG(llevError, "Spellbook %s lacks inventory\n", op->name);
00586 }
00587 if (op->type != SPELLBOOK) {
00588 snprintf(buf+len, size-len, " (lvl %d)", op->level);
00589 len += strlen(buf+len);
00590 }
00591 }
00592 break;
00593
00594 case SKILL:
00595 case AMULET:
00596 case RING:
00597 if (!op->title) {
00598
00599 char desc[VERY_BIG_BUF];
00600
00601 ring_desc(op, desc, VERY_BIG_BUF);
00602 if (desc[0]) {
00603 safe_strcat(buf, " ", &len, size);
00604 safe_strcat(buf, desc, &len, size);
00605 }
00606 }
00607 break;
00608
00609 default:
00610 if (op->magic
00611 && ((QUERY_FLAG(op, FLAG_BEEN_APPLIED) && need_identify(op)) || QUERY_FLAG(op, FLAG_IDENTIFIED))) {
00612 snprintf(buf+len, size-len, " %+d", op->magic);
00613 len += strlen(buf+len);
00614 }
00615 }
00616 }
00617
00628 void query_name(const object *op, char *buf, size_t size) {
00629 size_t len = 0;
00630 #ifdef NEW_MATERIAL_CODE
00631 materialtype_t *mt;
00632 #endif
00633
00634 buf[0] = '\0';
00635
00636 #ifdef NEW_MATERIAL_CODE
00637 if ((IS_ARMOR(op) || IS_WEAPON(op) || IS_SHIELD(op)) && op->materialname) {
00638 mt = name_to_material(op->materialname);
00639 if (mt) {
00640 safe_strcat(buf, mt->description, &len, size);
00641 safe_strcat(buf, " ", &len, size);
00642 }
00643 }
00644 #endif
00645
00646 query_short_name(op, buf+len, size-len);
00647 len += strlen(buf+len);
00648
00649 if (QUERY_FLAG(op, FLAG_INV_LOCKED))
00650 safe_strcat(buf, " *", &len, size);
00651 if (op->type == CONTAINER
00652 && ((op->env && op->env->container == op) || (!op->env && QUERY_FLAG(op, FLAG_APPLIED))))
00653 safe_strcat(buf, " (open)", &len, size);
00654
00655 if (QUERY_FLAG(op, FLAG_KNOWN_CURSED)) {
00656 if (QUERY_FLAG(op, FLAG_DAMNED))
00657 safe_strcat(buf, " (damned)", &len, size);
00658 else if (QUERY_FLAG(op, FLAG_CURSED))
00659 safe_strcat(buf, " (cursed)", &len, size);
00660 }
00661 if (QUERY_FLAG(op, FLAG_BLESSED) && QUERY_FLAG(op, FLAG_KNOWN_BLESSED))
00662 safe_strcat(buf, " (blessed)", &len, size);
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 if (QUERY_FLAG(op, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG(op, FLAG_IDENTIFIED))
00674 safe_strcat(buf, " (magic)", &len, size);
00675
00676 if (QUERY_FLAG(op, FLAG_APPLIED)) {
00677 switch (op->type) {
00678 case BOW:
00679 case WAND:
00680 case ROD:
00681 case HORN:
00682 safe_strcat(buf, " (readied)", &len, size);
00683 break;
00684
00685 case WEAPON:
00686 safe_strcat(buf, " (wielded)", &len, size);
00687 break;
00688
00689 case ARMOUR:
00690 case HELMET:
00691 case SHIELD:
00692 case RING:
00693 case BOOTS:
00694 case GLOVES:
00695 case AMULET:
00696 case GIRDLE:
00697 case BRACERS:
00698 case CLOAK:
00699 safe_strcat(buf, " (worn)", &len, size);
00700 break;
00701
00702 case CONTAINER:
00703 safe_strcat(buf, " (active)", &len, size);
00704 break;
00705
00706 case SKILL:
00707 default:
00708 safe_strcat(buf, " (applied)", &len, size);
00709 }
00710 }
00711 if (QUERY_FLAG(op, FLAG_UNPAID))
00712 safe_strcat(buf, " (unpaid)", &len, size);
00713 }
00714
00732 void query_base_name(const object *op, int plural, char *buf, size_t size) {
00733 size_t len;
00734 #ifdef NEW_MATERIAL_CODE
00735 materialtype_t *mt;
00736 #endif
00737
00738 if ((!plural && !op->name)
00739 || (plural && !op->name_pl)) {
00740 strncpy(buf, "(null)", size);
00741 return;
00742 }
00743
00744 if (!op->nrof && !op->weight && !op->title && !is_magical(op)) {
00745 strncpy(buf, op->name, size);
00746 return;
00747 }
00748
00749 buf[0] = '\0';
00750
00751 #ifdef NEW_MATERIAL_CODE
00752 if ((IS_ARMOR(op) || IS_WEAPON(op)) && op->materialname)
00753 mt = name_to_material(op->materialname);
00754 else
00755 mt = NULL;
00756
00757 if (mt
00758 && op->arch->clone.materialname != mt->name
00759 && !(op->material&M_SPECIAL)) {
00760 snprintf(buf, size, "%s", mt->description);
00761 len = strlen(buf);
00762 safe_strcat(buf, " ", &len, size);
00763 safe_strcat(buf, plural ? op->name_pl : op->name, &len, size);
00764 } else {
00765 #endif
00766 snprintf(buf, size, "%s", plural ? op->name_pl : op->name);
00767 len = strlen(buf);
00768 #ifdef NEW_MATERIAL_CODE
00769 }
00770 #endif
00771
00772 if (op->title && QUERY_FLAG(op, FLAG_IDENTIFIED)) {
00773 safe_strcat(buf, " ", &len, size);
00774 safe_strcat(buf, op->title, &len, size);
00775 }
00776
00777 switch (op->type) {
00778 case SPELLBOOK:
00779 case SCROLL:
00780 case WAND:
00781 case ROD:
00782 if (QUERY_FLAG(op, FLAG_IDENTIFIED)||QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
00783 if (!op->title) {
00784 safe_strcat(buf, " of ", &len, size);
00785 if (op->inv)
00786 safe_strcat(buf, op->inv->name, &len, size);
00787 else
00788 LOG(llevError, "Spellbook %s lacks inventory\n", op->name);
00789 }
00790 if (op->type != SPELLBOOK) {
00791 snprintf(buf+len, size-len, " (lvl %d)", op->level);
00792 len += strlen(buf+len);
00793 }
00794 }
00795 break;
00796
00797 case SKILL:
00798 case AMULET:
00799 case RING:
00800 if (!op->title) {
00801
00802 char s[MAX_BUF];
00803
00804 ring_desc(op, s, MAX_BUF);
00805 if (s[0]) {
00806 safe_strcat(buf, " ", &len, size);
00807 safe_strcat(buf, s, &len, size);
00808 }
00809 }
00810 break;
00811
00812 default:
00813 if (op->magic
00814 && ((QUERY_FLAG(op, FLAG_BEEN_APPLIED) && need_identify(op)) || QUERY_FLAG(op, FLAG_IDENTIFIED))) {
00815 snprintf(buf+strlen(buf), size-strlen(buf), " %+d", op->magic);
00816 }
00817 }
00818 }
00819
00840 void describe_monster(const object *op, char *retbuf, size_t size) {
00841 int i;
00842 size_t len;
00843
00844 retbuf[0] = '\0';
00845
00846
00847
00848
00849
00850 if (FABS(op->speed) > MIN_ACTIVE_SPEED) {
00851 switch ((int)((FABS(op->speed))*15)) {
00852 case 0:
00853 snprintf(retbuf, size, "(very slow movement)");
00854 break;
00855
00856 case 1:
00857 snprintf(retbuf, size, "(slow movement)");
00858 break;
00859
00860 case 2:
00861 snprintf(retbuf, size, "(normal movement)");
00862 break;
00863
00864 case 3:
00865 case 4:
00866 snprintf(retbuf, size, "(fast movement)");
00867 break;
00868
00869 case 5:
00870 case 6:
00871 snprintf(retbuf, size, "(very fast movement)");
00872 break;
00873
00874 case 7:
00875 case 8:
00876 case 9:
00877 case 10:
00878 snprintf(retbuf, size, "(extremely fast movement)");
00879 break;
00880
00881 default:
00882 snprintf(retbuf, size, "(lightning fast movement)");
00883 break;
00884 }
00885 }
00886 if (QUERY_FLAG(op, FLAG_UNDEAD))
00887 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(undead)");
00888 if (QUERY_FLAG(op, FLAG_SEE_INVISIBLE))
00889 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(see invisible)");
00890 if (QUERY_FLAG(op, FLAG_USE_WEAPON))
00891 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(wield weapon)");
00892 if (QUERY_FLAG(op, FLAG_USE_BOW))
00893 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(archer)");
00894 if (QUERY_FLAG(op, FLAG_USE_ARMOUR))
00895 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(wear armour)");
00896 if (QUERY_FLAG(op, FLAG_USE_RING))
00897 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(wear ring)");
00898 if (QUERY_FLAG(op, FLAG_USE_SCROLL))
00899 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(read scroll)");
00900 if (QUERY_FLAG(op, FLAG_USE_RANGE))
00901 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(fires wand/rod/horn)");
00902 if (QUERY_FLAG(op, FLAG_CAN_USE_SKILL))
00903 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(skill user)");
00904 if (QUERY_FLAG(op, FLAG_CAST_SPELL))
00905 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(spellcaster)");
00906 if (QUERY_FLAG(op, FLAG_FRIENDLY))
00907 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(friendly)");
00908 if (QUERY_FLAG(op, FLAG_UNAGGRESSIVE))
00909 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(unaggressive)");
00910 if (QUERY_FLAG(op, FLAG_HITBACK))
00911 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(hitback)");
00912 if (QUERY_FLAG(op, FLAG_STEALTH))
00913 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(stealthy)");
00914 if (op->randomitems != NULL) {
00915 treasure *t;
00916 int first = 1;
00917
00918 for (t = op->randomitems->items; t != NULL; t = t->next)
00919 if (t->item && (t->item->clone.type == SPELL)) {
00920 if (first) {
00921 first = 0;
00922 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(Spell abilities:)");
00923 }
00924 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(%s)", t->item->clone.name);
00925 }
00926 }
00927 if (op->type == PLAYER) {
00928 if (op->contr->digestion) {
00929 if (op->contr->digestion != 0)
00930 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(sustenance%+d)", op->contr->digestion);
00931 }
00932 if (op->contr->gen_grace) {
00933 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(grace%+d)", op->contr->gen_grace);
00934 }
00935 if (op->contr->gen_sp) {
00936 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(magic%+d)", op->contr->gen_sp);
00937 }
00938 if (op->contr->gen_hp) {
00939 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(regeneration%+d)", op->contr->gen_hp);
00940 }
00941 if (op->stats.luck) {
00942 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(luck%+d)", op->stats.luck);
00943 }
00944 }
00945
00946
00947 len = strlen(retbuf);
00948 if (is_dragon_pl(op)) {
00949
00950
00951
00952
00953 object *tmp;
00954
00955 for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
00956 if (tmp->type == SKILL && !strcmp(tmp->name, "clawing"))
00957 break;
00958
00959 if (tmp && tmp->attacktype != 0) {
00960 DESCRIBE_ABILITY_SAFE(retbuf, tmp->attacktype, "Claws", &len, size);
00961 } else {
00962 DESCRIBE_ABILITY_SAFE(retbuf, op->attacktype, "Attacks", &len, size);
00963 }
00964 } else {
00965 DESCRIBE_ABILITY_SAFE(retbuf, op->attacktype, "Attacks", &len, size);
00966 }
00967 DESCRIBE_PATH_SAFE(retbuf, op->path_attuned, "Attuned", &len, size);
00968 DESCRIBE_PATH_SAFE(retbuf, op->path_repelled, "Repelled", &len, size);
00969 DESCRIBE_PATH_SAFE(retbuf, op->path_denied, "Denied", &len, size);
00970 for (i = 0; i < NROFATTACKS; i++) {
00971 if (op->resist[i]) {
00972 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(%s %+d)", resist_plus[i], op->resist[i]);
00973 }
00974 }
00975 }
00976
01018 void describe_item(const object *op, const object *owner, char *retbuf, size_t size) {
01019 int identified, i;
01020
01021 retbuf[0] = '\0';
01022 if (QUERY_FLAG(op, FLAG_MONSTER) || op->type == PLAYER) {
01023 describe_monster(op, retbuf, size);
01024 return;
01025 }
01026
01027
01028
01029 if (!need_identify(op) || QUERY_FLAG(op, FLAG_IDENTIFIED))
01030 identified = 1;
01031 else {
01032 snprintf(retbuf, size, "(unidentified)");
01033 identified = 0;
01034 }
01035 switch (op->type) {
01036 case BOW:
01037 case ARROW:
01038 case WAND:
01039 case ROD:
01040 case HORN:
01041 case WEAPON:
01042 case ARMOUR:
01043 case HELMET:
01044 case SHIELD:
01045 case BOOTS:
01046 case GLOVES:
01047 case GIRDLE:
01048 case BRACERS:
01049 case CLOAK:
01050 case SKILL_TOOL:
01051 break;
01052
01053 case LAMP:
01054 break;
01055
01056 case POWER_CRYSTAL:
01057
01058 if (op->stats.maxsp == 0) {
01059 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(capacity %d).", op->stats.maxsp);
01060 } else {
01061 if (op->stats.maxsp > 1000) {
01062 i = (op->stats.maxsp%1000)/100;
01063 if (i)
01064 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(capacity %d.%dk). It is ", op->stats.maxsp/1000, i);
01065 else
01066 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(capacity %dk). It is ", op->stats.maxsp/1000);
01067 } else
01068 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(capacity %d). It is ", op->stats.maxsp);
01069 i = (op->stats.sp*10)/op->stats.maxsp;
01070 if (op->stats.sp == 0)
01071 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "empty.");
01072 else if (i == 0)
01073 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "almost empty.");
01074 else if (i < 3)
01075 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "partially filled.");
01076 else if (i < 6)
01077 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "half full.");
01078 else if (i < 9)
01079 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "well charged.");
01080 else if (op->stats.sp == op->stats.maxsp)
01081 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "fully charged.");
01082 else
01083 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "almost full.");
01084 }
01085 break;
01086
01087 case FOOD:
01088 case FLESH:
01089 case DRINK:
01090 if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
01091 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(food+%d)", op->stats.food);
01092
01093 if (op->type == FLESH && op->last_eat > 0 && atnr_is_dragon_enabled(op->last_eat)) {
01094 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(%s metabolism)", change_resist_msg[op->last_eat]);
01095 }
01096
01097 if (!QUERY_FLAG(op, FLAG_CURSED)) {
01098 if (op->stats.hp)
01099 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(heals)");
01100 if (op->stats.sp)
01101 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(spellpoint regen)");
01102 } else {
01103 if (op->stats.hp)
01104 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(damages)");
01105 if (op->stats.sp)
01106 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(spellpoint depletion)");
01107 }
01108 }
01109 break;
01110
01111 case SKILL:
01112 case RING:
01113 case AMULET:
01114 if (op->item_power) {
01115 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(item_power %+d)", op->item_power);
01116 }
01117 if (op->title) {
01118 ring_desc(op, retbuf+strlen(retbuf), size-strlen(retbuf));
01119 }
01120 return;
01121
01122 default:
01123 return;
01124 }
01125
01126
01127
01128
01129 if (identified || QUERY_FLAG(op, FLAG_BEEN_APPLIED)) {
01130 int attr, val;
01131
01132 for (attr = 0; attr < NUM_STATS; attr++) {
01133 if ((val = get_attr_value(&(op->stats), attr)) != 0) {
01134 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(%s%+d)", short_stat_name[attr], val);
01135 }
01136 }
01137 if (op->glow_radius)
01138 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(glowing)");
01139
01140 switch (op->type) {
01141 case FLESH:
01142 break;
01143
01144 default:
01145 if (op->stats.exp) {
01146 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(speed %+"FMT64")", op->stats.exp);
01147 }
01148 break;
01149 }
01150 switch (op->type) {
01151 case BOW:
01152 case ARROW:
01153 case GIRDLE:
01154 case HELMET:
01155 case SHIELD:
01156 case BOOTS:
01157 case GLOVES:
01158 case WEAPON:
01159 case SKILL:
01160 case RING:
01161 case AMULET:
01162 case ARMOUR:
01163 case BRACERS:
01164 case FORCE:
01165 case CLOAK:
01166 if (op->stats.wc) {
01167 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(wc%+d)", op->stats.wc);
01168 }
01169 if (op->stats.dam) {
01170 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(dam%+d)", op->stats.dam);
01171 }
01172 if (op->stats.ac) {
01173 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(ac%+d)", op->stats.ac);
01174 }
01175 if ((op->type == WEAPON || op->type == BOW) && op->level > 0) {
01176 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(improved %d/%d)", op->last_eat, op->level);
01177 }
01178 break;
01179
01180 default:
01181 break;
01182 }
01183 if (QUERY_FLAG(op, FLAG_XRAYS))
01184 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(xray-vision)");
01185 if (QUERY_FLAG(op, FLAG_SEE_IN_DARK))
01186 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(infravision)");
01187
01188
01189 if (op->move_type&MOVE_FLY_LOW)
01190 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(levitate)");
01191
01192 if (op->move_type&MOVE_FLY_HIGH)
01193 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(fly)");
01194
01195 if (op->move_type&MOVE_SWIM)
01196 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(swim)");
01197
01198
01199
01200 if (op->item_power) {
01201 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(item_power %+d)", op->item_power);
01202 }
01203 }
01204
01205
01206
01207
01208
01209 if (identified) {
01210 int more_info = 0;
01211 size_t len;
01212
01213 switch (op->type) {
01214 case ROD:
01215 case HORN:
01216 case BOW:
01217 case ARROW:
01218 case WAND:
01219 case FOOD:
01220 case FLESH:
01221 case DRINK:
01222 more_info = 0;
01223 break;
01224
01225
01226 case ARMOUR:
01227 case HELMET:
01228 case SHIELD:
01229 case BOOTS:
01230 case GLOVES:
01231 case GIRDLE:
01232 case BRACERS:
01233 case CLOAK:
01234 if (ARMOUR_SPEED(op)) {
01235 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(Max speed %1.2f)", ARMOUR_SPEED(op)/10.0);
01236 }
01237 if (ARMOUR_SPELLS(op)) {
01238 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(Spell regen penalty %d)", ARMOUR_SPELLS(op));
01239 }
01240 more_info = 1;
01241 break;
01242
01243 case WEAPON:
01244
01245
01246
01247 i = (WEAPON_SPEED(op)*2-op->magic)/2;
01248 if (i < 0)
01249 i = 0;
01250
01251 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(weapon speed %d)", i);
01252 more_info = 1;
01253 break;
01254 }
01255 if (more_info) {
01256 if (op->stats.food) {
01257 if (op->stats.food != 0)
01258 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(sustenance%+d)", op->stats.food);
01259 }
01260 if (op->stats.grace) {
01261 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(grace%+d)", op->stats.grace);
01262 }
01263 if (op->stats.sp) {
01264 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(magic%+d)", op->stats.sp);
01265 }
01266 if (op->stats.hp) {
01267 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(regeneration%+d)", op->stats.hp);
01268 }
01269 }
01270
01271 if (op->stats.luck) {
01272 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(luck%+d)", op->stats.luck);
01273 }
01274 if (QUERY_FLAG(op, FLAG_LIFESAVE))
01275 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(lifesaving)");
01276 if (QUERY_FLAG(op, FLAG_REFL_SPELL))
01277 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(reflect spells)");
01278 if (QUERY_FLAG(op, FLAG_REFL_MISSILE))
01279 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(reflect missiles)");
01280 if (QUERY_FLAG(op, FLAG_STEALTH))
01281 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(stealth)");
01282 if (op->slaying != NULL && op->type != FOOD) {
01283 snprintf(retbuf+strlen(retbuf), size-strlen(retbuf), "(slay %s)", op->slaying);
01284 }
01285 len = strlen(retbuf);
01286 DESCRIBE_ABILITY_SAFE(retbuf, op->attacktype, "Attacks", &len, size);
01287
01288
01289
01290 if (op->type != FLESH || (owner && is_dragon_pl(owner))) {
01291 describe_resistance(op, 0, retbuf+strlen(retbuf), size-strlen(retbuf));
01292 }
01293 len = strlen(retbuf);
01294 DESCRIBE_PATH_SAFE(retbuf, op->path_attuned, "Attuned", &len, size);
01295 DESCRIBE_PATH_SAFE(retbuf, op->path_repelled, "Repelled", &len, size);
01296 DESCRIBE_PATH_SAFE(retbuf, op->path_denied, "Denied", &len, size);
01297 }
01298 }
01299
01312 int is_magical(const object *op) {
01313 int i;
01314
01315
01316 if (QUERY_FLAG(op, FLAG_ALIVE))
01317 return 0;
01318
01319
01320 if (op->title != NULL)
01321 return 1;
01322
01323
01324
01325
01326 if ((op->type == AMULET || op->type == RING)
01327 && (op->stats.ac || op->stats.food || op->stats.exp || op->stats.dam || op->stats.wc || op->stats.sp || op->stats.hp || op->stats.luck))
01328 return 1;
01329
01330
01331
01332 if (op->type == BOOTS
01333 && ((QUERY_FLAG(op, FLAG_STEALTH) || op->move_type || op->stats.exp)))
01334 return 1;
01335
01336
01337 if ((op->type == AMULET || op->type == SHIELD)
01338 && (QUERY_FLAG(op, FLAG_REFL_SPELL) || QUERY_FLAG(op, FLAG_REFL_MISSILE)))
01339 return 1;
01340
01341
01342 if (op->type == HELMET
01343 && QUERY_FLAG(op, FLAG_XRAYS))
01344 return 1;
01345
01346
01347
01348
01349 if (op->type == POTION || op->type == ROD || (op->type == WAND && op->stats.food))
01350 return 1;
01351
01352
01353
01354
01355
01356 for (i = ATNR_PHYSICAL+1; i < NROFATTACKS; i++)
01357 if (op->resist[i])
01358 return 1;
01359
01360
01361
01362
01363 if (op->resist[ATNR_PHYSICAL]
01364 && op->type != HELMET
01365 && op->type != SHIELD
01366 && op->type != BOOTS
01367 && op->type != GLOVES
01368 && op->type != ARMOUR)
01369 return 1;
01370
01371
01372 if (op->magic
01373 || op->type == POWER_CRYSTAL
01374 || op->type == SPELLBOOK
01375 || op->type == SCROLL
01376 || op->type == GIRDLE)
01377 return 1;
01378
01379
01380 for (i = 0; i < NUM_STATS; i++)
01381 if (get_attr_value(&(op->stats), i) != 0)
01382 return 1;
01383
01384
01385
01386
01387 return 0;
01388 }
01389
01401 int need_identify(const object *op) {
01402 switch (op->type) {
01403 case RING:
01404 case WAND:
01405 case ROD:
01406 case HORN:
01407 case SCROLL:
01408 case SKILL:
01409 case SKILLSCROLL:
01410 case SPELLBOOK:
01411 case FOOD:
01412 case POTION:
01413 case BOW:
01414 case ARROW:
01415 case WEAPON:
01416 case ARMOUR:
01417 case SHIELD:
01418 case HELMET:
01419 case AMULET:
01420 case BOOTS:
01421 case GLOVES:
01422 case BRACERS:
01423 case GIRDLE:
01424 case CONTAINER:
01425 case DRINK:
01426 case FLESH:
01427 case INORGANIC:
01428 case CLOSE_CON:
01429 case CLOAK:
01430 case GEM:
01431 case POWER_CRYSTAL:
01432 case POISON:
01433 case BOOK:
01434 case SKILL_TOOL:
01435 return 1;
01436 }
01437 return 0;
01438 }
01439
01447 void identify(object *op) {
01448 object *pl;
01449
01450 SET_FLAG(op, FLAG_IDENTIFIED);
01451 CLEAR_FLAG(op, FLAG_KNOWN_MAGICAL);
01452 CLEAR_FLAG(op, FLAG_NO_SKILL_IDENT);
01453
01454
01455
01456
01457 if (QUERY_FLAG(op, FLAG_CURSED) || QUERY_FLAG(op, FLAG_DAMNED))
01458 SET_FLAG(op, FLAG_KNOWN_CURSED);
01459
01460 if (QUERY_FLAG(op, FLAG_BLESSED))
01461 SET_FLAG(op, FLAG_KNOWN_BLESSED);
01462
01463 if (op->type == POTION) {
01464 if (op->inv && op->randomitems) {
01465 if (op->title)
01466 free_string(op->title);
01467 op->title = add_refcount(op->inv->name);
01468 } else if (op->arch) {
01469 free_string(op->name);
01470 op->name = add_refcount(op->arch->clone.name);
01471 free_string(op->name_pl);
01472 op->name_pl = add_refcount(op->arch->clone.name_pl);
01473 }
01474 }
01475
01476
01477 if (op->map)
01478 update_object(op, UP_OBJ_FACE);
01479 else {
01480 pl = get_player_container(op->env);
01481 if (pl)
01482
01483
01484
01485 esrv_update_item(UPD_ALL, pl, op);
01486 }
01487 }