1 /* NetHack 3.6 ball.c $NHDT-Date: 1557088406 2019/05/05 20:33:26 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.36 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) David Cohrs, 2006. */
4 /* NetHack may be freely redistributed. See license for details. */
6 /* JNetHack Copyright */
7 /* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
8 /* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2019 */
9 /* JNetHack may be freely redistributed. See license for details. */
12 * =============================================================*/
16 STATIC_DCL int NDECL(bc_order);
17 STATIC_DCL void NDECL(litter);
26 pline("Startled, you drop the iron ball.");
28 pline("
\8bÁ
\82¢
\82Ä
\82 \82È
\82½
\82Í
\93S
\8b\85\82ð
\97\8e\82µ
\82½
\81D");
30 setuwep((struct obj *) 0);
31 if (uswapwep == uball)
32 setuswapwep((struct obj *) 0);
34 setuqwep((struct obj *) 0);
35 /* [this used to test 'if (uwep != uball)' but that always passes
36 after the setuwep() above] */
37 freeinv(uball); /* remove from inventory but don't place on floor */
42 /* ball&chain might hit hero when falling through a trap door */
48 gets_hit = (((uball->ox != u.ux) || (uball->oy != u.uy))
49 && ((uwep == uball) ? FALSE : (boolean) rn2(5)));
55 pline_The("iron ball falls on your %s.", body_part(HEAD));
57 pline("
\93S
\8b\85\82Í
\82 \82È
\82½
\82Ì%s
\82Ì
\8fã
\82É
\97\8e\82¿
\82½
\81D", body_part(HEAD));
59 if (is_metallic(uarmh)) {
61 pline("Fortunately, you are wearing a hard helmet.");
63 pline("
\8dK
\89^
\82É
\82à
\81C
\82 \82È
\82½
\82Í
\8cÅ
\82¢
\8a\95\82ð
\90g
\82É
\82Â
\82¯
\82Ä
\82¢
\82½
\81D");
65 } else if (flags.verbose)
67 pline("%s does not protect you.", Yname2(uarmh));
69 Your("%s
\82Å
\82Í
\8eç
\82ê
\82È
\82¢
\81D", xname(uarmh));
72 losehp(Maybe_Half_Phys(dmg), "crunched in the head by an iron ball",
75 losehp(Maybe_Half_Phys(dmg), "
\93S
\8b\85\82Å
\93ª
\82ð
\91Å
\82Á
\82Ä", KILLED_BY);
81 * To make this work, we have to mess with the hero's mind. The rules for
84 * 1. If the hero can see them, fine.
85 * 2. If the hero can't see either, it isn't seen.
86 * 3. If either is felt it is seen.
87 * 4. If either is felt and moved, it disappears.
89 * If the hero can see, then when a move is done, the ball and chain are
90 * first picked up, the positions under them are corrected, then they
91 * are moved after the hero moves. Not too bad.
93 * If the hero is blind, then she can "feel" the ball and/or chain at any
94 * time. However, when the hero moves, the felt ball and/or chain become
95 * unfelt and whatever was felt "under" the ball&chain appears. Pretty
96 * nifty, but it requires that the ball&chain "remember" what was under
97 * them --- i.e. they pick-up glyphs when they are felt and drop them when
98 * moved (and felt). When swallowed, the ball&chain are pulled completely
99 * off of the dungeon, but are still on the object chain. They are placed
100 * under the hero when she is expelled.
105 * int u.bglyph glyph under the ball
106 * int u.cglyph glyph under the chain
107 * int u.bc_felt mask for ball/chain being felt
108 * #define BC_BALL 0x01 bit mask in u.bc_felt for ball
109 * #define BC_CHAIN 0x02 bit mask in u.bc_felt for chain
110 * int u.bc_order ball & chain order
112 * u.bc_felt is also manipulated in display.c and read.c, the others only
113 * in this file. None of these variables are valid unless the player is
117 /* values for u.bc_order */
118 #define BCPOS_DIFFER 0 /* ball & chain at different positions */
119 #define BCPOS_CHAIN 1 /* chain on top of ball */
120 #define BCPOS_BALL 2 /* ball on top of chain */
123 * Place the ball & chain under the hero. Make sure that the ball & chain
124 * variables are set (actually only needed when blind, but what the heck).
125 * It is assumed that when this is called, the ball and chain are NOT
126 * attached to the object list.
128 * Should not be called while swallowed except on waterlevel.
133 if (!uchain || !uball) {
134 impossible("Where are your ball and chain?");
138 (void) flooreffects(uchain, u.ux, u.uy, ""); /* chain might rust */
140 if (carried(uball)) { /* the ball is carried */
141 u.bc_order = BCPOS_DIFFER;
143 /* ball might rust -- already checked when carried */
144 (void) flooreffects(uball, u.ux, u.uy, "");
145 place_object(uball, u.ux, u.uy);
146 u.bc_order = BCPOS_CHAIN;
149 place_object(uchain, u.ux, u.uy);
151 u.bglyph = u.cglyph = levl[u.ux][u.uy].glyph; /* pick up glyph */
160 if (Is_waterlevel(&u.uz)) {
161 /* we need to proceed with the removal from the floor
162 * so that movebubbles() processing will disregard it as
163 * intended. Ignore all the vision stuff.
166 obj_extract_self(uball);
167 obj_extract_self(uchain);
169 /* ball&chain not unplaced while swallowed */
173 if (!carried(uball)) {
174 obj_extract_self(uball);
175 if (Blind && (u.bc_felt & BC_BALL)) /* drop glyph */
176 levl[uball->ox][uball->oy].glyph = u.bglyph;
178 newsym(uball->ox, uball->oy);
180 obj_extract_self(uchain);
181 if (Blind && (u.bc_felt & BC_CHAIN)) /* drop glyph */
182 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
184 newsym(uchain->ox, uchain->oy);
185 u.bc_felt = 0; /* feel nothing */
189 * Return the stacking of the hero's ball & chain. This assumes that the
190 * hero is being punished.
197 if (uchain->ox != uball->ox || uchain->oy != uball->oy || carried(uball)
201 for (obj = level.objects[uball->ox][uball->oy]; obj;
202 obj = obj->nexthere) {
208 impossible("bc_order: ball&chain not in same location!");
215 * The hero is either about to go blind or already blind and just punished.
216 * Set up the ball and chain variables so that the ball and chain are "felt".
219 set_bc(already_blind)
222 int ball_on_floor = !carried(uball);
224 u.bc_order = bc_order(); /* get the order */
225 u.bc_felt = ball_on_floor ? BC_BALL | BC_CHAIN : BC_CHAIN; /* felt */
227 if (already_blind || u.uswallow) {
228 u.cglyph = u.bglyph = levl[u.ux][u.uy].glyph;
233 * Since we can still see, remove the ball&chain and get the glyph that
234 * would be beneath them. Then put the ball&chain back. This is pretty
235 * disgusting, but it will work.
237 remove_object(uchain);
239 remove_object(uball);
241 newsym(uchain->ox, uchain->oy);
242 u.cglyph = levl[uchain->ox][uchain->oy].glyph;
244 if (u.bc_order == BCPOS_DIFFER) { /* different locations */
245 place_object(uchain, uchain->ox, uchain->oy);
246 newsym(uchain->ox, uchain->oy);
248 newsym(uball->ox, uball->oy); /* see under ball */
249 u.bglyph = levl[uball->ox][uball->oy].glyph;
250 place_object(uball, uball->ox, uball->oy);
251 newsym(uball->ox, uball->oy); /* restore ball */
255 if (u.bc_order == BCPOS_CHAIN) {
256 place_object(uball, uball->ox, uball->oy);
257 place_object(uchain, uchain->ox, uchain->oy);
259 place_object(uchain, uchain->ox, uchain->oy);
260 place_object(uball, uball->ox, uball->oy);
262 newsym(uball->ox, uball->oy);
269 * Move the ball and chain. This is called twice for every move. The first
270 * time to pick up the ball and chain before the move, the second time to
271 * place the ball and chain after the move. If the ball is carried, this
272 * function should never have BC_BALL as part of its control.
274 * Should not be called while swallowed.
277 move_bc(before, control, ballx, bally, chainx, chainy)
279 xchar ballx, bally, chainx, chainy; /* only matter !before */
283 * The hero is blind. Time to work hard. The ball and chain that
284 * are attached to the hero are very special. The hero knows that
285 * they are attached, so when they move, the hero knows that they
286 * aren't at the last position remembered. This is complicated
287 * by the fact that the hero can "feel" the surrounding locations
288 * at any time, hence, making one or both of them show up again.
289 * So, we have to keep track of which is felt at any one time and
293 if ((control & BC_CHAIN) && (control & BC_BALL)) {
295 * Both ball and chain moved. If felt, drop glyph.
297 if (u.bc_felt & BC_BALL)
298 levl[uball->ox][uball->oy].glyph = u.bglyph;
299 if (u.bc_felt & BC_CHAIN)
300 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
303 /* Pick up glyph at new location. */
304 u.bglyph = levl[ballx][bally].glyph;
305 u.cglyph = levl[chainx][chainy].glyph;
307 movobj(uball, ballx, bally);
308 movobj(uchain, chainx, chainy);
309 } else if (control & BC_BALL) {
310 if (u.bc_felt & BC_BALL) {
311 if (u.bc_order == BCPOS_DIFFER) { /* ball by itself */
312 levl[uball->ox][uball->oy].glyph = u.bglyph;
313 } else if (u.bc_order == BCPOS_BALL) {
314 if (u.bc_felt & BC_CHAIN) { /* know chain is there */
315 map_object(uchain, 0);
317 levl[uball->ox][uball->oy].glyph = u.bglyph;
320 u.bc_felt &= ~BC_BALL; /* no longer feel the ball */
323 /* Pick up glyph at new position. */
324 u.bglyph = (ballx != chainx || bally != chainy)
325 ? levl[ballx][bally].glyph
328 movobj(uball, ballx, bally);
329 } else if (control & BC_CHAIN) {
330 if (u.bc_felt & BC_CHAIN) {
331 if (u.bc_order == BCPOS_DIFFER) {
332 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
333 } else if (u.bc_order == BCPOS_CHAIN) {
334 if (u.bc_felt & BC_BALL) {
335 map_object(uball, 0);
337 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
340 u.bc_felt &= ~BC_CHAIN;
342 /* Pick up glyph at new position. */
343 u.cglyph = (ballx != chainx || bally != chainy)
344 ? levl[chainx][chainy].glyph
347 movobj(uchain, chainx, chainy);
350 u.bc_order = bc_order(); /* reset the order */
355 * The hero is not blind. To make this work correctly, we need to
356 * pick up the ball and chain before the hero moves, then put them
357 * in their new positions after the hero moves.
362 * Neither ball nor chain is moving, so remember which was
363 * on top until !before. Use the variable u.bc_order
364 * since it is only valid when blind.
366 u.bc_order = bc_order();
369 remove_object(uchain);
370 newsym(uchain->ox, uchain->oy);
371 if (!carried(uball)) {
372 remove_object(uball);
373 newsym(uball->ox, uball->oy);
376 int on_floor = !carried(uball);
378 if ((control & BC_CHAIN)
379 || (!control && u.bc_order == BCPOS_CHAIN)) {
380 /* If the chain moved or nothing moved & chain on top. */
382 place_object(uball, ballx, bally);
383 place_object(uchain, chainx, chainy); /* chain on top */
385 place_object(uchain, chainx, chainy);
387 place_object(uball, ballx, bally);
390 newsym(chainx, chainy);
392 newsym(ballx, bally);
397 /* return TRUE if the caller needs to place the ball and chain down again
399 * Should not be called while swallowed. Should be called before movement,
400 * because we might want to move the ball or chain to the hero's old
403 * It is called if we are moving. It is also called if we are teleporting
404 * *if* the ball doesn't move and we thus must drag the chain. It is not
405 * called for ordinary teleportation.
407 * allow_drag is only used in the ugly special case where teleporting must
408 * drag the chain, while an identical-looking movement must drag both the ball
412 drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay,
416 xchar *ballx, *bally, *chainx, *chainy;
417 boolean *cause_delay;
420 struct trap *t = (struct trap *) 0;
421 boolean already_in_rock;
425 *chainx = uchain->ox;
426 *chainy = uchain->oy;
428 *cause_delay = FALSE;
430 if (dist2(x, y, uchain->ox, uchain->oy) <= 2) { /* nothing moved */
431 move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
435 /* only need to move the chain? */
436 if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) {
437 xchar oldchainx = uchain->ox, oldchainy = uchain->oy;
439 *bc_control = BC_CHAIN;
440 move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
441 if (carried(uball)) {
442 /* move chain only if necessary */
443 if (distmin(x, y, uchain->ox, uchain->oy) > 1) {
449 #define CHAIN_IN_MIDDLE(chx, chy) \
450 (distmin(x, y, chx, chy) <= 1 \
451 && distmin(chx, chy, uball->ox, uball->oy) <= 1)
452 #define IS_CHAIN_ROCK(x, y) \
453 (IS_ROCK(levl[x][y].typ) \
454 || (IS_DOOR(levl[x][y].typ) \
455 && (levl[x][y].doormask & (D_CLOSED | D_LOCKED))))
456 /* Don't ever move the chain into solid rock. If we have to, then instead
457 * undo the move_bc() and jump to the drag ball code. Note that this also
458 * means the "cannot carry and drag" message will not appear, since unless we
459 * moved at least two squares there is no possibility of the chain position
460 * being in solid rock.
462 #define SKIP_TO_DRAG \
464 *chainx = oldchainx; \
465 *chainy = oldchainy; \
466 move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy); \
469 if (IS_CHAIN_ROCK(u.ux, u.uy) || IS_CHAIN_ROCK(*chainx, *chainy)
470 || IS_CHAIN_ROCK(uball->ox, uball->oy))
471 already_in_rock = TRUE;
473 already_in_rock = FALSE;
475 switch (dist2(x, y, uball->ox, uball->oy)) {
476 /* two spaces diagonal from ball, move chain inbetween */
478 *chainx = (uball->ox + x) / 2;
479 *chainy = (uball->oy + y) / 2;
480 if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
484 /* player is distance 2/1 from ball; move chain to one of the
491 xchar tempx, tempy, tempx2, tempy2;
493 /* find position closest to current position of chain */
494 /* no effect if current position is already OK */
495 if (abs(x - uball->ox) == 1) {
498 tempy = tempy2 = (uball->oy + y) / 2;
500 tempx = tempx2 = (uball->ox + x) / 2;
504 if (IS_CHAIN_ROCK(tempx, tempy) && !IS_CHAIN_ROCK(tempx2, tempy2)
505 && !already_in_rock) {
507 /* Avoid pathological case *if* not teleporting:
509 * _X move northeast -----> X@
512 if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5
513 && dist2(x, y, tempx, tempy) == 1)
515 /* Avoid pathological case *if* not teleporting:
517 * _X move east -----> X_
520 if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4
521 && dist2(x, y, tempx, tempy) == 2)
526 } else if (!IS_CHAIN_ROCK(tempx, tempy)
527 && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) {
529 if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 5
530 && dist2(x, y, tempx2, tempy2) == 1)
532 if (dist2(u.ux, u.uy, uball->ox, uball->oy) == 4
533 && dist2(x, y, tempx2, tempy2) == 2)
538 } else if (IS_CHAIN_ROCK(tempx, tempy)
539 && IS_CHAIN_ROCK(tempx2, tempy2) && !already_in_rock) {
541 } else if (dist2(tempx, tempy, uchain->ox, uchain->oy)
542 < dist2(tempx2, tempy2, uchain->ox, uchain->oy)
543 || ((dist2(tempx, tempy, uchain->ox, uchain->oy)
544 == dist2(tempx2, tempy2, uchain->ox, uchain->oy))
555 /* ball is two spaces horizontal or vertical from player; move*/
556 /* chain inbetween *unless* current chain position is OK */
558 if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
560 *chainx = (x + uball->ox) / 2;
561 *chainy = (y + uball->oy) / 2;
562 if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
566 /* ball is one space diagonal from player. Check for the
567 * following special case:
569 * _ moving southwest becomes @_
571 * (This will also catch teleporting that happens to resemble
572 * this case, but oh well.) Otherwise fall through.
575 if (dist2(x, y, uball->ox, uball->oy) == 2
576 && dist2(x, y, uchain->ox, uchain->oy) == 4) {
581 if (IS_CHAIN_ROCK(*chainx, *chainy) && !already_in_rock)
588 /* do nothing if possible */
589 if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
591 /* otherwise try to drag chain to player's old position */
592 if (CHAIN_IN_MIDDLE(u.ux, u.uy)) {
597 /* otherwise use player's new position (they must have
598 teleported, for this to happen) */
604 impossible("bad chain movement");
608 #undef CHAIN_IN_MIDDLE
614 if (near_capacity() > SLT_ENCUMBER && dist2(x, y, u.ux, u.uy) <= 2) {
616 You("cannot %sdrag the heavy iron ball.",
617 invent ? "carry all that and also " : "");
619 You("%s
\8fd
\82¢
\93S
\8b\85\82ð
\82Ð
\82«
\82¸
\82é
\82±
\82Æ
\82ª
\82Å
\82«
\82È
\82¢
\81D",
620 invent ? "
\82»
\82ê
\82¾
\82¯
\82Ì
\89×
\95¨
\82ð
\8e\9d\82Á
\82½
\82Ü
\82Ü" : "");
626 if ((is_pool(uchain->ox, uchain->oy)
627 /* water not mere continuation of previous water */
628 && (levl[uchain->ox][uchain->oy].typ == POOL
629 || !is_pool(uball->ox, uball->oy)
630 || levl[uball->ox][uball->oy].typ == POOL))
631 || ((t = t_at(uchain->ox, uchain->oy))
632 && (is_pit(t->ttyp) || is_hole(t->ttyp)))) {
635 You_feel("a tug from the iron ball.");
637 You("
\93S
\8b\85\82É
\88ø
\82Á
\82Ï
\82ç
\82ê
\82½
\81D");
641 struct monst *victim;
644 You("are jerked back by the iron ball!");
646 You("
\93S
\8b\85\82É
\82®
\82¢
\82Æ
\88ø
\82Á
\82Ï
\82ç
\82ê
\82½
\81I");
647 if ((victim = m_at(uchain->ox, uchain->oy)) != 0) {
649 int dieroll = rnd(20);
651 tmp = -2 + Luck + find_mac(victim);
652 tmp += omon_adj(victim, uball, TRUE);
655 (void) hmon(victim, uball, HMON_DRAGGED, dieroll);
657 miss(xname(uball), victim);
659 } /* now check again in case mon died */
660 if (!m_at(uchain->ox, uchain->oy)) {
663 newsym(u.ux0, u.uy0);
667 *bc_control = BC_BALL;
668 move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
671 move_bc(0, *bc_control, *ballx, *bally, *chainx, *chainy);
677 *bc_control = BC_BALL | BC_CHAIN;
679 move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
680 if (dist2(x, y, u.ux, u.uy) > 2) {
681 /* Awful case: we're still in range of the ball, so we thought we
682 * could only move the chain, but it turned out that the target
683 * square for the chain was rock, so we had to drag it instead.
684 * But we can't drag it either, because we teleported and are more
685 * than one square from our old position. Revert to the teleport
688 *ballx = *chainx = x;
689 *bally = *chainy = y;
691 xchar newchainx = u.ux, newchainy = u.uy;
694 * Generally, chain moves to hero's previous location and ball
695 * moves to chain's previous location, except that we try to
696 * keep the chain directly between the hero and the ball. But,
697 * take the simple approach if the hero's previous location or
698 * the potential between location is inaccessible.
700 if (dist2(x, y, uchain->ox, uchain->oy) == 4
701 && !IS_CHAIN_ROCK(newchainx, newchainy)) {
702 newchainx = (x + uchain->ox) / 2;
703 newchainy = (y + uchain->oy) / 2;
704 if (IS_CHAIN_ROCK(newchainx, newchainy)) {
705 /* don't let chain move to inaccessible location */
724 * The punished hero drops or throws her iron ball. If the hero is
725 * blind, we must reset the order and glyph. Check for side effects.
726 * This routine expects the ball to be already placed.
728 * Should not be called while swallowed.
736 u.bc_order = bc_order();
738 u.bglyph = (u.bc_order) ? u.cglyph : levl[x][y].glyph;
741 if (x != u.ux || y != u.uy) {
743 static const char *pullmsg = "The ball pulls you out of the %s!";
745 static const char *pullmsg = "
\93S
\8b\85\82Í%s
\82©
\82ç
\82 \82È
\82½
\82ð
\88ø
\82Á
\82Ï
\82è
\8fo
\82µ
\82½
\81I";
750 && u.utraptype != TT_INFLOOR && u.utraptype != TT_BURIEDBALL) {
751 switch (u.utraptype) {
754 pline(pullmsg, "pit");
756 pline(pullmsg, "
\97\8e\82µ
\8c\8a");
760 pline(pullmsg, "web");
762 pline(pullmsg, "
\82
\82à
\82Ì
\91\83");
764 pline_The("web is destroyed!");
766 pline("
\82
\82à
\82Ì
\91\83\82Í
\82±
\82í
\82ê
\82½
\81I");
767 deltrap(t_at(u.ux, u.uy));
771 pline(pullmsg, hliquid("lava"));
773 pline(pullmsg, hliquid("
\97n
\8aâ"));
776 side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
778 pline(pullmsg, "bear trap");
780 pline(pullmsg, "
\8cF
\82Ìã©");
781 set_wounded_legs(side, rn1(1000, 500));
784 Your("%s %s is severely damaged.",
785 (side == LEFT_SIDE) ? "left" : "right",
788 Your("%s%s
\82Í
\82Ð
\82Ç
\82¢
\8f\9d\82ð
\95\89\82Á
\82½
\81D",
789 (side == LEFT_SIDE) ? "
\8d¶" : "
\89E",
793 losehp(Maybe_Half_Phys(2),
794 "leg damage from being pulled out of a bear trap",
797 losehp(Maybe_Half_Phys(2),
798 "
\8cF
\82Ìã©
\82©
\82ç
\94²
\82¯
\82æ
\82¤
\82Æ
\91«
\82ð
\88ø
\82Á
\82Ï
\82Á
\82Ä",
805 fill_pit(u.ux, u.uy);
810 if (!Levitation && !MON_AT(x, y) && !u.utrap
814 || is_hole(t->ttyp))))) {
821 vision_full_recalc = 1; /* hero has moved, recalculate vision later */
824 /* drop glyph under the chain */
825 if (u.bc_felt & BC_CHAIN)
826 levl[uchain->ox][uchain->oy].glyph = u.cglyph;
827 u.bc_felt = 0; /* feel nothing */
828 /* pick up new glyph */
829 u.cglyph = (u.bc_order) ? u.bglyph : levl[u.ux][u.uy].glyph;
831 movobj(uchain, u.ux, u.uy); /* has a newsym */
833 u.bc_order = bc_order();
835 newsym(u.ux0, u.uy0); /* clean up old position */
836 if (u.ux0 != u.ux || u.uy0 != u.uy) {
843 /* ball&chain cause hero to randomly lose stuff from inventory */
847 struct obj *otmp, *nextobj = 0;
848 int capacity = weight_cap();
850 for (otmp = invent; otmp; otmp = nextobj) {
851 nextobj = otmp->nobj;
852 if ((otmp != uball) && (rnd(capacity) <= (int) otmp->owt)) {
853 if (canletgo(otmp, "")) {
855 You("drop %s and %s %s down the stairs with you.",
856 yname(otmp), (otmp->quan == 1L) ? "it" : "they",
857 otense(otmp, "fall"));
859 You("%s
\82ð
\97\8e\82Æ
\82µ
\81C
\82»
\82ê
\82Í
\82 \82È
\82½
\82Æ
\88ê
\8f\8f\82É
\8aK
\92i
\82ð
\97\8e\82¿
\82Ä
\82¢
\82Á
\82½
\81D",
863 encumber_msg(); /* drop[xyz]() probably ought to to this... */
873 uchar dragchance = 3;
876 * Assume that the ball falls forward if:
878 * a) the character is wielding it, or
879 * b) the character has both hands available to hold it (i.e. is
880 * not wielding any weapon), or
881 * c) (perhaps) it falls forward out of his non-weapon hand
883 forward = carried(uball) && (uwep == uball || !uwep || !rn2(3));
887 You("lose your grip on the iron ball.");
889 You("
\93S
\8b\85\82ð
\8eè
\82©
\82ç
\97\8e\82µ
\82Ä
\82µ
\82Ü
\82Á
\82½
\81D");
891 cls(); /* previous level is still displayed although you
892 went down the stairs. Avoids bug C343-20 */
897 pline_The("iron ball drags you downstairs!");
899 You("
\93S
\8b\85\82É
\82æ
\82Á
\82Ä
\8aK
\92i
\82ð
\82±
\82ë
\82ª
\82è
\97\8e\82¿
\82½
\81I");
900 losehp(Maybe_Half_Phys(rnd(6)),
902 "dragged downstairs by an iron ball", NO_KILLER_PREFIX);
904 "
\93S
\8b\85\82É
\82æ
\82è
\8aK
\92i
\82ð
\82±
\82ë
\82ª
\82è
\97\8e\82¿
\82Ä", KILLED_BY);
910 pline_The("iron ball smacks into you!");
912 pline("
\93S
\8b\85\82Í
\82 \82È
\82½
\82É
\83S
\83c
\83\93\82Æ
\82Ô
\82Â
\82©
\82Á
\82½
\81I");
914 losehp(Maybe_Half_Phys(rnd(20)), "iron ball collision",
916 losehp(Maybe_Half_Phys(rnd(20)), "
\93S
\8b\85\82Ì
\8fÕ
\93Ë
\82Å",
918 exercise(A_STR, FALSE);
921 if ((int) dragchance >= rnd(6)) {
923 pline_The("iron ball drags you downstairs!");
925 You("
\93S
\8b\85\82É
\82æ
\82Á
\82Ä
\8aK
\92i
\82ð
\82±
\82ë
\82ª
\82è
\97\8e\82¿
\82½
\81I");
926 losehp(Maybe_Half_Phys(rnd(3)),
928 "dragged downstairs by an iron ball", NO_KILLER_PREFIX);
930 "
\93S
\8b\85\82É
\82æ
\82è
\8aK
\92i
\82ð
\82±
\82ë
\82ª
\82è
\97\8e\82¿
\82Ä", KILLED_BY);
931 exercise(A_STR, FALSE);
941 unsigned save_nameknown;
944 if (Punished && (!uball || !uchain)) {
945 impossible("Punished without %s%s%s?",
946 !uball ? "iron ball" : "",
947 (!uball && !uchain) ? " and " : "",
948 !uchain ? "attached chain" : "");
949 } else if (!Punished && (uball || uchain)) {
950 impossible("Attached %s%s%s without being Punished?",
951 uchain ? "chain" : "",
952 (uchain && uball) ? " and " : "",
953 uball ? "iron ball" : "");
955 /* ball is free when swallowed, changing levels, other times? */
956 if (uball && (uball->otyp != HEAVY_IRON_BALL
957 || (uball->where != OBJ_FLOOR
958 && uball->where != OBJ_INVENT
959 && uball->where != OBJ_FREE)
960 || (uball->owornmask & W_BALL) == 0L
961 || (uball->owornmask & ~(W_BALL | W_WEAPON)) != 0L)) {
963 if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
964 || !OBJ_NAME(objects[otyp])) {
967 save_nameknown = objects[otyp].oc_name_known;
968 objects[otyp].oc_name_known = 1;
969 onam = simple_typename(otyp);
970 objects[otyp].oc_name_known = save_nameknown;
972 impossible("uball: type %d (%s), where %d, wornmask=0x%08lx",
973 otyp, onam, uball->where, uball->owornmask);
975 /* similar check to ball except can't be in inventory */
976 if (uchain && (uchain->otyp != IRON_CHAIN
977 || (uchain->where != OBJ_FLOOR
978 && uchain->where != OBJ_FREE)
979 /* [could simplify this to owornmask != W_CHAIN] */
980 || (uchain->owornmask & W_CHAIN) == 0L
981 || (uchain->owornmask & ~W_CHAIN) != 0L)) {
983 if (otyp < STRANGE_OBJECT || otyp >= NUM_OBJECTS
984 || !OBJ_NAME(objects[otyp])) {
987 save_nameknown = objects[otyp].oc_name_known;
988 objects[otyp].oc_name_known = 1;
989 onam = simple_typename(otyp);
990 objects[otyp].oc_name_known = save_nameknown;
992 impossible("uchain: type %d (%s), where %d, wornmask=0x%08lx",
993 otyp, onam, uchain->where, uchain->owornmask);
995 /* [check bc_order too?] */