1 /* NetHack 3.6 dothrow.c $NHDT-Date: 1573688688 2019/11/13 23:44:48 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.164 $ */
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-2020 */
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;
1309 boolean crossbowing, clear_thrownobj = FALSE,
1310 impaired = (Confusion || Stunned || Blind
1311 || Hallucination || Fumbling),
1312 tethered_weapon = (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0);
1314 notonhead = FALSE; /* reset potentially stale value */
1315 if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
1316 boolean slipok = TRUE;
1318 if (ammo_and_launcher(obj, uwep)) {
1320 pline("%s!", Tobjnam(obj, "misfire"));
1322 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81I", xname(obj));
1324 /* only slip if it's greased or meant to be thrown */
1325 if (obj->greased || throwing_weapon(obj))
1326 /* BUG: this message is grammatically incorrect if obj has
1327 a plural name; greased gloves or boots for instance. */
1329 pline("%s as you throw it!", Tobjnam(obj, "slip"));
1331 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));
1344 if ((u.dx || u.dy || (u.dz < 1))
1345 && calc_capacity((int) obj->owt) > SLT_ENCUMBER
1346 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1347 : (u.uhp < 10 && u.uhp != u.uhpmax))
1348 && obj->owt > (unsigned) ((Upolyd ? u.mh : u.uhp) * 2)
1349 && !Is_airlevel(&u.uz)) {
1351 You("have so little stamina, %s drops from your grasp.",
1353 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",
1355 exercise(A_CON, FALSE);
1361 thrownobj->was_thrown = 1;
1362 iflags.returning_missile = ((obj->oartifact == ART_MJOLLNIR
1363 && Role_if(PM_VALKYRIE))
1364 || tethered_weapon) ? (genericptr_t) obj
1366 /* NOTE: No early returns after this point or returning_missile
1367 will be left with a stale pointer. */
1371 uball->ox = uchain->ox = u.ux;
1372 uball->oy = uchain->oy = u.uy;
1375 bhitpos.x = mon->mx;
1376 bhitpos.y = mon->my;
1377 if (tethered_weapon)
1378 tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
1381 /* Mjollnir must we wielded to be thrown--caller verifies this;
1382 aklys must we wielded as primary to return when thrown */
1383 && iflags.returning_missile
1386 pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"),
1387 ceiling(u.ux, u.uy));
1389 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj),
1390 ceiling(u.ux,u.uy));
1393 (void) encumber_msg();
1394 if (obj->owornmask & W_QUIVER) /* in case addinv() autoquivered */
1395 setuqwep((struct obj *) 0);
1397 u.twoweap = twoweap;
1398 } else if (u.dz < 0) {
1399 (void) toss_up(obj, rn2(5) && !Underwater);
1400 } else if (u.dz > 0 && u.usteed && obj->oclass == POTION_CLASS
1402 /* alternative to prayer or wand of opening/spell of knock
1403 for dealing with cursed saddle: throw holy water > */
1404 potionhit(u.usteed, obj, POTHIT_HERO_THROW);
1406 hitfloor(obj, TRUE);
1408 clear_thrownobj = TRUE;
1409 goto throwit_return;
1411 } else if (obj->otyp == BOOMERANG && !Underwater) {
1412 if (Is_airlevel(&u.uz) || Levitation)
1413 hurtle(-u.dx, -u.dy, 1, TRUE);
1414 mon = boomhit(obj, u.dx, u.dy);
1415 if (mon == &youmonst) { /* the thing was caught */
1416 exercise(A_DEX, TRUE);
1418 (void) encumber_msg();
1419 if (wep_mask && !(obj->owornmask & wep_mask)) {
1420 setworn(obj, wep_mask);
1421 u.twoweap = twoweap;
1423 clear_thrownobj = TRUE;
1424 goto throwit_return;
1427 /* crossbow range is independent of strength */
1428 crossbowing = (ammo_and_launcher(obj, uwep)
1429 && weapon_type(uwep) == P_CROSSBOW);
1430 urange = (crossbowing ? 18 : (int) ACURRSTR) / 2;
1431 /* balls are easy to throw or at least roll;
1432 * also, this insures the maximum range of a ball is greater
1433 * than 1, so the effects from throwing attached balls are
1436 if (obj->otyp == HEAVY_IRON_BALL)
1437 range = urange - (int) (obj->owt / 100);
1439 range = urange - (int) (obj->owt / 40);
1443 else if (range >= 5)
1450 if (ammo_and_launcher(obj, uwep)) {
1455 } else if (obj->oclass != GEM_CLASS)
1459 if (Is_airlevel(&u.uz) || Levitation) {
1460 /* action, reaction... */
1469 if (obj->otyp == BOULDER)
1470 range = 20; /* you must be giant */
1471 else if (obj->oartifact == ART_MJOLLNIR)
1472 range = (range + 1) / 2; /* it's heavy */
1473 else if (tethered_weapon) /* primary weapon is aklys */
1474 /* if an aklys is going to return, range is limited by the
1475 length of the attached cord [implicit aspect of item] */
1476 range = min(range, BOLT_LIM / 2);
1477 else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
1483 mon = bhit(u.dx, u.dy, range,
1484 tethered_weapon ? THROWN_TETHERED_WEAPON : THROWN_WEAPON,
1485 (int FDECL((*), (MONST_P, OBJ_P))) 0,
1486 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
1487 thrownobj = obj; /* obj may be null now */
1489 /* have to do this after bhit() so u.ux & u.uy are correct */
1490 if (Is_airlevel(&u.uz) || Levitation)
1491 hurtle(-u.dx, -u.dy, urange, TRUE);
1494 /* bhit display cleanup was left with this caller
1495 for tethered_weapon, but clean it up now since
1496 we're about to return */
1497 if (tethered_weapon)
1498 tmp_at(DISP_END, 0);
1499 goto throwit_return;
1506 if (mon->isshk && obj->where == OBJ_MINVENT && obj->ocarry == mon) {
1507 clear_thrownobj = TRUE;
1508 goto throwit_return; /* alert shk caught it */
1510 (void) snuff_candle(obj);
1511 notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
1512 obj_gone = thitmonst(mon, obj);
1513 /* Monster may have been tamed; this frees old mon [obsolete] */
1514 mon = m_at(bhitpos.x, bhitpos.y);
1516 /* [perhaps this should be moved into thitmonst or hmon] */
1517 if (mon && mon->isshk
1518 && (!inside_shop(u.ux, u.uy)
1519 || !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
1523 thrownobj = (struct obj *) 0;
1527 /* missile has already been handled */
1528 if (tethered_weapon)
1529 tmp_at(DISP_END, 0);
1530 } else if (u.uswallow && !iflags.returning_missile) {
1533 (void) mpickobj(u.ustuck, obj); /* clears 'thrownobj' */
1535 clear_thrownobj = TRUE;
1536 goto throwit_return;
1538 /* Mjollnir must be wielded to be thrown--caller verifies this;
1539 aklys must be wielded as primary to return when thrown */
1540 if (iflags.returning_missile) { /* Mjollnir or aklys */
1542 if (tethered_weapon)
1543 tmp_at(DISP_END, BACKTRACK);
1545 sho_obj_return_to_u(obj); /* display its flight */
1547 if (!impaired && rn2(100)) {
1549 pline("%s to your hand!", Tobjnam(obj, "return"));
1551 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj));
1553 (void) encumber_msg();
1554 /* addinv autoquivers an aklys if quiver is empty;
1555 if obj is quivered, remove it before wielding */
1556 if (obj->owornmask & W_QUIVER)
1557 setuqwep((struct obj *) 0);
1559 u.twoweap = twoweap;
1560 if (cansee(bhitpos.x, bhitpos.y))
1561 newsym(bhitpos.x, bhitpos.y);
1567 pline(Blind ? "%s lands %s your %s."
1568 : "%s back to you, landing %s your %s.",
1569 Blind ? Something : Tobjnam(obj, "return"),
1570 Levitation ? "beneath" : "at",
1571 makeplural(body_part(FOOT)));
1573 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82Ì%s
\82É
\97\8e\82¿
\82½
\81D",
1575 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1577 Levitation ? "
\89º" : "
\82»
\82Î");
1582 pline(Blind ? "%s your %s!"
1583 : "%s back toward you, hitting your %s!",
1584 Tobjnam(obj, Blind ? "hit" : "fly"),
1587 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81I",
1589 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1593 (void) artifact_hit((struct monst *) 0, &youmonst,
1596 losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
1601 Sprintf(jbuf, "%s
\82Å", xname(obj));
1602 losehp(Maybe_Half_Phys(dmg), jbuf, KILLED_BY);
1609 if (!ship_object(obj, u.ux, u.uy, FALSE))
1612 clear_thrownobj = TRUE;
1613 goto throwit_return;
1615 if (tethered_weapon)
1616 tmp_at(DISP_END, 0);
1617 /* when this location is stepped on, the weapon will be
1618 auto-picked up due to 'obj->was_thrown' of 1;
1619 addinv() prevents thrown Mjollnir from being placed
1620 into the quiver slot, but an aklys will end up there if
1621 that slot is empty at the time; since hero will need to
1622 explicitly rewield the weapon to get throw-and-return
1623 capability back anyway, quivered or not shouldn't matter */
1625 pline("%s to return!", Tobjnam(obj, "fail"));
1627 pline("%s
\82Í
\96ß
\82é
\82Ì
\82É
\8e¸
\94s
\82µ
\82½
\81I", xname(obj));
1631 /* continue below with placing 'obj' at target location */
1635 if ((!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj))
1636 /* venom [via #monster to spit while poly'd] fails breaktest()
1637 but we want to force breakage even when location IS_SOFT() */
1638 || obj->oclass == VENOM_CLASS) {
1639 tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng));
1640 tmp_at(bhitpos.x, bhitpos.y);
1642 tmp_at(DISP_END, 0);
1643 breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1644 breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1645 clear_thrownobj = TRUE;
1646 goto throwit_return;
1649 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall")) {
1651 if (flooreffects(obj,bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é")) {
1652 clear_thrownobj = TRUE;
1653 goto throwit_return;
1655 obj_no_longer_held(obj);
1656 if (mon && mon->isshk && is_pick(obj)) {
1657 if (cansee(bhitpos.x, bhitpos.y))
1659 pline("%s snatches up %s.", Monnam(mon), the(xname(obj)));
1661 pline("%s
\82Í%s
\82ð
\92D
\82¢
\82Æ
\82Á
\82½
\81D", Monnam(mon), xname(obj));
1662 if (*u.ushops || obj->unpaid)
1663 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1664 (void) mpickobj(mon, obj); /* may merge and free obj */
1665 clear_thrownobj = TRUE;
1666 goto throwit_return;
1668 (void) snuff_candle(obj);
1669 if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1670 clear_thrownobj = TRUE;
1671 goto throwit_return;
1673 thrownobj = (struct obj *) 0;
1674 place_object(obj, bhitpos.x, bhitpos.y);
1675 /* container contents might break;
1676 do so before turning ownership of thrownobj over to shk
1677 (container_impact_dmg handles item already owned by shop) */
1678 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
1679 /* <x,y> is spot where you initiated throw, not bhitpos */
1680 container_impact_dmg(obj, u.ux, u.uy);
1681 /* charge for items thrown out of shop;
1682 shk takes possession for items thrown into one */
1683 if ((*u.ushops || obj->unpaid) && obj != uball)
1684 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1688 drop_ball(bhitpos.x, bhitpos.y);
1689 if (cansee(bhitpos.x, bhitpos.y))
1690 newsym(bhitpos.x, bhitpos.y);
1691 if (obj_sheds_light(obj))
1692 vision_full_recalc = 1;
1696 iflags.returning_missile = (genericptr_t) 0;
1697 if (clear_thrownobj)
1698 thrownobj = (struct obj *) 0;
1702 /* an object may hit a monster; various factors adjust chance of hitting */
1704 omon_adj(mon, obj, mon_notices)
1707 boolean mon_notices;
1711 /* size of target affects the chance of hitting */
1712 tmp += (mon->data->msize - MZ_MEDIUM); /* -2..+5 */
1713 /* sleeping target is more likely to be hit */
1714 if (mon->msleeping) {
1719 /* ditto for immobilized target */
1720 if (!mon->mcanmove || !mon->data->mmove) {
1722 if (mon_notices && mon->data->mmove && !rn2(10)) {
1727 /* some objects are more likely to hit than others */
1728 switch (obj->otyp) {
1729 case HEAVY_IRON_BALL:
1737 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1738 || obj->oclass == GEM_CLASS)
1739 tmp += hitval(obj, mon);
1745 /* thrown object misses target monster */
1747 tmiss(obj, mon, maybe_wakeup)
1750 boolean maybe_wakeup;
1752 const char *missile = mshot_xname(obj);
1754 /* If the target can't be seen or doesn't look like a valid target,
1755 avoid "the arrow misses it," or worse, "the arrows misses the mimic."
1756 An attentive player will still notice that this is different from
1757 an arrow just landing short of any target (no message in that case),
1758 so will realize that there is a valid target here anyway. */
1759 if (!canseemon(mon) || (M_AP_TYPE(mon) && M_AP_TYPE(mon) != M_AP_MONSTER))
1761 pline("%s %s.", The(missile), otense(obj, "miss"));
1763 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81D", missile);
1766 if (maybe_wakeup && !rn2(3))
1771 #define quest_arti_hits_leader(obj, mon) \
1772 (obj->oartifact && is_quest_artifact(obj) \
1773 && mon->m_id == quest_status.leader_m_id)
1776 * Object thrown by player arrives at monster's location.
1777 * Return 1 if obj has disappeared or otherwise been taken care of,
1778 * 0 if caller must take care of it.
1779 * Also used for kicked objects and for polearms/grapnel applied at range.
1783 register struct monst *mon;
1784 register struct obj *obj; /* thrownobj or kickedobj or uwep */
1786 register int tmp; /* Base chance to hit */
1787 register int disttmp; /* distance modifier */
1788 int otyp = obj->otyp, hmode;
1789 boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
1792 hmode = (obj == uwep) ? HMON_APPLIED
1793 : (obj == kickedobj) ? HMON_KICKED
1796 /* Differences from melee weapons:
1798 * Dex still gives a bonus, but strength does not.
1799 * Polymorphed players lacking attacks may still throw.
1800 * There's a base -1 to hit.
1801 * No bonuses for fleeing or stunned targets (they don't dodge
1802 * melee blows as readily, but dodging arrows is hard anyway).
1803 * Not affected by traps, etc.
1804 * Certain items which don't in themselves do damage ignore 'tmp'.
1805 * Distance and monster size affect chance to hit.
1807 tmp = -1 + Luck + find_mac(mon) + u.uhitinc
1808 + maybe_polyd(youmonst.data->mlevel, u.ulevel);
1809 if (ACURR(A_DEX) < 4)
1811 else if (ACURR(A_DEX) < 6)
1813 else if (ACURR(A_DEX) < 8)
1815 else if (ACURR(A_DEX) >= 14)
1816 tmp += (ACURR(A_DEX) - 14);
1818 /* Modify to-hit depending on distance; but keep it sane.
1819 * Polearms get a distance penalty even when wielded; it's
1820 * hard to hit at a distance.
1822 disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1827 /* gloves are a hindrance to proper use of bows */
1828 if (uarmg && uwep && objects[uwep->otyp].oc_skill == P_BOW) {
1829 switch (uarmg->otyp) {
1830 case GAUNTLETS_OF_POWER: /* metal */
1833 case GAUNTLETS_OF_FUMBLING:
1836 case LEATHER_GLOVES:
1837 case GAUNTLETS_OF_DEXTERITY:
1840 impossible("Unknown type of gloves (%d)", uarmg->otyp);
1845 tmp += omon_adj(mon, obj, TRUE);
1846 if (is_orc(mon->data)
1847 && maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
1849 if (guaranteed_hit) {
1850 tmp += 1000; /* Guaranteed hit */
1853 if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
1854 if (mon->msleeping || !mon->mcanmove) {
1855 tmiss(obj, mon, FALSE);
1857 } else if (mon->mtame) {
1859 pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1861 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82Ä
\92u
\82¢
\82½
\81D", Monnam(mon), xname(obj));
1865 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1867 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82½
\81D", Monnam(mon), xname(obj));
1868 return gem_accept(mon, obj);
1872 /* don't make game unwinnable if naive player throws artifact
1873 at leader... (kicked artifact is ok too; HMON_APPLIED could
1874 occur if quest artifact polearm or grapnel ever gets added) */
1875 if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
1876 /* AIS: changes to wakeup() means that it's now less inappropriate here
1877 than it used to be, but the manual version works just as well */
1879 mon->mstrategy &= ~STRAT_WAITMASK;
1881 if (mon->mcanmove) {
1883 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1885 pline("%s
\82Í%s
\82ð
\92Í
\82ñ
\82¾
\81D", Monnam(mon), xname(obj));
1886 if (mon->mpeaceful) {
1887 boolean next2u = monnear(mon, u.ux, u.uy);
1889 finish_quest(obj); /* acknowledge quest completion */
1891 pline("%s %s %s back to you.", Monnam(mon),
1892 (next2u ? "hands" : "tosses"), the(xname(obj)));
1894 pline("%s
\82Í%s
\82ð
\82 \82È
\82½
\82É
\95Ô
\82µ
\82½
\81D", Monnam(mon),
1898 sho_obj_return_to_u(obj);
1899 obj = addinv(obj); /* back into your inventory */
1900 (void) encumber_msg();
1902 /* angry leader caught it and isn't returning it */
1903 if (*u.ushops || obj->unpaid) /* not very likely... */
1904 check_shop_obj(obj, mon->mx, mon->my, FALSE);
1905 (void) mpickobj(mon, obj);
1907 return 1; /* caller doesn't need to place it */
1914 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1915 || obj->oclass == GEM_CLASS) {
1916 if (hmode == HMON_KICKED) {
1917 /* throwing adjustments and weapon skill bonus don't apply */
1918 tmp -= (is_ammo(obj) ? 5 : 3);
1919 } else if (is_ammo(obj)) {
1920 if (!ammo_and_launcher(obj, uwep)) {
1923 tmp += uwep->spe - greatest_erosion(uwep);
1924 tmp += weapon_hit_bonus(uwep);
1925 if (uwep->oartifact)
1926 tmp += spec_abon(uwep, mon);
1928 * Elves and Samurais are highly trained w/bows,
1929 * especially their own special types of bow.
1930 * Polymorphing won't make you a bow expert.
1932 if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI))
1933 && (!Upolyd || your_race(youmonst.data))
1934 && objects[uwep->otyp].oc_skill == P_BOW) {
1936 if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW)
1938 else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI)
1942 } else { /* thrown non-ammo or applied polearm/grapnel */
1943 if (otyp == BOOMERANG) /* arbitrary */
1945 else if (throwing_weapon(obj)) /* meant to be thrown */
1947 else if (obj == thrownobj) /* not meant to be thrown */
1949 /* we know we're dealing with a weapon or weptool handled
1950 by WEAPON_SKILLS once ammo objects have been excluded */
1951 tmp += weapon_hit_bonus(obj);
1954 if (tmp >= dieroll) {
1955 boolean wasthrown = (thrownobj != 0),
1956 /* remember weapon attribute; hmon() might destroy obj */
1957 chopper = is_axe(obj);
1959 /* attack hits mon */
1960 if (hmode == HMON_APPLIED)
1961 u.uconduct.weaphit++;
1962 if (hmon(mon, obj, hmode, dieroll)) { /* mon still alive */
1964 cutworm(mon, bhitpos.x, bhitpos.y, chopper);
1966 exercise(A_DEX, TRUE);
1967 /* if hero was swallowed and projectile killed the engulfer,
1968 'obj' got added to engulfer's inventory and then dropped,
1969 so we can't safely use that pointer anymore; it escapes
1970 the chance to be used up here... */
1971 if (wasthrown && !thrownobj)
1974 /* projectiles other than magic stones sometimes disappear
1975 when thrown; projectiles aren't among the types of weapon
1976 that hmon() might have destroyed so obj is intact */
1977 if (objects[otyp].oc_skill < P_NONE
1978 && objects[otyp].oc_skill > -P_BOOMERANG
1979 && !objects[otyp].oc_magic) {
1980 /* we were breaking 2/3 of everything unconditionally.
1981 * we still don't want anything to survive unconditionally,
1982 * but we need ammo to stay around longer on average.
1986 chance = 3 + greatest_erosion(obj) - obj->spe;
1988 broken = rn2(chance);
1991 if (obj->blessed && !rnl(4))
1995 if (*u.ushops || obj->unpaid)
1996 check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
1997 obfree(obj, (struct obj *) 0);
2001 passive_obj(mon, obj, (struct attack *) 0);
2003 tmiss(obj, mon, TRUE);
2004 if (hmode == HMON_APPLIED)
2008 } else if (otyp == HEAVY_IRON_BALL) {
2009 exercise(A_STR, TRUE);
2010 if (tmp >= dieroll) {
2011 int was_swallowed = guaranteed_hit;
2013 exercise(A_DEX, TRUE);
2014 if (!hmon(mon, obj, hmode, dieroll)) { /* mon killed */
2015 if (was_swallowed && !u.uswallow && obj == uball)
2016 return 1; /* already did placebc() */
2019 tmiss(obj, mon, TRUE);
2022 } else if (otyp == BOULDER) {
2023 exercise(A_STR, TRUE);
2024 if (tmp >= dieroll) {
2025 exercise(A_DEX, TRUE);
2026 (void) hmon(mon, obj, hmode, dieroll);
2028 tmiss(obj, mon, TRUE);
2031 } else if ((otyp == EGG || otyp == CREAM_PIE || otyp == BLINDING_VENOM
2032 || otyp == ACID_VENOM)
2033 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
2034 (void) hmon(mon, obj, hmode, dieroll);
2035 return 1; /* hmon used it up */
2037 } else if (obj->oclass == POTION_CLASS
2038 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
2039 potionhit(mon, obj, POTHIT_HERO_THROW);
2042 } else if (befriend_with_obj(mon->data, obj)
2043 || (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
2044 if (tamedog(mon, obj)) {
2045 return 1; /* obj is gone */
2047 tmiss(obj, mon, FALSE);
2049 mon->mstrategy &= ~STRAT_WAITMASK;
2051 } else if (guaranteed_hit) {
2052 /* this assumes that guaranteed_hit is due to swallowing */
2054 if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
2055 if (is_animal(u.ustuck->data)) {
2056 minstapetrify(u.ustuck, TRUE);
2057 /* Don't leave a cockatrice corpse available in a statue */
2065 pline("%s into %s %s.", Tobjnam(obj, "vanish"),
2066 s_suffix(mon_nam(mon)),
2067 is_animal(u.ustuck->data) ? "entrails" : "currents");
2069 pline("%s
\82Í%s
\82Ì%s
\82Ö
\8fÁ
\82¦
\82½
\81D", xname(obj),
2071 is_animal(u.ustuck->data) ? "
\93à
\91\9f\82Ì
\92\86" : "
\97¬
\82ê");
2074 tmiss(obj, mon, TRUE);
2081 gem_accept(mon, obj)
2082 register struct monst *mon;
2083 register struct obj *obj;
2086 boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
2087 boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
2090 static NEARDATA const char nogood[] = " is not interested in your junk.";
2092 static NEARDATA const char nogood[] = "
\82 \82È
\82½
\82Ì
\83K
\83\89\83N
\83^
\82É
\8b»
\96¡
\82ð
\8e¦
\82³
\82È
\82¢
\81D";
2094 static NEARDATA const char acceptgift[] = " accepts your gift.";
2096 static NEARDATA const char acceptgift[] = "
\82 \82È
\82½
\82Ì
\91¡
\82è
\95¨
\82ð
\8eó
\82¯
\82Æ
\82Á
\82½
\81D";
2098 static NEARDATA const char maybeluck[] = " hesitatingly";
2100 static NEARDATA const char maybeluck[] = "
\82½
\82ß
\82ç
\82¢
\82È
\82ª
\82ç";
2102 static NEARDATA const char noluck[] = " graciously";
2104 static NEARDATA const char noluck[] = "
\92\9a\8fd
\82É";
2106 static NEARDATA const char addluck[] = " gratefully";
2108 static NEARDATA const char addluck[] = "
\8aì
\82ñ
\82Å";
2110 Strcpy(buf, Monnam(mon));
2112 Strcat(buf, "
\82Í");
2117 /* object properly identified */
2118 if (obj->dknown && objects[obj->otyp].oc_name_known) {
2121 Strcat(buf, addluck);
2124 Strcat(buf, maybeluck);
2125 change_luck(rn2(7) - 3);
2128 Strcat(buf, nogood);
2131 /* making guesses */
2132 } else if (has_oname(obj) || objects[obj->otyp].oc_uname) {
2135 Strcat(buf, addluck);
2138 Strcat(buf, maybeluck);
2139 change_luck(rn2(3) - 1);
2142 Strcat(buf, nogood);
2145 /* value completely unknown to @ */
2149 Strcat(buf, addluck);
2152 Strcat(buf, maybeluck);
2153 change_luck(rn2(3) - 1);
2156 Strcat(buf, noluck);
2159 Strcat(buf, acceptgift);
2160 if (*u.ushops || obj->unpaid)
2161 check_shop_obj(obj, mon->mx, mon->my, TRUE);
2162 (void) mpickobj(mon, obj); /* may merge and free obj */
2168 if (!tele_restrict(mon))
2169 (void) rloc(mon, TRUE);
2174 * Comments about the restructuring of the old breaks() routine.
2176 * There are now three distinct phases to object breaking:
2177 * breaktest() - which makes the check/decision about whether the
2178 * object is going to break.
2179 * breakmsg() - which outputs a message about the breakage,
2180 * appropriate for that particular object. Should
2181 * only be called after a positive breaktest().
2182 * on the object and, if it going to be called,
2183 * it must be called before calling breakobj().
2184 * Calling breakmsg() is optional.
2185 * breakobj() - which actually does the breakage and the side-effects
2186 * of breaking that particular object. This should
2187 * only be called after a positive breaktest() on the
2190 * Each of the above routines is currently static to this source module.
2191 * There are two routines callable from outside this source module which
2192 * perform the routines above in the correct sequence.
2194 * hero_breaks() - called when an object is to be broken as a result
2195 * of something that the hero has done. (throwing it,
2197 * breaks() - called when an object is to be broken for some
2198 * reason other than the hero doing something to it.
2202 * The hero causes breakage of an object (throwing, dropping it, etc.)
2203 * Return 0 if the object didn't break, 1 if the object broke.
2206 hero_breaks(obj, x, y, from_invent)
2208 xchar x, y; /* object location (ox, oy may not be right) */
2209 boolean from_invent; /* thrown or dropped by player; maybe on shop bill */
2211 boolean in_view = Blind ? FALSE : (from_invent || cansee(x, y));
2213 if (!breaktest(obj))
2215 breakmsg(obj, in_view);
2216 breakobj(obj, x, y, TRUE, from_invent);
2221 * The object is going to break for a reason other than the hero doing
2223 * Return 0 if the object doesn't break, 1 if the object broke.
2228 xchar x, y; /* object location (ox, oy may not be right) */
2230 boolean in_view = Blind ? FALSE : cansee(x, y);
2232 if (!breaktest(obj))
2234 breakmsg(obj, in_view);
2235 breakobj(obj, x, y, FALSE, FALSE);
2240 release_camera_demon(obj, x, y)
2246 && (mtmp = makemon(&mons[rn2(3) ? PM_HOMUNCULUS : PM_IMP], x, y,
2247 NO_MM_FLAGS)) != 0) {
2248 if (canspotmon(mtmp))
2250 pline("%s is released!", Hallucination
2251 ? An(rndmonnam(NULL))
2252 : "The picture-painting demon");
2254 pline("%s
\82ª
\89ð
\95ú
\82³
\82ê
\82½
\81I", Hallucination
2256 : "
\82¨
\8aG
\95`
\82«
\82Ì
\88«
\96\82");
2258 mtmp->mpeaceful = !obj->cursed;
2264 * Unconditionally break an object. Assumes all resistance checks
2265 * and break messages have been delivered prior to getting here.
2268 breakobj(obj, x, y, hero_caused, from_invent)
2270 xchar x, y; /* object location (ox, oy may not be right) */
2271 boolean hero_caused; /* is this the hero's fault? */
2272 boolean from_invent;
2274 boolean fracture = FALSE;
2276 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2281 case POT_WATER: /* really, all potions */
2282 obj->in_use = 1; /* in case it's fatal */
2283 if (obj->otyp == POT_OIL && obj->lamplit) {
2284 explode_oil(obj, x, y);
2285 } else if (distu(x, y) <= 2) {
2286 if (!breathless(youmonst.data) || haseyes(youmonst.data)) {
2287 if (obj->otyp != POT_WATER) {
2288 if (!breathless(youmonst.data)) {
2289 /* [what about "familiar odor" when known?] */
2291 You("smell a peculiar odor...");
2293 You("
\96ò
\82Á
\82Û
\82¢
\93õ
\82¢
\82ª
\82µ
\82½
\81D
\81D
\81D");
2296 const char *eyes = body_part(EYE);
2298 if (eyecount(youmonst.data) != 1)
2299 eyes = makeplural(eyes);
2300 Your("%s %s.", eyes, vtense(eyes, "water"));
2302 You("
\97Ü%s
\82É
\82È
\82Á
\82½
\81D", body_part(EYE));
2309 /* monster breathing isn't handled... [yet?] */
2311 case EXPENSIVE_CAMERA:
2312 release_camera_demon(obj, x, y);
2315 /* breaking your own eggs is bad luck */
2316 if (hero_caused && obj->spe && obj->corpsenm >= LOW_PM)
2317 change_luck((schar) -min(obj->quan, 5L));
2321 /* caller will handle object disposition;
2322 we're just doing the shop theft handling */
2330 if (from_invent || obj->unpaid) {
2331 if (*u.ushops || obj->unpaid)
2332 check_shop_obj(obj, x, y, TRUE);
2333 } else if (!obj->no_charge && costly_spot(x, y)) {
2334 /* it is assumed that the obj is a floor-object */
2335 char *o_shop = in_rooms(x, y, SHOPBASE);
2336 struct monst *shkp = shop_keeper(*o_shop);
2338 if (shkp) { /* (implies *o_shop != '\0') */
2339 static NEARDATA long lastmovetime = 0L;
2340 static NEARDATA boolean peaceful_shk = FALSE;
2341 /* We want to base shk actions on her peacefulness
2342 at start of this turn, so that "simultaneous"
2343 multiple breakage isn't drastically worse than
2344 single breakage. (ought to be done via ESHK) */
2345 if (moves != lastmovetime)
2346 peaceful_shk = shkp->mpeaceful;
2347 if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L
2348 && (*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy))
2349 && moves != lastmovetime)
2350 make_angry_shk(shkp, x, y);
2351 lastmovetime = moves;
2360 * Check to see if obj is going to break, but don't actually break it.
2361 * Return 0 if the object isn't going to break, 1 if it is.
2367 if (obj_resists(obj, 1, 99))
2369 if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact
2370 && obj->oclass != GEM_CLASS)
2372 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2373 case EXPENSIVE_CAMERA:
2374 case POT_WATER: /* really, all potions */
2379 case BLINDING_VENOM:
2387 breakmsg(obj, in_view)
2391 const char *to_pieces;
2396 /* "shatter"
\81¨ "
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½"
2397 "shatter into a thousand pieces"
\81¨ "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç
\82É
\82È
\82Á
\82½" */
2398 to_pieces = "
\82±
\82È
\82²
\82È";
2400 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2401 default: /* glass or crystal wand */
2402 if (obj->oclass != WAND_CLASS)
2403 impossible("breaking odd object?");
2405 case CRYSTAL_PLATE_MAIL:
2409 case EXPENSIVE_CAMERA:
2411 to_pieces = " into a thousand pieces";
2413 to_pieces = "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç";
2415 case POT_WATER: /* really, all potions */
2418 You_hear("%s shatter!", something);
2420 You_hear("%s
\82ª
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81I", something);
2423 pline("%s shatter%s%s!", Doname2(obj),
2424 (obj->quan == 1L) ? "s" : "", to_pieces);
2426 pline("%s
\82Í%s
\82É
\82È
\82Á
\82½
\81I", Doname2(obj), to_pieces);
2434 pline("
\83r
\83`
\83\83\81I");
2439 pline("What a mess!");
2441 pline("
\82±
\82è
\82á
\82Ð
\82Ç
\82¢
\81I");
2444 case BLINDING_VENOM:
2448 pline("
\83r
\83`
\83\83\81I");
2457 int range, odx, ody;
2458 register struct monst *mon;
2460 if (!u.dx && !u.dy && !u.dz) {
2462 You("cannot throw gold at yourself.");
2464 pline("
\8e©
\95ª
\82É
\8bà
\89Ý
\82ð
\93\8a\82°
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2470 pline(is_animal(u.ustuck->data) ? "%s in the %s's entrails."
2472 "The money disappears", mon_nam(u.ustuck));
2474 pline(is_animal(u.ustuck->data) ? "
\8bà
\89Ý
\82Í%s
\82Ì
\95 \82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D"
2475 : "
\8bà
\89Ý
\82Í%s
\82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D",
2478 add_to_minv(u.ustuck, obj);
2483 if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater
2484 && !Is_waterlevel(&u.uz)) {
2486 pline_The("gold hits the %s, then falls back on top of your %s.",
2487 ceiling(u.ux, u.uy), body_part(HEAD));
2489 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",
2490 ceiling(u.ux,u.uy), body_part(HEAD));
2492 /* some self damage? */
2495 pline("Fortunately, you are wearing %s!",
2497 pline("
\8dK
\89^
\82È
\82±
\82Æ
\82É
\81C
\82 \82È
\82½
\82Í%s
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é
\81I",
2498 an(helm_simple_name(uarmh)));
2503 /* consistent with range for normal objects */
2504 range = (int) ((ACURRSTR) / 2 - obj->owt / 40);
2506 /* see if the gold has a place to move into */
2509 if (!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
2513 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
2514 (int FDECL((*), (MONST_P, OBJ_P))) 0,
2515 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
2517 return 1; /* object is gone */
2519 if (ghitm(mon, obj)) /* was it caught? */
2522 if (ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
2529 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall"))
2531 if (flooreffects(obj, bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é"))
2535 pline_The("gold hits the %s.", surface(bhitpos.x, bhitpos.y));
2537 pline("
\8bà
\89Ý
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", surface(bhitpos.x, bhitpos.y));
2538 place_object(obj, bhitpos.x, bhitpos.y);
2540 sellobj(obj, bhitpos.x, bhitpos.y);
2542 newsym(bhitpos.x, bhitpos.y);