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*/