1 /* NetHack 3.6 dothrow.c $NHDT-Date: 1446975465 2015/11/08 09:37:45 $ $NHDT-Branch: master $:$NHDT-Revision: 1.113 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 /* Contains code for 't' (throw) */
7 /* JNetHack Copyright */
8 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
9 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
10 /* JNetHack may be freely redistributed. See license for details. */
14 STATIC_DCL int FDECL(throw_obj, (struct obj *, int));
15 STATIC_DCL boolean FDECL(ok_to_throw, (int *));
16 STATIC_DCL void NDECL(autoquiver);
17 STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *));
18 STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *, BOOLEAN_P));
19 STATIC_DCL int FDECL(throw_gold, (struct obj *));
20 STATIC_DCL void FDECL(check_shop_obj, (struct obj *, XCHAR_P, XCHAR_P,
22 STATIC_DCL void FDECL(breakmsg, (struct obj *, BOOLEAN_P));
23 STATIC_DCL boolean FDECL(toss_up, (struct obj *, BOOLEAN_P));
24 STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *));
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 * For the last, if player's response is a stack, we put
405 * that stack into quiver slot provided it's not wielded.
407 if (!ok_to_throw(&shotlimit))
410 if ((obj = uquiver) == 0) {
411 if (!flags.autoquiver) {
413 You("have no ammunition readied.");
415 You("
\94
\8eË
\8f\80\94õ
\82ª
\90®
\82Á
\82Ä
\82¢
\82È
\82¢
\81I");
418 if ((obj = uquiver) == 0)
420 You("have nothing appropriate for your quiver.");
422 You("
\94
\8eË
\82·
\82é
\82à
\82Ì
\82ª
\82È
\82¢
\81D");
424 /* if autoquiver is disabled or has failed, prompt for missile;
425 fill quiver with it if it's not wielded */
427 obj = getobj(uslinging() ? bullets : toss_objs, "throw");
428 /* Q command doesn't allow gold in quiver */
429 if (obj && !obj->owornmask && obj->oclass != COIN_CLASS)
430 setuqwep(obj); /* demi-autoquiver */
432 /* give feedback if quiver has now been filled */
434 uquiver->owornmask &= ~W_QUIVER; /* less verbose */
436 prinv("You ready:", uquiver, 0L);
438 prinv("
\8f\80\94õ
\81F", uquiver, 0L);
439 uquiver->owornmask |= W_QUIVER;
443 return obj ? throw_obj(obj, shotlimit) : 0;
446 /* if in midst of multishot shooting/throwing, stop early */
448 endmultishot(verbose)
451 if (m_shot.i < m_shot.n) {
452 if (verbose && !context.mon_moving) {
454 You("stop %s after the %d%s %s.",
455 m_shot.s ? "firing" : "throwing", m_shot.i, ordin(m_shot.i),
456 m_shot.s ? "shot" : "toss");
458 You("%d
\94
\96Ú
\82ð%s
\82Æ
\82±
\82ë
\82Å
\8ec
\82è
\82ð%s
\82Ì
\82ð
\82â
\82ß
\82½
\81D", m_shot.i,
459 m_shot.s ? "
\8c\82\82Á
\82½" : "
\93\8a\82°
\82½",
460 m_shot.s ? "
\8c\82\82Â" : "
\93\8a\82°
\82é");
463 m_shot.n = m_shot.i; /* make current shot be the last */
468 * Object hits floor at hero's feet. Called from drop() and throwit().
472 register struct obj *obj;
474 if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
478 if (IS_ALTAR(levl[u.ux][u.uy].typ))
482 pline("%s hit%s the %s.", Doname2(obj), (obj->quan == 1L) ? "s" : "",
483 surface(u.ux, u.uy));
485 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", Doname2(obj),
489 if (hero_breaks(obj, u.ux, u.uy, TRUE))
491 if (ship_object(obj, u.ux, u.uy, FALSE))
497 * Walk a path from src_cc to dest_cc, calling a proc for each location
498 * except the starting one. If the proc returns FALSE, stop walking
499 * and return FALSE. If stopped early, dest_cc will be the location
500 * before the failed callback.
503 walk_path(src_cc, dest_cc, check_proc, arg)
506 boolean FDECL((*check_proc), (genericptr_t, int, int));
509 int x, y, dx, dy, x_change, y_change, err, i, prev_x, prev_y;
510 boolean keep_going = TRUE;
512 /* Use Bresenham's Line Algorithm to walk from src to dest */
513 dx = dest_cc->x - src_cc->x;
514 dy = dest_cc->y - src_cc->y;
515 prev_x = x = src_cc->x;
516 prev_y = y = src_cc->y;
540 /* check for early exit condition */
541 if (!(keep_going = (*check_proc)(arg, x, y)))
554 /* check for early exit condition */
555 if (!(keep_going = (*check_proc)(arg, x, y)))
561 return TRUE; /* successful */
569 * Single step for the hero flying through the air from jumping, flying,
570 * etc. Called from hurtle() and jump() via walk_path(). We expect the
571 * argument to be a pointer to an integer -- the range -- which is
572 * used in the calculation of points off if we hit something.
574 * Bumping into monsters won't cause damage but will wake them and make
575 * them angry. Auto-pickup isn't done, since you don't have control over
576 * your movements at the time.
578 * Possible additions/changes:
579 * o really attack monster if we hit one
580 * o set stunned if we hit a wall or door
581 * o reset nomul when we stop
582 * o creepy feeling if pass through monster (if ever implemented...)
584 * o let jumps go over boulders
587 hurtle_step(arg, x, y)
591 int ox, oy, *range = (int *) arg;
594 boolean may_pass = TRUE;
600 You_feel("the spirits holding you back.");
602 You_feel("
\82 \82È
\82½
\82ð
\95ß
\82Ü
\82¦
\82Ä
\82¢
\82½
\8d°
\82ª
\96ß
\82Á
\82½
\8bC
\82ª
\82µ
\82½
\81D");
604 } else if (!in_out_region(x, y)) {
606 } else if (*range == 0) {
607 return FALSE; /* previous step wants to stop now */
610 if (!Passes_walls || !(may_pass = may_passwall(x, y))) {
611 if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
617 pline("
\82¢
\82Ä
\82Á
\81I");
618 if (IS_TREE(levl[x][y].typ))
620 s = "bumping into a tree";
622 s = "
\96Ø
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
623 else if (IS_ROCK(levl[x][y].typ))
625 s = "bumping into a wall";
627 s = "
\95Ç
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
630 s = "bumping into a door";
632 s = "
\94à
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä";
633 dmg = rnd(2 + *range);
634 losehp(Maybe_Half_Phys(dmg), s, KILLED_BY);
635 wake_nearto(x,y, 10);
638 if (levl[x][y].typ == IRONBARS) {
640 You("crash into some iron bars. Ouch!");
642 You("
\93S
\82Ì
\96_
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D
\82¢
\82Ä
\82Á
\81I");
643 dmg = rnd(2 + *range);
645 losehp(Maybe_Half_Phys(dmg), "crashing into iron bars",
648 losehp(Maybe_Half_Phys(dmg), "
\93S
\82Ì
\96_
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä",
651 wake_nearto(x,y, 20);
654 if ((obj = sobj_at(BOULDER, x, y)) != 0) {
656 You("bump into a %s. Ouch!", xname(obj));
658 You("%s
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D
\82¢
\82Ä
\82Á
\81I", xname(obj));
659 dmg = rnd(2 + *range);
661 losehp(Maybe_Half_Phys(dmg), "bumping into a boulder", KILLED_BY);
663 losehp(Maybe_Half_Phys(dmg), "
\8aâ
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82Ä", KILLED_BY);
664 wake_nearto(x,y, 10);
668 /* did we hit a no-dig non-wall position? */
670 You("smack into something!");
672 You("
\89½
\82©
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81I");
673 dmg = rnd(2 + *range);
675 losehp(Maybe_Half_Phys(dmg), "touching the edge of the universe",
678 losehp(Maybe_Half_Phys(dmg), "
\90¢
\8aE
\82Ì
\89Ê
\82Ä
\82É
\90G
\82ê
\82Ä",
681 wake_nearto(x,y, 10);
684 if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
685 && bad_rock(youmonst.data, x, u.uy)) {
687 (invent && (inv_weight() + weight_cap() > 600));
688 /* Move at a diagonal. */
689 if (bigmonst(youmonst.data) || too_much) {
691 You("%sget forcefully wedged into a crevice.",
692 too_much ? "and all your belongings " : "");
694 You("%s
\82Í
\82Þ
\82è
\82â
\82è
\82·
\82«
\8aÔ
\82É
\89\9f\82µ
\8d\9e\82ß
\82ç
\82ê
\82½
\81D",
695 too_much ? "
\82Æ
\91S
\95\94\82Ì
\89×
\95¨" : "");
697 dmg = rnd(2 + *range);
699 losehp(Maybe_Half_Phys(dmg), "wedging into a narrow crevice",
702 losehp(Maybe_Half_Phys(dmg), "
\8b·
\82¢
\82·
\82«
\8aÔ
\82É
\89\9f\82µ
\8d\9e\82ß
\82ç
\82ê
\82Ä",
705 wake_nearto(x,y, 10);
711 if ((mon = m_at(x, y)) != 0) {
713 You("bump into %s.", a_monnam(mon));
715 You("%s
\82É
\82Ô
\82¿
\82 \82½
\82Á
\82½
\81D", a_monnam(mon));
717 wake_nearto(x,y, 10);
720 if ((u.ux - x) && (u.uy - y) && bad_rock(youmonst.data, u.ux, y)
721 && bad_rock(youmonst.data, x, u.uy)) {
722 /* Move at a diagonal. */
725 You("come to an abrupt halt!");
727 You("
\82Æ
\82Â
\82º
\82ñ
\92â
\8e~
\82µ
\82½
\81I");
734 u_on_newpos(x, y); /* set u.<ux,uy>, u.usteed-><mx,my>; cliparound(); */
735 newsym(ox, oy); /* update old position */
736 vision_recalc(1); /* update for new position */
739 * Each trap should really trigger on the recoil if
740 * it would trigger during normal movement. However,
741 * not all the possible side-effects of this are
742 * tested [as of 3.4.0] so we trigger those that
743 * we have tested, and offer a message for the
744 * ones that we have not yet tested.
746 if ((ttmp = t_at(x, y)) != 0) {
747 if (ttmp->ttyp == MAGIC_PORTAL) {
750 } else if (ttmp->ttyp == VIBRATING_SQUARE) {
751 pline("The ground vibrates as you pass it.");
752 dotrap(ttmp, 0); /* doesn't print messages */
753 } else if (ttmp->ttyp == FIRE_TRAP) {
755 } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT
756 || ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR)
758 /* Air currents overcome the recoil */
765 You("pass right over %s.",
766 an(defsyms[trap_to_defsym(ttmp->ttyp)].explanation));
768 You("%s
\82Ì
\90^
\8fã
\82ð
\92Ê
\89ß
\82µ
\82½
\81D",
769 defsyms[trap_to_defsym(ttmp->ttyp)].explanation);
773 if (--*range < 0) /* make sure our range never goes negative */
781 mhurtle_step(arg, x, y)
785 struct monst *mon = (struct monst *) arg;
787 /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially
788 * rather than just stopping before.
790 if (goodpos(x, y, mon, 0) && m_in_out_region(mon, x, y)) {
791 remove_monster(mon->mx, mon->my);
792 newsym(mon->mx, mon->my);
793 place_monster(mon, x, y);
794 newsym(mon->mx, mon->my);
803 * The player moves through the air for a few squares as a result of
804 * throwing or kicking something.
806 * dx and dy should be the direction of the hurtle, not of the original
807 * kick or throw and be only.
810 hurtle(dx, dy, range, verbose)
816 /* The chain is stretched vertically, so you shouldn't be able to move
817 * very far diagonally. The premise that you should be able to move one
818 * spot leads to calculations that allow you to only move one spot away
819 * from the ball, if you are levitating over the ball, or one spot
820 * towards the ball, if you are at the end of the chain. Rather than
821 * bother with all of that, assume that there is no slack in the chain
822 * for diagonal movement, give the player a message and return.
824 if (Punished && !carried(uball)) {
826 You_feel("a tug from the iron ball.");
828 You_feel("
\93S
\8b\85\82É
\82Ð
\82Á
\82Ï
\82ç
\82ê
\82Ä
\82¢
\82é
\82æ
\82¤
\82È
\8bC
\82ª
\82µ
\82½
\81D");
831 } else if (u.utrap) {
833 You("are anchored by the %s.",
834 u.utraptype == TT_WEB
836 : u.utraptype == TT_LAVA
838 : u.utraptype == TT_INFLOOR
839 ? surface(u.ux, u.uy)
840 : u.utraptype == TT_BURIEDBALL ? "buried ball"
843 You("%s
\82É
\90\98\82¦
\82Â
\82¯
\82ç
\82ê
\82Ä
\82¢
\82é
\81D",
844 u.utraptype == TT_WEB
845 ? "
\82
\82à
\82Ì
\91\83"
846 : u.utraptype == TT_LAVA
848 : u.utraptype == TT_INFLOOR
850 : u.utraptype == TT_BURIEDBALL ? "
\96\84\82Ü
\82Á
\82Ä
\82¢
\82é
\8b\85"
857 /* make sure dx and dy are [-1,0,1] */
861 if (!range || (!dx && !dy) || u.ustuck)
862 return; /* paranoia */
866 multi_reason = "moving through the air";
868 multi_reason = "
\8bó
\92\86\82ð
\88Ú
\93®
\82µ
\82Ä
\82¢
\82é
\8e\9e\82É";
869 nomovemsg = ""; /* it just happens */
872 You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
874 You("
\8bt
\95û
\8cü
\82É
\94ò
\82Î
\82³
\82ê
\82½
\81D");
875 /* if we're in the midst of shooting multiple projectiles, stop */
880 /* this setting of cc is only correct if dx and dy are [-1,0,1] only */
881 cc.x = u.ux + (dx * range);
882 cc.y = u.uy + (dy * range);
883 (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t) &range);
886 /* Move a monster through the air for a few squares.
889 mhurtle(mon, dx, dy, range)
895 /* At the very least, debilitate the monster */
899 /* Is the monster stuck or too heavy to push?
900 * (very large monsters have too much inertia, even floaters and flyers)
902 if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped)
905 /* Make sure dx and dy are [-1,0,1] */
908 if (!range || (!dx && !dy))
909 return; /* paranoia */
910 /* don't let grid bugs be hurtled diagonally */
911 if (dx && dy && NODIAG(monsndx(mon->data)))
914 /* Send the monster along the path */
917 cc.x = mon->mx + (dx * range);
918 cc.y = mon->my + (dy * range);
919 (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t) mon);
924 check_shop_obj(obj, x, y, broken)
929 struct monst *shkp = shop_keeper(*u.ushops);
934 if (broken || !costly_spot(x, y)
935 || *in_rooms(x, y, SHOPBASE) != *u.ushops) {
936 /* thrown out of a shop or into a different shop */
938 (void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
943 if (costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
945 subfrombill(obj, shkp);
946 else if (x != shkp->mx || y != shkp->my)
953 * Hero tosses an object upwards with appropriate consequences.
955 * Returns FALSE if the object is gone.
958 toss_up(obj, hitsroof)
963 boolean petrifier = ((obj->otyp == EGG || obj->otyp == CORPSE)
964 && touch_petrifies(&mons[obj->corpsenm]));
965 /* note: obj->quan == 1 */
967 if (!has_ceiling(&u.uz)) {
969 action = "flies up into"; /* into "the sky" or "the water above" */
971 action = "
\82Ì
\92\86\82ð
\94ò
\82ñ
\82¾"; /* into "the sky" or "the water above" */
973 } else if (hitsroof) {
974 if (breaktest(obj)) {
976 pline("%s hits the %s.", Doname2(obj), ceiling(u.ux, u.uy));
978 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", Doname2(obj), ceiling(u.ux, u.uy));
979 breakmsg(obj, !Blind);
980 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
986 action = "
\82É
\96½
\92\86\82µ
\82½";
989 action = "almost hits";
991 action = "
\82É
\82à
\82¤
\8f
\82µ
\82Å
\96½
\92\86\82·
\82é
\82Æ
\82±
\82ë
\82¾
\82Á
\82½";
994 pline("%s %s the %s, then falls back on top of your %s.", Doname2(obj),
995 action, ceiling(u.ux, u.uy), body_part(HEAD));
997 pline("%s
\82Í%s%s
\81C
\82»
\82µ
\82Ä%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82Ä
\82«
\82½
\81D", Doname2(obj),
998 ceiling(u.ux, u.uy), action, body_part(HEAD));
1001 /* object now hits you */
1003 if (obj->oclass == POTION_CLASS) {
1004 potionhit(&youmonst, obj, TRUE);
1005 } else if (breaktest(obj)) {
1006 int otyp = obj->otyp;
1009 /* need to check for blindness result prior to destroying obj */
1010 blindinc = ((otyp == CREAM_PIE || otyp == BLINDING_VENOM)
1011 /* AT_WEAP is ok here even if attack type was AT_SPIT */
1012 && can_blnd(&youmonst, &youmonst, AT_WEAP, obj))
1015 breakmsg(obj, !Blind);
1016 breakobj(obj, u.ux, u.uy, TRUE, TRUE);
1017 obj = 0; /* it's now gone */
1020 if (petrifier && !Stone_resistance
1021 && !(poly_when_stoned(youmonst.data)
1022 && polymon(PM_STONE_GOLEM))) {
1023 /* egg ends up "all over your face"; perhaps
1024 visored helmet should still save you here */
1027 Your("%s fails to protect you.", helm_simple_name(uarmh));
1029 Your("%s
\82Í
\82 \82È
\82½
\82ð
\8eç
\82ê
\82È
\82©
\82Á
\82½
\81D", helm_simple_name(uarmh));
1033 case BLINDING_VENOM:
1035 pline("You've got it all over your %s!", body_part(FACE));
1037 pline("
\82»
\82ê
\82Í%s
\82ð
\82×
\82Á
\82Æ
\82è
\82Æ
\95¢
\82Á
\82½
\81I", body_part(FACE));
1039 if (otyp == BLINDING_VENOM && !Blind)
1041 pline("It blinds you!");
1043 pline("
\96Ú
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½
\81I");
1044 u.ucreamed += blindinc;
1045 make_blinded(Blinded + (long) blindinc, FALSE);
1047 Your1(vision_clears);
1054 } else { /* neither potion nor other breaking object */
1055 boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE;
1056 int dmg = dmgval(obj, &youmonst);
1059 /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */
1060 artimsg = artifact_hit((struct monst *) 0, &youmonst, obj, &dmg,
1063 if (!dmg) { /* probably wasn't a weapon; base damage on weight */
1064 dmg = (int) obj->owt / 100;
1069 if (youmonst.data == &mons[PM_SHADE]
1070 && objects[obj->otyp].oc_material != SILVER)
1073 if (dmg > 1 && less_damage)
1078 dmg = 0; /* beware negative rings of increase damage */
1079 dmg = Maybe_Half_Phys(dmg);
1082 if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) {
1085 pline("Fortunately, you are wearing a hard helmet.");
1087 pline("
\8dK
\89^
\82É
\82à
\81C
\82 \82È
\82½
\82Í
\8cÅ
\82¢
\8a\95\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82½
\81D");
1088 /* helmet definitely protects you when it blocks petrification
1090 } else if (!petrifier) {
1093 Your("%s does not protect you.", helm_simple_name(uarmh));
1095 Your("%s
\82Å
\82Í
\96h
\82¬
\82«
\82ê
\82È
\82©
\82Á
\82½
\81D", helm_simple_name(uarmh));
1097 } else if (petrifier && !Stone_resistance
1098 && !(poly_when_stoned(youmonst.data)
1099 && polymon(PM_STONE_GOLEM))) {
1101 killer.format = KILLED_BY;
1103 Strcpy(killer.name, "elementary physics"); /* "what goes up..." */
1105 Strcpy(killer.name, "
\8f\89\93\99\95¨
\97\9d\82É
\82æ
\82è"); /* "what goes up..." */
1108 You("turn to stone.");
1110 You("
\90Î
\82É
\82È
\82Á
\82½
\81D");
1112 dropy(obj); /* bypass most of hitfloor() */
1113 thrownobj = 0; /* now either gone or on floor */
1115 return obj ? TRUE : FALSE;
1120 losehp(Maybe_Half_Phys(dmg), "falling object", KILLED_BY_AN);
1122 losehp(Maybe_Half_Phys(dmg), "
\97\8e\89º
\95¨
\82Å", KILLED_BY_AN);
1128 /* return true for weapon meant to be thrown; excludes ammo */
1130 throwing_weapon(obj)
1133 return (boolean) (is_missile(obj) || is_spear(obj)
1134 /* daggers and knife (excludes scalpel) */
1135 || (is_blade(obj) && !is_sword(obj)
1136 && (objects[obj->otyp].oc_dir & PIERCE))
1137 /* special cases [might want to add AXE] */
1138 || obj->otyp == WAR_HAMMER || obj->otyp == AKLYS);
1141 /* the currently thrown object is returning to you (not for boomerangs) */
1143 sho_obj_return_to_u(obj)
1146 /* might already be our location (bounced off a wall) */
1147 if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
1148 int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
1150 tmp_at(DISP_FLASH, obj_to_glyph(obj));
1151 while (x != u.ux || y != u.uy) {
1157 tmp_at(DISP_END, 0);
1161 /* throw an object, NB: obj may be consumed in the process */
1163 throwit(obj, wep_mask, twoweap)
1165 long wep_mask; /* used to re-equip returning boomerang */
1167 twoweap; /* used to restore twoweapon mode if wielded weapon returns */
1169 register struct monst *mon;
1170 register int range, urange;
1171 boolean crossbowing, impaired = (Confusion || Stunned || Blind
1172 || Hallucination || Fumbling);
1174 notonhead = FALSE; /* reset potentially stale value */
1175 if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
1176 boolean slipok = TRUE;
1177 if (ammo_and_launcher(obj, uwep))
1179 pline("%s!", Tobjnam(obj, "misfire"));
1181 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81I", xname(obj));
1183 /* only slip if it's greased or meant to be thrown */
1184 if (obj->greased || throwing_weapon(obj))
1185 /* BUG: this message is grammatically incorrect if obj has
1186 a plural name; greased gloves or boots for instance. */
1188 pline("%s as you throw it!", Tobjnam(obj, "slip"));
1190 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));
1203 if ((u.dx || u.dy || (u.dz < 1))
1204 && calc_capacity((int) obj->owt) > SLT_ENCUMBER
1205 && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
1206 : (u.uhp < 10 && u.uhp != u.uhpmax))
1207 && obj->owt > (unsigned) ((Upolyd ? u.mh : u.uhp) * 2)
1208 && !Is_airlevel(&u.uz)) {
1210 You("have so little stamina, %s drops from your grasp.",
1212 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",
1214 exercise(A_CON, FALSE);
1220 thrownobj->was_thrown = 1;
1224 bhitpos.x = mon->mx;
1225 bhitpos.y = mon->my;
1227 if (u.dz < 0 && Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR
1230 pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"),
1231 ceiling(u.ux, u.uy));
1233 pline("%s
\82Í%s
\82É
\96½
\92\86\82µ
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj),
1234 ceiling(u.ux,u.uy));
1237 (void) encumber_msg();
1239 u.twoweap = twoweap;
1240 } else if (u.dz < 0) {
1241 (void) toss_up(obj, rn2(5) && !Underwater);
1242 } else if (u.dz > 0 && u.usteed && obj->oclass == POTION_CLASS
1244 /* alternative to prayer or wand of opening/spell of knock
1245 for dealing with cursed saddle: throw holy water > */
1246 potionhit(u.usteed, obj, TRUE);
1250 thrownobj = (struct obj *) 0;
1253 } else if (obj->otyp == BOOMERANG && !Underwater) {
1254 if (Is_airlevel(&u.uz) || Levitation)
1255 hurtle(-u.dx, -u.dy, 1, TRUE);
1256 mon = boomhit(obj, u.dx, u.dy);
1257 if (mon == &youmonst) { /* the thing was caught */
1258 exercise(A_DEX, TRUE);
1260 (void) encumber_msg();
1261 if (wep_mask && !(obj->owornmask & wep_mask)) {
1262 setworn(obj, wep_mask);
1263 u.twoweap = twoweap;
1265 thrownobj = (struct obj *) 0;
1269 /* crossbow range is independent of strength */
1271 (ammo_and_launcher(obj, uwep) && weapon_type(uwep) == P_CROSSBOW);
1272 urange = (crossbowing ? 18 : (int) ACURRSTR) / 2;
1273 /* balls are easy to throw or at least roll;
1274 * also, this insures the maximum range of a ball is greater
1275 * than 1, so the effects from throwing attached balls are
1278 if (obj->otyp == HEAVY_IRON_BALL)
1279 range = urange - (int) (obj->owt / 100);
1281 range = urange - (int) (obj->owt / 40);
1285 else if (range >= 5)
1292 if (ammo_and_launcher(obj, uwep)) {
1297 } else if (obj->oclass != GEM_CLASS)
1301 if (Is_airlevel(&u.uz) || Levitation) {
1302 /* action, reaction... */
1311 if (obj->otyp == BOULDER)
1312 range = 20; /* you must be giant */
1313 else if (obj->oartifact == ART_MJOLLNIR)
1314 range = (range + 1) / 2; /* it's heavy */
1315 else if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
1321 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
1322 (int FDECL((*), (MONST_P, OBJ_P))) 0,
1323 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
1324 thrownobj = obj; /* obj may be null now */
1326 /* have to do this after bhit() so u.ux & u.uy are correct */
1327 if (Is_airlevel(&u.uz) || Levitation)
1328 hurtle(-u.dx, -u.dy, urange, TRUE);
1337 if (mon->isshk && obj->where == OBJ_MINVENT && obj->ocarry == mon) {
1338 thrownobj = (struct obj *) 0;
1339 return; /* alert shk caught it */
1341 (void) snuff_candle(obj);
1342 notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
1343 obj_gone = thitmonst(mon, obj);
1344 /* Monster may have been tamed; this frees old mon */
1345 mon = m_at(bhitpos.x, bhitpos.y);
1347 /* [perhaps this should be moved into thitmonst or hmon] */
1348 if (mon && mon->isshk
1349 && (!inside_shop(u.ux, u.uy)
1350 || !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops)))
1358 ; /* missile has already been handled */
1359 } else if (u.uswallow) {
1360 /* ball is not picked up by monster */
1362 (void) mpickobj(u.ustuck, obj);
1363 thrownobj = (struct obj *) 0;
1365 /* the code following might become part of dropy() */
1366 if (obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)
1368 /* we must be wearing Gauntlets of Power to get here */
1369 sho_obj_return_to_u(obj); /* display its flight */
1371 if (!impaired && rn2(100)) {
1373 pline("%s to your hand!", Tobjnam(obj, "return"));
1375 pline("%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82É
\96ß
\82Á
\82Ä
\82«
\82½
\81I", xname(obj));
1377 (void) encumber_msg();
1379 u.twoweap = twoweap;
1380 if (cansee(bhitpos.x, bhitpos.y))
1381 newsym(bhitpos.x, bhitpos.y);
1386 pline(Blind ? "%s lands %s your %s."
1387 : "%s back to you, landing %s your %s.",
1388 Blind ? Something : Tobjnam(obj, "return"),
1389 Levitation ? "beneath" : "at",
1390 makeplural(body_part(FOOT)));
1392 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82Ì%s
\82É
\97\8e\82¿
\82½
\81D",
1394 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1396 Levitation ? "
\89º" : "
\82»
\82Î");
1401 pline(Blind ? "%s your %s!"
1402 : "%s back toward you, hitting your %s!",
1403 Tobjnam(obj, Blind ? "hit" : "fly"),
1406 pline("%s
\82Í%s
\82 \82È
\82½
\82Ì%s
\82É
\96½
\92\86\82µ
\82½
\81I",
1408 Blind ? "" : "
\96ß
\82Á
\82Ä
\82«
\82Ä
\81C",
1411 (void) artifact_hit((struct monst *) 0, &youmonst, obj,
1414 losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
1419 Sprintf(jbuf, "%s
\82Å", xname(obj));
1420 losehp(Maybe_Half_Phys(dmg), jbuf, KILLED_BY);
1424 if (ship_object(obj, u.ux, u.uy, FALSE)) {
1425 thrownobj = (struct obj *) 0;
1430 thrownobj = (struct obj *) 0;
1434 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj)) {
1435 tmp_at(DISP_FLASH, obj_to_glyph(obj));
1436 tmp_at(bhitpos.x, bhitpos.y);
1438 tmp_at(DISP_END, 0);
1439 breakmsg(obj, cansee(bhitpos.x, bhitpos.y));
1440 breakobj(obj, bhitpos.x, bhitpos.y, TRUE, TRUE);
1441 thrownobj = (struct obj *) 0;
1445 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall")) {
1447 if (flooreffects(obj,bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é")) {
1448 thrownobj = (struct obj *) 0;
1451 obj_no_longer_held(obj);
1452 if (mon && mon->isshk && is_pick(obj)) {
1453 if (cansee(bhitpos.x, bhitpos.y))
1455 pline("%s snatches up %s.", Monnam(mon), the(xname(obj)));
1457 pline("%s
\82Í%s
\82ð
\92D
\82¢
\82Æ
\82Á
\82½
\81D", Monnam(mon), xname(obj));
1458 if (*u.ushops || obj->unpaid)
1459 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1460 (void) mpickobj(mon, obj); /* may merge and free obj */
1461 thrownobj = (struct obj *) 0;
1464 (void) snuff_candle(obj);
1465 if (!mon && ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) {
1466 thrownobj = (struct obj *) 0;
1469 thrownobj = (struct obj *) 0;
1470 place_object(obj, bhitpos.x, bhitpos.y);
1471 /* container contents might break;
1472 do so before turning ownership of thrownobj over to shk
1473 (container_impact_dmg handles item already owned by shop) */
1474 if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ))
1475 /* <x,y> is spot where you initiated throw, not bhitpos */
1476 container_impact_dmg(obj, u.ux, u.uy);
1477 /* charge for items thrown out of shop;
1478 shk takes possession for items thrown into one */
1479 if ((*u.ushops || obj->unpaid) && obj != uball)
1480 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
1484 drop_ball(bhitpos.x, bhitpos.y);
1485 if (cansee(bhitpos.x, bhitpos.y))
1486 newsym(bhitpos.x, bhitpos.y);
1487 if (obj_sheds_light(obj))
1488 vision_full_recalc = 1;
1492 /* an object may hit a monster; various factors adjust the chance of hitting
1495 omon_adj(mon, obj, mon_notices)
1498 boolean mon_notices;
1502 /* size of target affects the chance of hitting */
1503 tmp += (mon->data->msize - MZ_MEDIUM); /* -2..+5 */
1504 /* sleeping target is more likely to be hit */
1505 if (mon->msleeping) {
1510 /* ditto for immobilized target */
1511 if (!mon->mcanmove || !mon->data->mmove) {
1513 if (mon_notices && mon->data->mmove && !rn2(10)) {
1518 /* some objects are more likely to hit than others */
1519 switch (obj->otyp) {
1520 case HEAVY_IRON_BALL:
1528 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1529 || obj->oclass == GEM_CLASS)
1530 tmp += hitval(obj, mon);
1536 /* thrown object misses target monster */
1538 tmiss(obj, mon, maybe_wakeup)
1541 boolean maybe_wakeup;
1543 const char *missile = mshot_xname(obj);
1545 /* If the target can't be seen or doesn't look like a valid target,
1546 avoid "the arrow misses it," or worse, "the arrows misses the mimic."
1547 An attentive player will still notice that this is different from
1548 an arrow just landing short of any target (no message in that case),
1549 so will realize that there is a valid target here anyway. */
1550 if (!canseemon(mon) || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER))
1552 pline("%s %s.", The(missile), otense(obj, "miss"));
1554 pline("%s
\82Í
\82Í
\82¸
\82ê
\82½
\81D", missile);
1557 if (maybe_wakeup && !rn2(3))
1562 #define quest_arti_hits_leader(obj, mon) \
1563 (obj->oartifact && is_quest_artifact(obj) \
1564 && mon->m_id == quest_status.leader_m_id)
1567 * Object thrown by player arrives at monster's location.
1568 * Return 1 if obj has disappeared or otherwise been taken care of,
1569 * 0 if caller must take care of it.
1570 * Also used for kicked objects and for polearms/grapnel applied at range.
1574 register struct monst *mon;
1575 register struct obj *obj; /* thrownobj or kickedobj or uwep */
1577 register int tmp; /* Base chance to hit */
1578 register int disttmp; /* distance modifier */
1579 int otyp = obj->otyp, hmode;
1580 boolean guaranteed_hit = (u.uswallow && mon == u.ustuck);
1582 hmode = (obj == uwep) ? HMON_APPLIED : (obj == kickedobj) ? HMON_KICKED
1585 /* Differences from melee weapons:
1587 * Dex still gives a bonus, but strength does not.
1588 * Polymorphed players lacking attacks may still throw.
1589 * There's a base -1 to hit.
1590 * No bonuses for fleeing or stunned targets (they don't dodge
1591 * melee blows as readily, but dodging arrows is hard anyway).
1592 * Not affected by traps, etc.
1593 * Certain items which don't in themselves do damage ignore tmp.
1594 * Distance and monster size affect chance to hit.
1596 tmp = -1 + Luck + find_mac(mon) + u.uhitinc
1597 + maybe_polyd(youmonst.data->mlevel, u.ulevel);
1598 if (ACURR(A_DEX) < 4)
1600 else if (ACURR(A_DEX) < 6)
1602 else if (ACURR(A_DEX) < 8)
1604 else if (ACURR(A_DEX) >= 14)
1605 tmp += (ACURR(A_DEX) - 14);
1607 /* Modify to-hit depending on distance; but keep it sane.
1608 * Polearms get a distance penalty even when wielded; it's
1609 * hard to hit at a distance.
1611 disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
1616 /* gloves are a hindrance to proper use of bows */
1617 if (uarmg && uwep && objects[uwep->otyp].oc_skill == P_BOW) {
1618 switch (uarmg->otyp) {
1619 case GAUNTLETS_OF_POWER: /* metal */
1622 case GAUNTLETS_OF_FUMBLING:
1625 case LEATHER_GLOVES:
1626 case GAUNTLETS_OF_DEXTERITY:
1629 impossible("Unknown type of gloves (%d)", uarmg->otyp);
1634 tmp += omon_adj(mon, obj, TRUE);
1635 if (is_orc(mon->data)
1636 && maybe_polyd(is_elf(youmonst.data), Race_if(PM_ELF)))
1638 if (guaranteed_hit) {
1639 tmp += 1000; /* Guaranteed hit */
1642 if (obj->oclass == GEM_CLASS && is_unicorn(mon->data)) {
1643 if (mon->msleeping || !mon->mcanmove) {
1644 tmiss(obj, mon, FALSE);
1646 } else if (mon->mtame) {
1648 pline("%s catches and drops %s.", Monnam(mon), the(xname(obj)));
1650 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82Ä
\92u
\82¢
\82½
\81D", Monnam(mon), xname(obj));
1654 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1656 pline("%s
\82Í%s
\82ð
\82
\82í
\82¦
\82½
\81D", Monnam(mon), xname(obj));
1657 return gem_accept(mon, obj);
1661 /* don't make game unwinnable if naive player throws artifact
1662 at leader... (kicked artifact is ok too; HMON_APPLIED could
1663 occur if quest artifact polearm or grapnel ever gets added) */
1664 if (hmode != HMON_APPLIED && quest_arti_hits_leader(obj, mon)) {
1665 /* not wakeup(), which angers non-tame monsters */
1667 mon->mstrategy &= ~STRAT_WAITMASK;
1669 if (mon->mcanmove) {
1671 pline("%s catches %s.", Monnam(mon), the(xname(obj)));
1673 pline("%s
\82Í%s
\82ð
\92Í
\82ñ
\82¾
\81D", Monnam(mon), xname(obj));
1674 if (mon->mpeaceful) {
1675 boolean next2u = monnear(mon, u.ux, u.uy);
1677 finish_quest(obj); /* acknowledge quest completion */
1679 pline("%s %s %s back to you.", Monnam(mon),
1680 (next2u ? "hands" : "tosses"), the(xname(obj)));
1682 pline("%s
\82Í%s
\82ð
\82 \82È
\82½
\82É
\95Ô
\82µ
\82½
\81D", Monnam(mon),
1686 sho_obj_return_to_u(obj);
1687 obj = addinv(obj); /* back into your inventory */
1688 (void) encumber_msg();
1690 /* angry leader caught it and isn't returning it */
1691 if (*u.ushops || obj->unpaid) /* not very likely... */
1692 check_shop_obj(obj, mon->mx, mon->my, FALSE);
1693 (void) mpickobj(mon, obj);
1695 return 1; /* caller doesn't need to place it */
1700 if (obj->oclass == WEAPON_CLASS || is_weptool(obj)
1701 || obj->oclass == GEM_CLASS) {
1702 if (hmode == HMON_KICKED) {
1703 /* throwing adjustments and weapon skill bonus don't apply */
1704 tmp -= (is_ammo(obj) ? 5 : 3);
1705 } else if (is_ammo(obj)) {
1706 if (!ammo_and_launcher(obj, uwep)) {
1709 tmp += uwep->spe - greatest_erosion(uwep);
1710 tmp += weapon_hit_bonus(uwep);
1711 if (uwep->oartifact)
1712 tmp += spec_abon(uwep, mon);
1714 * Elves and Samurais are highly trained w/bows,
1715 * especially their own special types of bow.
1716 * Polymorphing won't make you a bow expert.
1718 if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI))
1719 && (!Upolyd || your_race(youmonst.data))
1720 && objects[uwep->otyp].oc_skill == P_BOW) {
1722 if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW)
1724 else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI)
1728 } else { /* thrown non-ammo or applied polearm/grapnel */
1729 if (otyp == BOOMERANG) /* arbitrary */
1731 else if (throwing_weapon(obj)) /* meant to be thrown */
1733 else if (obj == thrownobj) /* not meant to be thrown */
1735 /* we know we're dealing with a weapon or weptool handled
1736 by WEAPON_SKILLS once ammo objects have been excluded */
1737 tmp += weapon_hit_bonus(obj);
1740 if (tmp >= rnd(20)) {
1741 if (hmode == HMON_APPLIED)
1742 u.uconduct.weaphit++;
1743 if (hmon(mon, obj, hmode)) { /* mon still alive */
1744 cutworm(mon, bhitpos.x, bhitpos.y, obj);
1746 exercise(A_DEX, TRUE);
1747 /* if hero is swallowed and projectile kills the engulfer,
1748 obj gets added to engulfer's inventory and then dropped,
1749 so we can't safely use that pointer anymore; it escapes
1750 the chance to be used up here... */
1753 /* projectiles other than magic stones
1754 sometimes disappear when thrown */
1755 if (objects[otyp].oc_skill < P_NONE
1756 && objects[otyp].oc_skill > -P_BOOMERANG
1757 && !objects[otyp].oc_magic) {
1758 /* we were breaking 2/3 of everything unconditionally.
1759 * we still don't want anything to survive unconditionally,
1760 * but we need ammo to stay around longer on average.
1763 chance = 3 + greatest_erosion(obj) - obj->spe;
1765 broken = rn2(chance);
1768 if (obj->blessed && !rnl(4))
1772 if (*u.ushops || obj->unpaid)
1773 check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
1774 obfree(obj, (struct obj *) 0);
1778 passive_obj(mon, obj, (struct attack *) 0);
1780 tmiss(obj, mon, TRUE);
1781 if (hmode == HMON_APPLIED)
1785 } else if (otyp == HEAVY_IRON_BALL) {
1786 exercise(A_STR, TRUE);
1787 if (tmp >= rnd(20)) {
1788 int was_swallowed = guaranteed_hit;
1790 exercise(A_DEX, TRUE);
1791 if (!hmon(mon, obj, hmode)) { /* mon killed */
1792 if (was_swallowed && !u.uswallow && obj == uball)
1793 return 1; /* already did placebc() */
1796 tmiss(obj, mon, TRUE);
1799 } else if (otyp == BOULDER) {
1800 exercise(A_STR, TRUE);
1801 if (tmp >= rnd(20)) {
1802 exercise(A_DEX, TRUE);
1803 (void) hmon(mon, obj, hmode);
1805 tmiss(obj, mon, TRUE);
1808 } else if ((otyp == EGG || otyp == CREAM_PIE || otyp == BLINDING_VENOM
1809 || otyp == ACID_VENOM)
1810 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1811 (void) hmon(mon, obj, hmode);
1812 return 1; /* hmon used it up */
1814 } else if (obj->oclass == POTION_CLASS
1815 && (guaranteed_hit || ACURR(A_DEX) > rnd(25))) {
1816 potionhit(mon, obj, TRUE);
1819 } else if (befriend_with_obj(mon->data, obj)
1820 || (mon->mtame && dogfood(mon, obj) <= ACCFOOD)) {
1821 if (tamedog(mon, obj)) {
1822 return 1; /* obj is gone */
1824 tmiss(obj, mon, FALSE);
1826 mon->mstrategy &= ~STRAT_WAITMASK;
1828 } else if (guaranteed_hit) {
1829 /* this assumes that guaranteed_hit is due to swallowing */
1831 if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) {
1832 if (is_animal(u.ustuck->data)) {
1833 minstapetrify(u.ustuck, TRUE);
1834 /* Don't leave a cockatrice corpse available in a statue */
1842 pline("%s into %s %s.", Tobjnam(obj, "vanish"),
1843 s_suffix(mon_nam(mon)),
1844 is_animal(u.ustuck->data) ? "entrails" : "currents");
1846 pline("%s
\82Í%s
\82Ì%s
\82Ö
\8fÁ
\82¦
\82½
\81D", xname(obj),
1848 is_animal(u.ustuck->data) ? "
\93à
\91\9f\82Ì
\92\86" : "
\97¬
\82ê");
1851 tmiss(obj, mon, TRUE);
1858 gem_accept(mon, obj)
1859 register struct monst *mon;
1860 register struct obj *obj;
1863 boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
1864 boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
1867 static NEARDATA const char nogood[] = " is not interested in your junk.";
1869 static NEARDATA const char nogood[] = "
\82 \82È
\82½
\82Ì
\83K
\83\89\83N
\83^
\82É
\8b»
\96¡
\82ð
\8e¦
\82³
\82È
\82¢
\81D";
1871 static NEARDATA const char acceptgift[] = " accepts your gift.";
1873 static NEARDATA const char acceptgift[] = "
\82 \82È
\82½
\82Ì
\91¡
\82è
\95¨
\82ð
\8eó
\82¯
\82Æ
\82Á
\82½
\81D";
1875 static NEARDATA const char maybeluck[] = " hesitatingly";
1877 static NEARDATA const char maybeluck[] = "
\82½
\82ß
\82ç
\82¢
\82È
\82ª
\82ç";
1879 static NEARDATA const char noluck[] = " graciously";
1881 static NEARDATA const char noluck[] = "
\92\9a\8fd
\82É";
1883 static NEARDATA const char addluck[] = " gratefully";
1885 static NEARDATA const char addluck[] = "
\8aì
\82ñ
\82Å";
1887 Strcpy(buf, Monnam(mon));
1889 Strcat(buf, "
\82Í");
1894 /* object properly identified */
1895 if (obj->dknown && objects[obj->otyp].oc_name_known) {
1898 Strcat(buf, addluck);
1901 Strcat(buf, maybeluck);
1902 change_luck(rn2(7) - 3);
1905 Strcat(buf, nogood);
1908 /* making guesses */
1909 } else if (has_oname(obj) || objects[obj->otyp].oc_uname) {
1912 Strcat(buf, addluck);
1915 Strcat(buf, maybeluck);
1916 change_luck(rn2(3) - 1);
1919 Strcat(buf, nogood);
1922 /* value completely unknown to @ */
1926 Strcat(buf, addluck);
1929 Strcat(buf, maybeluck);
1930 change_luck(rn2(3) - 1);
1933 Strcat(buf, noluck);
1936 Strcat(buf, acceptgift);
1937 if (*u.ushops || obj->unpaid)
1938 check_shop_obj(obj, mon->mx, mon->my, TRUE);
1939 (void) mpickobj(mon, obj); /* may merge and free obj */
1945 if (!tele_restrict(mon))
1946 (void) rloc(mon, TRUE);
1951 * Comments about the restructuring of the old breaks() routine.
1953 * There are now three distinct phases to object breaking:
1954 * breaktest() - which makes the check/decision about whether the
1955 * object is going to break.
1956 * breakmsg() - which outputs a message about the breakage,
1957 * appropriate for that particular object. Should
1958 * only be called after a positive breaktest().
1959 * on the object and, if it going to be called,
1960 * it must be called before calling breakobj().
1961 * Calling breakmsg() is optional.
1962 * breakobj() - which actually does the breakage and the side-effects
1963 * of breaking that particular object. This should
1964 * only be called after a positive breaktest() on the
1967 * Each of the above routines is currently static to this source module.
1968 * There are two routines callable from outside this source module which
1969 * perform the routines above in the correct sequence.
1971 * hero_breaks() - called when an object is to be broken as a result
1972 * of something that the hero has done. (throwing it,
1974 * breaks() - called when an object is to be broken for some
1975 * reason other than the hero doing something to it.
1979 * The hero causes breakage of an object (throwing, dropping it, etc.)
1980 * Return 0 if the object didn't break, 1 if the object broke.
1983 hero_breaks(obj, x, y, from_invent)
1985 xchar x, y; /* object location (ox, oy may not be right) */
1986 boolean from_invent; /* thrown or dropped by player; maybe on shop bill */
1988 boolean in_view = Blind ? FALSE : (from_invent || cansee(x, y));
1989 if (!breaktest(obj))
1991 breakmsg(obj, in_view);
1992 breakobj(obj, x, y, TRUE, from_invent);
1997 * The object is going to break for a reason other than the hero doing
1999 * Return 0 if the object doesn't break, 1 if the object broke.
2004 xchar x, y; /* object location (ox, oy may not be right) */
2006 boolean in_view = Blind ? FALSE : cansee(x, y);
2008 if (!breaktest(obj))
2010 breakmsg(obj, in_view);
2011 breakobj(obj, x, y, FALSE, FALSE);
2016 release_camera_demon(obj, x, y)
2022 && (mtmp = makemon(&mons[rn2(3) ? PM_HOMUNCULUS : PM_IMP], x, y,
2023 NO_MM_FLAGS)) != 0) {
2024 if (canspotmon(mtmp))
2026 pline("%s is released!", Hallucination
2027 ? An(rndmonnam(NULL))
2028 : "The picture-painting demon");
2030 pline("%s
\82ª
\89ð
\95ú
\82³
\82ê
\82½
\81I", Hallucination
2032 : "
\82¨
\8aG
\95`
\82«
\82Ì
\88«
\96\82");
2034 mtmp->mpeaceful = !obj->cursed;
2040 * Unconditionally break an object. Assumes all resistance checks
2041 * and break messages have been delivered prior to getting here.
2044 breakobj(obj, x, y, hero_caused, from_invent)
2046 xchar x, y; /* object location (ox, oy may not be right) */
2047 boolean hero_caused; /* is this the hero's fault? */
2048 boolean from_invent;
2050 boolean fracture = FALSE;
2052 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2057 case POT_WATER: /* really, all potions */
2058 obj->in_use = 1; /* in case it's fatal */
2059 if (obj->otyp == POT_OIL && obj->lamplit) {
2060 explode_oil(obj, x, y);
2061 } else if (distu(x, y) <= 2) {
2062 if (!breathless(youmonst.data) || haseyes(youmonst.data)) {
2063 if (obj->otyp != POT_WATER) {
2064 if (!breathless(youmonst.data)) {
2065 /* [what about "familiar odor" when known?] */
2067 You("smell a peculiar odor...");
2069 You("
\96ò
\82Á
\82Û
\82¢
\93õ
\82¢
\82ª
\82µ
\82½
\81D
\81D
\81D");
2072 const char *eyes = body_part(EYE);
2074 if (eyecount(youmonst.data) != 1)
2075 eyes = makeplural(eyes);
2076 Your("%s %s.", eyes, vtense(eyes, "water"));
2078 You("
\97Ü%s
\82É
\82È
\82Á
\82½
\81D", body_part(EYE));
2085 /* monster breathing isn't handled... [yet?] */
2087 case EXPENSIVE_CAMERA:
2088 release_camera_demon(obj, x, y);
2091 /* breaking your own eggs is bad luck */
2092 if (hero_caused && obj->spe && obj->corpsenm >= LOW_PM)
2093 change_luck((schar) -min(obj->quan, 5L));
2097 /* caller will handle object disposition;
2098 we're just doing the shop theft handling */
2106 if (from_invent || obj->unpaid) {
2107 if (*u.ushops || obj->unpaid)
2108 check_shop_obj(obj, x, y, TRUE);
2109 } else if (!obj->no_charge && costly_spot(x, y)) {
2110 /* it is assumed that the obj is a floor-object */
2111 char *o_shop = in_rooms(x, y, SHOPBASE);
2112 struct monst *shkp = shop_keeper(*o_shop);
2114 if (shkp) { /* (implies *o_shop != '\0') */
2115 static NEARDATA long lastmovetime = 0L;
2116 static NEARDATA boolean peaceful_shk = FALSE;
2117 /* We want to base shk actions on her peacefulness
2118 at start of this turn, so that "simultaneous"
2119 multiple breakage isn't drastically worse than
2120 single breakage. (ought to be done via ESHK) */
2121 if (moves != lastmovetime)
2122 peaceful_shk = shkp->mpeaceful;
2123 if (stolen_value(obj, x, y, peaceful_shk, FALSE) > 0L
2124 && (*o_shop != u.ushops[0] || !inside_shop(u.ux, u.uy))
2125 && moves != lastmovetime)
2126 make_angry_shk(shkp, x, y);
2127 lastmovetime = moves;
2136 * Check to see if obj is going to break, but don't actually break it.
2137 * Return 0 if the object isn't going to break, 1 if it is.
2143 if (obj_resists(obj, 1, 99))
2145 if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact
2146 && obj->oclass != GEM_CLASS)
2148 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2149 case EXPENSIVE_CAMERA:
2150 case POT_WATER: /* really, all potions */
2155 case BLINDING_VENOM:
2163 breakmsg(obj, in_view)
2167 const char *to_pieces;
2172 /* "shatter"
\81¨ "
\82±
\82È
\82²
\82È
\82É
\82È
\82Á
\82½"
2173 "shatter into a thousand pieces"
\81¨ "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç
\82É
\82È
\82Á
\82½" */
2174 to_pieces = "
\82±
\82È
\82²
\82È";
2176 switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
2177 default: /* glass or crystal wand */
2178 if (obj->oclass != WAND_CLASS)
2179 impossible("breaking odd object?");
2180 case CRYSTAL_PLATE_MAIL:
2184 case EXPENSIVE_CAMERA:
2186 to_pieces = " into a thousand pieces";
2188 to_pieces = "
\82
\82¾
\82¯
\82Ä
\82Î
\82ç
\82Î
\82ç";
2190 case POT_WATER: /* really, all potions */
2193 You_hear("%s shatter!", something);
2195 You_hear("%s
\82ª
\89ó
\82ê
\82é
\89¹
\82ð
\95·
\82¢
\82½
\81I", something);
2198 pline("%s shatter%s%s!", Doname2(obj),
2199 (obj->quan == 1L) ? "s" : "", to_pieces);
2201 pline("%s
\82Í%s
\82É
\82È
\82Á
\82½
\81I", Doname2(obj), to_pieces);
2209 pline("
\83r
\83`
\83\83\81I");
2214 pline("What a mess!");
2216 pline("
\82±
\82è
\82á
\82Ð
\82Ç
\82¢
\81I");
2219 case BLINDING_VENOM:
2223 pline("
\83r
\83`
\83\83\81I");
2232 int range, odx, ody;
2233 register struct monst *mon;
2235 if (!u.dx && !u.dy && !u.dz) {
2237 You("cannot throw gold at yourself.");
2239 pline("
\8e©
\95ª
\82É
\8bà
\89Ý
\82ð
\93\8a\82°
\82é
\82±
\82Æ
\82Í
\82Å
\82«
\82È
\82¢
\81D");
2245 pline(is_animal(u.ustuck->data) ? "%s in the %s's entrails."
2247 "The money disappears", mon_nam(u.ustuck));
2249 pline(is_animal(u.ustuck->data) ? "
\8bà
\89Ý
\82Í%s
\82Ì
\95 \82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D"
2250 : "
\8bà
\89Ý
\82Í%s
\82Ì
\92\86\82Ö
\8fÁ
\82¦
\82Ä
\82¢
\82Á
\82½
\81D",
2253 add_to_minv(u.ustuck, obj);
2258 if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater
2259 && !Is_waterlevel(&u.uz)) {
2261 pline_The("gold hits the %s, then falls back on top of your %s.",
2262 ceiling(u.ux, u.uy), body_part(HEAD));
2264 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",
2265 ceiling(u.ux,u.uy), body_part(HEAD));
2267 /* some self damage? */
2270 pline("Fortunately, you are wearing %s!",
2272 pline("
\8dK
\89^
\82È
\82±
\82Æ
\82É
\81C
\82 \82È
\82½
\82Í%s
\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82é
\81I",
2273 an(helm_simple_name(uarmh)));
2278 /* consistent with range for normal objects */
2279 range = (int) ((ACURRSTR) / 2 - obj->owt / 40);
2281 /* see if the gold has a place to move into */
2284 if (!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
2288 mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
2289 (int FDECL((*), (MONST_P, OBJ_P))) 0,
2290 (int FDECL((*), (OBJ_P, OBJ_P))) 0, &obj);
2292 return 1; /* object is gone */
2294 if (ghitm(mon, obj)) /* was it caught? */
2297 if (ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
2304 if (flooreffects(obj, bhitpos.x, bhitpos.y, "fall"))
2306 if (flooreffects(obj, bhitpos.x, bhitpos.y, "
\97\8e\82¿
\82é"))
2310 pline_The("gold hits the %s.", surface(bhitpos.x, bhitpos.y));
2312 pline("
\8bà
\89Ý
\82Í%s
\82É
\96½
\92\86\82µ
\82½
\81D", surface(bhitpos.x, bhitpos.y));
2313 place_object(obj, bhitpos.x, bhitpos.y);
2315 sellobj(obj, bhitpos.x, bhitpos.y);
2317 newsym(bhitpos.x, bhitpos.y);