tweaks for #wizlevelflip
For interactive level flip, flip cached travel destination and interrupted digging position. Also, ball and chain handling wasn't right if the ball was carried. The fix for that is untested because I don't know how to judge where the flip area starts and stops and this code is for the case where that boundary is straddled rather than having hero and ball and chain all inside or all outside the flip area.
This commit is contained in:
+79
-46
@@ -1,4 +1,4 @@
|
|||||||
/* NetHack 3.6 sp_lev.c $NHDT-Date: 1585361055 2020/03/28 02:04:15 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.183 $ */
|
/* NetHack 3.6 sp_lev.c $NHDT-Date: 1585569501 2020/03/30 11:58:21 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.185 $ */
|
||||||
/* Copyright (c) 1989 by Jean-Christophe Collet */
|
/* Copyright (c) 1989 by Jean-Christophe Collet */
|
||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
@@ -30,6 +30,7 @@ static void FDECL(lvlfill_solid, (SCHAR_P, SCHAR_P));
|
|||||||
static void FDECL(lvlfill_swamp, (SCHAR_P, SCHAR_P, SCHAR_P));
|
static void FDECL(lvlfill_swamp, (SCHAR_P, SCHAR_P, SCHAR_P));
|
||||||
static void FDECL(flip_drawbridge_horizontal, (struct rm *));
|
static void FDECL(flip_drawbridge_horizontal, (struct rm *));
|
||||||
static void FDECL(flip_drawbridge_vertical, (struct rm *));
|
static void FDECL(flip_drawbridge_vertical, (struct rm *));
|
||||||
|
static void FDECL(flip_visuals, (int, int, int, int, int));
|
||||||
static int FDECL(flip_encoded_direction_bits, (int, int));
|
static int FDECL(flip_encoded_direction_bits, (int, int));
|
||||||
static void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
|
static void FDECL(set_wall_property, (XCHAR_P, XCHAR_P, XCHAR_P, XCHAR_P,
|
||||||
int));
|
int));
|
||||||
@@ -370,16 +371,17 @@ struct rm *lev;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* for #wizlevelflip; not needed when flipping during level creation;
|
/* for #wizlevelflip; not needed when flipping during level creation;
|
||||||
update seen vector for whole level and glyph for walls */
|
update seen vector for whole flip area and glyph for known walls */
|
||||||
static void
|
static void
|
||||||
flip_visuals(flp)
|
flip_visuals(flp, minx, miny, maxx, maxy)
|
||||||
int flp;
|
int flp;
|
||||||
|
int minx, miny, maxx, maxy;
|
||||||
{
|
{
|
||||||
struct rm *lev;
|
struct rm *lev;
|
||||||
int x, y, seenv;
|
int x, y, seenv;
|
||||||
|
|
||||||
for (y = 0; y < ROWNO; ++y) {
|
for (y = miny; y <= maxy; ++y) {
|
||||||
for (x = 1; x < COLNO; ++x) {
|
for (x = minx; x <= maxx; ++x) {
|
||||||
lev = &levl[x][y];
|
lev = &levl[x][y];
|
||||||
seenv = lev->seenv & 0xff;
|
seenv = lev->seenv & 0xff;
|
||||||
/* locations which haven't been seen can be skipped */
|
/* locations which haven't been seen can be skipped */
|
||||||
@@ -432,7 +434,17 @@ flip_encoded_direction_bits(int flp, int val)
|
|||||||
|
|
||||||
#define FlipX(val) ((maxx - (val)) + minx)
|
#define FlipX(val) ((maxx - (val)) + minx)
|
||||||
#define FlipY(val) ((maxy - (val)) + miny)
|
#define FlipY(val) ((maxy - (val)) + miny)
|
||||||
#define inFlipArea(x,y) ((x) >= minx && (x) <= maxx && (y) >= miny && (y) <= maxy)
|
#define inFlipArea(x,y) \
|
||||||
|
((x) >= minx && (x) <= maxx && (y) >= miny && (y) <= maxy)
|
||||||
|
#define Flip_coord(cc) \
|
||||||
|
do { \
|
||||||
|
if ((cc).x && inFlipArea((cc).x, (cc).y)) { \
|
||||||
|
if (flp & 1) \
|
||||||
|
(cc).y = FlipY((cc).y); \
|
||||||
|
if (flp & 2) \
|
||||||
|
(cc).x = FlipX((cc).x); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* transpose top with bottom or left with right or both; sometimes called
|
/* transpose top with bottom or left with right or both; sometimes called
|
||||||
for new special levels, or for any level via the #wizlevelflip command */
|
for new special levels, or for any level via the #wizlevelflip command */
|
||||||
@@ -450,8 +462,11 @@ boolean extras;
|
|||||||
struct engr *etmp;
|
struct engr *etmp;
|
||||||
struct mkroom *sroom;
|
struct mkroom *sroom;
|
||||||
timer_element *timer;
|
timer_element *timer;
|
||||||
boolean ball_active = (Punished && uball->where != OBJ_FREE);
|
boolean ball_active = FALSE, ball_fliparea = FALSE;
|
||||||
boolean ball_fliparea;
|
|
||||||
|
/* nothing to do unless (flp & 1) or (flp & 2) or both */
|
||||||
|
if ((flp & 3) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
get_level_extends(&minx, &miny, &maxx, &maxy);
|
get_level_extends(&minx, &miny, &maxx, &maxy);
|
||||||
/* get_level_extends() returns -1,-1 to COLNO,ROWNO at max */
|
/* get_level_extends() returns -1,-1 to COLNO,ROWNO at max */
|
||||||
@@ -464,12 +479,25 @@ boolean extras;
|
|||||||
if (maxy >= ROWNO)
|
if (maxy >= ROWNO)
|
||||||
maxy = (ROWNO - 1);
|
maxy = (ROWNO - 1);
|
||||||
|
|
||||||
ball_fliparea = Punished
|
if (extras) {
|
||||||
&& inFlipArea(uball->ox, uball->oy) == inFlipArea(uchain->ox, uchain->oy)
|
if (Punished && uball->where != OBJ_FREE) {
|
||||||
&& inFlipArea(uball->ox, uball->oy) == inFlipArea(u.ux, u.uy);
|
ball_active = TRUE;
|
||||||
|
/* if hero and ball and chain are all inside flip area,
|
||||||
if (ball_active && extras && !ball_fliparea)
|
flip b&c coordinates along with other objects; if they
|
||||||
unplacebc();
|
are all outside, leave them to be rejected when flipping
|
||||||
|
so that they stay as is; if some are inside and some are
|
||||||
|
outside, un-place here and subsequently re-place them on
|
||||||
|
hero's [possibly new] spot below */
|
||||||
|
if (carried(uball))
|
||||||
|
uball->ox = u.ux, uball->oy = u.uy;
|
||||||
|
ball_fliparea = ((inFlipArea(uball->ox, uball->oy)
|
||||||
|
== inFlipArea(uchain->ox, uchain->oy))
|
||||||
|
&& (inFlipArea(uball->ox, uball->oy)
|
||||||
|
== inFlipArea(u.ux, u.uy)));
|
||||||
|
if (!ball_fliparea)
|
||||||
|
unplacebc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* stairs and ladders */
|
/* stairs and ladders */
|
||||||
if (flp & 1) {
|
if (flp & 1) {
|
||||||
@@ -550,28 +578,28 @@ boolean extras;
|
|||||||
/* skip the occasional earth elemental outside the flip area */
|
/* skip the occasional earth elemental outside the flip area */
|
||||||
if (!inFlipArea(mtmp->mx, mtmp->my))
|
if (!inFlipArea(mtmp->mx, mtmp->my))
|
||||||
continue;
|
continue;
|
||||||
if (flp & 1) {
|
if (flp & 1)
|
||||||
mtmp->my = FlipY(mtmp->my);
|
mtmp->my = FlipY(mtmp->my);
|
||||||
if (mtmp->ispriest)
|
if (flp & 2)
|
||||||
EPRI(mtmp)->shrpos.y = FlipY(EPRI(mtmp)->shrpos.y);
|
|
||||||
else if (mtmp->isshk) {
|
|
||||||
ESHK(mtmp)->shk.y = FlipY(ESHK(mtmp)->shk.y);
|
|
||||||
ESHK(mtmp)->shd.y = FlipY(ESHK(mtmp)->shd.y);
|
|
||||||
} else if (mtmp->wormno) {
|
|
||||||
flip_worm_segs_vertical(mtmp, miny, maxy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flp & 2) {
|
|
||||||
mtmp->mx = FlipX(mtmp->mx);
|
mtmp->mx = FlipX(mtmp->mx);
|
||||||
if (mtmp->ispriest)
|
|
||||||
EPRI(mtmp)->shrpos.x = FlipX(EPRI(mtmp)->shrpos.x);
|
if (mtmp->ispriest) {
|
||||||
else if (mtmp->isshk) {
|
Flip_coord(EPRI(mtmp)->shrpos);
|
||||||
ESHK(mtmp)->shk.x = FlipX(ESHK(mtmp)->shk.x);
|
} else if (mtmp->isshk) {
|
||||||
ESHK(mtmp)->shd.x = FlipX(ESHK(mtmp)->shd.x);
|
Flip_coord(ESHK(mtmp)->shk); /* shk's preferred spot */
|
||||||
} else if (mtmp->wormno) {
|
Flip_coord(ESHK(mtmp)->shd); /* shop door */
|
||||||
|
} else if (mtmp->wormno) {
|
||||||
|
if (flp & 1)
|
||||||
|
flip_worm_segs_vertical(mtmp, miny, maxy);
|
||||||
|
if (flp & 2)
|
||||||
flip_worm_segs_horizontal(mtmp, minx, maxx);
|
flip_worm_segs_horizontal(mtmp, minx, maxx);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#if 0 /* not useful unless tracking also gets flipped */
|
||||||
|
if (extras) {
|
||||||
|
if (mtmp->tame && has_edog(mtmp))
|
||||||
|
Flip_coord(EDOG(mtmp)->ogoal);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* engravings */
|
/* engravings */
|
||||||
@@ -621,8 +649,9 @@ boolean extras;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* rooms */
|
/* rooms */
|
||||||
for(sroom = &g.rooms[0]; ; sroom++) {
|
for (sroom = &g.rooms[0]; ; sroom++) {
|
||||||
if (sroom->hx < 0) break;
|
if (sroom->hx < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (flp & 1) {
|
if (flp & 1) {
|
||||||
sroom->ly = FlipY(sroom->ly);
|
sroom->ly = FlipY(sroom->ly);
|
||||||
@@ -670,10 +699,7 @@ boolean extras;
|
|||||||
|
|
||||||
/* doors */
|
/* doors */
|
||||||
for (i = 0; i < g.doorindex; i++) {
|
for (i = 0; i < g.doorindex; i++) {
|
||||||
if (flp & 1)
|
Flip_coord(g.doors[i]);
|
||||||
g.doors[i].y = FlipY(g.doors[i].y);
|
|
||||||
if (flp & 2)
|
|
||||||
g.doors[i].x = FlipX(g.doors[i].x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the map */
|
/* the map */
|
||||||
@@ -723,32 +749,39 @@ boolean extras;
|
|||||||
/* timed effects */
|
/* timed effects */
|
||||||
for (timer = g.timer_base; timer; timer = timer->next) {
|
for (timer = g.timer_base; timer; timer = timer->next) {
|
||||||
if (timer->func_index == MELT_ICE_AWAY) {
|
if (timer->func_index == MELT_ICE_AWAY) {
|
||||||
long ty = ((long)timer->arg.a_void) & 0xFFFF;
|
long ty = ((long) timer->arg.a_void) & 0xffff;
|
||||||
long tx = (((long)timer->arg.a_void) >> 16) & 0xFFFF;
|
long tx = (((long) timer->arg.a_void) >> 16) & 0xffff;
|
||||||
|
|
||||||
if (flp & 1)
|
if (flp & 1)
|
||||||
ty = FlipY(ty);
|
ty = FlipY(ty);
|
||||||
if (flp & 2)
|
if (flp & 2)
|
||||||
tx = FlipX(tx);
|
tx = FlipX(tx);
|
||||||
timer->arg.a_void = (genericptr_t)((tx << 16) | ty);
|
timer->arg.a_void = (genericptr_t) ((tx << 16) | ty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extras) {
|
if (extras) { /* for #wizlevelflip rather than during level creation */
|
||||||
/* flip hero location only if inside the flippable area */
|
/* flip hero location only if inside the flippable area */
|
||||||
if (!(u.ux < minx || u.ux > maxx || u.uy < miny || u.uy > maxy)) {
|
if (inFlipArea(u.ux, u.uy)) {
|
||||||
if (flp & 1)
|
if (flp & 1)
|
||||||
u.uy = FlipY(u.uy), u.uy0 = FlipY(u.uy0);
|
u.uy = FlipY(u.uy);
|
||||||
if (flp & 2)
|
if (flp & 2)
|
||||||
u.ux = FlipX(u.ux), u.ux0 = FlipX(u.ux0);
|
u.ux = FlipX(u.ux);
|
||||||
|
/* we could flip <ux0,uy0> too if it's inside the flip area,
|
||||||
|
but have to resort to this if outside, so just do this */
|
||||||
|
u.ux0 = u.ux, u.uy0 = u.uy;
|
||||||
}
|
}
|
||||||
if (ball_active && !ball_fliparea)
|
if (ball_active && !ball_fliparea)
|
||||||
placebc();
|
placebc();
|
||||||
|
Flip_coord(iflags.travelcc);
|
||||||
|
Flip_coord(g.context.digging.pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fix_wall_spines(1, 0, COLNO - 1, ROWNO - 1);
|
fix_wall_spines(1, 0, COLNO - 1, ROWNO - 1);
|
||||||
if (extras && flp) {
|
if (extras && flp) {
|
||||||
set_wall_state();
|
set_wall_state();
|
||||||
flip_visuals(flp); /* after wall_spines; flips seenv and wall joins */
|
/* after wall_spines; flips seenv and wall joins */
|
||||||
|
flip_visuals(flp, minx, miny, maxx, maxy);
|
||||||
}
|
}
|
||||||
vision_reset();
|
vision_reset();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user