1/* SCCS Id: @(#)wield.c 3.4 2003/01/29 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6 7/* KMH -- Differences between the three weapon slots. 8 * 9 * The main weapon (uwep): 10 * 1. Is filled by the (w)ield command. 11 * 2. Can be filled with any type of item. 12 * 3. May be carried in one or both hands. 13 * 4. Is used as the melee weapon and as the launcher for 14 * ammunition. 15 * 5. Only conveys intrinsics when it is a weapon, weapon-tool, 16 * or artifact. 17 * 6. Certain cursed items will weld to the hand and cannot be 18 * unwielded or dropped. See erodeable_wep() and will_weld() 19 * below for the list of which items apply. 20 * 21 * The secondary weapon (uswapwep): 22 * 1. Is filled by the e(x)change command, which swaps this slot 23 * with the main weapon. If the "pushweapon" option is set, 24 * the (w)ield command will also store the old weapon in the 25 * secondary slot. 26 * 2. Can be field with anything that will fit in the main weapon 27 * slot; that is, any type of item. 28 * 3. Is usually NOT considered to be carried in the hands. 29 * That would force too many checks among the main weapon, 30 * second weapon, shield, gloves, and rings; and it would 31 * further be complicated by bimanual weapons. A special 32 * exception is made for two-weapon combat. 33 * 4. Is used as the second weapon for two-weapon combat, and as 34 * a convenience to swap with the main weapon. 35 * 5. Never conveys intrinsics. 36 * 6. Cursed items never weld (see #3 for reasons), but they also 37 * prevent two-weapon combat. 38 * 39 * The quiver (uquiver): 40 * 1. Is filled by the (Q)uiver command. 41 * 2. Can be filled with any type of item. 42 * 3. Is considered to be carried in a special part of the pack. 43 * 4. Is used as the item to throw with the (f)ire command. 44 * This is a convenience over the normal (t)hrow command. 45 * 5. Never conveys intrinsics. 46 * 6. Cursed items never weld; their effect is handled by the normal 47 * throwing code. 48 * 49 * No item may be in more than one of these slots. 50 */ 51 52 53STATIC_DCL int FDECL(ready_weapon, (struct obj *)); 54 55/* used by will_weld() */ 56/* probably should be renamed */ 57#define erodeable_wep(optr) ((optr)->oclass == WEAPON_CLASS \ 58 || is_weptool(optr) \ 59 || (optr)->otyp == HEAVY_IRON_BALL \ 60 || (optr)->otyp == IRON_CHAIN) 61 62/* used by welded(), and also while wielding */ 63#define will_weld(optr) ((optr)->cursed \ 64 && (erodeable_wep(optr) \ 65 || (optr)->otyp == TIN_OPENER)) 66 67 68/*** Functions that place a given item in a slot ***/ 69/* Proper usage includes: 70 * 1. Initializing the slot during character generation or a 71 * restore. 72 * 2. Setting the slot due to a player's actions. 73 * 3. If one of the objects in the slot are split off, these 74 * functions can be used to put the remainder back in the slot. 75 * 4. Putting an item that was thrown and returned back into the slot. 76 * 5. Emptying the slot, by passing a null object. NEVER pass 77 * zeroobj! 78 * 79 * If the item is being moved from another slot, it is the caller's 80 * responsibility to handle that. It's also the caller's responsibility 81 * to print the appropriate messages. 82 */ 83void 84setuwep(obj) 85register struct obj *obj; 86{ 87 struct obj *olduwep = uwep; 88 89 if (obj == uwep) return; /* necessary to not set unweapon */ 90 /* This message isn't printed in the caller because it happens 91 * *whenever* Sunsword is unwielded, from whatever cause. 92 */ 93 setworn(obj, W_WEP); 94 if (uwep == obj && artifact_light(olduwep) && olduwep->lamplit) { 95 end_burn(olduwep, FALSE); 96 if (!Blind) pline("%s glowing.", Tobjnam(olduwep, "stop")); 97 } 98 /* Note: Explicitly wielding a pick-axe will not give a "bashing" 99 * message. Wielding one via 'a'pplying it will. 100 * 3.2.2: Wielding arbitrary objects will give bashing message too. 101 */ 102 if (obj) { 103 unweapon = (obj->oclass == WEAPON_CLASS) ? 104 is_launcher(obj) || is_ammo(obj) || 105 is_missile(obj) || (is_pole(obj) 106#ifdef STEED 107 && !u.usteed 108#endif 109 ) : !is_weptool(obj); 110 } else 111 unweapon = TRUE; /* for "bare hands" message */ 112 update_inventory(); 113} 114 115STATIC_OVL int 116ready_weapon(wep) 117struct obj *wep; 118{ 119 /* Separated function so swapping works easily */ 120 int res = 0; 121 122 if (!wep) { 123 /* No weapon */ 124 if (uwep) { 125 You("are empty %s.", body_part(HANDED)); 126 setuwep((struct obj *) 0); 127 res++; 128 } else 129 You("are already empty %s.", body_part(HANDED)); 130 } else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE 131 && touch_petrifies(&mons[wep->corpsenm])) { 132 /* Prevent wielding cockatrice when not wearing gloves --KAA */ 133 char kbuf[BUFSZ]; 134 135 You("wield the %s corpse in your bare %s.", 136 mons[wep->corpsenm].mname, makeplural(body_part(HAND))); 137 Sprintf(kbuf, "%s corpse", an(mons[wep->corpsenm].mname)); 138 instapetrify(kbuf); 139 } else if (uarms && bimanual(wep)) 140 You("cannot wield a two-handed %s while wearing a shield.", 141 is_sword(wep) ? "sword" : 142 wep->otyp == BATTLE_AXE ? "axe" : "weapon"); 143 else if (wep->oartifact && !touch_artifact(wep, &youmonst)) { 144 res++; /* takes a turn even though it doesn't get wielded */ 145 } else { 146 /* Weapon WILL be wielded after this point */ 147 res++; 148 if (will_weld(wep)) { 149 const char *tmp = xname(wep), *thestr = "The "; 150 if (strncmp(tmp, thestr, 4) && !strncmp(The(tmp),thestr,4)) 151 tmp = thestr; 152 else tmp = ""; 153 pline("%s%s %s to your %s!", tmp, aobjnam(wep, "weld"), 154 (wep->quan == 1L) ? "itself" : "themselves", /* a3 */ 155 bimanual(wep) ? 156 (const char *)makeplural(body_part(HAND)) 157 : body_part(HAND)); 158 wep->bknown = TRUE; 159 } else { 160 /* The message must be printed before setuwep (since 161 * you might die and be revived from changing weapons), 162 * and the message must be before the death message and 163 * Lifesaved rewielding. Yet we want the message to 164 * say "weapon in hand", thus this kludge. 165 */ 166 long dummy = wep->owornmask; 167 wep->owornmask |= W_WEP; 168 prinv((char *)0, wep, 0L); 169 wep->owornmask = dummy; 170 } 171 setuwep(wep); 172 173 /* KMH -- Talking artifacts are finally implemented */ 174 arti_speak(wep); 175 176 if (artifact_light(wep) && !wep->lamplit) { 177 begin_burn(wep, FALSE); 178 if (!Blind) 179 pline("%s to glow brilliantly!", Tobjnam(wep, "begin")); 180 } 181 182#if 0 183 /* we'll get back to this someday, but it's not balanced yet */ 184 if (Race_if(PM_ELF) && !wep->oartifact && 185 objects[wep->otyp].oc_material == IRON) { 186 /* Elves are averse to wielding cold iron */ 187 You("have an uneasy feeling about wielding cold iron."); 188 change_luck(-1); 189 } 190#endif 191 192 if (wep->unpaid) { 193 struct monst *this_shkp; 194 195 if ((this_shkp = shop_keeper(inside_shop(u.ux, u.uy))) != 196 (struct monst *)0) { 197 pline("%s says \"You be careful with my %s!\"", 198 shkname(this_shkp), 199 xname(wep)); 200 } 201 } 202 } 203 return(res); 204} 205 206void 207setuqwep(obj) 208register struct obj *obj; 209{ 210 setworn(obj, W_QUIVER); 211 update_inventory(); 212} 213 214void 215setuswapwep(obj) 216register struct obj *obj; 217{ 218 setworn(obj, W_SWAPWEP); 219 update_inventory(); 220} 221 222 223/*** Commands to change particular slot(s) ***/ 224 225static NEARDATA const char wield_objs[] = 226 { ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0 }; 227static NEARDATA const char ready_objs[] = 228 { ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0 }; 229static NEARDATA const char bullets[] = /* (note: different from dothrow.c) */ 230 { ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 }; 231 232int 233dowield() 234{ 235 register struct obj *wep, *oldwep; 236 int result; 237 238 /* May we attempt this? */ 239 multi = 0; 240 if (cantwield(youmonst.data)) { 241 pline("Don't be ridiculous!"); 242 return(0); 243 } 244 245 /* Prompt for a new weapon */ 246 if (!(wep = getobj(wield_objs, "wield"))) 247 /* Cancelled */ 248 return (0); 249 else if (wep == uwep) { 250 You("are already wielding that!"); 251 if (is_weptool(wep)) unweapon = FALSE; /* [see setuwep()] */ 252 return (0); 253 } else if (welded(uwep)) { 254 weldmsg(uwep); 255 /* previously interrupted armor removal mustn't be resumed */ 256 reset_remarm(); 257 return (0); 258 } 259 260 /* Handle no object, or object in other slot */ 261 if (wep == &zeroobj) 262 wep = (struct obj *) 0; 263 else if (wep == uswapwep) 264 return (doswapweapon()); 265 else if (wep == uquiver) 266 setuqwep((struct obj *) 0); 267 else if (wep->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL 268#ifdef STEED 269 | W_SADDLE 270#endif 271 )) { 272 You("cannot wield that!"); 273 return (0); 274 } 275 276 /* Set your new primary weapon */ 277 oldwep = uwep; 278 result = ready_weapon(wep); 279 if (flags.pushweapon && oldwep && uwep != oldwep) 280 setuswapwep(oldwep); 281 untwoweapon(); 282 283 return (result); 284} 285 286int 287doswapweapon() 288{ 289 register struct obj *oldwep, *oldswap; 290 int result = 0; 291 292 293 /* May we attempt this? */ 294 multi = 0; 295 if (cantwield(youmonst.data)) { 296 pline("Don't be ridiculous!"); 297 return(0); 298 } 299 if (welded(uwep)) { 300 weldmsg(uwep); 301 return (0); 302 } 303 304 /* Unwield your current secondary weapon */ 305 oldwep = uwep; 306 oldswap = uswapwep; 307 setuswapwep((struct obj *) 0); 308 309 /* Set your new primary weapon */ 310 result = ready_weapon(oldswap); 311 312 /* Set your new secondary weapon */ 313 if (uwep == oldwep) 314 /* Wield failed for some reason */ 315 setuswapwep(oldswap); 316 else { 317 setuswapwep(oldwep); 318 if (uswapwep) 319 prinv((char *)0, uswapwep, 0L); 320 else 321 You("have no secondary weapon readied."); 322 } 323 324 if (u.twoweap && !can_twoweapon()) 325 untwoweapon(); 326 327 return (result); 328} 329 330int 331dowieldquiver() 332{ 333 register struct obj *newquiver; 334 const char *quivee_types = (uslinging() || 335 (uswapwep && objects[uswapwep->otyp].oc_skill == P_SLING)) ? 336 bullets : ready_objs; 337 338 /* Since the quiver isn't in your hands, don't check cantwield(), */ 339 /* will_weld(), touch_petrifies(), etc. */ 340 multi = 0; 341 342 /* Because 'Q' used to be quit... */ 343 if (flags.suppress_alert < FEATURE_NOTICE_VER(3,3,0)) 344 pline("Note: Please use #quit if you wish to exit the game."); 345 346 /* Prompt for a new quiver */ 347 if (!(newquiver = getobj(quivee_types, "ready"))) 348 /* Cancelled */ 349 return (0); 350 351 /* Handle no object, or object in other slot */ 352 /* Any type is okay, since we give no intrinsics anyways */ 353 if (newquiver == &zeroobj) { 354 /* Explicitly nothing */ 355 if (uquiver) { 356 You("now have no ammunition readied."); 357 setuqwep(newquiver = (struct obj *) 0); 358 } else { 359 You("already have no ammunition readied!"); 360 return(0); 361 } 362 } else if (newquiver == uquiver) { 363 pline("That ammunition is already readied!"); 364 return(0); 365 } else if (newquiver == uwep) { 366 /* Prevent accidentally readying the main weapon */ 367 pline("%s already being used as a weapon!", 368 !is_plural(uwep) ? "That is" : "They are"); 369 return(0); 370 } else if (newquiver->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL 371#ifdef STEED 372 | W_SADDLE 373#endif 374 )) { 375 You("cannot ready that!"); 376 return (0); 377 } else { 378 long dummy; 379 380 381 /* Check if it's the secondary weapon */ 382 if (newquiver == uswapwep) { 383 setuswapwep((struct obj *) 0); 384 untwoweapon(); 385 } 386 387 /* Okay to put in quiver; print it */ 388 dummy = newquiver->owornmask; 389 newquiver->owornmask |= W_QUIVER; 390 prinv((char *)0, newquiver, 0L); 391 newquiver->owornmask = dummy; 392 } 393 394 /* Finally, place it in the quiver */ 395 setuqwep(newquiver); 396 /* Take no time since this is a convenience slot */ 397 return (0); 398} 399 400/* used for #rub and for applying pick-axe, whip, grappling hook, or polearm */ 401/* (moved from apply.c) */ 402boolean 403wield_tool(obj, verb) 404struct obj *obj; 405const char *verb; /* "rub",&c */ 406{ 407 const char *what; 408 boolean more_than_1; 409 410 if (obj == uwep) return TRUE; /* nothing to do if already wielding it */ 411 412 if (!verb) verb = "wield"; 413 what = xname(obj); 414 more_than_1 = (obj->quan > 1L || 415 strstri(what, "pair of ") != 0 || 416 strstri(what, "s of ") != 0); 417 418 if (obj->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL)) { 419 char yourbuf[BUFSZ]; 420 421 You_cant("%s %s %s while wearing %s.", 422 verb, shk_your(yourbuf, obj), what, 423 more_than_1 ? "them" : "it"); 424 return FALSE; 425 } 426 if (welded(uwep)) { 427 if (flags.verbose) { 428 const char *hand = body_part(HAND); 429 430 if (bimanual(uwep)) hand = makeplural(hand); 431 if (strstri(what, "pair of ") != 0) more_than_1 = FALSE; 432 pline( 433 "Since your weapon is welded to your %s, you cannot %s %s %s.", 434 hand, verb, more_than_1 ? "those" : "that", xname(obj)); 435 } else { 436 You_cant("do that."); 437 } 438 return FALSE; 439 } 440 if (cantwield(youmonst.data)) { 441 You_cant("hold %s strongly enough.", more_than_1 ? "them" : "it"); 442 return FALSE; 443 } 444 /* check shield */ 445 if (uarms && bimanual(obj)) { 446 You("cannot %s a two-handed %s while wearing a shield.", 447 verb, (obj->oclass == WEAPON_CLASS) ? "weapon" : "tool"); 448 return FALSE; 449 } 450 if (uquiver == obj) setuqwep((struct obj *)0); 451 if (uswapwep == obj) { 452 (void) doswapweapon(); 453 /* doswapweapon might fail */ 454 if (uswapwep == obj) return FALSE; 455 } else { 456 You("now wield %s.", doname(obj)); 457 setuwep(obj); 458 } 459 if (uwep != obj) return FALSE; /* rewielded old object after dying */ 460 /* applying weapon or tool that gets wielded ends two-weapon combat */ 461 if (u.twoweap) 462 untwoweapon(); 463 if (obj->oclass != WEAPON_CLASS) 464 unweapon = TRUE; 465 return TRUE; 466} 467 468int 469can_twoweapon() 470{ 471 struct obj *otmp; 472 473#define NOT_WEAPON(obj) (!is_weptool(obj) && obj->oclass != WEAPON_CLASS) 474 if (!could_twoweap(youmonst.data)) { 475 if (Upolyd) 476 You_cant("use two weapons in your current form."); 477 else 478 pline("%s aren't able to use two weapons at once.", 479 makeplural((flags.female && urole.name.f) ? 480 urole.name.f : urole.name.m)); 481 } else if (!uwep || !uswapwep) 482 Your("%s%s%s empty.", uwep ? "left " : uswapwep ? "right " : "", 483 body_part(HAND), (!uwep && !uswapwep) ? "s are" : " is"); 484 else if (NOT_WEAPON(uwep) || NOT_WEAPON(uswapwep)) { 485 otmp = NOT_WEAPON(uwep) ? uwep : uswapwep; 486 pline("%s %s.", Yname2(otmp), 487 is_plural(otmp) ? "aren't weapons" : "isn't a weapon"); 488 } else if (bimanual(uwep) || bimanual(uswapwep)) { 489 otmp = bimanual(uwep) ? uwep : uswapwep; 490 pline("%s isn't one-handed.", Yname2(otmp)); 491 } else if (uarms) 492 You_cant("use two weapons while wearing a shield."); 493 else if (uswapwep->oartifact) 494 pline("%s %s being held second to another weapon!", 495 Yname2(uswapwep), otense(uswapwep, "resist")); 496 else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && 497 touch_petrifies(&mons[uswapwep->corpsenm]))) { 498 char kbuf[BUFSZ]; 499 500 You("wield the %s corpse with your bare %s.", 501 mons[uswapwep->corpsenm].mname, body_part(HAND)); 502 Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); 503 instapetrify(kbuf); 504 } else if (Glib || uswapwep->cursed) { 505 if (!Glib) 506 uswapwep->bknown = TRUE; 507 drop_uswapwep(); 508 } else 509 return (TRUE); 510 return (FALSE); 511} 512 513void 514drop_uswapwep() 515{ 516 char str[BUFSZ]; 517 struct obj *obj = uswapwep; 518 519 /* Avoid trashing makeplural's static buffer */ 520 Strcpy(str, makeplural(body_part(HAND))); 521 Your("%s from your %s!", aobjnam(obj, "slip"), str); 522 dropx(obj); 523} 524 525int 526dotwoweapon() 527{ 528 /* You can always toggle it off */ 529 if (u.twoweap) { 530 You("switch to your primary weapon."); 531 u.twoweap = 0; 532 update_inventory(); 533 return (0); 534 } 535 536 /* May we use two weapons? */ 537 if (can_twoweapon()) { 538 /* Success! */ 539 You("begin two-weapon combat."); 540 u.twoweap = 1; 541 update_inventory(); 542 return (rnd(20) > ACURR(A_DEX)); 543 } 544 return (0); 545} 546 547/*** Functions to empty a given slot ***/ 548/* These should be used only when the item can't be put back in 549 * the slot by life saving. Proper usage includes: 550 * 1. The item has been eaten, stolen, burned away, or rotted away. 551 * 2. Making an item disappear for a bones pile. 552 */ 553void 554uwepgone() 555{ 556 if (uwep) { 557 if (artifact_light(uwep) && uwep->lamplit) { 558 end_burn(uwep, FALSE); 559 if (!Blind) pline("%s glowing.", Tobjnam(uwep, "stop")); 560 } 561 setworn((struct obj *)0, W_WEP); 562 unweapon = TRUE; 563 update_inventory(); 564 } 565} 566 567void 568uswapwepgone() 569{ 570 if (uswapwep) { 571 setworn((struct obj *)0, W_SWAPWEP); 572 update_inventory(); 573 } 574} 575 576void 577uqwepgone() 578{ 579 if (uquiver) { 580 setworn((struct obj *)0, W_QUIVER); 581 update_inventory(); 582 } 583} 584 585void 586untwoweapon() 587{ 588 if (u.twoweap) { 589 You("can no longer use two weapons at once."); 590 u.twoweap = FALSE; 591 update_inventory(); 592 } 593 return; 594} 595 596/* Maybe rust object, or corrode it if acid damage is called for */ 597void 598erode_obj(target, acid_dmg, fade_scrolls) 599struct obj *target; /* object (e.g. weapon or armor) to erode */ 600boolean acid_dmg; 601boolean fade_scrolls; 602{ 603 int erosion; 604 struct monst *victim; 605 boolean vismon; 606 boolean visobj; 607 608 if (!target) 609 return; 610 victim = carried(target) ? &youmonst : 611 mcarried(target) ? target->ocarry : (struct monst *)0; 612 vismon = victim && (victim != &youmonst) && canseemon(victim); 613 visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */ 614 615 erosion = acid_dmg ? target->oeroded2 : target->oeroded; 616 617 if (target->greased) { 618 grease_protect(target,(char *)0,victim); 619 } else if (target->oclass == SCROLL_CLASS) { 620 if(fade_scrolls && target->otyp != SCR_BLANK_PAPER 621#ifdef MAIL 622 && target->otyp != SCR_MAIL 623#endif 624 ) 625 { 626 if (!Blind) { 627 if (victim == &youmonst) 628 Your("%s.", aobjnam(target, "fade")); 629 else if (vismon) 630 pline("%s's %s.", Monnam(victim), 631 aobjnam(target, "fade")); 632 else if (visobj) 633 pline_The("%s.", aobjnam(target, "fade")); 634 } 635 target->otyp = SCR_BLANK_PAPER; 636 target->spe = 0; 637 } 638 } else if (target->oerodeproof || 639 (acid_dmg ? !is_corrodeable(target) : !is_rustprone(target))) { 640 if (flags.verbose || !(target->oerodeproof && target->rknown)) { 641 if (victim == &youmonst) 642 Your("%s not affected.", aobjnam(target, "are")); 643 else if (vismon) 644 pline("%s's %s not affected.", Monnam(victim), 645 aobjnam(target, "are")); 646 /* no message if not carried */ 647 } 648 if (target->oerodeproof) target->rknown = TRUE; 649 } else if (erosion < MAX_ERODE) { 650 if (victim == &youmonst) 651 Your("%s%s!", aobjnam(target, acid_dmg ? "corrode" : "rust"), 652 erosion+1 == MAX_ERODE ? " completely" : 653 erosion ? " further" : ""); 654 else if (vismon) 655 pline("%s's %s%s!", Monnam(victim), 656 aobjnam(target, acid_dmg ? "corrode" : "rust"), 657 erosion+1 == MAX_ERODE ? " completely" : 658 erosion ? " further" : ""); 659 else if (visobj) 660 pline_The("%s%s!", 661 aobjnam(target, acid_dmg ? "corrode" : "rust"), 662 erosion+1 == MAX_ERODE ? " completely" : 663 erosion ? " further" : ""); 664 if (acid_dmg) 665 target->oeroded2++; 666 else 667 target->oeroded++; 668 } else { 669 if (flags.verbose) { 670 if (victim == &youmonst) 671 Your("%s completely %s.", 672 aobjnam(target, Blind ? "feel" : "look"), 673 acid_dmg ? "corroded" : "rusty"); 674 else if (vismon) 675 pline("%s's %s completely %s.", Monnam(victim), 676 aobjnam(target, "look"), 677 acid_dmg ? "corroded" : "rusty"); 678 else if (visobj) 679 pline_The("%s completely %s.", 680 aobjnam(target, "look"), 681 acid_dmg ? "corroded" : "rusty"); 682 } 683 } 684} 685 686int 687chwepon(otmp, amount) 688register struct obj *otmp; 689register int amount; 690{ 691 const char *color = hcolor((amount < 0) ? NH_BLACK : NH_BLUE); 692 const char *xtime; 693 int otyp = STRANGE_OBJECT; 694 695 if(!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) { 696 char buf[BUFSZ]; 697 698 Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)), 699 (amount >= 0) ? "twitch" : "itch"); 700 strange_feeling(otmp, buf); 701 exercise(A_DEX, (boolean) (amount >= 0)); 702 return(0); 703 } 704 705 if (otmp && otmp->oclass == SCROLL_CLASS) otyp = otmp->otyp; 706 707 if(uwep->otyp == WORM_TOOTH && amount >= 0) { 708 uwep->otyp = CRYSKNIFE; 709 uwep->oerodeproof = 0; 710 Your("weapon seems sharper now."); 711 uwep->cursed = 0; 712 if (otyp != STRANGE_OBJECT) makeknown(otyp); 713 return(1); 714 } 715 716 if(uwep->otyp == CRYSKNIFE && amount < 0) { 717 uwep->otyp = WORM_TOOTH; 718 uwep->oerodeproof = 0; 719 Your("weapon seems duller now."); 720 if (otyp != STRANGE_OBJECT && otmp->bknown) makeknown(otyp); 721 return(1); 722 } 723 724 if (amount < 0 && uwep->oartifact && restrict_name(uwep, ONAME(uwep))) { 725 if (!Blind) 726 Your("%s %s.", aobjnam(uwep, "faintly glow"), color); 727 return(1); 728 } 729 /* there is a (soft) upper and lower limit to uwep->spe */ 730 if(((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0)) 731 && rn2(3)) { 732 if (!Blind) 733 Your("%s %s for a while and then %s.", 734 aobjnam(uwep, "violently glow"), color, 735 otense(uwep, "evaporate")); 736 else 737 Your("%s.", aobjnam(uwep, "evaporate")); 738 739 useupall(uwep); /* let all of them disappear */ 740 return(1); 741 } 742 if (!Blind) { 743 xtime = (amount*amount == 1) ? "moment" : "while"; 744 Your("%s %s for a %s.", 745 aobjnam(uwep, amount == 0 ? "violently glow" : "glow"), 746 color, xtime); 747 if (otyp != STRANGE_OBJECT && uwep->known && 748 (amount > 0 || (amount < 0 && otmp->bknown))) 749 makeknown(otyp); 750 } 751 uwep->spe += amount; 752 if(amount > 0) uwep->cursed = 0; 753 754 /* 755 * Enchantment, which normally improves a weapon, has an 756 * addition adverse reaction on Magicbane whose effects are 757 * spe dependent. Give an obscure clue here. 758 */ 759 if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) { 760 Your("right %s %sches!", 761 body_part(HAND), 762 (((amount > 1) && (uwep->spe > 1)) ? "flin" : "it")); 763 } 764 765 /* an elven magic clue, cookie@keebler */ 766 /* elven weapons vibrate warningly when enchanted beyond a limit */ 767 if ((uwep->spe > 5) 768 && (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7))) 769 Your("%s unexpectedly.", 770 aobjnam(uwep, "suddenly vibrate")); 771 772 return(1); 773} 774 775int 776welded(obj) 777register struct obj *obj; 778{ 779 if (obj && obj == uwep && will_weld(obj)) { 780 obj->bknown = TRUE; 781 return 1; 782 } 783 return 0; 784} 785 786void 787weldmsg(obj) 788register struct obj *obj; 789{ 790 long savewornmask; 791 792 savewornmask = obj->owornmask; 793 Your("%s %s welded to your %s!", 794 xname(obj), otense(obj, "are"), 795 bimanual(obj) ? (const char *)makeplural(body_part(HAND)) 796 : body_part(HAND)); 797 obj->owornmask = savewornmask; 798} 799 800/*wield.c*/ 801