U453 and buglist item - travel command updates

I wrote to the devteam early last week:
> Given my understanding of travel, it's supposed to be somewhat intelligent,
> and "convenient", and should, therefore avoid walking into water, lava,
> traps, or other things that distant movement would avoid, even if you're
> right next it.  Unless...  the travel destination is the "bad" location
> next to you when the travel starts.
To that end...
- add a context (iflags in 3.4.3 to maintain savefile compat) flag to
differenciate the first travel step from later steps, to allow the
detection of the final sentence, above.
- several changes to set/reset the travel1 flag as needed
- add code to findtravelpath to treat the first step specially if it's
the only step, allowing forced travel into a "bad" location
- correct the "don't travel over traps" code, which was getting confused
because hero's starting location was being avoided
- add code to avoid traveling into water and lava, duplicating
checks used for non-travel running
- fix some strange "guess" travel behavior: avoid zigzag paths when there's
a more direct path (even though the number of moves is the same)
- trunk change adds a new DISP_ALL tmp_at type, and uses it in some debug
code for travel, debug changes not added to the 3.4.3 branch
This commit is contained in:
cohrs
2003-10-21 02:27:43 +00:00
parent 4e09be0163
commit 231b2b16f8
7 changed files with 101 additions and 19 deletions

View File

@@ -61,6 +61,8 @@ allow a crystal ball to detect ghosts-and-shades via space key, and display
allow a crystal ball to detect boulders using the user-defined boulder symbol
allow a crystal ball to detect mimics via ']'
prevent boulder option from accepting a symbol that matches a monster symbol
traveling while standing on a trap would sometime step in the wrong direction
avoid traveling into water/lava, using usual running rules
Platform- and/or Interface-Specific Fixes

View File

