crossing long worms' tails (trunk only)
This is one of the items from "#Q397: List of Bugs from #nethack" sent
in Janurary by <email deleted> and containing a list
of things collected from the IRC channel associated with nethack.alt.org's
public server. Moving diagonally between segments of a worm tail is
conceptually passing right through the worm's body. This patch prevents
moving in such a fashion for both the hero and monsters (it's still
possible to fight in that position though). It only applies when the two
tail segments are consecutive.
|...... In the diagram here, where tail segments are represented by
|.w1?.. digits indicating relative sequence number, the @ can still
|..@2.. move between segments 2 and 5 to reach !, but can no longer
|.65!3. move between 1 and 2 to reach ?. [However, if there is a
|...4.. monster at the ? spot, it can still hit @ and vice versa.]
Missiles and wand zaps still pass through such diagonals without
noticing or affecting the worm. I'm not sure whether this ought to be
extended to change that--it might get pretty messy since it would need
to be considered during monsters' targetting as well as during the path
traversal itself.
This commit is contained in:
@@ -255,6 +255,7 @@ wizard mode: WIZKIT wishes could overflow inventory's 52 slots
|
|||||||
when loading bones files, censor suspect characters from player-supplied
|
when loading bones files, censor suspect characters from player-supplied
|
||||||
strings such as pet and fruit names
|
strings such as pet and fruit names
|
||||||
can't swap places with tame grid bug when moving diagonally
|
can't swap places with tame grid bug when moving diagonally
|
||||||
|
can't move diagonally through a long worm's body (can still fight that way)
|
||||||
require confirmation to read a scroll of mail if doing so will be the first
|
require confirmation to read a scroll of mail if doing so will be the first
|
||||||
violation of illiteracy conduct
|
violation of illiteracy conduct
|
||||||
|
|
||||||
|
|||||||
@@ -2588,6 +2588,7 @@ E void FDECL(remove_worm, (struct monst *));
|
|||||||
E void FDECL(place_worm_tail_randomly, (struct monst *,XCHAR_P,XCHAR_P));
|
E void FDECL(place_worm_tail_randomly, (struct monst *,XCHAR_P,XCHAR_P));
|
||||||
E int FDECL(count_wsegs, (struct monst *));
|
E int FDECL(count_wsegs, (struct monst *));
|
||||||
E boolean FDECL(worm_known, (struct monst *));
|
E boolean FDECL(worm_known, (struct monst *));
|
||||||
|
E boolean FDECL(worm_cross, (int,int,int,int));
|
||||||
|
|
||||||
/* ### worn.c ### */
|
/* ### worn.c ### */
|
||||||
|
|
||||||
|
|||||||
@@ -708,6 +708,10 @@ int mode;
|
|||||||
default:
|
default:
|
||||||
break; /* can squeeze through */
|
break; /* can squeeze through */
|
||||||
}
|
}
|
||||||
|
} else if (dx && dy && worm_cross(ux, uy, x, y)) {
|
||||||
|
/* consecutive long worm segments are at <ux,y> and <x,uy> */
|
||||||
|
if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y)));
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* Pick travel path that does not require crossing a trap.
|
/* Pick travel path that does not require crossing a trap.
|
||||||
* Avoid water and lava using the usual running rules.
|
* Avoid water and lava using the usual running rules.
|
||||||
@@ -828,7 +832,7 @@ boolean guess;
|
|||||||
int y = travelstepy[set][i];
|
int y = travelstepy[set][i];
|
||||||
static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
|
static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
|
||||||
/* no diagonal movement for grid bugs */
|
/* no diagonal movement for grid bugs */
|
||||||
int dirmax = u.umonnum == PM_GRID_BUG ? 4 : 8;
|
int dirmax = NODIAG(u.umonnum) ? 4 : 8;
|
||||||
|
|
||||||
for (dir = 0; dir < dirmax; ++dir) {
|
for (dir = 0; dir < dirmax; ++dir) {
|
||||||
int nx = x+xdir[ordered[dir]];
|
int nx = x+xdir[ordered[dir]];
|
||||||
|
|||||||
32
src/mon.c
32
src/mon.c
@@ -1018,7 +1018,7 @@ mfndpos(mon, poss, info, flag)
|
|||||||
y = mon->my;
|
y = mon->my;
|
||||||
nowtyp = levl[x][y].typ;
|
nowtyp = levl[x][y].typ;
|
||||||
|
|
||||||
nodiag = (mdat == &mons[PM_GRID_BUG]);
|
nodiag = NODIAG(mdat - mons);
|
||||||
wantpool = mdat->mlet == S_EEL;
|
wantpool = mdat->mlet == S_EEL;
|
||||||
poolok = is_flyer(mdat) || is_clinger(mdat) ||
|
poolok = is_flyer(mdat) || is_clinger(mdat) ||
|
||||||
(is_swimmer(mdat) && !wantpool);
|
(is_swimmer(mdat) && !wantpool);
|
||||||
@@ -1063,21 +1063,23 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
|
|||||||
!((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
|
!((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
|
||||||
/* KMH -- Added iron bars */
|
/* KMH -- Added iron bars */
|
||||||
if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
|
if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
|
||||||
if(IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
|
if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
|
||||||
((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
|
(((levl[nx][ny].doormask & D_CLOSED) &&
|
||||||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
|
!(flag & OPENDOOR)) ||
|
||||||
!thrudoor) continue;
|
((levl[nx][ny].doormask & D_LOCKED) &&
|
||||||
if(nx != x && ny != y && (nodiag ||
|
!(flag & UNLOCKDOOR))) &&
|
||||||
|
!thrudoor) continue;
|
||||||
|
/* first diagonal checks (tight squeezes handled below) */
|
||||||
|
if (nx != x && ny != y && (nodiag ||
|
||||||
|
(IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
|
||||||
|
(IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)) ||
|
||||||
#ifdef REINCARNATION
|
#ifdef REINCARNATION
|
||||||
((IS_DOOR(nowtyp) &&
|
((IS_DOOR(nowtyp) || IS_DOOR(ntyp)) && Is_rogue_level(&u.uz)) ||
|
||||||
((levl[x][y].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))) ||
|
|
||||||
(IS_DOOR(ntyp) &&
|
|
||||||
((levl[nx][ny].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))))
|
|
||||||
#else
|
|
||||||
((IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
|
|
||||||
(IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)))
|
|
||||||
#endif
|
#endif
|
||||||
))
|
/* mustn't pass between adjacent long worm segments,
|
||||||
|
but can attack that way */
|
||||||
|
(m_at(x, ny) && m_at(nx, y) && worm_cross(x, y, nx, ny) &&
|
||||||
|
!m_at(nx, ny) && (nx != u.ux || ny != u.uy))))
|
||||||
continue;
|
continue;
|
||||||
if((is_pool(nx,ny) == wantpool || poolok) &&
|
if((is_pool(nx,ny) == wantpool || poolok) &&
|
||||||
(lavaok || !is_lava(nx,ny))) {
|
(lavaok || !is_lava(nx,ny))) {
|
||||||
@@ -1279,7 +1281,7 @@ register int x,y;
|
|||||||
{
|
{
|
||||||
register int distance = dist2(mon->mx, mon->my, x, y);
|
register int distance = dist2(mon->mx, mon->my, x, y);
|
||||||
|
|
||||||
if (distance==2 && mon->data==&mons[PM_GRID_BUG]) return 0;
|
if (distance == 2 && NODIAG(mon->data - mons)) return 0;
|
||||||
return((boolean)(distance < 3));
|
return((boolean)(distance < 3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
49
src/worm.c
49
src/worm.c
@@ -1,4 +1,4 @@
|
|||||||
/* SCCS Id: @(#)worm.c 3.5 2005/07/13 */
|
/* SCCS Id: @(#)worm.c 3.5 2007/07/15 */
|
||||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -746,4 +746,51 @@ struct monst *worm;
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* would moving from <x1,y1> to <x2,y2> involve passing between two
|
||||||
|
consecutive segments of the same worm? */
|
||||||
|
boolean
|
||||||
|
worm_cross(x1, y1, x2, y2)
|
||||||
|
int x1, y1, x2, y2;
|
||||||
|
{
|
||||||
|
struct monst *worm;
|
||||||
|
struct wseg *curr, *wnxt;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* With digits representing relative sequence number of the segments,
|
||||||
|
* returns true when testing between @ and ? (passes through worm's
|
||||||
|
* body), false between @ and ! (stays on same side of worm).
|
||||||
|
* .w1?..
|
||||||
|
* ..@2..
|
||||||
|
* .65!3.
|
||||||
|
* ...4..
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (distmin(x1, y1, x2, y2) != 1) {
|
||||||
|
impossible("worm_cross checking for non-adjacent location?");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
/* attempting to pass between worm segs is only relevant for diagonal */
|
||||||
|
if (x1 == x2 || y1 == y2) return FALSE;
|
||||||
|
|
||||||
|
/* is the same monster at <x1,y2> and at <x2,y1>? */
|
||||||
|
worm = m_at(x1, y2);
|
||||||
|
if (!worm || m_at(x2, y1) != worm) return FALSE;
|
||||||
|
|
||||||
|
/* same monster is at both adjacent spots, so must be a worm; we need
|
||||||
|
to figure out if the two spots are occupied by consecutive segments */
|
||||||
|
for (curr = wtails[worm->wormno]; curr; curr = wnxt) {
|
||||||
|
wnxt = curr->nseg;
|
||||||
|
if (!wnxt) break; /* no next segment; can't continue */
|
||||||
|
|
||||||
|
/* we don't know which of <x1,y2> or <x2,y1> we'll hit first, but
|
||||||
|
whichever it is, they're consecutive iff next seg is the other */
|
||||||
|
if (curr->wx == x1 && curr->wy == y2)
|
||||||
|
return (boolean)(wnxt->wx == x2 && wnxt->wy == y1);
|
||||||
|
if (curr->wx == x2 && curr->wy == y1)
|
||||||
|
return (boolean)(wnxt->wx == x1 && wnxt->wy == y2);
|
||||||
|
}
|
||||||
|
/* should never reach here... */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*worm.c*/
|
/*worm.c*/
|
||||||
|
|||||||
Reference in New Issue
Block a user