when loading bones files, censor suspect characters from player-supplied
strings such as pet and fruit names
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
violation of illiteracy conduct
E void FDECL(place_worm_tail_randomly, (struct monst *,XCHAR_P,XCHAR_P));
E int FDECL(count_wsegs, (struct monst *));
E boolean FDECL(worm_known, (struct monst *));
+E boolean FDECL(worm_cross, (int,int,int,int));
/* ### worn.c ### */
default:
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.
* Avoid water and lava using the usual running rules.
int y = travelstepy[set][i];
static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
/* 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) {
int nx = x+xdir[ordered[dir]];
y = mon->my;
nowtyp = levl[x][y].typ;
- nodiag = (mdat == &mons[PM_GRID_BUG]);
+ nodiag = NODIAG(mdat - mons);
wantpool = mdat->mlet == S_EEL;
poolok = is_flyer(mdat) || is_clinger(mdat) ||
(is_swimmer(mdat) && !wantpool);
!((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
/* KMH -- Added iron bars */
if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
- if(IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
- ((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
- (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
- !thrudoor) continue;
- if(nx != x && ny != y && (nodiag ||
+ if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
+ (((levl[nx][ny].doormask & D_CLOSED) &&
+ !(flag & OPENDOOR)) ||
+ ((levl[nx][ny].doormask & D_LOCKED) &&
+ !(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
- ((IS_DOOR(nowtyp) &&
- ((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)))
+ ((IS_DOOR(nowtyp) || IS_DOOR(ntyp)) && Is_rogue_level(&u.uz)) ||
#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;
if((is_pool(nx,ny) == wantpool || poolok) &&
(lavaok || !is_lava(nx,ny))) {
{
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));
}
-/* 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. */
/* NetHack may be freely redistributed. See license for details. */
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*/