@@ -77,6 +77,7 @@ struct context_info {
long stethoscope_move;
short stethoscope_movement;
boolean travel; /* find way automatically to u.tx,u.ty */
boolean travel1; /* first travel step */
boolean forcefight;
boolean nopick; /* do not pickup objects (as when running) */
boolean made_amulet;

View File

@@ -175,11 +175,12 @@
* tmp_at() control calls.
*/
#define DISP_BEAM (-1) /* Keep all glyphs showing & clean up at end. */
#define DISP_FLASH (-2) /* Clean up each glyph before displaying new one. */
#define DISP_ALWAYS (-3) /* Like flash, but still displayed if not visible. */
#define DISP_CHANGE (-4) /* Change glyph. */
#define DISP_END (-5) /* Clean up. */
#define DISP_FREEMEM (-6) /* Free all memory during exit only. */
#define DISP_ALL (-2) /* Like beam, but still displayed if not visible. */
#define DISP_FLASH (-3) /* Clean up each glyph before displaying new one. */
#define DISP_ALWAYS (-4) /* Like flash, but still displayed if not visible. */
#define DISP_CHANGE (-5) /* Change glyph. */
#define DISP_END (-6) /* Clean up. */
#define DISP_FREEMEM (-7) /* Free all memory during exit only. */
/* Total number of cmap indices in the sheild_static[] array. */

View File

@@ -393,7 +393,8 @@ moveloop()
}
if (context.mv) {
if(multi < COLNO && !--multi)
context.travel = context.mv = context.run = 0;
context.travel = context.travel1 =
context.mv = context.run = 0;
domove();
} else {
--multi;

View File

@@ -1845,7 +1845,7 @@ register char *cmd;
}
/* handle most movement commands */
do_walk = do_rush = prefix_seen = FALSE;
context.travel = 0;
context.travel = context.travel1 = 0;
switch (*cmd) {
case 'g': if (movecmd(cmd[1])) {
context.run = 2;
@@ -1901,6 +1901,7 @@ register char *cmd;
case CMD_TRAVEL:
if (flags.travelcmd) {
context.travel = 1;
context.travel1 = 1;
context.run = 8;
context.nopick = 1;
do_rush = TRUE;

View File

@@ -834,6 +834,7 @@ tmp_at(x, y)
switch (x) {
case DISP_BEAM:
case DISP_ALL:
case DISP_FLASH:
case DISP_ALWAYS:
if (!tglyph)
@@ -868,7 +869,7 @@ tmp_at(x, y)
break;
case DISP_END:
if (tglyph->style == DISP_BEAM) {
if (tglyph->style == DISP_BEAM || tglyph->style == DISP_ALL) {
register int i;
/* Erase (reset) from source to end */
@@ -885,8 +886,9 @@ tmp_at(x, y)
break;
default: /* do it */
if (tglyph->style == DISP_BEAM) {
if (!cansee(x,y)) break;
if (tglyph->style == DISP_BEAM || tglyph->style == DISP_ALL) {
if (tglyph->style != DISP_ALL && !cansee(x,y)) break;
if (tglyph->sidx >= COLNO) break; /* too many locations */
/* save pos for later erasing */
tglyph->saved[tglyph->sidx].x = x;
tglyph->saved[tglyph->sidx].y = y;

View File

@@ -4,6 +4,8 @@
#include "hack.h"
/* #define DEBUG */ /* uncomment for debugging */
STATIC_DCL void NDECL(maybe_wail);
STATIC_DCL int NDECL(moverock);
STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P));
@@ -633,11 +635,17 @@ int mode;
return FALSE;
}
}
/* pick a path that does not require crossing a trap */
if (context.run == 8 && mode != DO_MOVE) {
/* Pick travel path that does not require crossing a trap.
* Avoid water and lava using the usual running rules.
* (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
struct trap* t = t_at(x, y);
if (t && t->tseen) return FALSE;
if ((t && t->tseen) ||
(!Levitation && !Flying &&
!is_clinger(youmonst.data) &&
(is_pool(x, y) || is_lava(x, y)) && levl[x][y].seenv))
return FALSE;
}
ust = &levl[ux][uy];
@@ -684,6 +692,17 @@ int mode;
return TRUE;
}
#ifdef DEBUG
static boolean trav_debug = FALSE;
int
wiz_debug_cmd() /* in this case, toggle display of travel debug info */
{
trav_debug = !trav_debug;
return 0;
}
#endif /* DEBUG */
/*
* Find a path from the destination (u.tx,u.ty) back to (u.ux,u.uy).
* A shortest path is returned. If guess is TRUE, consider various
@@ -694,6 +713,18 @@ static boolean
findtravelpath(guess)
boolean guess;
{
/* if travel to adjacent, reachable location, use normal movement rules */
if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1) {
context.run = 0;
if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
u.dx = u.tx-u.ux;
u.dy = u.ty-u.uy;
nomul(0);
iflags.travelcc.x = iflags.travelcc.y = -1;
return TRUE;
}
context.run = 8;
}
if (u.tx != u.ux || u.ty != u.uy) {
xchar travel[COLNO][ROWNO];
xchar travelstepx[2][COLNO*ROWNO];
@@ -770,7 +801,23 @@ boolean guess;
}
}
}
#ifdef DEBUG
if (trav_debug) {
/* Use of warning glyph is arbitrary. It stands out. */
tmp_at(DISP_ALL, warning_to_glyph(1));
for (i = 0; i < nn; ++i) {
tmp_at(travelstepx[1-set][i], travelstepy[1-set][i]);
}
delay_output();
if (flags.runmode == RUN_CRAWL) {
delay_output();
delay_output();
}
tmp_at(DISP_END,0);
}
#endif /* DEBUG */
n = nn;
set = 1-set;
radius++;
@@ -779,15 +826,25 @@ boolean guess;
/* if guessing, find best location in travel matrix and go there */
if (guess) {
int px = tx, py = ty; /* pick location */
int dist, nxtdist;
int dist, nxtdist, d2, nd2;
dist = distmin(ux, uy, tx, ty);
d2 = dist2(ux, uy, tx, ty);
for (tx = 1; tx < COLNO; ++tx)
for (ty = 0; ty < ROWNO; ++ty)
if (travel[tx][ty]) {
nxtdist = distmin(ux, uy, tx, ty);
if (nxtdist < dist && couldsee(tx, ty)) {
px = tx; py = ty; dist = nxtdist;
if (nxtdist == dist && couldsee(tx, ty)) {
nd2 = dist2(ux, uy, tx, ty);
if (nd2 < d2) {
/* prefer non-zigzag path */
px = tx; py = ty;
d2 = nd2;
}
} else if (nxtdist < dist && couldsee(tx, ty)) {
px = tx; py = ty;
dist = nxtdist;
d2 = dist2(ux, uy, tx, ty);
}
}
@@ -799,6 +856,21 @@ boolean guess;
return TRUE;
goto found;
}
#ifdef DEBUG
if (trav_debug) {
/* Use of warning glyph is arbitrary. It stands out. */
tmp_at(DISP_ALL, warning_to_glyph(2));
tmp_at(px, py);
delay_output();
if (flags.runmode == RUN_CRAWL) {
delay_output();
delay_output();
delay_output();
delay_output();
}
tmp_at(DISP_END,0);
}
#endif /* DEBUG */
tx = px;
ty = py;
ux = u.ux;
@@ -834,9 +906,11 @@ domove()
u_wipe_engr(rnd(5));
if (context.travel)
if (context.travel) {
if (!findtravelpath(FALSE))
(void) findtravelpath(TRUE);
context.travel1 = 0;
}
if(((wtcap = near_capacity()) >= OVERLOADED
|| (wtcap > SLT_ENCUMBER &&
@@ -2038,7 +2112,7 @@ nomul(nval)
u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
u.usleep = 0;
multi = nval;
context.travel = context.mv = context.run = 0;
context.travel = context.travel1 = context.mv = context.run = 0;
}
/* called when a non-movement, multi-turn action has completed */