OSDN Git Service

rearrange main dungeon
[nethackexpress/trunk.git] / src / wield.c
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
53 STATIC_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  */
83 void
84 setuwep(obj)
85 register 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
115 STATIC_OVL int
116 ready_weapon(wep)
117 struct 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
206 void
207 setuqwep(obj)
208 register struct obj *obj;
209 {
210         setworn(obj, W_QUIVER);
211         update_inventory();
212 }
213
214 void
215 setuswapwep(obj)
216 register struct obj *obj;
217 {
218         setworn(obj, W_SWAPWEP);
219         update_inventory();
220 }
221
222
223 /*** Commands to change particular slot(s) ***/
224
225 static NEARDATA const char wield_objs[] =
226         { ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0 };
227 static NEARDATA const char ready_objs[] =
228         { ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0 };
229 static NEARDATA const char bullets[] =  /* (note: different from dothrow.c) */
230         { ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 };
231
232 int
233 dowield()
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
286 int
287 doswapweapon()
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
330 int
331 dowieldquiver()
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) */
402 boolean
403 wield_tool(obj, verb)
404 struct obj *obj;
405 const 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
468 int
469 can_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
513 void
514 drop_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
525 int
526 dotwoweapon()
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  */
553 void
554 uwepgone()
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
567 void
568 uswapwepgone()
569 {
570         if (uswapwep) {
571                 setworn((struct obj *)0, W_SWAPWEP);
572                 update_inventory();
573         }
574 }
575
576 void
577 uqwepgone()
578 {
579         if (uquiver) {
580                 setworn((struct obj *)0, W_QUIVER);
581                 update_inventory();
582         }
583 }
584
585 void
586 untwoweapon()
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 */
597 void
598 erode_obj(target, acid_dmg, fade_scrolls)
599 struct obj *target;             /* object (e.g. weapon or armor) to erode */
600 boolean acid_dmg;
601 boolean 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
686 int
687 chwepon(otmp, amount)
688 register struct obj *otmp;
689 register 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
775 int
776 welded(obj)
777 register 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
786 void
787 weldmsg(obj)
788 register 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*/