1    | /*	SCCS Id: @(#)wield.c	3.3	2000/06/04	*/
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 int FDECL(ready_weapon, (struct obj *));
54   | 
55   | /* elven weapons vibrate warningly when enchanted beyond a limit */
56   | #define is_elven_weapon(optr)	((optr)->otyp == ELVEN_ARROW\
57   | 				|| (optr)->otyp == ELVEN_SPEAR\
58   | 				|| (optr)->otyp == ELVEN_DAGGER\
59   | 				|| (optr)->otyp == ELVEN_SHORT_SWORD\
60   | 				|| (optr)->otyp == ELVEN_BROADSWORD\
61   | 				|| (optr)->otyp == ELVEN_BOW)
62   | 
63   | /* used by will_weld() */
64   | /* probably should be renamed */
65   | #define erodeable_wep(optr)	((optr)->oclass == WEAPON_CLASS \
66   | 				|| is_weptool(optr) \
67   | 				|| (optr)->otyp == HEAVY_IRON_BALL \
68   | 				|| (optr)->otyp == IRON_CHAIN)
69   | 
70   | /* used by welded(), and also while wielding */
71   | #define will_weld(optr)		((optr)->cursed \
72   | 				&& (erodeable_wep(optr) \
73   | 				   || (optr)->otyp == TIN_OPENER))
74   | 
75   | 
76   | /*** Functions that place a given item in a slot ***/
77   | /* Proper usage includes:
78   |  * 1.  Initializing the slot during character generation or a
79   |  *     restore.
80   |  * 2.  Setting the slot due to a player's actions.
81   |  * 3.  If one of the objects in the slot are split off, these
82   |  *     functions can be used to put the remainder back in the slot.
83   |  * 4.  Putting an item that was thrown and returned back into the slot.
84   |  * 5.  Emptying the slot, by passing a null object.  NEVER pass
85   |  *     zeroobj!
86   |  *
87   |  * Note: setuwep() with a null obj, and uwepgone(), are NOT the same!
88   |  * Sometimes unwielding a weapon can kill you, and lifesaving will then
89   |  * put it back into your hand.  If lifesaving is permitted to do this,
90   |  * use setwuep((struct obj *)0); otherwise use uwepgone().
91   |  *
92   |  * If the item is being moved from another slot, it is the caller's
93   |  * responsibility to handle that.  It's also the caller's responsibility
94   |  * to print the appropriate messages.
95   |  */
96   | void
97   | setuwep(obj)
98   | register struct obj *obj;
99   | {
100  | 	if (obj == uwep) return; /* necessary to not set unweapon */
101  | 	setworn(obj, W_WEP);
102  | 	/* Note: Explicitly wielding a pick-axe will not give a "bashing"
103  | 	 * message.  Wielding one via 'a'pplying it will.
104  | 	 * 3.2.2:  Wielding arbitrary objects will give bashing message too.
105  | 	 */
106  | 	if (obj) {
107  | 		unweapon = (obj->oclass == WEAPON_CLASS) ?
108  | 				is_launcher(obj) || is_ammo(obj) ||
109  | 				is_missile(obj) || is_pole(obj) :
110  | 			   !is_weptool(obj);
111  | 	} else
112  | 		unweapon = TRUE;	/* for "bare hands" message */
113  | 	update_inventory();
114  | }
115  | 
116  | static int
117  | ready_weapon(wep)
118  | struct obj *wep;
119  | {
120  | 	/* Separated function so swapping works easily */
121  | 	int res = 0;
122  | 
123  | 	if (!wep) {
124  | 	    /* No weapon */
125  | 	    if (uwep) {
126  | 		You("are empty %s.", body_part(HANDED));
127  | 		setuwep((struct obj *) 0);
128  | 		res++;
129  | 	    } else
130  | 		You("are already empty %s.", body_part(HANDED));
131  | 	} else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE
132  | 				&& touch_petrifies(&mons[wep->corpsenm])) {
133  | 	    /* Prevent wielding cockatrice when not wearing gloves --KAA */
134  | 	    char kbuf[BUFSZ];
135  | 
136  | 	    You("wield the %s corpse in your bare %s.",
137  | 		mons[wep->corpsenm].mname, makeplural(body_part(HAND)));
138  | 	    Sprintf(kbuf, "%s corpse", an(mons[wep->corpsenm].mname));
139  | 	    instapetrify(kbuf);
140  | 	} else if (uarms && bimanual(wep))
141  | 	    You("cannot wield a two-handed %s while wearing a shield.",
142  | 		is_sword(wep) ? "sword" :
143  | 		    wep->otyp == BATTLE_AXE ? "axe" : "weapon");
144  | 	else if (wep->oartifact && !touch_artifact(wep, &youmonst)) {
145  | 	    res++;	/* takes a turn even though it doesn't get wielded */
146  | 	} else {
147  | 	    /* Weapon WILL be wielded after this point */
148  | 	    res++;
149  | 	    if (will_weld(wep)) {
150  | 		const char *tmp = xname(wep), *thestr = "The ";
151  | 		if (strncmp(tmp, thestr, 4) && !strncmp(The(tmp),thestr,4))
152  | 		    tmp = thestr;
153  | 		else tmp = "";
154  | 		pline("%s%s %s to your %s!", tmp, aobjnam(wep, "weld"),
155  | 			(wep->quan == 1L) ? "itself" : "themselves", /* a3 */
156  | 			bimanual(wep) ?
157  | 				(const char *)makeplural(body_part(HAND))
158  | 				: body_part(HAND));
159  | 		wep->bknown = TRUE;
160  | 	    } else {
161  | 		/* The message must be printed before setuwep (since
162  | 		 * you might die and be revived from changing weapons),
163  | 		 * and the message must be before the death message and
164  | 		 * Lifesaved rewielding.  Yet we want the message to
165  | 		 * say "weapon in hand", thus this kludge.
166  | 		 */
167  | 		long dummy = wep->owornmask;
168  | 		wep->owornmask |= W_WEP;
169  | 		prinv((char *)0, wep, 0L);
170  | 		wep->owornmask = dummy;
171  | 	    }
172  | 	    setuwep(wep);
173  | 
174  | 	    /* KMH -- Talking artifacts are finally implemented */
175  | 	    arti_speak(wep);
176  | 
177  | #if 0
178  | 	    /* we'll get back to this someday, but it's not balanced yet */
179  | 	    if (Race_if(PM_ELF) && !wep->oartifact &&
180  | 			    objects[wep->otyp].oc_material == IRON) {
181  | 		/* Elves are averse to wielding cold iron */
182  | 		You("have an uneasy feeling about wielding cold iron.");
183  | 		change_luck(-1);
184  | 	    }
185  | #endif
186  | 
187  | 	    if (wep->unpaid) {
188  | 		struct monst *this_shkp;
189  | 
190  | 		if ((this_shkp = shop_keeper(inside_shop(u.ux, u.uy))) !=
191  | 		    (struct monst *)0) {
192  | 		    pline("%s says \"You be careful with my %s!\"",
193  | 			  shkname(this_shkp),
194  | 			  xname(wep));
195  | 		}
196  | 	    }
197  | 	}
198  | 	return(res);
199  | }
200  | 
201  | void
202  | setuqwep(obj)
203  | register struct obj *obj;
204  | {
205  | 	setworn(obj, W_QUIVER);
206  | 	update_inventory();
207  | }
208  | 
209  | void
210  | setuswapwep(obj)
211  | register struct obj *obj;
212  | {
213  | 	setworn(obj, W_SWAPWEP);
214  | 	update_inventory();
215  | }
216  | 
217  | 
218  | /*** Commands to change particular slot(s) ***/
219  | 
220  | static NEARDATA const char wield_objs[] =
221  | 	{ ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, TOOL_CLASS, 0 };
222  | static NEARDATA const char ready_objs[] =
223  | 	{ ALL_CLASSES, ALLOW_NONE, WEAPON_CLASS, 0 };
224  | static NEARDATA const char bullets[] =	/* (note: different from dothrow.c) */
225  | 	{ ALL_CLASSES, ALLOW_NONE, GEM_CLASS, WEAPON_CLASS, 0 };
226  | 
227  | int
228  | dowield()
229  | {
230  | 	register struct obj *wep;
231  | 	int result;
232  | 
233  | 	/* May we attempt this? */
234  | 	multi = 0;
235  | 	if (cantwield(youmonst.data)) {
236  | 		pline("Don't be ridiculous!");
237  | 		return(0);
238  | 	}
239  | 
240  | 	/* Prompt for a new weapon */
241  | 	if (!(wep = getobj(wield_objs, "wield")))
242  | 		/* Cancelled */
243  | 		return (0);
244  | 	else if (wep == uwep) {
245  | 	    You("are already wielding that!");
246  | 	    if (is_weptool(wep)) unweapon = FALSE;	/* [see setuwep()] */
247  | 		return (0);
248  | 	} else if (welded(uwep)) {
249  | 		weldmsg(uwep);
250  | 		return (0);
251  | 	}
252  | 
253  | 	/* Handle no object, or object in other slot */
254  | 	if (wep == &zeroobj)
255  | 		wep = (struct obj *) 0;
256  | 	else if (wep == uswapwep)
257  | 		return (doswapweapon());
258  | 	else if (wep == uquiver)
259  | 		setuqwep((struct obj *) 0);
260  | 	else if (wep->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL
261  | #ifdef STEED
262  | 			| W_SADDLE
263  | #endif
264  | 			)) {
265  | 		You("cannot wield that!");
266  | 		return (0);
267  | 	}
268  | 
269  | 	/* Set your new primary weapon */
270  | 	if (flags.pushweapon && uwep)
271  | 		setuswapwep(uwep);
272  | 	result = ready_weapon(wep);
273  | 	untwoweapon();
274  | 
275  | 	return (result);
276  | }
277  | 
278  | int
279  | doswapweapon()
280  | {
281  | 	register struct obj *oldwep, *oldswap;
282  | 	int result = 0;
283  | 
284  | 
285  | 	/* May we attempt this? */
286  | 	multi = 0;
287  | 	if (cantwield(youmonst.data)) {
288  | 		pline("Don't be ridiculous!");
289  | 		return(0);
290  | 	}
291  | 	if (welded(uwep)) {
292  | 		weldmsg(uwep);
293  | 		return (0);
294  | 	}
295  | 
296  | 	/* Unwield your current secondary weapon */
297  | 	oldwep = uwep;
298  | 	oldswap = uswapwep;
299  | 	setuswapwep((struct obj *) 0);
300  | 
301  | 	/* Set your new primary weapon */
302  | 	result = ready_weapon(oldswap);
303  | 
304  | 	/* Set your new secondary weapon */
305  | 	if (uwep == oldwep)
306  | 		/* Wield failed for some reason */
307  | 		setuswapwep(oldswap);
308  | 	else {
309  | 		setuswapwep(oldwep);
310  | 		if (uswapwep)
311  | 			prinv((char *)0, uswapwep, 0L);
312  | 		else
313  | 			You("have no secondary weapon readied.");
314  | 	}
315  | 
316  | 	if (u.twoweap && !can_twoweapon())
317  | 		untwoweapon();
318  | 
319  | 	return (result);
320  | }
321  | 
322  | int
323  | dowieldquiver()
324  | {
325  | 	register struct obj *newquiver;
326  | 
327  | 
328  | 	/* Since the quiver isn't in your hands, don't check cantwield(), */
329  | 	/* will_weld(), touch_petrifies(), etc. */
330  | 	multi = 0;
331  | 
332  | 	/* Because 'Q' used to be quit... */
333  | 	if (!flags.suppress_alert || flags.suppress_alert < FEATURE_NOTICE_VER(3,3,0))
334  | 		pline("Note: Please use #quit if you wish to exit the game.");
335  | 
336  | 	/* Prompt for a new quiver */
337  | 	if (!(newquiver = getobj(uslinging() ? bullets : ready_objs, "ready")))
338  | 		/* Cancelled */
339  | 		return (0);
340  | 
341  | 	/* Handle no object, or object in other slot */
342  | 	/* Any type is okay, since we give no intrinsics anyways */
343  | 	if (newquiver == &zeroobj) {
344  | 		/* Explicitly nothing */
345  | 		if (uquiver) {
346  | 			You("now have no ammunition readied.");
347  | 			setuqwep(newquiver = (struct obj *) 0);
348  | 		} else {
349  | 			You("already have no ammunition readied!");
350  | 			return(0);
351  | 		}
352  | 	} else if (newquiver == uquiver) {
353  | 		pline("That ammunition is already readied!");
354  | 		return(0);
355  | 	} else if (newquiver == uwep) {
356  | 		/* Prevent accidentally readying the main weapon */
357  | 		pline("%s already being used as a weapon!",
358  | 		      (uwep->quan == 1L) ? "That is" : "They are");
359  | 		return(0);
360  | 	} else if (newquiver->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL
361  | #ifdef STEED
362  | 			| W_SADDLE
363  | #endif
364  | 			)) {
365  | 		You("cannot ready that!");
366  | 		return (0);
367  | 	} else {
368  | 		long dummy;
369  | 
370  | 
371  | 		/* Check if it's the secondary weapon */
372  | 		if (newquiver == uswapwep) {
373  | 			setuswapwep((struct obj *) 0);
374  | 			untwoweapon();
375  | 		}
376  | 
377  | 		/* Okay to put in quiver; print it */
378  | 		dummy = newquiver->owornmask;
379  | 		newquiver->owornmask |= W_QUIVER;
380  | 		prinv((char *)0, newquiver, 0L);
381  | 		newquiver->owornmask = dummy;
382  | 	}
383  | 
384  | 	/* Finally, place it in the quiver */
385  | 	setuqwep(newquiver);
386  | 	/* Take no time since this is a convenience slot */
387  | 	return (0);
388  | }
389  | 
390  | int
391  | can_twoweapon()
392  | {
393  | 	struct obj *otmp;
394  | 
395  | #define NOT_WEAPON(obj) (!is_weptool(obj) && obj->oclass != WEAPON_CLASS)
396  | 	if (Upolyd)
397  | 		You("can only use two weapons in your normal form.");
398  | 	else if (!uwep || !uswapwep)
399  | 		Your("%s%s%s empty.", uwep ? "left " : uswapwep ? "right " : "",
400  | 			body_part(HAND), (!uwep && !uswapwep) ? "s are" : " is");
401  | 	else if (NOT_WEAPON(uwep) || NOT_WEAPON(uswapwep)) {
402  | 		otmp = NOT_WEAPON(uwep) ? uwep : uswapwep;
403  | 		pline("%s %s.", Yname2(otmp),
404  | 		    (otmp->quan) > 1L ? "aren't weapons" : "isn't a weapon");
405  | 	} else if (bimanual(uwep) || bimanual(uswapwep)) {
406  | 		otmp = bimanual(uwep) ? uwep : uswapwep;
407  | 		pline("%s isn't one-handed.", Yname2(otmp));
408  | 	} else if (uarms)
409  | 		You_cant("use two weapons while wearing a shield.");
410  | 	else if (uswapwep->oartifact)
411  | 		pline("%s resists being held second to another weapon!",
412  | 			Yname2(uswapwep));
413  | 	else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE &&
414  | 		    touch_petrifies(&mons[uswapwep->corpsenm]))) {
415  | 		char kbuf[BUFSZ];
416  | 
417  | 		You("wield the %s corpse with your bare %s.",
418  | 		    mons[uswapwep->corpsenm].mname, body_part(HAND));
419  | 		Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname));
420  | 		instapetrify(kbuf);
421  | 	} else if (Glib || uswapwep->cursed) {
422  | 		struct obj *obj = uswapwep;
423  | 
424  | 		Your("%s from your %s!",  aobjnam(obj, "slip"),
425  | 				makeplural(body_part(HAND)));
426  | 		if (!Glib)
427  | 			obj->bknown = TRUE;
428  | 		setuswapwep((struct obj *) 0);
429  | 		dropx(obj);
430  | 	} else
431  | 		return (TRUE);
432  | 	return (FALSE);
433  | }
434  | 
435  | int
436  | dotwoweapon()
437  | {
438  | 	/* You can always toggle it off */
439  | 	if (u.twoweap) {
440  | 		You("switch to your primary weapon.");
441  | 		u.twoweap = 0;
442  | 		update_inventory();
443  | 		return (0);
444  | 	}
445  | 
446  | 	/* May we use two weapons? */
447  | 	if (can_twoweapon()) {
448  | 		/* Success! */
449  | 		You("begin two-weapon combat.");
450  | 		u.twoweap = 1;
451  | 		update_inventory();
452  | 		return (rnd(20) > ACURR(A_DEX));
453  | 	}
454  | 	return (0);
455  | }
456  | 
457  | /*** Functions to empty a given slot ***/
458  | /* These should be used only when the item can't be put back in
459  |  * the slot by life saving.  Proper usage includes:
460  |  * 1.  The item has been eaten, stolen, burned away, or rotted away.
461  |  * 2.  Making an item disappear for a bones pile.
462  |  */
463  | void
464  | uwepgone()
465  | {
466  | 	if (uwep) {
467  | 		setworn((struct obj *)0, W_WEP);
468  | 		unweapon = TRUE;
469  | 		update_inventory();
470  | 	}
471  | }
472  | 
473  | void
474  | uswapwepgone()
475  | {
476  | 	if (uswapwep) {
477  | 		setworn((struct obj *)0, W_SWAPWEP);
478  | 		update_inventory();
479  | 	}
480  | }
481  | 
482  | void
483  | uqwepgone()
484  | {
485  | 	if (uquiver) {
486  | 		setworn((struct obj *)0, W_QUIVER);
487  | 		update_inventory();
488  | 	}
489  | }
490  | 
491  | void
492  | untwoweapon()
493  | {
494  | 	if (u.twoweap) {
495  | 		You("can no longer use two weapons at once.");
496  | 		u.twoweap = FALSE;
497  | 		update_inventory();
498  | 	}
499  | 	return;
500  | }
501  | 
502  | /* Maybe rust weapon, or corrode it if acid damage is called for */
503  | void
504  | erode_weapon(target, acid_dmg)
505  | struct obj *target;
506  | boolean acid_dmg;
507  | {
508  | 	int erosion;
509  | 	struct monst *victim;
510  | 	boolean vismon;
511  | 
512  | 	if (!target)
513  | 	    return;
514  | 	if (!carried(target) && !mcarried(target))
515  | 	    panic("erode whose weapon? (%d)", (int)target->where);
516  | 	victim = carried(target) ? &youmonst : target->ocarry;
517  | 	vismon = (victim != &youmonst) && canseemon(victim);
518  | 
519  | 	erosion = acid_dmg ? target->oeroded2 : target->oeroded;
520  | 
521  | 	if (target->greased) {
522  | 	    grease_protect(target,(char *)0,FALSE,victim);
523  | 	} else if (target->oclass == SCROLL_CLASS) {
524  | #ifdef MAIL
525  | 	    if(target->otyp != SCR_MAIL)
526  | #endif
527  | 	    {
528  | 		if (!Blind) {
529  | 		    if (victim == &youmonst)
530  | 			Your("%s.", aobjnam(target, "fade"));
531  | 		    else if (vismon)
532  | 			pline("%s's %s.", Monnam(victim),
533  | 			      aobjnam(target, "fade"));
534  | 		}
535  | 		target->otyp = SCR_BLANK_PAPER;
536  | 		target->spe = 0;
537  | 	    }
538  | 	} else if (target->oerodeproof ||
539  | 		(acid_dmg ? !is_corrodeable(target) : !is_rustprone(target))) {
540  | 	    if (flags.verbose || !(target->oerodeproof && target->rknown)) {
541  | 		if (victim == &youmonst)
542  | 		    Your("%s not affected.", aobjnam(target, "are"));
543  | 		else if (vismon)
544  | 		    pline("%s's %s not affected.", Monnam(victim),
545  | 			aobjnam(target, "are"));
546  | 	    }
547  | 	    if (target->oerodeproof) target->rknown = TRUE;
548  | 	} else if (erosion < MAX_ERODE) {
549  | 	    if (victim == &youmonst)
550  | 		Your("%s%s!", aobjnam(target, acid_dmg ? "corrode" : "rust"),
551  | 		    erosion+1 == MAX_ERODE ? " completely" :
552  | 		    erosion ? " further" : "");
553  | 	    else if (vismon)
554  | 		pline("%s's %s%s!", Monnam(victim),
555  | 		    aobjnam(target, acid_dmg ? "corrode" : "rust"),
556  | 		    erosion+1 == MAX_ERODE ? " completely" :
557  | 		    erosion ? " further" : "");
558  | 	    if (acid_dmg)
559  | 		target->oeroded2++;
560  | 	    else
561  | 		target->oeroded++;
562  | 	} else {
563  | 	    if (flags.verbose) {
564  | 		if (victim == &youmonst)
565  | 		    Your("%s completely %s.",
566  | 			aobjnam(target, Blind ? "feel" : "look"),
567  | 			acid_dmg ? "corroded" : "rusty");
568  | 		else if (vismon)
569  | 		    pline("%s's %s completely %s.", Monnam(victim),
570  | 			aobjnam(target, "look"),
571  | 			acid_dmg ? "corroded" : "rusty");
572  | 	    }
573  | 	}
574  | }
575  | 
576  | int
577  | chwepon(otmp, amount)
578  | register struct obj *otmp;
579  | register int amount;
580  | {
581  | 	register const char *color = hcolor((amount < 0) ? Black : blue);
582  | 	register const char *xtime;
583  | 
584  | 	if(!uwep || (uwep->oclass != WEAPON_CLASS && !is_weptool(uwep))) {
585  | 		char buf[BUFSZ];
586  | 
587  | 		Sprintf(buf, "Your %s %s.", makeplural(body_part(HAND)),
588  | 			(amount >= 0) ? "twitch" : "itch");
589  | 		strange_feeling(otmp, buf);
590  | 		exercise(A_DEX, (boolean) (amount >= 0));
591  | 		return(0);
592  | 	}
593  | 
594  | 	if(uwep->otyp == WORM_TOOTH && amount >= 0) {
595  | 		uwep->otyp = CRYSKNIFE;
596  | 		uwep->oerodeproof = 0;
597  | 		Your("weapon seems sharper now.");
598  | 		uwep->cursed = 0;
599  | 		return(1);
600  | 	}
601  | 
602  | 	if(uwep->otyp == CRYSKNIFE && amount < 0) {
603  | 		uwep->otyp = WORM_TOOTH;
604  | 		uwep->oerodeproof = 0;
605  | 		Your("weapon seems duller now.");
606  | 		return(1);
607  | 	}
608  | 
609  | 	if (amount < 0 && uwep->oartifact && restrict_name(uwep, ONAME(uwep))) {
610  | 	    if (!Blind)
611  | 		Your("%s %s.", aobjnam(uwep, "faintly glow"), color);
612  | 	    return(1);
613  | 	}
614  | 	/* there is a (soft) upper and lower limit to uwep->spe */
615  | 	if(((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0))
616  | 								&& rn2(3)) {
617  | 	    if (!Blind)
618  | 	    Your("%s %s for a while and then evaporate%s.",
619  | 		 aobjnam(uwep, "violently glow"), color,
620  | 		 uwep->quan == 1L ? "s" : "");
621  | 	    else
622  | 		Your("%s.", aobjnam(uwep, "evaporate"));
623  | 
624  | 	    while(uwep)		/* let all of them disappear */
625  | 				/* note: uwep->quan = 1 is nogood if unpaid */
626  | 		useup(uwep);
627  | 	    return(1);
628  | 	}
629  | 	if (!Blind) {
630  | 	    xtime = (amount*amount == 1) ? "moment" : "while";
631  | 	    Your("%s %s for a %s.",
632  | 		 aobjnam(uwep, amount == 0 ? "violently glow" : "glow"),
633  | 		 color, xtime);
634  | 	}
635  | 	uwep->spe += amount;
636  | 	if(amount > 0) uwep->cursed = 0;
637  | 
638  | 	/*
639  | 	 * Enchantment, which normally improves a weapon, has an
640  | 	 * addition adverse reaction on Magicbane whose effects are
641  | 	 * spe dependent.  Give an obscure clue here.
642  | 	 */
643  | 	if (uwep->oartifact == ART_MAGICBANE && uwep->spe >= 0) {
644  | 		Your("right %s %sches!",
645  | 			body_part(HAND),
646  | 			(((amount > 1) && (uwep->spe > 1)) ? "flin" : "it"));
647  | 	}
648  | 
649  | 	/* an elven magic clue, cookie@keebler */
650  | 	if ((uwep->spe > 5)
651  | 		&& (is_elven_weapon(uwep) || uwep->oartifact || !rn2(7)))
652  | 	    Your("%s unexpectedly.",
653  | 		aobjnam(uwep, "suddenly vibrate"));
654  | 
655  | 	return(1);
656  | }
657  | 
658  | int
659  | welded(obj)
660  | register struct obj *obj;
661  | {
662  | 	if (obj && obj == uwep && will_weld(obj)) {
663  | 		obj->bknown = TRUE;
664  | 		return 1;
665  | 	}
666  | 	return 0;
667  | }
668  | 
669  | void
670  | weldmsg(obj)
671  | register struct obj *obj;
672  | {
673  | 	long savewornmask;
674  | 
675  | 	savewornmask = obj->owornmask;
676  | 	Your("%s %s welded to your %s!",
677  | 		xname(obj), (obj->quan == 1L) ? "is" : "are",
678  | 		bimanual(obj) ? (const char *)makeplural(body_part(HAND))
679  | 				: body_part(HAND));
680  | 	obj->owornmask = savewornmask;
681  | }
682  | 
683  | /*wield.c*/