1 /* NetHack 3.6 dothrow.c $NHDT-Date: 1556201496 2019/04/25 14:11:36 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.160 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Robert Patrick Rankin, 2013. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* Contains code for 't' (throw) */
8 /* JNetHack Copyright */
9 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
10 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
11 /* JNetHack may be freely redistributed. See license for details. */
15 STATIC_DCL int FDECL(throw_obj, (struct obj *, int));
16 STATIC_DCL boolean FDECL(ok_to_throw, (int *));
17 STATIC_DCL void NDECL(autoquiver);
18 STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
19 STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *, BOOLEAN_P));
20 STATIC_DCL int FDECL(throw_gold, (struct obj *));
21 STATIC_DCL void FDECL(check_shop_obj, (struct obj *, XCHAR_P, XCHAR_P,
23 STATIC_DCL void FDECL(breakmsg, (struct obj *, BOOLEAN_P));
24 STATIC_DCL boolean FDECL(toss_up, (struct obj *, BOOLEAN_P));
25 STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj * obj));
26 STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t, int, int));
28 static NEARDATA const char toss_objs[] = { ALLOW_COUNT, COIN_CLASS,
29 ALL_CLASSES, WEAPON_CLASS, 0 };
30 /* different default choices when wielding a sling (gold must be included) */
31 static NEARDATA const char bullets[] = { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES,
34 /* thrownobj (decl.c) tracks an object until it lands */
36 extern boolean notonhead; /* for long worms */
38 /* Throw the selected object, asking for direction */
40 throw_obj(obj, shotlimit)
48 boolean twoweap, weakmultishot;
50 /* ask "in what direction?" */
51 if (!getdir((char *) 0)) {
52 /* No direction specified, so cancel the throw;
53 * might need to undo an object split.
54 * We used to use freeinv(obj),addinv(obj) here, but that can
55 * merge obj into another stack--usually quiver--even if it hadn't
56 * been split from there (possibly triggering a panic in addinv),
57 * and freeinv+addinv potentially has other side-effects.
59 if (obj->o_id == context.objsplit.parent_oid
60 || obj->o_id == context.objsplit.child_oid)
61 (void) unsplitobj(obj);
62 return 0; /* no time passes */
66 * Throwing money is usually for getting rid of it when
67 * a leprechaun approaches, or for bribing an oncoming
68 * angry monster. So throw the whole object.
70 * If the money is in quiver, throw one coin at a time,
71 * possibly using a sling.
73 if (obj->oclass == COIN_CLASS && obj != uquiver)
74 return throw_gold(obj);
77 if (!canletgo(obj, "throw"))
79 if (!canletgo(obj, "
\93\8a\82°
\82é"))
81 if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
83 pline("%s must be wielded before it can be thrown.", The(xname(obj)));
85 pline("
\93\8a\82°
\82é
\91O
\82É%s
\82ð
\91\95\94õ
\82µ
\82È
\82
\82Ä
\82Í
\82È
\82ç
\82È
\82¢
\81D", xname(obj));
88 if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) < STR19(25))
89 || (obj->otyp == BOULDER && !throws_rocks(youmonst.data))) {
91 pline("It's too heavy.");
93 pline("
\8fd
\82·
\82¬
\82Ä
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
96 if (!u.dx && !u.dy && !u.dz) {
98 You("cannot throw an object at yourself.");
100 pline("
\8e©
\95ª
\82É
\8cü
\82©
\82Á
\82Ä
\82Í
\93\8a\82°
\82ç
\82ê
\82È
\82¢
\81D");
104 if (!uarmg && obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])
105 && !Stone_resistance) {
107 You("throw %s with your bare %s.",
108 corpse_xname(obj, (const char *) 0, CXN_PFX_THE),
109 /* throwing with one hand, but pluralize since the
110 expression "with your bare hands" sounds better */
111 makeplural(body_part(HAND)));
113 You("
\91f%s
\82Å%s
\82Ì
\8e\80\91Ì
\82ð
\93\8a\82°
\82½
\81D",
115 corpse_xname(obj, (const char *) 0, CXN_PFX_THE));
118 Sprintf(killer.name, "throwing %s bare-handed", killer_xname(obj));
120 Sprintf(killer.name, "%s
\82Ì
\8e\80\91Ì
\82ð
\91f
\8eè
\82Å
\93\8a\82°
\82Ä", killer_xname(obj));
121 instapetrify(killer.name);
127 if (is_wet_towel(obj))
128 dry_a_towel(obj, -1, FALSE);
130 /* Multishot calculations
131 * (potential volley of up to N missiles; default for N is 1)
134 skill = objects[obj->otyp].oc_skill;
135 if (obj->quan > 1L /* no point checking if there's only 1 */
136 /* ammo requires corresponding launcher be wielded */
137 && (is_ammo(obj) ? matching_launcher(obj, uwep)
138 /* otherwise any stackable (non-ammo) weapon */
139 : obj->oclass == WEAPON_CLASS)
140 && !(Confusion || Stunned)) {
141 /* some roles don't get a volley bonus until becoming expert */
142 weakmultishot = (Role_if(PM_WIZARD) || Role_if(PM_PRIEST)
143 || (Role_if(PM_HEALER) && skill != P_KNIFE)
144 || (Role_if(PM_TOURIST) && skill != -P_DART)
145 /* poor dexterity also inhibits multishot */
146 || Fumbling || ACURR(A_DEX) <= 6);
148 /* Bonus if the player is proficient in this weapon... */
149 switch (P_SKILL(weapon_type(obj))) {
157 default: /* basic or unskilled: no bonus */
160 /* ...or is using a special weapon for their role... */
161 switch (Role_switch) {
163 /* give bonus for low-tech gear */
164 if (skill == -P_SLING || skill == P_SPEAR)
168 /* allow higher volley count despite skill limitation */
169 if (skill == -P_SHURIKEN)
173 /* arbitrary; encourage use of other missiles beside daggers */
174 if (skill != P_DAGGER)
178 /* possibly should add knives... */
179 if (skill == P_DAGGER)
183 /* role-specific launcher and its ammo */
184 if (obj->otyp == YA && uwep && uwep->otyp == YUMI)
188 break; /* No bonus */
190 /* ...or using their race's special bow; no bonus for spears */
192 switch (Race_switch) {
194 if (obj->otyp == ELVEN_ARROW && uwep
195 && uwep->otyp == ELVEN_BOW)
199 if (obj->otyp == ORCISH_ARROW && uwep
200 && uwep->otyp == ORCISH_BOW)
204 /* arbitrary; there isn't any gnome-specific gear */
205 if (skill == -P_CROSSBOW)
211 break; /* No bonus */
214 /* crossbows are slow to load and probably shouldn't allow multiple
215 shots at all, but that would result in players never using them;
216 instead, high strength is necessary to load and shoot quickly */
217 if (multishot > 1 && skill == -P_CROSSBOW
218 && ammo_and_launcher(obj, uwep)
219 && (int) ACURRSTR < (Race_if(PM_GNOME) ? 16 : 18))
220 multishot = rnd(multishot);
222 multishot = rnd(multishot);
223 if ((long) multishot > obj->quan)
224 multishot = (int) obj->quan;
225 if (shotlimit > 0 && multishot > shotlimit)
226 multishot = shotlimit;
229 m_shot.s = ammo_and_launcher(obj, uwep) ? TRUE : FALSE;
230 /* give a message if shooting more than one, or if player
231 attempted to specify a count */
232 if (multishot > 1 || shotlimit > 0) {
233 /* "You shoot N arrows." or "You throw N daggers." */
235 You("%s %d %s.", m_shot.s ? "shoot" : "throw",
236 multishot, /* (might be 1 if player gave shotlimit) */
237 (multishot == 1) ? singular(obj, xname) : xname(obj));
239 You("%d%s
\82Ì%s
\82ð%s
\81D",
241 numeral(obj), xname(obj),
242 m_shot.s ? "
\8c\82\82Á
\82½" : "
\93\8a\82°
\82½");
246 wep_mask = obj->owornmask;
247 m_shot.o = obj->otyp;
248 m_shot.n = multishot;
249 for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) {
251 /* split this object off from its slot if necessary */
252 if (obj->quan > 1L) {
253 otmp = splitobj(obj, 1L);
257 remove_worn_item(otmp, FALSE);
260 throwit(otmp, wep_mask, twoweap);
262 m_shot.n = m_shot.i = 0;
263 m_shot.o = STRANGE_OBJECT;
269 /* common to dothrow() and dofire() */
271 ok_to_throw(shotlimit_p)
272 int *shotlimit_p; /* (see dothrow()) */
274 /* kludge to work around parse()'s pre-decrement of `multi' */
275 *shotlimit_p = (multi || save_cm) ? multi + 1 : 0;
276 multi = 0; /* reset; it's been used up */
278 if (notake(youmonst.data)) {
280 You("are physically incapable of throwing or shooting anything.");
282 You("
\89½
\82©
\82ð
\93\8a\82°
\82é
\82Ì
\82Í
\95¨
\97\9d\93I
\82É
\96³
\97\9d\82¾
\81D");
284 } else if (nohands(youmonst.data)) {
286 You_cant("throw or shoot without hands."); /* not body_part(HAND) */
288 You("
\8eè
\82ª
\82È
\82¢
\81D"); /* not body_part(HAND) */
291 /*[what about !freehand(), aside from cursed missile launcher?]*/
293 if (check_capacity((char *) 0))
298 /* t command - throw */
302 register struct obj *obj;
306 * Since some characters shoot multiple missiles at one time,
307 * allow user to specify a count prefix for 'f' or 't' to limit
308 * number of items thrown (to avoid possibly hitting something
309 * behind target after killing it, or perhaps to conserve ammo).
311 * Prior to 3.3.0, command ``3t'' meant ``t(shoot) t(shoot) t(shoot)''
312 * and took 3 turns. Now it means ``t(shoot at most 3 missiles)''.
314 * [3.6.0: shot count setup has been moved into ok_to_throw().]
316 if (!ok_to_throw(&shotlimit))
319 obj = getobj(uslinging() ? bullets : toss_objs, "throw");
320 /* it is also possible to throw food */
321 /* (or jewels, or iron balls... ) */
323 return obj ? throw_obj(obj, shotlimit) : 0;
326 /* KMH -- Automatically fill quiver */
327 /* Suggested by Jeffrey Bay <jbay@convex.hp.com> */
331 struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0, *altammo = 0;
336 /* Scan through the inventory */
337 for (otmp = invent; otmp; otmp = otmp->nobj) {
338 if (otmp->owornmask || otmp->oartifact || !otmp->dknown) {
340 } else if (otmp->otyp == ROCK
341 /* seen rocks or known flint or known glass */
342 || (otmp->otyp == FLINT
343 && objects[otmp->otyp].oc_name_known)
344 || (otmp->oclass == GEM_CLASS
345 && objects[otmp->otyp].oc_material == GLASS
346 && objects[otmp->otyp].oc_name_known)) {
349 else if (ammo_and_launcher(otmp, uswapwep))
353 } else if (otmp->oclass == GEM_CLASS) {
354 ; /* skip non-rock gems--they're ammo but
355 player has to select them explicitly */
356 } else if (is_ammo(otmp)) {
357 if (ammo_and_launcher(otmp, uwep))
358 /* Ammo matched with launcher (bow+arrow, crossbow+bolt) */
360 else if (ammo_and_launcher(otmp, uswapwep))
363 /* Mismatched ammo (no better than an ordinary weapon) */
365 } else if (is_missile(otmp)) {
366 /* Missile (dart, shuriken, etc.) */
368 } else if (otmp->oclass == WEAPON_CLASS && throwing_weapon(otmp)) {
369 /* Ordinary weapon */
370 if (objects[otmp->otyp].oc_skill == P_DAGGER && !omissile)
377 /* Pick the best choice */
390 /* f command -- fire: throw from the quiver */
398 * Same as dothrow(), except we use quivered missile instead
399 * of asking what to throw/shoot.
401 * If quiver is empty, we use autoquiver to fill it when the
402 * corresponding option is on. If the option is off or if
403 * autoquiver doesn't select anything, we ask what to throw.
404 * Then we put the chosen item into the quiver slot unless
405 * it is already in another slot. [Matters most if it is a
406 * stack but also matters for single item if this throw gets
407 * aborted (ESC at the direction prompt). Already wielded
408 * item is excluded because wielding might be necessary
409 * (Mjollnir) or make the throw behave differently (aklys),
410 * and alt-wielded item is excluded because switching slots
411 * would end two-weapon combat even if throw gets aborted.]
413 if (!ok_to_throw(&shotlimit))
416 if ((obj = uquiver) == 0) {
417 if (!flags.autoquiver) {
419 You("have no ammunition readied.");
421 You("
\94
\8eË
\8f\80\94õ
\82ª
\90®
\82Á
\82Ä
\82¢
\82È
\82¢
\81I");
424 if ((obj = uquiver) == 0)
426 You("have nothing appropriate for your quiver.");
428 You("
\94
\8eË
\82·
\82é
\82à
\82Ì
\82ª
\82È
\82¢
\81D");
430 /* if autoquiver is disabled or has failed, prompt for missile;
431 fill quiver with it if it's not wielded or worn */
433 /* in case we're using ^A to repeat prior 'f' command, don't
434 use direction of previous throw as getobj()'s choice here */
436 /* choose something from inventory, then usually quiver it */
437 obj = getobj(uslinging() ? bullets : toss_objs, "throw");
438 /* Q command doesn't allow gold in quiver */
439 if (obj && !obj->owornmask && obj->oclass != COIN_CLASS)
440 setuqwep(obj); /* demi-autoquiver */
442 /* give feedback if quiver has now been filled */
444 uquiver->owornmask &= ~W_QUIVER; /* less verbose */
446 prinv("You ready:", uquiver, 0L);
448 prinv("
\8f\80\94õ
\81F", uquiver, 0L);
449 uquiver->owornmask |= W_QUIVER;
453 return obj ? throw_obj(obj, shotlimit) : 0;
456 /* if in midst of multishot shooting/throwing, stop early */
458 endmultishot(verbose)
461 if (m_shot.i < m_shot.n) {
462 if (verbose && !context.mon_moving) {
464 You("stop %s after the %d%s %s.",
465 m_shot.s ? "firing" : "throwing", m_shot.i, ordin(m_shot.i),
466 m_shot.s ? "shot" : "toss");
468 You("%d
\94
\96Ú
\82ð%s
\82Æ
\82±
\82ë
\82Å
\8ec
\82è
\82ð%s
\82Ì
\82ð
\82â
\82ß
\82½
\81D", m_shot.i,
469 m_shot.s ? "
\8c\82\82Á
\82½" : "
\93\8a\82°
\82½",
470 m_shot.s ? "
\8c\82\82Â" : "
\93\8a\82°
\82é");
473 m_shot.n = m_shot.i; /* make current shot be the last */
477 /* Object hits floor at hero's feet.
478 Called from drop(), throwit(), hold_another_object(). */
480 hitfloor(obj, verbosely)
482 boolean verbosely; /* usually True; False if caller has given drop message */
484 if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater || u.uswallow) {
488 if (IS_ALTAR(levl[u.ux][u.uy].typ))
492 pline("%s %s the %s.", Doname2(obj), otense(obj, "hit"),
493 surface(u.ux, u.uy));
495 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", Doname2(obj),
496 surface(u.ux, u.uy));
499 if (hero_breaks(obj, u.ux, u.uy, TRUE))
501 if (ship_object(obj, u.ux, u.uy, FALSE))
507 * Walk a path from src_cc to dest_cc, calling a proc for each location
508 * except the starting one. If the proc returns FALSE, stop walking
509 * and return FALSE. If stopped early, dest_cc will be the location
510 * before the failed callback.
513 walk_path(src_cc, dest_cc, check_proc, arg)
516 boolean FDECL((*check_proc), (genericptr_t, int, int));
519 int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
520 boolean keep_going = TRUE;
522 /* Use Bresenham's Line Algorithm to walk from src to dest.
524 * This should be replaced with a more versatile algorithm
525 * since it handles slanted moves in a suboptimal way.
526 * Going from 'x' to 'y' needs to pass through 'z', and will
527 * fail if there's an obstable there, but it could choose to
528 * pass through 'Z' instead if that way imposes no obstacle.
531 * Perhaps we should check both paths and accept whichever
532 * one isn't blocked. But then multiple zigs and zags could
533 * potentially produce a meandering path rather than the best
534 * attempt at a straight line. And (*check_proc)() would
535 * need to work more like 'travel', distinguishing between
536 * testing a possible move and actually attempting that move.
538 dx = dest_cc->x - src_cc->x;
539 dy = dest_cc->y - src_cc->y;
540 prev_x = x = src_cc->x;
541 prev_y = y = src_cc->y;
565 /* check for early exit condition */
566 if (!(keep_going = (*check_proc)(arg, x, y)))
579 /* check for early exit condition */
580 if (!(keep_going = (*check_proc)(arg, x, y)))
586 return TRUE; /* successful */
593 /* hack for hurtle_step() -- it ought to be changed to take an argument
594 indicating lev/fly-to-dest vs lev/fly-to-dest-minus-one-land-on-dest
595 vs drag-to-dest; original callers use first mode, jumping wants second,
596 grappling hook backfire and thrown chained ball need third */
598 hurtle_jump(arg, x, y)
603 long save_EWwalking = EWwalking;
605 /* prevent jumping over water from being placed in that water */
606 EWwalking |= I_SPECIAL;
607 res = hurtle_step(arg, x, y);
608 EWwalking = save_EWwalking;
613 * Single step for the hero flying through the air from jumping, flying,
614 * etc. Called from hurtle() and jump() via walk_path(). We expect the
615 * argument to be a pointer to an integer -- the range -- which is
616 * used in the calculation of points off if we hit something.
618 * Bumping into monsters won't cause damage but will wake them and make
619 * them angry. Auto-pickup isn't done, since you don't have control over
620 * your movements at the time.
622 * Possible additions/changes:
623 * o really attack monster if we hit one
624 * o set stunned if we hit a wall or door
625 * o reset nomul when we stop
626 * o creepy feeling if pass through monster (if ever implemented...)
628 * o let jumps go over boulders
631 hurtle_step(arg, x, y)
635 int ox, oy, *range = (int *) arg;
638 boolean may_pass = TRUE, via_jumping, stopping_short;
644 You_feel("the spirits holding you back.");
646 You_feel("
\82 \82È
\82½
\82ð
\95ß
\82Ü
\82¦
\82Ä
\82¢
\82½
\8d°
\82ª
\96ß
\82Á
\82½
\8bC
\82ª
\82µ
\82½
\81D");
648 } else if (!in_out_region(x, y)) {
650 } else if (*range == 0) {
651 return FALSE; /* previous step wants to stop now */
653 via_jumping = (EWwalking & I_SPECIAL) != 0L;
654 stopping_short = (via_jumping && *range < 2);
656 if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
657 boolean odoor_diag = (IS_DOOR(levl[x][y].typ)
658 && (levl[x][y].doormask & D_ISOPEN)
659 && (u.ux - x) && (u.uy - y));
661 if (IS_ROCK(levl[x][y].typ) || closed_door(x, y) || odoor_diag) {
666 You("hit the door edge!");
668 You("
\94à
\82Ì
\92[
\82É
\93\96\82½
\82Á
\82½
\81I");
672 pline("
\82¢
\82Ä
\82Á
\81I");
673 if (IS_TREE(levl[x][y].typ))
675 s = "bumping into a tree";
677 s = "
\96Ø
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
678 else if (IS_ROCK(levl[x][y].typ))
680 s = "bumping into a wall";
682 s = "
\95Ç
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
685 s = "bumping into a door";
687 s = "
\94à
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
688 dmg = rnd(2 + *range);
689 losehp(Maybe_Half_Phys(dmg), s, KILLED_BY);
690 wake_nearto(x,y, 10);
693 if (levl[x][y].typ == IRONBARS) {
695 You("crash into some iron bars. Ouch!");
697 You("
\93S
\82Ì
\96_
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D
\82¢
\82Ä
\82Á
\81I");
698 dmg = rnd(2 + *range);
700 losehp(Maybe_Half_Phys(dmg), "crashing into iron bars",
703 losehp(Maybe_Half_Phys(dmg), "
\93S
\82Ì
\96_
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä",
706 wake_nearto(x,y, 20);
709 if ((obj = sobj_at(BOULDER, x, y)) != 0) {
711 You("bump into a %s. Ouch!", xname(obj));
713 You("%s
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D
\82¢
\82Ä
\82Á
\81I", xname(obj));
714 dmg = rnd(2 + *range);
716 losehp(Maybe_Half_Phys(dmg), "bumping into a boulder", KILLED_BY);
718 losehp(Maybe_Half_Phys(dmg), "
\8aâ
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä", KILLED_BY);
719 wake_nearto(x,y, 10);
723 /* did we hit a no-dig non-wall position? */
725 You("smack into something!");
727 You("
\89½
\82©
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81I");
728 dmg = rnd(2 + *range);
730 losehp(Maybe_Half_Phys(dmg), "touching the edge of the universe",
733 losehp(Maybe_Half_Phys(dmg), "
\90¢
\8aE
\82Ì
\89Ê
\82Ä
\82É
\90G
\82ê
\82Ä",
736 wake_nearto(x,y, 10);
739 if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
740 && bad_rock(youmonst.data, x, u.uy)) {
741 boolean too_much = (invent && (inv_weight() + weight_cap() > 600));
743 /* Move at a diagonal. */
744 if (bigmonst(youmonst.data) || too_much) {
746 You("%sget forcefully wedged into a crevice.",
747 too_much ? "and all your belongings " : "");
749 You("%s
\82Í
\82Þ
\82è
\82â
\82è
\82·
\82«
\8aÔ
\82É
\89\9f\82µ
\8d\9e\82ß
\82ç
\82ê
\82½
\81D",
750 too_much ? "
\82Æ
\91S
\95\94\82Ì
\89×
\95¨" : "");
752 dmg = rnd(2 + *range);
754 losehp(Maybe_Half_Phys(dmg), "wedging into a narrow crevice",
757 losehp(Maybe_Half_Phys(dmg), "
\8b·
\82¢
\82·
\82«
\8aÔ
\82É
\89\9f\82µ
\8d\9e\82ß
\82ç
\82ê
\82Ä",
760 wake_nearto(x,y, 10);
766 if ((mon = m_at(x, y)) != 0
767 #if 0 /* we can't include these two exceptions unless we know we're
768 * going to end up past the current spot rather than on it;
769 * for that, we need to know that the range is not exhausted
770 * and also that the next spot doesn't contain an obstacle */
771 && !(mon->mundetected && hides_under(mon) && (Flying || Levitation))
772 && !(mon->mundetected && mon->data->mlet == S_EEL
773 && (Flying || Levitation || Wwalking))
776 const char *mnam, *pronoun;
777 int glyph = glyph_at(x, y);
779 mon->mundetected = 0; /* wakeup() will handle mimic */
780 mnam = a_monnam(mon); /* after unhiding */
781 pronoun = noit_mhim(mon);
783 if (!strcmp(mnam, "it")) {
785 if (!strcmp(mnam, "
\89½
\8eÒ
\82©")) {
788 mnam = !strcmp(pronoun, "it") ? "something" : "someone";
790 mnam = !strcmp(pronoun, "
\89½
\8eÒ
\82©") ? "
\89½
\82©" : "
\89½
\8eÒ
\82©";
793 if (!glyph_is_monster(glyph) && !glyph_is_invisible(glyph))
795 You("find %s by bumping into %s.", mnam, pronoun);
797 You("
\82Ô
\82¿
\82 \82½
\82Á
\82½
\82±
\82Æ
\82Å%s
\82ð
\8c©
\82Â
\82¯
\82½
\81D", mnam);
801 You("bump into %s.", mnam);
803 You("%s
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D", mnam);
805 if (!canspotmon(mon))
806 map_invisible(mon->mx, mon->my);
807 setmangry(mon, FALSE);
808 wake_nearto(x, y, 10);
812 if ((u.ux - x) && (u.uy - y)
813 && bad_rock(youmonst.data, u.ux, y)
814 && bad_rock(youmonst.data, x, u.uy)) {
815 /* Move at a diagonal. */
818 You("come to an abrupt halt!");
820 You("
\82Æ
\82Â
\82º
\82ñ
\92â
\8e~
\82µ
\82½
\81I");
825 /* Caller has already determined that dragging the ball is allowed */
826 if (Punished && uball->where == OBJ_FLOOR) {
828 xchar ballx, bally, chainx, chainy;
831 if (drag_ball(x, y, &bc_control, &ballx, &bally, &chainx,
832 &chainy, &cause_delay, TRUE))
833 move_bc(0, bc_control, ballx, bally, chainx, chainy);
838 u_on_newpos(x, y); /* set u.<ux,uy>, u.usteed-><mx,my>; cliparound(); */
839 newsym(ox, oy); /* update old position */
840 vision_recalc(1); /* update for new position */
842 /* if terrain type changes, levitation or flying might become blocked
843 or unblocked; might issue message, so do this after map+vision has
844 been updated for new location instead of right after u_on_newpos() */
845 if (levl[u.ux][u.uy].typ != levl[ox][oy].typ)
848 if (is_pool(x, y) && !u.uinwater) {
849 if ((Is_waterlevel(&u.uz) && levl[x][y].typ == WATER)
850 || !(Levitation || Flying || Wwalking)) {
851 multi = 0; /* can move, so drown() allows crawling out of water */
854 } else if (!Is_waterlevel(&u.uz) && !stopping_short) {
856 Norep("You move over %s.", an(is_moat(x, y) ? "moat" : "pool"));
858 Norep("
\82 \82È
\82½
\82Í%s
\82Ì
\8fã
\82ð
\88Ú
\93®
\82µ
\82½
\81D", is_moat(x, y) ? "
\96x" : "
\90\85\82½
\82Ü
\82è");
860 } else if (is_lava(x, y) && !stopping_short) {
862 Norep("You move over some lava.");
864 Norep("
\82 \82È
\82½
\82Í
\97n
\8aâ
\82Ì
\8fã
\82ð
\88Ú
\93®
\82µ
\82½
\81D");
868 * Each trap should really trigger on the recoil if it would
869 * trigger during normal movement. However, not all the possible
870 * side-effects of this are tested [as of 3.4.0] so we trigger
871 * those that we have tested, and offer a message for the ones
872 * that we have not yet tested.
874 if ((ttmp = t_at(x, y)) != 0) {
875 if (stopping_short) {
876 ; /* see the comment above hurtle_jump() */
877 } else if (ttmp->ttyp == MAGIC_PORTAL) {
880 } else if (ttmp->ttyp == VIBRATING_SQUARE) {
882 pline("The ground vibrates as you pass it.");
884 pline("
\82 \82È
\82½
\82ª
\92Ê
\89ß
\82·
\82é
\82Æ
\92n
\96Ê
\82ª
\90k
\93®
\82µ
\82½
\81D");
885 dotrap(ttmp, 0); /* doesn't print messages */
886 } else if (ttmp->ttyp == FIRE_TRAP) {
888 } else if ((is_pit(ttmp->ttyp) || is_hole(ttmp->ttyp))
890 /* air currents overcome the recoil in Sokoban;
891 when jumping, caller performs last step and enters trap */
899 You("pass right over %s.",
900 an(defsyms[trap_to_defsym(ttmp->ttyp)].explanation));
902 You("%s
\82Ì
\90^
\8fã
\82ð
\92Ê
\89ß
\82µ
\82½
\81D",
903 defsyms[trap_to_defsym(ttmp->ttyp)].explanation);
907 if (--*range < 0) /* make sure our range never goes negative */
915 mhurtle_step(arg, x, y)
919 struct monst *mon = (struct monst *) arg;
921 /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
922 * rather than just stopping before.
924 if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
925 remove_monster(mon->mx, mon->my);
926 newsym(mon->mx, mon->my);
927 place_monster(mon, x, y);
928 newsym(mon->mx, mon->my);
937 * The player moves through the air for a few squares as a result of
938 * throwing or kicking something.
940 * dx and dy should be the direction of the hurtle, not of the original
941 * kick or throw and be only.
944 hurtle(dx, dy, range, verbose)
950 /* The chain is stretched vertically, so you shouldn't be able to move
951 * very far diagonally. The premise that you should be able to move one
952 * spot leads to calculations that allow you to only move one spot away
953 * from the ball, if you are levitating over the ball, or one spot
954 * towards the ball, if you are at the end of the chain. Rather than
955 * bother with all of that, assume that there is no slack in the chain
956 * for diagonal movement, give the player a message and return.
958 if (Punished && !carried(uball)) {
960 You_feel("a tug from the iron ball.");
962 You_feel("
\93S
\8b\85\82É
\82Ð
\82Á
\82Ï
\82ç
\82ê
\82Ä
\82¢
\82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
965 } else if (u.utrap) {
967 You("are anchored by the %s.",
968 u.utraptype == TT_WEB
970 : u.utraptype == TT_LAVA
972 : u.utraptype == TT_INFLOOR
973 ? surface(u.ux, u.uy)
974 : u.utraptype == TT_BURIEDBALL ? "buried ball"
977 You("%s
\82É
\90\98\82¦
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é
\81D",
978 u.utraptype == TT_WEB
979 ? "
\82
\82à
\82Ì
\91\83"
980 : u.utraptype == TT_LAVA
982 : u.utraptype == TT_INFLOOR
984 : u.utraptype == TT_BURIEDBALL ? "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85"
991 /* make sure dx and dy are [-1,0,1] */
995 if (!range || (!dx && !dy) || u.ustuck)
996 return; /* paranoia */
1000 multi_reason = "moving through the air";
1002 multi_reason = "
\8bó
\92\86\82ð
\88Ú
\93®
\82µ
\82Ä
\82¢
\82é
\8e\9e\82É";
1003 nomovemsg = ""; /* it just happens */
1006 You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
1008 You("
\8bt
\95û
\8cü
\82É
\94ò
\82Î
\82³
\82ê
\82½
\81D");
1009 /* if we're in the midst of shooting multiple projectiles, stop */
1014 /* this setting of cc is only correct if dx and dy are [-1,0,1] only */
1015 cc.x = u.ux + (dx * range);
1016 cc.y = u.uy + (dy * range);
1017 (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
1020 /* Move a monster through the air for a few squares. */
1022 mhurtle(mon, dx, dy, range)
1028 /* At the very least, debilitate the monster */
1032 /* Is the monster stuck or too heavy to push?
1033 * (very large monsters have too much inertia, even floaters and flyers)
1035 if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
1038 /* Make sure dx and dy are [-1,0,1] */
1041 if (!range || (!dx && !dy))
1042 return; /* paranoia */
1043 /* don't let grid bugs be hurtled diagonally */
1044 if (dx && dy && NODIAG(monsndx(mon->data)))
1047 /* Send the monster along the path */
1050 cc.x = mon->mx + (dx * range);
1051 cc.y = mon->my + (dy * range);
1052 (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t) mon);
1057 check_shop_obj(obj, x, y, broken)
1063 struct monst *shkp = shop_keeper(*u.ushops);
1068 costly_xy = costly_spot(x, y);
1069 if (broken || !costly_xy || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
1070 /* thrown out of a shop or into a different shop */
1072 (void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
1076 } else if (costly_xy) {
1077 char *oshops = in_rooms(x, y, SHOPBASE);
1079 /* ushops0: in case we threw while levitating and recoiled
1080 out of shop (most likely to the shk's spot in front of door) */
1081 if (*oshops == *u.ushops || *oshops == *u.ushops0) {
1083 subfrombill(obj, shkp);
1084 else if (x != shkp->mx || y != shkp->my)
1091 * Hero tosses an object upwards with appropriate consequences.
1093 * Returns FALSE if the object is gone.
1096 toss_up(obj, hitsroof)
1101 boolean petrifier = ((obj->otyp == EGG || obj->otyp == CORPSE)
1102 && touch_petrifies(&mons[obj->corpsenm]));
1103 /* note: obj->quan == 1 */
1105 if (!has_ceiling(&u.uz)) {
1107 action = "flies up into"; /* into "the sky" or "the water above" */
1109 action = "
\82Ì
\92\86\82ð
\94ò
\82ñ
\82¾"; /* into "the sky" or "the water above" */
1111 } else if (hitsroof) {
1112 if (breaktest(obj)) {
1114 pline("%s hits the %s.", Doname2(obj), ceiling(u.ux, u.uy));
1116 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", Doname2(obj), ceiling(u.ux, u.uy));
1117 breakmsg(obj, !Blind);
1118 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
1124 action = "
\82É
\96½
\92\86\82µ
\82½";
1127 action = "almost hits";
1129 action = "
\82É
\82à
\82¤
\8f
\82µ
\82Å
\96½
\92\86\82·
\82é
\82Æ
\82±
\82ë
\82¾
\82Á
\82½";
1132 pline("%s %s the %s, then falls back on top of your %s.", Doname2(obj),
1133 action, ceiling(u.ux, u.uy), body_part(HEAD));
1135 pline("%s
\82Í%s%s
\81C
\82»
\82µ
\82Ä%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82Ä
\82«
\82½
\81D", Doname2(obj),
1136 ceiling(u.ux, u.uy), action, body_part(HEAD));
1139 /* object now hits you */
1141 if (obj->oclass == POTION_CLASS) {
1142 potionhit(&youmonst, obj, POTHIT_HERO_THROW);
1143 } else if (breaktest(obj)) {
1144 int otyp = obj->otyp;
1147 /* need to check for blindness result prior to destroying obj */
1148 blindinc = ((otyp == CREAM_PIE || otyp == BLINDING_VENOM)
1149 /* AT_WEAP is ok here even if attack type was AT_SPIT */
1150 && can_blnd(&youmonst, &youmonst, AT_WEAP, obj))
1153 breakmsg(obj, !Blind);
1154 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
1155 obj = 0; /* it's now gone */
1158 if (petrifier && !Stone_resistance
1159 && !(poly_when_stoned(youmonst.data)
1160 && polymon(PM_STONE_GOLEM))) {
1161 /* egg ends up "all over your face"; perhaps
1162 visored helmet should still save you here */
1165 Your("%s fails to protect you.", helm_simple_name(uarmh));
1167 Your("%s
\82Í
\82 \82È
\82½
\82ð
\8eç
\82ê
\82È
\82©
\82Á
\82½
\81D", helm_simple_name(uarmh));
1172 case BLINDING_VENOM:
1174 pline("You've got it all over your %s!", body_part(FACE));
1176 pline("
\82»
\82ê
\82Í%s
\82ð
\82×
\82Á
\82Æ
\82è
\82Æ
\95¢
\82Á
\82½
\81I", body_part(FACE));
1178 if (otyp == BLINDING_VENOM && !Blind)
1180 pline("It blinds you!");
1182 pline("
\96Ú
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½
\81I");
1183 u.ucreamed += blindinc;
1184 make_blinded(Blinded + (long) blindinc, FALSE);
1186 Your1(vision_clears);
1193 } else { /* neither potion nor other breaking object */
1194 boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE;
1195 int dmg = dmgval(obj, &youmonst);
1198 /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */
1199 artimsg = artifact_hit((struct monst *) 0, &youmonst, obj, &dmg,
1202 if (!dmg) { /* probably wasn't a weapon; base damage on weight */
1203 dmg = (int) obj->owt / 100;
1208 if (youmonst.data == &mons[PM_SHADE]
1209 && objects[obj->otyp].oc_material != SILVER)
1212 if (dmg > 1 && less_damage)
1217 dmg = 0; /* beware negative rings of increase damage */
1218 dmg = Maybe_Half_Phys(dmg);
1221 if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) {
1224 pline("Fortunately, you are wearing a hard helmet.");
1226 pline("
\8dK
\89^
\82É
\82à
\81C
\82 \82È
\82½
\82Í
\8cÅ
\82¢
\8a\95\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82½
\81D");
1227 /* helmet definitely protects you when it blocks petrification
1229 } else if (!petrifier) {
1232 Your("%s does not protect you.", helm_simple_name(uarmh));
1234 Your("%s
\82Å
\82Í
\96h
\82¬
\82«
\82ê
\82È
\82©
\82Á
\82½
\81D", helm_simple_name(uarmh));
1236 } else if (petrifier && !Stone_resistance
1237 && !(poly_when_stoned(youmonst.data)
1238 && polymon(PM_STONE_GOLEM))) {
1240 killer.format = KILLED_BY;
1242 Strcpy(killer.name, "elementary physics"); /* "what goes up..." */
1244 Strcpy(killer.name, "
\8f\89\93\99\95¨
\97\9d\82É
\82æ
\82è"); /* "what goes up..." */
1247 You("turn to stone.");
1249 You("
\90Î
\82É
\82È
\82Á
\82½
\81D");
1251 dropy(obj); /* bypass most of hitfloor() */
1252 thrownobj = 0; /* now either gone or on floor */
1254 return obj ? TRUE : FALSE;
1256 hitfloor(obj, TRUE);
1259 losehp(Maybe_Half_Phys(dmg), "falling object", KILLED_BY_AN);
1261 losehp(Maybe_Half_Phys(dmg), "
\97\8e\89º
\95¨
\82Å", KILLED_BY_AN);
1267 /* return true for weapon meant to be thrown; excludes ammo */
1269 throwing_weapon(obj)
1272 return (boolean) (is_missile(obj) || is_spear(obj)
1273 /* daggers and knife (excludes scalpel) */
1274 || (is_blade(obj) && !is_sword(obj)
1275 && (objects[obj->otyp].oc_dir & PIERCE))
1276 /* special cases [might want to add AXE] */
1277 || obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
1280 /* the currently thrown object is returning to you (not for boomerangs) */
1282 sho_obj_return_to_u(obj)
1285 /* might already be our location (bounced off a wall) */
1286 if ((u.dx || u.dy) && (bhitpos.x != u.ux || bhitpos.y != u.uy)) {
1287 int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
1289 tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng));
1290 while (isok(x,y) && (x != u.ux || y != u.uy)) {
1296 tmp_at(DISP_END, 0);
1300 /* throw an object, NB: obj may be consumed in the process */
1302 throwit(obj, wep_mask, twoweap)
1304 long wep_mask; /* used to re-equip returning boomerang */
1305 boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
1307 register struct monst *mon;
1308 register int range, urange;
1309 boolean crossbowing, impaired = (Confusion || Stunned || Blind
1310 || Hallucination || Fumbling);
1311 boolean tethered_weapon = (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0);
1313 notonhead = FALSE; /* reset potentially stale value */
1314 if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
1315 boolean slipok = TRUE;
1317 if (ammo_and_launcher(obj, uwep)) {
1319 pline("%s!", Tobjnam(obj, "misfire"));
1321 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81I", xname(obj));
1323 /* only slip if it's greased or meant to be thrown */
1324 if (obj->greased || throwing_weapon(obj))
1325 /* BUG: this message is grammatically incorrect if obj has
1326 a plural name; greased gloves or boots for instance. */
1328 pline("%s as you throw it!", Tobjnam(obj, "slip"));
1330 pline("%s
\82ð
\93\8a\82°
\82æ
\82¤
\82Æ
\82µ
\82½
\82ª
\81C
\82¸
\82è
\97\8e\82¿
\82Ä
\82µ
\82Ü
\82Á
\82½
\81I", xname(obj));
1343 if ((u.dx || u.dy || (u.dz < 1))
1344 && calc_capacity((int) obj->owt) > SLT_ENCUMBER
1345 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1346 : (u.uhp < 10 && u.uhp != u.uhpmax))
1347 && obj->owt > (unsigned) ((Upolyd ? u.mh : u.uhp) * 2)
1348 && !Is_airlevel(&u.uz)) {
1350 You("have so little stamina, %s drops from your grasp.",
1352 You("
\88¬
\97Í
\82ª
\82È
\82
\82È
\82Á
\82Ä
\82¢
\82½
\82Ì
\82Å
\81C%s
\82ð
\88¬
\82è
\82»
\82±
\82Ë
\82Ä
\97\8e\82Æ
\82µ
\82½
\81D",
1354 exercise(A_CON, FALSE);
1360 thrownobj->was_thrown = 1;
1364 bhitpos.x = mon->mx;
1365 bhitpos.y = mon->my;
1366 if (tethered_weapon)
1367 tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
1370 /* Mjollnir must we wielded to be thrown--caller verifies this;
1371 aklys must we wielded as primary to return when thrown */
1372 && ((Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR)
1376 pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"),
1377 ceiling(u.ux, u.uy));
1379 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj),
1380 ceiling(u.ux,u.uy));
1383 (void) encumber_msg();
1384 if (obj->owornmask & W_QUIVER) /* in case addinv() autoquivered */
1385 setuqwep((struct obj *) 0);
1387 u.twoweap = twoweap;
1388 } else if (u.dz < 0) {
1389 (void) toss_up(obj, rn2(5) && !Underwater);
1390 } else if (u.dz > 0 && u.usteed && obj->oclass == POTION_CLASS
1392 /* alternative to prayer or wand of opening/spell of knock
1393 for dealing with cursed saddle: throw holy water > */
1394 potionhit(u.usteed, obj, POTHIT_HERO_THROW);
1396 hitfloor(obj, TRUE);
1398 thrownobj = (struct obj *) 0;
1401 } else if (obj->otyp == BOOMERANG && !Underwater) {
1402 if (Is_airlevel(&u.uz) || Levitation)
1403 hurtle(-u.dx, -u.dy, 1, TRUE);
1404 mon = boomhit(obj, u.dx, u.dy);
1405 if (mon == &youmonst) { /* the thing was caught */
1406 exercise(A_DEX, TRUE);
1408 (void) encumber_msg();
1409 if (wep_mask && !(obj->owornmask & wep_mask)) {
1410 setworn(obj, wep_mask);
1411 u.twoweap = twoweap;
1413 thrownobj = (struct obj *) 0;
1417 /* crossbow range is independent of strength */
1418 crossbowing = (ammo_and_launcher(obj, uwep)
1419 && weapon_type(uwep) == P_CROSSBOW);
1420 urange = (crossbowing ? 18 : (int) ACURRSTR) / 2;
1421 /* balls are easy to throw or at least roll;
1422 * also, this insures the maximum range of a ball is greater
1423 * than 1, so the effects from throwing attached balls are
1426 if (obj->otyp == HEAVY_IRON_BALL)
1427 range = urange - (int) (obj->owt / 100);
1429 range = urange - (int) (obj->owt / 40);
1433 else if (range >= 5)
1440 if (ammo_and_launcher(obj, uwep)) {
1445 } else if (obj->oclass != GEM_CLASS)
1449 if (Is_airlevel(&u.uz) || Levitation) {
1450 /* action, reaction... */
1459 if (obj->otyp == BOULDER)
1460 range = 20; /* you must be giant */
1461 else if (obj->oartifact == ART_MJOLLNIR)
1462 range = (range + 1) / 2; /* it's heavy */
1463 else if (tethered_weapon) /* primary weapon is aklys */
1464 /* if an aklys is going to return, range is limited by the
1465 length of the attached cord [implicit aspect of item] */
1466 range = min(range, BOLT_LIM / 2);
1467 else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
1473 mon = bhit(u.dx, u.dy, range,
1474 tethered_weapon ? THROWN_TETHERED_WEAPON : THROWN_WEAPON,
1475 (int FDECL((*), (MONST_P, OBJ_P))) 0,
1476 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
1477 thrownobj = obj; /* obj may be null now */
1479 /* have to do this after bhit() so u.ux & u.uy are correct */
1480 if (Is_airlevel(&u.uz) || Levitation)
1481 hurtle(-u.dx, -u.dy, urange, TRUE);
1484 /* bhit display cleanup was left with this caller
1485 for tethered_weapon, but clean it up now since
1486 we're about to return */
1487 if (tethered_weapon)
1488 tmp_at(DISP_END, 0);
1496 if (mon->isshk && obj->where == OBJ_MINVENT && obj->ocarry == mon) {
1497 thrownobj = (struct obj *) 0;
1498 return; /* alert shk caught it */
1500 (void) snuff_candle(obj);
1501 notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
1502 obj_gone = thitmonst(mon, obj);
1503 /* Monster may have been tamed; this frees old mon */
1504 mon = m_at(bhitpos.x, bhitpos.y);
1506 /* [perhaps this should be moved into thitmonst or hmon] */
1507 if (mon && mon->isshk
1508 && (!inside_shop(u.ux, u.uy)
1509 || !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
1517 /* missile has already been handled */
1518 if (tethered_weapon) tmp_at(DISP_END, 0);
1519 } else if (u.uswallow) {
1520 if (tethered_weapon) {
1521 tmp_at(DISP_END, 0);
1523 pline("%s returns to your hand!", The(xname(thrownobj)));
1525 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", The(xname(thrownobj)));
1526 thrownobj = addinv(thrownobj);
1527 (void) encumber_msg();
1528 /* in case addinv() autoquivered */
1529 if (thrownobj->owornmask & W_QUIVER)
1530 setuqwep((struct obj *) 0);
1533 /* ball is not picked up by monster */
1535 (void) mpickobj(u.ustuck, obj);
1536 thrownobj = (struct obj *) 0;
1539 /* Mjollnir must we wielded to be thrown--caller verifies this;
1540 aklys must we wielded as primary to return when thrown */
1541 if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE))
1542 || tethered_weapon) {
1544 if (tethered_weapon)
1545 tmp_at(DISP_END, BACKTRACK);
1547 sho_obj_return_to_u(obj); /* display its flight */
1549 if (!impaired && rn2(100)) {
1551 pline("%s to your hand!", Tobjnam(obj, "return"));
1553 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj));
1555 (void) encumber_msg();
1556 /* addinv autoquivers an aklys if quiver is empty;
1557 if obj is quivered, remove it before wielding */
1558 if (obj->owornmask & W_QUIVER)
1559 setuqwep((struct obj *) 0);
1561 u.twoweap = twoweap;
1562 if (cansee(bhitpos.x, bhitpos.y))
1563 newsym(bhitpos.x, bhitpos.y);
1569 pline(Blind ? "%s lands %s your %s."
1570 : "%s back to you, landing %s your %s.",
1571 Blind ? Something : Tobjnam(obj, "return"),
1572 Levitation ? "beneath" : "at",
1573 makeplural(body_part(FOOT)));
1575 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82Ì%s
\82É
\97\8e\82¿
\82½
\81D",
1577 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1579 Levitation ? "
\89º" : "
\82»
\82Î");
1584 pline(Blind ? "%s your %s!"
1585 : "%s back toward you, hitting your %s!",
1586 Tobjnam(obj, Blind ? "hit" : "fly"),
1589 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81I",
1591 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1595 (void) artifact_hit((struct monst *) 0, &youmonst,
1598 losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
1603 Sprintf(jbuf, "%s
\82Å", xname(obj));
1604 losehp(Maybe_Half_Phys(dmg), jbuf, KILLED_BY);
1608 if (ship_object(obj, u.ux, u.uy, FALSE)) {
1609 thrownobj = (struct obj *) 0;
1614 thrownobj = (struct obj *) 0;
1617 if (tethered_weapon)
1618 tmp_at(DISP_END, 0);
1619 /* when this location is stepped on, the weapon will be
1620 auto-picked up due to 'obj->was_thrown' of 1;
1621 addinv() prevents thrown Mjollnir from being placed
1622 into the quiver slot, but an aklys will end up there if
1623 that slot is empty at the time; since hero will need to
1624 explicitly rewield the weapon to get throw-and-return
1625 capability back anyway, quivered or not shouldn't matter */
1627 pline("%s to return!", Tobjnam(obj, "fail"));
1629 pline("%s
\82Í
\96ß
\82é
\82Ì
\82É
\8e¸
\94s
\82µ
\82½
\81I", xname(obj));
1630 /* continue below with placing 'obj' at target location */
1634 if ((!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj))
1635 /* venom [via #monster to spit while poly'd] fails breaktest()
1636 but we want to force breakage even when location IS_SOFT() */
1637 || obj->oclass == VENOM_CLASS) {
1638 tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng));
1639 tmp_at(bhitpos.x, bhitpos.y);
1641 tmp_at(DISP_END, 0);
1642 breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1643 breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1644 thrownobj = (struct obj *) 0;
1648 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall")) {
1650 if (flooreffects(obj,bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é")) {
1651 thrownobj = (struct obj *) 0;
1654 obj_no_longer_held(obj);
1655 if (mon && mon->isshk && is_pick(obj)) {
1656 if (cansee(bhitpos.x, bhitpos.y))
1658 pline("%s snatches up %s.", Monnam(mon), the(xname(obj)));
1660 pline("%s
\82Í%s
\82ð
\92D
\82¢
\82Æ
\82Á
\82½
\81D", Monnam(mon), xname(obj));
1661 if (*u.ushops || obj->unpaid)
1662 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1663 (void) mpickobj(mon, obj); /* may merge and free obj */
1664 thrownobj = (struct obj *) 0;
1667 (void) snuff_candle(obj);
1668 if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1669 thrownobj = (struct obj *) 0;
1672 thrownobj = (struct obj *) 0;
1673 place_object(obj, bhitpos.x, bhitpos.y);
1674 /* container contents might break;
1675 do so before turning ownership of thrownobj over to shk
1676 (container_impact_dmg handles item already owned by shop) */
1677 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
1678 /* <x,y> is spot where you initiated throw, not bhitpos */
1679 container_impact_dmg(obj, u.ux, u.uy);
1680 /* charge for items thrown out of shop;
1681 shk takes possession for items thrown into one */
1682 if ((*u.ushops || obj->unpaid) && obj != uball)
1683 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1687 drop_ball(bhitpos.x, bhitpos.y);
1688 if (cansee(bhitpos.x, bhitpos.y))
1689 newsym(bhitpos.x, bhitpos.y);
1690 if (obj_sheds_light(obj))
1691 vision_full_recalc = 1;
1695 /* an object may hit a monster; various factors adjust chance of hitting */
1697 omon_adj(mon, obj, mon_notices)
1700 boolean mon_notices;
1704 /* size of target affects the chance of hitting */
1705 tmp += (mon->data->msize - MZ_MEDIUM); /* -2..+5 */
1706 /* sleeping target is more likely to be hit */
1707 if (mon->msleeping) {
1712 /* ditto for immobilized target */
1713 if (!mon->mcanmove || !mon->data->mmove) {
1715 if (mon_notices && mon->data->mmove && !rn2(10)) {
1720 /* some objects are more likely to hit than others */
1721 switch (obj->otyp) {
1722 case HEAVY_IRON_BALL:
1730 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1731 || obj->oclass == GEM_CLASS)
1732 tmp += hitval(obj, mon);
1738 /* thrown object misses target monster */
1740 tmiss(obj, mon, maybe_wakeup)
1743 boolean maybe_wakeup;
1745 const char *missile = mshot_xname(obj);
1747 /* If the target can't be seen or doesn't look like a valid target,
1748 avoid "the arrow misses it," or worse, "the arrows misses the mimic."
1749 An attentive player will still notice that this is different from
1750 an arrow just landing short of any target (no message in that case),
1751 so will realize that there is a valid target here anyway. */
1752 if (!canseemon(mon) || (M_AP_TYPE(mon) && M_AP_TYPE(mon) != M_AP_MONSTER))
1754 pline("%s %s.", The(missile), otense(obj, "miss"));
1756 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81D", missile);
1759 if (maybe_wakeup && !rn2(3))
1764 #define quest_arti_hits_leader(obj, mon) \
1765 (obj->oartifact && is_quest_artifact(obj) \
1766 && mon->m_id == quest_status.leader_m_id)
1769 * Object thrown by player arrives at monster's location.
1770 * Return 1 if obj has disappeared or otherwise been taken care of,
1771 * 0 if caller must take care of it.
1772 * Also used for kicked objects and for polearms/grapnel applied at range.
1776 register struct monst *mon;
1777 register struct obj *obj; /* thrownobj or kickedobj or uwep */
1779 register int tmp; /* Base chance to hit */
1780 register int disttmp; /* distance modifier */
1781 int otyp = obj->otyp, hmode;
1782 boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
1785 hmode = (obj == uwep) ? HMON_APPLIED
1786 : (obj == kickedobj) ? HMON_KICKED
1789 /* Differences from melee weapons:
1791 * Dex still gives a bonus, but strength does not.
1792 * Polymorphed players lacking attacks may still throw.
1793 * There's a base -1 to hit.
1794 * No bonuses for fleeing or stunned targets (they don't dodge
1795 * melee blows as readily, but dodging arrows is hard anyway).
1796 * Not affected by traps, etc.
1797 * Certain items which don't in themselves do damage ignore 'tmp'.
1798 * Distance and monster size affect chance to hit.
1800 tmp = -1 + Luck + find_mac(mon) + u.uhitinc
1801 + maybe_polyd(youmonst.data->mlevel, u.ulevel);
1802 if (ACURR(A_DEX) < 4)
1804 else if (ACURR(A_DEX) < 6)
1806 else if (ACURR(A_DEX) < 8)
1808 else if (ACURR(A_DEX) >= 14)
1809 tmp += (ACURR(A_DEX) - 14);
1811 /* Modify to-hit depending on distance; but keep it sane.
1812 * Polearms get a distance penalty even when wielded; it's
1813 * hard to hit at a distance.
1815 disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1820 /* gloves are a hindrance to proper use of bows */
1821 if (uarmg && uwep && objects[uwep->otyp].oc_skill == P_BOW) {
1822 switch (uarmg->otyp) {
1823 case GAUNTLETS_OF_POWER: /* metal */
1826 case GAUNTLETS_OF_FUMBLING:
1829 case LEATHER_GLOVES:
1830 case GAUNTLETS_OF_DEXTERITY:
1833 impossible("Unknown type of gloves (%d)", uarmg->otyp);
1838 tmp += omon_adj(mon, obj, TRUE);
1839 if (is_orc(mon->data)
1840 && maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
1842 if (guaranteed_hit) {
1843 tmp += 1000; /* Guaranteed hit */
1846 if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
1847 if (mon->msleeping || !mon->mcanmove) {
1848 tmiss(obj, mon, FALSE);
1850 } else if (mon->mtame) {
1852 pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1854 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82Ä
\92u
\82¢
\82½
\81D", Monnam(mon), xname(obj));
1858 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1860 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82½
\81D", Monnam(mon), xname(obj));
1861 return gem_accept(mon, obj);
1865 /* don't make game unwinnable if naive player throws artifact
1866 at leader... (kicked artifact is ok too; HMON_APPLIED could
1867 occur if quest artifact polearm or grapnel ever gets added) */
1868 if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
1869 /* AIS: changes to wakeup() means that it's now less inappropriate here
1870 than it used to be, but the manual version works just as well */
1872 mon->mstrategy &= ~STRAT_WAITMASK;
1874 if (mon->mcanmove) {
1876 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1878 pline("%s
\82Í%s
\82ð
\92Í
\82ñ
\82¾
\81D", Monnam(mon), xname(obj));
1879 if (mon->mpeaceful) {
1880 boolean next2u = monnear(mon, u.ux, u.uy);
1882 finish_quest(obj); /* acknowledge quest completion */
1884 pline("%s %s %s back to you.", Monnam(mon),
1885 (next2u ? "hands" : "tosses"), the(xname(obj)));
1887 pline("%s
\82Í%s
\82ð
\82 \82È
\82½
\82É
\95Ô
\82µ
\82½
\81D", Monnam(mon),
1891 sho_obj_return_to_u(obj);
1892 obj = addinv(obj); /* back into your inventory */
1893 (void) encumber_msg();
1895 /* angry leader caught it and isn't returning it */
1896 if (*u.ushops || obj->unpaid) /* not very likely... */
1897 check_shop_obj(obj, mon->mx, mon->my, FALSE);
1898 (void) mpickobj(mon, obj);
1900 return 1; /* caller doesn't need to place it */
1907 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1908 || obj->oclass == GEM_CLASS) {
1909 if (hmode == HMON_KICKED) {
1910 /* throwing adjustments and weapon skill bonus don't apply */
1911 tmp -= (is_ammo(obj) ? 5 : 3);
1912 } else if (is_ammo(obj)) {
1913 if (!ammo_and_launcher(obj, uwep)) {
1916 tmp += uwep->spe - greatest_erosion(uwep);
1917 tmp += weapon_hit_bonus(uwep);
1918 if (uwep->oartifact)
1919 tmp += spec_abon(uwep, mon);
1921 * Elves and Samurais are highly trained w/bows,
1922 * especially their own special types of bow.
1923 * Polymorphing won't make you a bow expert.
1925 if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI))
1926 && (!Upolyd || your_race(youmonst.data))
1927 && objects[uwep->otyp].oc_skill == P_BOW) {
1929 if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW)
1931 else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI)
1935 } else { /* thrown non-ammo or applied polearm/grapnel */
1936 if (otyp == BOOMERANG) /* arbitrary */
1938 else if (throwing_weapon(obj)) /* meant to be thrown */
1940 else if (obj == thrownobj) /* not meant to be thrown */
1942 /* we know we're dealing with a weapon or weptool handled
1943 by WEAPON_SKILLS once ammo objects have been excluded */
1944 tmp += weapon_hit_bonus(obj);
1947 if (tmp >= dieroll) {
1948 boolean wasthrown = (thrownobj != 0),
1949 /* remember weapon attribute; hmon() might destroy obj */
1950 chopper = is_axe(obj);
1952 /* attack hits mon */
1953 if (hmode == HMON_APPLIED)
1954 u.uconduct.weaphit++;
1955 if (hmon(mon, obj, hmode, dieroll)) { /* mon still alive */
1957 cutworm(mon, bhitpos.x, bhitpos.y, chopper);
1959 exercise(A_DEX, TRUE);
1960 /* if hero was swallowed and projectile killed the engulfer,
1961 'obj' got added to engulfer's inventory and then dropped,
1962 so we can't safely use that pointer anymore; it escapes
1963 the chance to be used up here... */
1964 if (wasthrown && !thrownobj)
1967 /* projectiles other than magic stones sometimes disappear
1968 when thrown; projectiles aren't among the types of weapon
1969 that hmon() might have destroyed so obj is intact */
1970 if (objects[otyp].oc_skill < P_NONE
1971 && objects[otyp].oc_skill > -P_BOOMERANG
1972 && !objects[otyp].oc_magic) {
1973 /* we were breaking 2/3 of everything unconditionally.
1974 * we still don't want anything to survive unconditionally,
1975 * but we need ammo to stay around longer on average.
1979 chance = 3 + greatest_erosion(obj) - obj->spe;
1981 broken = rn2(chance);
1984 if (obj->blessed && !rnl(4))
1988 if (*u.ushops || obj->unpaid)
1989 check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
1990 obfree(obj, (struct obj *) 0);
1994 passive_obj(mon, obj, (struct attack *) 0);
1996 tmiss(obj, mon, TRUE);
1997 if (hmode == HMON_APPLIED)
2001 } else if (otyp == HEAVY_IRON_BALL) {
2002 exercise(A_STR, TRUE);
2003 if (tmp >= dieroll) {
2004 int was_swallowed = guaranteed_hit;
2006 exercise(A_DEX, TRUE);
2007 if (!hmon(mon, obj, hmode, dieroll)) { /* mon killed */
2008 if (was_swallowed && !u.uswallow && obj == uball)
2009 return 1; /* already did placebc() */
2012 tmiss(obj, mon, TRUE);
2015 } else if (otyp == BOULDER) {
2016 exercise(A_STR, TRUE);
2017 if (tmp >= dieroll) {
2018 exercise(A_DEX, TRUE);
2019 (void) hmon(mon, obj, hmode, dieroll);
2021 tmiss(obj, mon, TRUE);
2024 } else if ((otyp == EGG || otyp == CREAM_PIE || otyp == BLINDING_VENOM
2025 || otyp == ACID_VENOM)
2026 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
2027 (void) hmon(mon, obj, hmode, dieroll);
2028 return 1; /* hmon used it up */
2030 } else if (obj->oclass == POTION_CLASS
2031 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
2032 potionhit(mon, obj, POTHIT_HERO_THROW);
2035 } else if (befriend_with_obj(mon->data, obj)
2036 || (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
2037 if (tamedog(mon, obj)) {
2038 return 1; /* obj is gone */
2040 tmiss(obj, mon, FALSE);
2042 mon->mstrategy &= ~STRAT_WAITMASK;
2044 } else if (guaranteed_hit) {
2045 /* this assumes that guaranteed_hit is due to swallowing */
2047 if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
2048 if (is_animal(u.ustuck->data)) {
2049 minstapetrify(u.ustuck, TRUE);
2050 /* Don't leave a cockatrice corpse available in a statue */
2058 pline("%s into %s %s.", Tobjnam(obj, "vanish"),
2059 s_suffix(mon_nam(mon)),
2060 is_animal(u.ustuck->data) ? "entrails" : "currents");
2062 pline("%s
\82Í%s
\82Ì%s
\82Ö
\8fÁ
\82¦
\82½
\81D", xname(obj),
2064 is_animal(u.ustuck->data) ? "
\93à
\91\9f\82Ì
\92\86" : "
\97¬
\82ê");
2067 tmiss(obj, mon, TRUE);
2074 gem_accept(mon, obj)
2075 register struct monst *mon;
2076 register struct obj *obj;
2079 boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
2080 boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
2083 static NEARDATA const char nogood[] = " is not interested in your junk.";
2085 static NEARDATA const char nogood[] = "
\82 \82È
\82½
\82Ì
\83K
\83\89\83N
\83^
\82É
\8b»
\96¡
\82ð
\8e¦
\82³
\82È
\82¢
\81D";
2087 static NEARDATA const char acceptgift[] = " accepts your gift.";
2089 static NEARDATA const char acceptgift[] = "
\82 \82È
\82½
\82Ì
\91¡
\82è
\95¨
\82ð
\8eó
\82¯
\82Æ
\82Á
\82½
\81D";
2091 static NEARDATA const char maybeluck[] = " hesitatingly";
2093 static NEARDATA const char maybeluck[] = "
\82½
\82ß
\82ç
\82¢
\82È
\82ª
\82ç";
2095 static NEARDATA const char noluck[] = " graciously";
2097 static NEARDATA const char noluck[] = "
\92\9a\8fd
\82É";
2099 static NEARDATA const char addluck[] = " gratefully";
2101 static NEARDATA const char addluck[] = "
\8aì
\82ñ
\82Å";
2103 Strcpy(buf, Monnam(mon));
2105 Strcat(buf, "
\82Í");
2110 /* object properly identified */
2111 if (obj->dknown && objects[obj->otyp].oc_name_known) {
2114 Strcat(buf, addluck);
2117 Strcat(buf, maybeluck);
2118 change_luck(rn2(7) - 3);
2121 Strcat(buf, nogood);
2124 /* making guesses */
2125 } else if (has_oname(obj) || objects[obj->otyp].oc_uname) {
2128 Strcat(buf, addluck);
2131 Strcat(buf, maybeluck);
2132 change_luck(rn2(3) - 1);
2135 Strcat(buf, nogood);
2138 /* value completely unknown to @ */
2142 Strcat(buf, addluck);
2145 Strcat(buf, maybeluck);
2146 change_luck(rn2(3) - 1);
2149 Strcat(buf, noluck);
2152 Strcat(buf, acceptgift);
2153 if (*u.ushops || obj->unpaid)
2154 check_shop_obj(obj, mon->mx, mon->my, TRUE);
2155 (void) mpickobj(mon, obj); /* may merge and free obj */
2161 if (!tele_restrict(mon))
2162 (void) rloc(mon, TRUE);
2167 * Comments about the restructuring of the old breaks() routine.
2169 * There are now three distinct phases to object breaking:
2170 * breaktest() - which makes the check/decision about whether the
2171 * object is going to break.
2172 * breakmsg() - which outputs a message about the breakage,
2173 * appropriate for that particular object. Should
2174 * only be called after a positive breaktest().
2175 * on the object and, if it going to be called,
2176 * it must be called before calling breakobj().
2177 * Calling breakmsg() is optional.
2178 * breakobj() - which actually does the breakage and the side-effects
2179 * of breaking that particular object. This should
2180 * only be called after a positive breaktest() on the
2183 * Each of the above routines is currently static to this source module.
2184 * There are two routines callable from outside this source module which
2185 * perform the routines above in the correct sequence.
2187 * hero_breaks() - called when an object is to be broken as a result
2188 * of something that the hero has done. (throwing it,
2190 * breaks() - called when an object is to be broken for some
2191 * reason other than the hero doing something to it.
2195 * The hero causes breakage of an object (throwing, dropping it, etc.)
2196 * Return 0 if the object didn't break, 1 if the object broke.
2199 hero_breaks(obj, x, y, from_invent)
2201 xchar x, y; /* object location (ox, oy may not be right) */
2202 boolean from_invent; /* thrown or dropped by player; maybe on shop bill */
2204 boolean in_view = Blind ? FALSE : (from_invent || cansee(x, y));
2206 if (!breaktest(obj))
2208 breakmsg(obj, in_view);
2209 breakobj(obj, x, y, TRUE, from_invent);
2214 * The object is going to break for a reason other than the hero doing
2216 * Return 0 if the object doesn't break, 1 if the object broke.
2221 xchar x, y; /* object location (ox, oy may not be right) */
2223 boolean in_view = Blind ? FALSE : cansee(x, y);
2225 if (!breaktest(obj))
2227 breakmsg(obj, in_view);
2228 breakobj(obj, x, y, FALSE, FALSE);
2233 release_camera_demon(obj, x, y)
2239 && (mtmp = makemon(&mons[rn2(3) ? PM_HOMUNCULUS : PM_IMP], x, y,
2240 NO_MM_FLAGS)) != 0) {
2241 if (canspotmon(mtmp))
2243 pline("%s is released!", Hallucination
2244 ? An(rndmonnam(NULL))
2245 : "The picture-painting demon");
2247 pline("%s
\82ª
\89ð
\95ú
\82³
\82ê
\82½
\81I", Hallucination
2249 : "
\82¨
\8aG
\95`
\82«
\82Ì
\88«
\96\82");
2251 mtmp->mpeaceful = !obj->cursed;
2257 * Unconditionally break an object. Assumes all resistance checks
2258 * and break messages have been delivered prior to getting here.
2261 breakobj(obj, x, y, hero_caused, from_invent)
2263 xchar x, y; /* object location (ox, oy may not be right) */
2264 boolean hero_caused; /* is this the hero's fault? */
2265 boolean from_invent;
2267 boolean fracture = FALSE;
2269 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2274 case POT_WATER: /* really, all potions */
2275 obj->in_use = 1; /* in case it's fatal */
2276 if (obj->otyp == POT_OIL && obj->lamplit) {
2277 explode_oil(obj, x, y);
2278 } else if (distu(x, y) <= 2) {
2279 if (!breathless(youmonst.data) || haseyes(youmonst.data)) {
2280 if (obj->otyp != POT_WATER) {
2281 if (!breathless(youmonst.data)) {
2282 /* [what about "familiar odor" when known?] */
2284 You("smell a peculiar odor...");
2286 You("
\96ò
\82Á
\82Û
\82¢
\93õ
\82¢
\82ª
\82µ
\82½
\81D
\81D
\81D");
2289 const char *eyes = body_part(EYE);
2291 if (eyecount(youmonst.data) != 1)
2292 eyes = makeplural(eyes);
2293 Your("%s %s.", eyes, vtense(eyes, "water"));
2295 You("
\97Ü%s
\82É
\82È
\82Á
\82½
\81D", body_part(EYE));
2302 /* monster breathing isn't handled... [yet?] */
2304 case EXPENSIVE_CAMERA:
2305 release_camera_demon(obj, x, y);
2308 /* breaking your own eggs is bad luck */
2309 if (hero_caused && obj->spe && obj->corpsenm >= LOW_PM)
2310 change_luck((schar) -min(obj->quan, 5L));
2314 /* caller will handle object disposition;
2315 we're just doing the shop theft handling */
2323 if (from_invent || obj->unpaid) {
2324 if (*u.ushops || obj->unpaid)
2325 check_shop_obj(obj, x, y, TRUE);
2326 } else if (!obj->no_charge && costly_spot(x, y)) {
2327 /* it is assumed that the obj is a floor-object */
2328 char *o_shop = in_rooms(x, y, SHOPBASE);
2329 struct monst *shkp = shop_keeper(*o_shop);
2331 if (shkp) { /* (implies *o_shop != '\0') */
2332 static NEARDATA long lastmovetime = 0L;
2333 static NEARDATA boolean peaceful_shk = FALSE;
2334 /* We want to base shk actions on her peacefulness
2335 at start of this turn, so that "simultaneous"
2336 multiple breakage isn't drastically worse than
2337 single breakage. (ought to be done via ESHK) */
2338 if (moves != lastmovetime)
2339 peaceful_shk = shkp->mpeaceful;
2340 if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L
2341 && (*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy))
2342 && moves != lastmovetime)
2343 make_angry_shk(shkp, x, y);
2344 lastmovetime = moves;
2353 * Check to see if obj is going to break, but don't actually break it.
2354 * Return 0 if the object isn't going to break, 1 if it is.
2360 if (obj_resists(obj, 1, 99))
2362 if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact
2363 && obj->oclass != GEM_CLASS)
2365 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2366 case EXPENSIVE_CAMERA:
2367 case POT_WATER: /* really, all potions */
2372 case BLINDING_VENOM:
2380 breakmsg(obj, in_view)
2384 const char *to_pieces;
2389 /* "shatter"
\81¨ "
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½"
2390 "shatter into a thousand pieces"
\81¨ "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç
\82É
\82È
\82Á
\82½" */
2391 to_pieces = "
\82±
\82È
\82²
\82È";
2393 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2394 default: /* glass or crystal wand */
2395 if (obj->oclass != WAND_CLASS)
2396 impossible("breaking odd object?");
2398 case CRYSTAL_PLATE_MAIL:
2402 case EXPENSIVE_CAMERA:
2404 to_pieces = " into a thousand pieces";
2406 to_pieces = "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç";
2408 case POT_WATER: /* really, all potions */
2411 You_hear("%s shatter!", something);
2413 You_hear("%s
\82ª
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81I", something);
2416 pline("%s shatter%s%s!", Doname2(obj),
2417 (obj->quan == 1L) ? "s" : "", to_pieces);
2419 pline("%s
\82Í%s
\82É
\82È
\82Á
\82½
\81I", Doname2(obj), to_pieces);
2427 pline("
\83r
\83`
\83\83\81I");
2432 pline("What a mess!");
2434 pline("
\82±
\82è
\82á
\82Ð
\82Ç
\82¢
\81I");
2437 case BLINDING_VENOM:
2441 pline("
\83r
\83`
\83\83\81I");
2450 int range, odx, ody;
2451 register struct monst *mon;
2453 if (!u.dx && !u.dy && !u.dz) {
2455 You("cannot throw gold at yourself.");
2457 pline("
\8e©
\95ª
\82É
\8bà
\89Ý
\82ð
\93\8a\82°
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2463 pline(is_animal(u.ustuck->data) ? "%s in the %s's entrails."
2465 "The money disappears", mon_nam(u.ustuck));
2467 pline(is_animal(u.ustuck->data) ? "
\8bà
\89Ý
\82Í%s
\82Ì
\95 \82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D"
2468 : "
\8bà
\89Ý
\82Í%s
\82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D",
2471 add_to_minv(u.ustuck, obj);
2476 if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater
2477 && !Is_waterlevel(&u.uz)) {
2479 pline_The("gold hits the %s, then falls back on top of your %s.",
2480 ceiling(u.ux, u.uy), body_part(HEAD));
2482 pline("
\8bà
\89Ý
\82Í%s
\82É
\96½
\92\86\82µ
\81C
\82 \82È
\82½
\82Ì%s
\82Ì
\90^
\8fã
\82É
\97\8e\82¿
\82Ä
\82«
\82½
\81D",
2483 ceiling(u.ux,u.uy), body_part(HEAD));
2485 /* some self damage? */
2488 pline("Fortunately, you are wearing %s!",
2490 pline("
\8dK
\89^
\82È
\82±
\82Æ
\82É
\81C
\82 \82È
\82½
\82Í%s
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é
\81I",
2491 an(helm_simple_name(uarmh)));
2496 /* consistent with range for normal objects */
2497 range = (int) ((ACURRSTR) / 2 - obj->owt / 40);
2499 /* see if the gold has a place to move into */
2502 if (!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
2506 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
2507 (int FDECL((*), (MONST_P, OBJ_P))) 0,
2508 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
2510 return 1; /* object is gone */
2512 if (ghitm(mon, obj)) /* was it caught? */
2515 if (ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
2522 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall"))
2524 if (flooreffects(obj, bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é"))
2528 pline_The("gold hits the %s.", surface(bhitpos.x, bhitpos.y));
2530 pline("
\8bà
\89Ý
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", surface(bhitpos.x, bhitpos.y));
2531 place_object(obj, bhitpos.x, bhitpos.y);
2533 sellobj(obj, bhitpos.x, bhitpos.y);
2535 newsym(bhitpos.x, bhitpos.y);