-/* NetHack 3.6 worm.c $NHDT-Date: 1456528599 2016/02/26 23:16:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
+/* NetHack 3.6 worm.c $NHDT-Date: 1561340880 2019/06/24 01:48:00 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.30 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2009. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
*/
for (seg = wtails[wnum]; seg; seg = seg->nseg)
if (distu(seg->wx, seg->wy) < 3)
- (void) mattacku(worm);
+ if (mattacku(worm))
+ return; /* your passive ability killed the worm */
}
/* cutworm()
* that both halves will survive.
*/
void
-cutworm(worm, x, y, weap)
+cutworm(worm, x, y, cuttier)
struct monst *worm;
xchar x, y;
-struct obj *weap;
+boolean cuttier; /* hit is by wielded blade or axe or by thrown axe */
{
register struct wseg *curr, *new_tail;
register struct monst *new_worm;
if (x == worm->mx && y == worm->my)
return; /* hit on head */
- /* cutting goes best with a bladed weapon */
- cut_chance = rnd(20); /* Normally 1-16 does not cut */
- /* Normally 17-20 does */
-
- if (weap && is_blade(weap)) /* With a blade 1- 6 does not cut */
- cut_chance += 10; /* 7-20 does */
+ /* cutting goes best with a cuttier weapon */
+ cut_chance = rnd(20); /* Normally 1-16 does not cut, 17-20 does, */
+ if (cuttier)
+ cut_chance += 10; /* with a blade 1- 6 does not cut, 7-20 does. */
if (cut_chance < 17)
return; /* not good enough */
/* Sometimes the tail end dies. */
if (!new_worm) {
+ place_worm_seg(worm, x, y); /* place the "head" segment back */
if (context.mon_moving) {
if (canspotmon(worm))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Part of %s tail has been cut off.",
s_suffix(mon_nam(worm)));
#else
wgrowtime[new_wnum] = 0L; /* trying to call initworm(). */
/* Place the new monster at all the segment locations. */
- place_wsegs(new_worm);
+ place_wsegs(new_worm, worm);
if (context.mon_moving)
/*JP
struct wseg *curr = wtails[worm->wormno];
/* if (!mtmp->wormno) return; bullet proofing */
+ int what_tail = what_mon(PM_LONG_WORM_TAIL, newsym_rn2);
while (curr != wheads[worm->wormno]) {
num = use_detection_glyph
- ? detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
+ ? detected_monnum_to_glyph(what_tail)
: (worm->mtame
- ? petnum_to_glyph(what_mon(PM_LONG_WORM_TAIL))
- : monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)));
+ ? petnum_to_glyph(what_tail)
+ : monnum_to_glyph(what_tail));
show_glyph(curr->wx, curr->wy, num);
curr = curr->nseg;
}
* place_wsegs()
*
* Place the segments of the given worm. Called from restore.c
+ * If oldworm is not NULL, assumes the oldworm segments are on map
+ * in the same location as worm segments
*/
void
-place_wsegs(worm)
-struct monst *worm;
+place_wsegs(worm, oldworm)
+struct monst *worm, *oldworm;
{
struct wseg *curr = wtails[worm->wormno];
/* if (!mtmp->wormno) return; bullet proofing */
while (curr != wheads[worm->wormno]) {
- place_worm_seg(worm, curr->wx, curr->wy);
+ xchar x = curr->wx;
+ xchar y = curr->wy;
+
+ if (oldworm) {
+ if (m_at(x,y) == oldworm)
+ remove_monster(x, y);
+ else
+ impossible("placing worm seg <%i,%i> over another mon", x, y);
+ }
+ place_worm_seg(worm, x, y);
curr = curr->nseg;
}
}
curr = wtails[worm->wormno];
while (curr != wheads[worm->wormno]) {
- if (!isok(curr->wx, curr->wy))
- panic("worm seg not isok");
- if (level.monsters[curr->wx][curr->wy] != worm)
- panic("worm not at seg location");
+ if (curr->wx) {
+ if (!isok(curr->wx, curr->wy))
+ panic("worm seg not isok");
+ if (level.monsters[curr->wx][curr->wy] != worm)
+ panic("worm not at seg location");
+ }
curr = curr->nseg;
}
}
/* if (!mtmp->wormno) return; bullet proofing */
while (curr) {
- remove_monster(curr->wx, curr->wy);
- newsym(curr->wx, curr->wy);
+ if (curr->wx) {
+ remove_monster(curr->wx, curr->wy);
+ newsym(curr->wx, curr->wy);
+ curr->wx = 0;
+ }
curr = curr->nseg;
}
}
char tryct = 0;
/* pick a random direction from x, y and search for goodpos() */
-
do {
random_dir(ox, oy, &nx, &ny);
} while (!goodpos(nx, ny, worm, 0) && (tryct++ < 50));
STATIC_OVL
void
random_dir(x, y, nx, ny)
-register xchar x, y;
-register xchar *nx, *ny;
+xchar x, y;
+xchar *nx, *ny;
{
- *nx = x;
- *ny = y;
-
- *nx += (x > 1 /* extreme left ? */
- ? (x < COLNO /* extreme right ? */
- ? (rn2(3) - 1) /* neither so +1, 0, or -1 */
- : -rn2(2)) /* 0, or -1 */
- : rn2(2)); /* 0, or 1 */
-
- *ny += (*nx == x /* same kind of thing with y */
- ? (y > 1 ? (y < ROWNO ? (rn2(2) ? 1 : -1) : -1) : 1)
- : (y > 1 ? (y < ROWNO ? (rn2(3) - 1) : -rn2(2)) : rn2(2)));
+ *nx = x + (x > 1 /* extreme left ? */
+ ? (x < COLNO - 1 /* extreme right ? */
+ ? (rn2(3) - 1) /* neither so +1, 0, or -1 */
+ : -rn2(2)) /* right edge, use -1 or 0 */
+ : rn2(2)); /* left edge, use 0 or 1 */
+ if (*nx != x) /* if x has changed, do same thing with y */
+ *ny = y + (y > 0 /* y==0 is ok (x==0 is not) */
+ ? (y < ROWNO - 1
+ ? (rn2(3) - 1)
+ : -rn2(2))
+ : rn2(2));
+ else /* when x has remained the same, force y to change */
+ *ny = y + (y > 0
+ ? (y < ROWNO - 1
+ ? (rn2(2) ? 1 : -1) /* not at edge, so +1 or -1 */
+ : -1) /* bottom, use -1 */
+ : 1); /* top, use +1 */
}
/* for size_monst(cmd.c) to support #stats */