Rework stairs structure

Use a linked list to store stair and ladder information, instead
of having fixed up/down stairs/ladders and a single "special" (branch)
stair.

Breaks saves and bones.

Adds information to migrating objects and monsters for the dungeon
and level where they are migrating from.
This commit is contained in:
Pasi Kallinen
2020-11-13 20:27:17 +02:00
parent e23f764d11
commit 6ec55a3624
34 changed files with 552 additions and 361 deletions
+12 -34
View File
@@ -712,43 +712,21 @@ do_positionbar()
{
static char pbar[COLNO];
char *p;
stairway *stway = g.stairs;
p = pbar;
/* up stairway */
if (g.upstair.sx
&& (glyph_to_cmap(g.level.locations[g.upstair.sx][g.upstair.sy].glyph)
== S_upstair
|| glyph_to_cmap(g.level.locations[g.upstair.sx][g.upstair.sy].glyph)
== S_upladder)) {
*p++ = '<';
*p++ = g.upstair.sx;
}
if (g.sstairs.sx
&& (glyph_to_cmap(g.level.locations[g.sstairs.sx][g.sstairs.sy].glyph)
== S_upstair
|| glyph_to_cmap(g.level.locations[g.sstairs.sx][g.sstairs.sy].glyph)
== S_upladder)) {
*p++ = '<';
*p++ = g.sstairs.sx;
}
/* TODO: use the same method as getpos() so objects don't cover stairs */
while (stway) {
int x = stway->sx;
int y = stway->sy;
int glyph = glyph_to_cmap(g.level.locations[x][y].glyph);
/* down stairway */
if (g.dnstair.sx
&& (glyph_to_cmap(g.level.locations[g.dnstair.sx][g.dnstair.sy].glyph)
== S_dnstair
|| glyph_to_cmap(g.level.locations[g.dnstair.sx][g.dnstair.sy].glyph)
== S_dnladder)) {
*p++ = '>';
*p++ = g.dnstair.sx;
}
if (g.sstairs.sx
&& (glyph_to_cmap(g.level.locations[g.sstairs.sx][g.sstairs.sy].glyph)
== S_dnstair
|| glyph_to_cmap(g.level.locations[g.sstairs.sx][g.sstairs.sy].glyph)
== S_dnladder)) {
*p++ = '>';
*p++ = g.sstairs.sx;
}
if (is_cmap_stairs(glyph)) {
*p++ = (stway->up ? '<' : '>');
*p++ = stway->sx;
}
stway = stway->next;
}
/* hero location */
if (u.ux) {
+4 -4
View File
@@ -2556,10 +2556,10 @@ struct obj *otmp;
what = "in water";
else if (is_lava(u.ux, u.uy))
what = "in lava";
else if (On_stairs(u.ux, u.uy))
what = (u.ux == xdnladder || u.ux == xupladder) ? "on the ladder"
: "on the stairs";
else if (IS_FURNITURE(levtyp) || IS_ROCK(levtyp)
else if (On_stairs(u.ux, u.uy)) {
stairway *stway = stairway_at(u.ux, u.uy);
what = stway->isladder ? "on the ladder" : "on the stairs";
} else if (IS_FURNITURE(levtyp) || IS_ROCK(levtyp)
|| closed_door(u.ux, u.uy) || t_at(u.ux, u.uy))
what = "here";
else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
+5 -6
View File
@@ -3958,6 +3958,7 @@ boolean doit;
schar typ = levl[u.ux][u.uy].typ;
int npick;
menu_item *picks = (menu_item *) 0;
stairway *stway = stairway_at(u.ux, u.uy);
win = create_nhwindow(NHW_MENU);
start_menu(win, MENU_BEHAVE_STANDARD);
@@ -3974,16 +3975,14 @@ boolean doit;
add_herecmd_menuitem(win, dosit,
"Sit on the throne");
if (On_stairs_up(u.ux, u.uy)) {
if (stway && stway->up) {
Sprintf(buf, "Go up the %s",
(u.ux == xupladder && u.uy == yupladder)
? "ladder" : "stairs");
stway->isladder ? "ladder" : "stairs");
add_herecmd_menuitem(win, doup, buf);
}
if (On_stairs_dn(u.ux, u.uy)) {
if (stway && !stway->up) {
Sprintf(buf, "Go down the %s",
(u.ux == xupladder && u.uy == yupladder)
? "ladder" : "stairs");
stway->isladder ? "ladder" : "stairs");
add_herecmd_menuitem(win, dodown, buf);
}
if (u.usteed) { /* another movement choice */
+1 -8
View File
@@ -270,10 +270,7 @@ const struct instance_globals g_init = {
(ROWNO - 1) & ~1, /* y_maze_max */
UNDEFINED_VALUE, /* otg_temp */
0, /* in_doagain */
DUMMY, /* dnstair */
DUMMY, /* upstair */
DUMMY, /* dnladder */
DUMMY, /* upladder */
NULL, /* stairs */
DUMMY, /* smeq */
0, /* doorindex */
NULL, /* save_cm */
@@ -294,7 +291,6 @@ const struct instance_globals g_init = {
UNDEFINED_PTR, /* sp_levchn */
{ 0, 0, STRANGE_OBJECT, FALSE }, /* m_shot */
UNDEFINED_VALUES, /* dungeons */
{ 0, 0, { 0, 0 }, 0 }, /* sstairs */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* updest */
{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* dndest */
{ 0, 0} , /* inv_pos */
@@ -305,9 +301,6 @@ const struct instance_globals g_init = {
FALSE, /* mrg_to_wielded */
NULL, /* plinemsg_types */
UNDEFINED_VALUES, /* toplines */
UNDEFINED_PTR, /* upstairs_room */
UNDEFINED_PTR, /* dnstairs_room */
UNDEFINED_PTR, /* sstairs_room */
DUMMY, /* bhitpos */
FALSE, /* in_steed_dismounting */
DUMMY, /* doors */
+6 -5
View File
@@ -188,7 +188,8 @@ int x, y;
(madeby == BY_YOU && uwep && is_axe(uwep)) ? "chop" : "dig in";
if (On_stairs(x, y)) {
if (x == xdnladder || x == xupladder) {
stairway *stway = stairway_at(x, y);
if (stway->isladder) {
if (verbose)
pline_The("ladder resists your effort.");
} else if (verbose)
@@ -1431,12 +1432,12 @@ zap_dig()
if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !Underwater) {
if (u.dz < 0 || On_stairs(u.ux, u.uy)) {
int dmg;
if (On_stairs(u.ux, u.uy))
if (On_stairs(u.ux, u.uy)) {
stairway *stway = stairway_at(u.ux, u.uy);
pline_The("beam bounces off the %s and hits the %s.",
(u.ux == xdnladder || u.ux == xupladder)
? "ladder"
: "stairs",
stway->isladder ? "ladder" : "stairs",
ceiling(u.ux, u.uy));
}
You("loosen a rock from the %s.", ceiling(u.ux, u.uy));
pline("It falls on your %s!", body_part(HEAD));
dmg = rnd((uarmh && is_metallic(uarmh)) ? 2 : 6);
+13 -12
View File
@@ -950,10 +950,9 @@ int
dodown()
{
struct trap *trap = 0;
boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair)
|| (u.ux == g.sstairs.sx && u.uy == g.sstairs.sy
&& !g.sstairs.up)),
ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
stairway *stway = stairway_at(u.ux, u.uy);
boolean stairs_down = (stway && !stway->up && !stway->isladder),
ladder_down = (stway && !stway->up && stway->isladder);
if (u_rooted())
return 1;
@@ -1105,6 +1104,8 @@ dodown()
int
doup()
{
stairway *stway = stairway_at(u.ux,u.uy);
if (u_rooted())
return 1;
@@ -1114,10 +1115,7 @@ doup()
return 1;
}
if ((u.ux != xupstair || u.uy != yupstair)
&& (!xupladder || u.ux != xupladder || u.uy != yupladder)
&& (!g.sstairs.sx || u.ux != g.sstairs.sx || u.uy != g.sstairs.sy
|| !g.sstairs.up)) {
if (!stway || (stway && !stway->up)) {
You_cant("go up here.");
return 0;
}
@@ -1458,6 +1456,7 @@ boolean at_stairs, falling, portal;
dunlev_reached(&u.uz) = dunlev(&u.uz);
}
stairway_free_all();
/* set default level change destination areas */
/* the special level code may override these */
(void) memset((genericptr_t) &g.updest, 0, sizeof g.updest);
@@ -1528,8 +1527,9 @@ boolean at_stairs, falling, portal;
}
} else if (at_stairs && !In_endgame(&u.uz)) {
if (up) {
if (g.at_ladder)
u_on_newpos(xdnladder, ydnladder);
stairway *stway = stairway_find_from(&u.uz0, g.at_ladder);
if (stway)
u_on_newpos(stway->sx, stway->sy);
else if (newdungeon)
u_on_sstairs(1);
else
@@ -1544,8 +1544,9 @@ boolean at_stairs, falling, portal;
(Flying && g.at_ladder) ? " along" : "",
g.at_ladder ? "ladder" : "stairs");
} else { /* down */
if (g.at_ladder)
u_on_newpos(xupladder, yupladder);
stairway *stway = stairway_find_from(&u.uz0, g.at_ladder);
if (stway)
u_on_newpos(stway->sx, stway->sy);
else if (newdungeon)
u_on_sstairs(0);
else
+26 -5
View File
@@ -306,6 +306,8 @@ boolean with_you;
xchar xlocale, ylocale, xyloc, xyflags, wander;
int num_segs;
boolean failed_to_place = FALSE;
stairway *stway;
d_level fromdlev;
mtmp->nmon = fmon;
fmon = mtmp;
@@ -331,6 +333,8 @@ boolean with_you;
xyflags = mtmp->mtrack[0].y;
xlocale = mtmp->mtrack[1].x;
ylocale = mtmp->mtrack[1].y;
fromdlev.dnum = mtmp->mtrack[2].x;
fromdlev.dlevel = mtmp->mtrack[2].y;
memset(mtmp->mtrack, 0, sizeof mtmp->mtrack);
if (mtmp == u.usteed)
@@ -376,19 +380,34 @@ boolean with_you;
xlocale = u.ux, ylocale = u.uy;
break;
case MIGR_STAIRS_UP:
xlocale = xupstair, ylocale = yupstair;
if ((stway = stairway_find_from(&fromdlev, FALSE)) != 0) {
xlocale = stway->sx;
ylocale = stway->sy;
}
break;
case MIGR_STAIRS_DOWN:
xlocale = xdnstair, ylocale = ydnstair;
if ((stway = stairway_find_from(&fromdlev, FALSE)) != 0) {
xlocale = stway->sx;
ylocale = stway->sy;
}
break;
case MIGR_LADDER_UP:
xlocale = xupladder, ylocale = yupladder;
if ((stway = stairway_find_from(&fromdlev, TRUE)) != 0) {
xlocale = stway->sx;
ylocale = stway->sy;
}
break;
case MIGR_LADDER_DOWN:
xlocale = xdnladder, ylocale = ydnladder;
if ((stway = stairway_find_from(&fromdlev, TRUE)) != 0) {
xlocale = stway->sx;
ylocale = stway->sy;
}
break;
case MIGR_SSTAIRS:
xlocale = g.sstairs.sx, ylocale = g.sstairs.sy;
if ((stway = stairway_find(&fromdlev)) != 0) {
xlocale = stway->sx;
ylocale = stway->sy;
}
break;
case MIGR_PORTAL:
if (In_endgame(&u.uz)) {
@@ -719,6 +738,8 @@ coord *cc; /* optional destination coordinates */
xyflags |= 2;
mtmp->wormno = num_segs;
mtmp->mlstmv = g.monstermoves;
mtmp->mtrack[2].x = u.uz.dnum; /* migrating from this dungeon */
mtmp->mtrack[2].y = u.uz.dlevel; /* migrating from this dungeon level */
mtmp->mtrack[1].x = cc ? cc->x : mtmp->mx;
mtmp->mtrack[1].y = cc ? cc->y : mtmp->my;
mtmp->mtrack[0].x = xyloc;
+38 -20
View File
@@ -19,7 +19,7 @@ static int FDECL(kick_object, (XCHAR_P, XCHAR_P, char *));
static int FDECL(really_kick_object, (XCHAR_P, XCHAR_P));
static char *FDECL(kickstr, (char *, const char *));
static void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
static void FDECL(drop_to, (coord *, SCHAR_P));
static void FDECL(drop_to, (coord *, SCHAR_P, XCHAR_P, XCHAR_P));
static const char kick_passes_thru[] = "kick passes harmlessly through";
@@ -1322,10 +1322,13 @@ dokick()
}
static void
drop_to(cc, loc)
drop_to(cc, loc, x,y)
coord *cc;
schar loc;
xchar x,y;
{
stairway *stway = stairway_at(x, y);
/* cover all the MIGR_xxx choices generated by down_gate() */
switch (loc) {
case MIGR_RANDOM: /* trap door or hole */
@@ -1340,12 +1343,14 @@ schar loc;
/*FALLTHRU*/
case MIGR_STAIRS_UP:
case MIGR_LADDER_UP:
cc->x = u.uz.dnum;
cc->y = u.uz.dlevel + 1;
break;
case MIGR_SSTAIRS:
cc->x = g.sstairs.tolev.dnum;
cc->y = g.sstairs.tolev.dlevel;
if (stway) {
cc->x = stway->tolev.dnum;
cc->y = stway->tolev.dlevel;
} else {
cc->x = u.uz.dnum;
cc->y = u.uz.dlevel + 1;
}
break;
default:
case MIGR_NOWHERE:
@@ -1373,7 +1378,7 @@ xchar dlev; /* if !0 send to dlev near player */
return;
toloc = down_gate(x, y);
drop_to(&cc, toloc);
drop_to(&cc, toloc, x, y);
if (!cc.y)
return;
@@ -1502,7 +1507,7 @@ boolean shop_floor_obj;
return FALSE;
if ((toloc = down_gate(x, y)) == MIGR_NOWHERE)
return FALSE;
drop_to(&cc, toloc);
drop_to(&cc, toloc, x, y);
if (!cc.y)
return FALSE;
@@ -1586,6 +1591,7 @@ boolean shop_floor_obj;
otmp->ox = cc.x;
otmp->oy = cc.y;
otmp->owornmask = (long) toloc;
/* boulder from rolling boulder trap, no longer part of the trap */
if (otmp->otyp == BOULDER)
otmp->otrapped = 0;
@@ -1614,6 +1620,9 @@ boolean near_hero;
register int nx, ny;
int where;
boolean nobreak, noscatter;
stairway *stway;
d_level fromdlev;
boolean isladder;
for (otmp = g.migrating_objs; otmp; otmp = otmp2) {
otmp2 = otmp->nobj;
@@ -1633,16 +1642,21 @@ boolean near_hero;
obj_extract_self(otmp);
otmp->owornmask = 0L;
fromdlev.dnum = otmp->omigr_from_dnum;
fromdlev.dlevel = otmp->omigr_from_dlevel;
isladder = FALSE;
switch (where) {
case MIGR_STAIRS_UP:
nx = xupstair, ny = yupstair;
break;
case MIGR_LADDER_UP:
nx = xupladder, ny = yupladder;
break;
isladder = TRUE;
case MIGR_STAIRS_UP:
case MIGR_SSTAIRS:
nx = g.sstairs.sx, ny = g.sstairs.sy;
if ((stway = stairway_find_from(&fromdlev, isladder)) != 0) {
nx = stway->sx;
nx = stway->sy;
}
break;
break;
case MIGR_WITH_HERO:
nx = u.ux, ny = u.uy;
@@ -1652,6 +1666,8 @@ boolean near_hero;
nx = ny = 0;
break;
}
otmp->omigr_from_dnum = 0;
otmp->omigr_from_dlevel = 0;
if (nx > 0) {
place_object(otmp, nx, ny);
if (!nobreak && !IS_SOFT(levl[nx][ny].typ)) {
@@ -1727,6 +1743,8 @@ unsigned long deliverflags;
free_oname(otmp);
}
otmp->migr_species = NON_PM;
otmp->omigr_from_dnum = 0;
otmp->omigr_from_dlevel = 0;
(void) add_to_minv(mtmp, otmp);
cnt++;
if (maxobj && cnt >= maxobj)
@@ -1773,19 +1791,19 @@ down_gate(x, y)
xchar x, y;
{
struct trap *ttmp;
stairway *stway = stairway_at(x, y);
g.gate_str = 0;
/* this matches the player restriction in goto_level() */
if (on_level(&u.uz, &qstart_level) && !ok_to_quest())
return MIGR_NOWHERE;
if ((xdnstair == x && ydnstair == y)
|| (g.sstairs.sx == x && g.sstairs.sy == y && !g.sstairs.up)) {
if (stway && !stway->up && !stway->isladder) {
g.gate_str = "down the stairs";
return (xdnstair == x && ydnstair == y) ? MIGR_STAIRS_UP
: MIGR_SSTAIRS;
return (stway->tolev.dnum == u.uz.dnum) ? MIGR_STAIRS_UP
: MIGR_SSTAIRS;
}
if (xdnladder == x && ydnladder == y) {
if (stway && !stway->up && stway->isladder) {
g.gate_str = "down the ladder";
return MIGR_LADDER_UP;
}
+167 -30
View File
@@ -1398,13 +1398,14 @@ void
next_level(at_stairs)
boolean at_stairs;
{
if (at_stairs && u.ux == g.sstairs.sx && u.uy == g.sstairs.sy) {
/* Taking a down dungeon branch. */
goto_level(&g.sstairs.tolev, at_stairs, FALSE, FALSE);
} else {
/* Going down a stairs or jump in a trap door. */
d_level newlevel;
stairway *stway = stairway_at(u.ux, u.uy);
d_level newlevel;
if (at_stairs && stway) {
newlevel.dnum = stway->tolev.dnum;
newlevel.dlevel = stway->tolev.dlevel;
goto_level(&newlevel, at_stairs, FALSE, FALSE);
} else {
newlevel.dnum = u.uz.dnum;
newlevel.dlevel = u.uz.dlevel + 1;
goto_level(&newlevel, at_stairs, !at_stairs, FALSE);
@@ -1416,17 +1417,22 @@ void
prev_level(at_stairs)
boolean at_stairs;
{
if (at_stairs && u.ux == g.sstairs.sx && u.uy == g.sstairs.sy) {
stairway *stway = stairway_at(u.ux, u.uy);
d_level newlevel;
if (at_stairs && stway && stway->tolev.dnum != u.uz.dnum) {
/* Taking an up dungeon branch. */
/* KMH -- Upwards branches are okay if not level 1 */
/* (Just make sure it doesn't go above depth 1) */
if (!u.uz.dnum && u.uz.dlevel == 1 && !u.uhave.amulet)
done(ESCAPED);
else
goto_level(&g.sstairs.tolev, at_stairs, FALSE, FALSE);
else {
newlevel.dnum = stway->tolev.dnum;
newlevel.dlevel = stway->tolev.dlevel;
goto_level(&newlevel, at_stairs, FALSE, FALSE);
}
} else {
/* Going up a stairs or rising through the ceiling. */
d_level newlevel;
newlevel.dnum = u.uz.dnum;
newlevel.dlevel = u.uz.dlevel - 1;
goto_level(&newlevel, at_stairs, FALSE, FALSE);
@@ -1492,13 +1498,141 @@ int upflag;
switch_terrain();
}
void
stairway_add(x,y, up, ladder, dest)
int x,y;
boolean up, ladder;
d_level *dest;
{
stairway *tmp = (stairway *)alloc(sizeof(stairway));
tmp->sx = x;
tmp->sy = y;
tmp->up = up;
tmp->isladder = ladder;
assign_level(&(tmp->tolev), dest);
tmp->next = g.stairs;
g.stairs = tmp;
}
void
stairway_free_all()
{
stairway *tmp = g.stairs;
while (tmp) {
stairway *tmp2 = tmp->next;
free(tmp);
tmp = tmp2;
}
g.stairs = NULL;
}
stairway *
stairway_at(x,y)
int x,y;
{
stairway *tmp = g.stairs;
while (tmp && !(tmp->sx == x && tmp->sy == y))
tmp = tmp->next;
return tmp;
}
stairway *
stairway_find(fromdlev)
d_level *fromdlev;
{
stairway *tmp = g.stairs;
while (tmp) {
if (tmp->tolev.dnum == fromdlev->dnum
&& tmp->tolev.dlevel == fromdlev->dlevel)
return tmp;
tmp = tmp->next;
}
return tmp;
}
stairway *
stairway_find_from(fromdlev, ladder)
d_level *fromdlev;
boolean ladder;
{
stairway *tmp = g.stairs;
while (tmp) {
if (tmp->tolev.dnum == fromdlev->dnum
&& tmp->tolev.dlevel == fromdlev->dlevel
&& tmp->isladder == ladder)
return tmp;
tmp = tmp->next;
}
return tmp;
}
stairway *
stairway_find_dir(up)
boolean up;
{
stairway *tmp = g.stairs;
while (tmp && !(tmp->up == up))
tmp = tmp->next;
return tmp;
}
stairway *
stairway_find_ladder()
{
stairway *tmp = g.stairs;
while (tmp && !tmp->isladder)
tmp = tmp->next;
return tmp;
}
stairway *
stairway_find_type_dir(ladder,up)
boolean ladder, up;
{
stairway *tmp = g.stairs;
while (tmp && !(tmp->isladder == ladder && tmp->up == up))
tmp = tmp->next;
return tmp;
}
stairway *
stairway_find_special_dir(up)
boolean up;
{
stairway *tmp = g.stairs;
while (tmp) {
if (tmp->tolev.dnum != u.uz.dnum && tmp->up != up)
return tmp;
tmp = tmp->next;
}
return tmp;
}
/* place you on the special staircase */
void
u_on_sstairs(upflag)
int upflag;
{
if (g.sstairs.sx)
u_on_newpos(g.sstairs.sx, g.sstairs.sy);
stairway *stway = stairway_find_special_dir(upflag);
if (stway)
u_on_newpos(stway->sx, stway->sy);
else
u_on_rndspot(upflag);
}
@@ -1507,8 +1641,10 @@ int upflag;
void
u_on_upstairs()
{
if (xupstair)
u_on_newpos(xupstair, yupstair);
stairway *stway = stairway_find_dir(TRUE);
if (stway)
u_on_newpos(stway->sx, stway->sy);
else
u_on_sstairs(0); /* destination upstairs implies moving down */
}
@@ -1517,8 +1653,10 @@ u_on_upstairs()
void
u_on_dnstairs()
{
if (xdnstair)
u_on_newpos(xdnstair, ydnstair);
stairway *stway = stairway_find_dir(FALSE);
if (stway)
u_on_newpos(stway->sx, stway->sy);
else
u_on_sstairs(1); /* destination dnstairs implies moving up */
}
@@ -1527,37 +1665,34 @@ boolean
On_stairs(x, y)
xchar x, y;
{
return (boolean) ((x == xupstair && y == yupstair)
|| (x == xdnstair && y == ydnstair)
|| (x == xdnladder && y == ydnladder)
|| (x == xupladder && y == yupladder)
|| (x == g.sstairs.sx && y == g.sstairs.sy));
return (stairway_at(x,y) != NULL);
}
boolean
On_ladder(x, y)
xchar x, y;
{
return (boolean) ((x == xdnladder && y == ydnladder)
|| (x == xupladder && y == yupladder));
stairway *stway = stairway_at(x,y);
return (boolean) (stway && stway->isladder);
}
boolean
On_stairs_up(x, y)
xchar x, y;
{
return ((x == xupstair && y == yupstair)
|| (x == g.sstairs.sx && y == g.sstairs.sy && g.sstairs.up)
|| (x == xupladder && y == yupladder));
stairway *stway = stairway_at(x,y);
return (boolean) (stway && stway->up);
}
boolean
On_stairs_dn(x, y)
xchar x, y;
{
return ((x == xdnstair && y == ydnstair)
|| (x == g.sstairs.sx && y == g.sstairs.sy && !g.sstairs.up)
|| (x == xdnladder && y == ydnladder));
stairway *stway = stairway_at(x,y);
return (boolean) (stway && !stway->up);
}
boolean
@@ -1599,6 +1734,8 @@ Can_rise_up(x, y, lev)
int x, y;
d_level *lev;
{
stairway *stway = stairway_find_special_dir(FALSE);
/* can't rise up from inside the top of the Wizard's tower */
/* KMH -- or in sokoban */
if (In_endgame(lev) || In_sokoban(lev)
@@ -1607,7 +1744,7 @@ d_level *lev;
return (boolean) (lev->dlevel > 1
|| (g.dungeons[lev->dnum].entry_lev == 1
&& ledger_no(lev) != 1
&& g.sstairs.sx && g.sstairs.up));
&& stway && stway->up));
}
boolean
+5 -6
View File
@@ -3362,6 +3362,7 @@ char *buf;
int ltyp = lev->typ, cmap = -1;
const char *dfeature = 0;
static char altbuf[BUFSZ];
stairway *stway = stairway_at(x,y);
if (IS_DOOR(ltyp)) {
switch (lev->doormask) {
@@ -3402,15 +3403,13 @@ char *buf;
a_gname(),
align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
dfeature = altbuf;
} else if ((x == xupstair && y == yupstair)
|| (x == g.sstairs.sx && y == g.sstairs.sy && g.sstairs.up))
} else if (stway && !stway->isladder && stway->up)
cmap = S_upstair; /* "staircase up" */
else if ((x == xdnstair && y == ydnstair)
|| (x == g.sstairs.sx && y == g.sstairs.sy && !g.sstairs.up))
else if (stway && !stway->isladder && !stway->up)
cmap = S_dnstair; /* "staircase down" */
else if (x == xupladder && y == yupladder)
else if (stway && stway->isladder && stway->up)
cmap = S_upladder; /* "ladder up" */
else if (x == xdnladder && y == ydnladder)
else if (stway && stway->isladder && !stway->up)
cmap = S_dnladder; /* "ladder down" */
else if (ltyp == DRAWBRIDGE_DOWN)
cmap = S_vodbridge; /* "lowered drawbridge" */
+8 -9
View File
@@ -151,6 +151,7 @@ coord *startp;
int lax; /* if TRUE, pick a position in sight. */
int dd; /* distance to current point */
int max_distance; /* max distance found so far */
stairway *stway = g.stairs;
/*
* If blind and not telepathic, then it doesn't matter what we pick ---
@@ -166,15 +167,13 @@ coord *startp;
* Arrive at an up or down stairwell if it is in line of sight from the
* hero.
*/
if (couldsee(g.upstair.sx, g.upstair.sy)) {
startp->x = g.upstair.sx;
startp->y = g.upstair.sy;
return TRUE;
}
if (couldsee(g.dnstair.sx, g.dnstair.sy)) {
startp->x = g.dnstair.sx;
startp->y = g.dnstair.sy;
return TRUE;
while (stway) {
if (stway->tolev.dnum == u.uz.dnum && couldsee(stway->sx, stway->sy)) {
startp->x = stway->sx;
startp->y = stway->sy;
return TRUE;
}
stway = stway->next;
}
/*
+8 -12
View File
@@ -1095,20 +1095,16 @@ coord *cc;
goto gotgood;
}
if (bl == 0 && (!mon || mon->data->mmove)) {
stairway *stway = g.stairs;
/* all map positions are visible (or not good),
try to pick something logical */
if (g.dnstair.sx && !rn2(2)) {
nx = g.dnstair.sx;
ny = g.dnstair.sy;
} else if (g.upstair.sx && !rn2(2)) {
nx = g.upstair.sx;
ny = g.upstair.sy;
} else if (g.dnladder.sx && !rn2(2)) {
nx = g.dnladder.sx;
ny = g.dnladder.sy;
} else if (g.upladder.sx && !rn2(2)) {
nx = g.upladder.sx;
ny = g.upladder.sy;
while (stway) {
if (stway->tolev.dnum == u.uz.dnum && !rn2(2)) {
nx = stway->sx;
ny = stway->sy;
break;
}
stway = stway->next;
}
if (goodpos(nx, ny, mon, gpflags))
goto gotgood;
+15 -25
View File
@@ -719,10 +719,7 @@ clear_level_structures()
g.doorindex = 0;
init_rect();
init_vault();
xdnstair = ydnstair = xupstair = yupstair = 0;
g.sstairs.sx = g.sstairs.sy = 0;
xdnladder = ydnladder = xupladder = yupladder = 0;
g.dnstairs_room = g.upstairs_room = g.sstairs_room = (struct mkroom *) 0;
stairway_free_all();
g.made_branch = FALSE;
clear_regions();
g.xstart = 1;
@@ -1112,13 +1109,6 @@ mklev()
for (ridx = 0; ridx < SIZE(g.rooms); ridx++)
g.rooms[ridx].orig_rtype = g.rooms[ridx].rtype;
/* something like this usually belongs in clear_level_structures()
but these aren't saved and restored so might not retain their
values for the life of the current level; reset them to default
now so that they never do and no one will be tempted to introduce
a new use of them for anything on this level */
g.dnstairs_room = g.upstairs_room = g.sstairs_room = (struct mkroom *) 0;
reseed_random(rn2);
reseed_random(rn2_on_display_rng);
}
@@ -1262,14 +1252,10 @@ xchar x, y; /* location */
if (br->type == BR_PORTAL) {
mkportal(x, y, dest->dnum, dest->dlevel);
} else if (make_stairs) {
g.sstairs.sx = x;
g.sstairs.sy = y;
g.sstairs.up =
(char) on_level(&br->end1, &u.uz) ? br->end1_up : !br->end1_up;
assign_level(&g.sstairs.tolev, dest);
g.sstairs_room = br_room;
boolean goes_up = on_level(&br->end1, &u.uz) ? br->end1_up : !br->end1_up;
levl[x][y].ladder = g.sstairs.up ? LA_UP : LA_DOWN;
stairway_add(x,y, goes_up, FALSE, dest);
levl[x][y].ladder = goes_up ? LA_UP : LA_DOWN;
levl[x][y].typ = STAIRS;
}
/*
@@ -1633,13 +1619,17 @@ struct mkroom *croom;
return;
if (up) {
xupstair = x;
yupstair = y;
g.upstairs_room = croom;
d_level dest;
dest.dnum = u.uz.dnum;
dest.dlevel = u.uz.dlevel - 1;
stairway_add(x,y, TRUE, FALSE, &dest);
} else {
xdnstair = x;
ydnstair = y;
g.dnstairs_room = croom;
d_level dest;
dest.dnum = u.uz.dnum;
dest.dlevel = u.uz.dlevel + 1;
stairway_add(x,y, FALSE, FALSE, &dest);
}
levl[x][y].typ = STAIRS;
@@ -1659,7 +1649,7 @@ struct mkroom *croom;
int phase;
{
return (croom && (croom->needjoining || (phase < 0))
&& ((croom != g.dnstairs_room && croom != g.upstairs_room)
&& ((!has_dnstairs(croom) && !has_upstairs(croom))
|| phase < 1)
&& (croom->rtype == OROOM
|| ((phase < 2) && croom->rtype == THEMEROOM)));
+6 -4
View File
@@ -1015,6 +1015,7 @@ const char *s;
mazexy(&mm);
mkstairs(mm.x, mm.y, 0, (struct mkroom *) 0); /* down */
} else { /* choose "vibrating square" location */
stairway *stway;
int trycnt = 0;
#define x_maze_min 2
#define y_maze_min 2
@@ -1047,10 +1048,11 @@ const char *s;
to be on a spot that's already in use (wall|trap) */
if (++trycnt > 1000)
break;
} while (x == xupstair || y == yupstair /*(direct line)*/
|| abs(x - xupstair) == abs(y - yupstair)
|| distmin(x, y, xupstair, yupstair) <= INVPOS_DISTANCE
|| !SPACE_POS(levl[x][y].typ) || occupied(x, y));
} while (((stway = stairway_find_dir(TRUE)) != 0)
&& (x == stway->sx || y == stway->sy /*(direct line)*/
|| abs(x - stway->sx) == abs(y - stway->sy)
|| distmin(x, y, stway->sx, stway->sy) <= INVPOS_DISTANCE
|| !SPACE_POS(levl[x][y].typ) || occupied(x, y)));
g.inv_pos.x = x;
g.inv_pos.y = y;
maketrap(g.inv_pos.x, g.inv_pos.y, VIBRATING_SQUARE);
+2
View File
@@ -2130,6 +2130,8 @@ struct obj *obj;
obj->where = OBJ_MIGRATING;
obj->nobj = g.migrating_objs;
obj->omigr_from_dnum = u.uz.dnum;
obj->omigr_from_dlevel = u.uz.dlevel;
g.migrating_objs = obj;
}
+14 -8
View File
@@ -622,10 +622,13 @@ boolean
has_dnstairs(sroom)
register struct mkroom *sroom;
{
if (sroom == g.dnstairs_room)
return TRUE;
if (g.sstairs.sx && !g.sstairs.up)
return (boolean) (sroom == g.sstairs_room);
stairway *stway = g.stairs;
while (stway) {
if (!stway->up && inside_room(sroom, stway->sx, stway->sy))
return TRUE;
stway = stway->next;
}
return FALSE;
}
@@ -633,10 +636,13 @@ boolean
has_upstairs(sroom)
register struct mkroom *sroom;
{
if (sroom == g.upstairs_room)
return TRUE;
if (g.sstairs.sx && g.sstairs.up)
return (boolean) (sroom == g.sstairs_room);
stairway *stway = g.stairs;
while (stway) {
if (stway->up && inside_room(sroom, stway->sx, stway->sy))
return TRUE;
stway = stway->next;
}
return FALSE;
}
+6 -2
View File
@@ -2327,11 +2327,15 @@ register struct monst *mtmp;
#endif
if (mtmp->data->mlet == S_KOP) {
stairway *stway = stairway_find_type_dir(FALSE, FALSE);
/* Dead Kops may come back. */
switch (rnd(5)) {
case 1: /* returns near the stairs */
(void) makemon(mtmp->data, xdnstair, ydnstair, NO_MM_FLAGS);
break;
if (stway) {
(void) makemon(mtmp->data, stway->sx, stway->sy, NO_MM_FLAGS);
break;
}
case 2: /* randomly */
(void) makemon(mtmp->data, 0, 0, NO_MM_FLAGS);
break;
+35 -21
View File
@@ -336,6 +336,7 @@ struct monst *mtmp;
int fraction, x = mtmp->mx, y = mtmp->my;
boolean stuck = (mtmp == u.ustuck),
immobile = (mtmp->data->mmove == 0);
stairway *stway;
if (is_animal(mtmp->data) || mindless(mtmp->data))
return FALSE;
@@ -432,23 +433,25 @@ struct monst *mtmp;
if (stuck || immobile) {
; /* fleeing by stairs or traps is not possible */
} else if (levl[x][y].typ == STAIRS) {
if (x == xdnstair && y == ydnstair) {
stway = stairway_at(x,y);
if (stway && !stway->up && stway->tolev.dnum == u.uz.dnum) {
if (!is_floater(mtmp->data))
g.m.has_defense = MUSE_DOWNSTAIRS;
} else if (x == xupstair && y == yupstair) {
} else if (stway && stway->up && stway->tolev.dnum == u.uz.dnum) {
g.m.has_defense = MUSE_UPSTAIRS;
} else if (g.sstairs.sx && x == g.sstairs.sx && y == g.sstairs.sy) {
if (g.sstairs.up || !is_floater(mtmp->data))
} else if (stway && stway->tolev.dnum != u.uz.dnum) {
if (stway->up || !is_floater(mtmp->data))
g.m.has_defense = MUSE_SSTAIRS;
}
} else if (levl[x][y].typ == LADDER) {
if (x == xupladder && y == yupladder) {
stway = stairway_at(x,y);
if (stway && stway->up && stway->tolev.dnum == u.uz.dnum) {
g.m.has_defense = MUSE_UP_LADDER;
} else if (x == xdnladder && y == ydnladder) {
} else if (stway && !stway->up && stway->tolev.dnum == u.uz.dnum) {
if (!is_floater(mtmp->data))
g.m.has_defense = MUSE_DN_LADDER;
} else if (g.sstairs.sx && x == g.sstairs.sx && y == g.sstairs.sy) {
if (g.sstairs.up || !is_floater(mtmp->data))
} else if (stway && stway->tolev.dnum != u.uz.dnum) {
if (stway->up || !is_floater(mtmp->data))
g.m.has_defense = MUSE_SSTAIRS;
}
} else {
@@ -653,6 +656,7 @@ struct monst *mtmp;
struct obj *otmp = g.m.defensive;
boolean vis, vismon, oseen;
const char *Mnam;
stairway *stway;
if ((i = precheck(mtmp, otmp)) != 0)
return i;
@@ -770,8 +774,7 @@ struct monst *mtmp;
if (IS_FURNITURE(levl[mtmp->mx][mtmp->my].typ)
|| IS_DRAWBRIDGE(levl[mtmp->mx][mtmp->my].typ)
|| (is_drawbridge_wall(mtmp->mx, mtmp->my) >= 0)
|| (g.sstairs.sx && g.sstairs.sx == mtmp->mx
&& g.sstairs.sy == mtmp->my)) {
|| stairway_at(mtmp->mx, mtmp->my)) {
pline_The("digging ray is ineffective.");
return 2;
}
@@ -893,6 +896,9 @@ struct monst *mtmp;
return 2;
case MUSE_UPSTAIRS:
m_flee(mtmp);
stway = stairway_at(mtmp->mx, mtmp->my);
if (!stway)
return 0;
if (ledger_no(&u.uz) == 1)
goto escape; /* impossible; level 1 upstairs are SSTAIRS */
if (Inhell && mon_has_amulet(mtmp) && !rn2(4)
@@ -910,33 +916,45 @@ struct monst *mtmp;
} else {
if (vismon)
pline("%s escapes upstairs!", Monnam(mtmp));
migrate_to_level(mtmp, ledger_no(&u.uz) - 1, MIGR_STAIRS_DOWN,
migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_STAIRS_DOWN,
(coord *) 0);
}
return 2;
case MUSE_DOWNSTAIRS:
m_flee(mtmp);
stway = stairway_at(mtmp->mx, mtmp->my);
if (!stway)
return 0;
if (vismon)
pline("%s escapes downstairs!", Monnam(mtmp));
migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_STAIRS_UP,
migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_STAIRS_UP,
(coord *) 0);
return 2;
case MUSE_UP_LADDER:
m_flee(mtmp);
stway = stairway_at(mtmp->mx, mtmp->my);
if (!stway)
return 0;
if (vismon)
pline("%s escapes up the ladder!", Monnam(mtmp));
migrate_to_level(mtmp, ledger_no(&u.uz) - 1, MIGR_LADDER_DOWN,
migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_LADDER_DOWN,
(coord *) 0);
return 2;
case MUSE_DN_LADDER:
m_flee(mtmp);
stway = stairway_at(mtmp->mx, mtmp->my);
if (!stway)
return 0;
if (vismon)
pline("%s escapes down the ladder!", Monnam(mtmp));
migrate_to_level(mtmp, ledger_no(&u.uz) + 1, MIGR_LADDER_UP,
migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_LADDER_UP,
(coord *) 0);
return 2;
case MUSE_SSTAIRS:
m_flee(mtmp);
stway = stairway_at(mtmp->mx, mtmp->my);
if (!stway)
return 0;
if (ledger_no(&u.uz) == 1) {
escape:
/* Monsters without the Amulet escape the dungeon and
@@ -959,12 +977,12 @@ struct monst *mtmp;
}
if (vismon)
pline("%s escapes %sstairs!", Monnam(mtmp),
g.sstairs.up ? "up" : "down");
stway->up ? "up" : "down");
/* going from the Valley to Castle (Stronghold) has no sstairs
to target, but having g.sstairs.<sx,sy> == <0,0> will work the
same as specifying MIGR_RANDOM when mon_arrive() eventually
places the monster, so we can use MIGR_SSTAIRS unconditionally */
migrate_to_level(mtmp, ledger_no(&g.sstairs.tolev), MIGR_SSTAIRS,
migrate_to_level(mtmp, ledger_no(&(stway->tolev)), MIGR_SSTAIRS,
(coord *) 0);
return 2;
case MUSE_TELEPORT_TRAP:
@@ -1223,11 +1241,7 @@ struct monst *mtmp;
&& !Teleport_control
/* do try to move hero to a more vulnerable spot */
&& (onscary(u.ux, u.uy, mtmp)
|| (u.ux == xupstair && u.uy == yupstair)
|| (u.ux == xdnstair && u.uy == ydnstair)
|| (u.ux == g.sstairs.sx && u.uy == g.sstairs.sy)
|| (u.ux == xupladder && u.uy == yupladder)
|| (u.ux == xdnladder && u.uy == ydnladder))) {
|| (stairway_at(u.ux, u.uy))) {
g.m.offensive = obj;
g.m.has_offense = MUSE_WAN_TELEPORTATION;
}
+1 -3
View File
@@ -1051,9 +1051,7 @@ register struct obj *otmp;
HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
if (BLevitation) {
; /* rising via levitation is blocked */
} else if ((u.ux == xupstair && u.uy == yupstair)
|| (g.sstairs.up && u.ux == g.sstairs.sx && u.uy == g.sstairs.sy)
|| (xupladder && u.ux == xupladder && u.uy == yupladder)) {
} else if (stairway_find_dir(TRUE)) {
(void) doup();
/* in case we're already Levitating, which would have
resulted in incrementing 'nothing' */
+51 -10
View File
@@ -905,6 +905,33 @@ NHFILE *nhfp;
return 1;
}
void
rest_stairs(nhfp)
NHFILE *nhfp;
{
int buflen = 0;
stairway stway;
int len = 0;
stairway_free_all();
while (1) {
if (nhfp->structlevel) {
len += sizeof(buflen);
mread(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
if (buflen == -1)
break;
if (nhfp->structlevel) {
len += sizeof(stairway);
mread(nhfp->fd, (genericptr_t) &stway, sizeof(stairway));
}
stairway_add(stway.sx, stway.sy, stway.up, stway.isladder, &(stway.tolev));
}
}
void
restcemetery(nhfp, cemeteryaddr)
NHFILE *nhfp;
@@ -1050,11 +1077,7 @@ xchar lev;
elapsed = g.monstermoves - g.omoves;
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t)&g.upstair, sizeof(stairway));
mread(nhfp->fd, (genericptr_t)&g.dnstair, sizeof(stairway));
mread(nhfp->fd, (genericptr_t)&g.upladder, sizeof(stairway));
mread(nhfp->fd, (genericptr_t)&g.dnladder, sizeof(stairway));
mread(nhfp->fd, (genericptr_t)&g.sstairs, sizeof(stairway));
rest_stairs(nhfp);
mread(nhfp->fd, (genericptr_t)&g.updest, sizeof(dest_area));
mread(nhfp->fd, (genericptr_t)&g.dndest, sizeof(dest_area));
mread(nhfp->fd, (genericptr_t)&g.level.flags, sizeof(g.level.flags));
@@ -1132,22 +1155,33 @@ xchar lev;
rest_regions(nhfp);
if (ghostly) {
stairway *stway = g.stairs;
while (stway) {
if (!stway->isladder && !stway->up && stway->tolev.dnum == u.uz.dnum)
break;
stway = stway->next;
}
/* Now get rid of all the temp fruits... */
freefruitchn(g.oldfruit), g.oldfruit = 0;
if (lev > ledger_no(&medusa_level)
&& lev < ledger_no(&stronghold_level) && xdnstair == 0) {
&& lev < ledger_no(&stronghold_level) && !stway) {
coord cc;
d_level dest;
dest.dnum = u.uz.dnum;
dest.dlevel = u.uz.dlevel + 1;
mazexy(&cc);
xdnstair = cc.x;
ydnstair = cc.y;
stairway_add(cc.x, cc.y, FALSE, FALSE, &dest);
levl[cc.x][cc.y].typ = STAIRS;
}
br = Is_branchlev(&u.uz);
if (br && u.uz.dlevel == 1) {
d_level ltmp;
stairway *stway;
if (on_level(&u.uz, &br->end1))
assign_level(&ltmp, &br->end2);
@@ -1157,8 +1191,15 @@ xchar lev;
switch (br->type) {
case BR_STAIR:
case BR_NO_END1:
case BR_NO_END2: /* OK to assign to g.sstairs if it's not used */
assign_level(&g.sstairs.tolev, &ltmp);
case BR_NO_END2:
stway = g.stairs;
while (stway) {
if (stway->tolev.dnum != u.uz.dnum)
break;
stway = stway->next;
}
if (stway)
assign_level(&(stway->tolev), &ltmp);
break;
case BR_PORTAL: /* max of 1 portal per level */
for (trap = g.ftrap; trap; trap = trap->ntrap)
+31 -5
View File
@@ -28,6 +28,7 @@ static void FDECL(savedamage, (NHFILE *));
static void FDECL(saveobj, (NHFILE *,struct obj *));
static void FDECL(savemon, (NHFILE *,struct monst *));
static void FDECL(savelevl, (NHFILE *,BOOLEAN_P));
static void FDECL(save_stairs, (NHFILE *));
static void FDECL(saveobjchn, (NHFILE *,struct obj *));
static void FDECL(savemonchn, (NHFILE *,struct monst *));
static void FDECL(savetrapchn, (NHFILE *,struct trap *));
@@ -457,11 +458,7 @@ xchar lev;
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) g.lastseentyp, sizeof g.lastseentyp);
bwrite(nhfp->fd, (genericptr_t) &g.monstermoves, sizeof g.monstermoves);
bwrite(nhfp->fd, (genericptr_t) &g.upstair, sizeof (stairway));
bwrite(nhfp->fd, (genericptr_t) &g.dnstair, sizeof (stairway));
bwrite(nhfp->fd, (genericptr_t) &g.upladder, sizeof (stairway));
bwrite(nhfp->fd, (genericptr_t) &g.dnladder, sizeof (stairway));
bwrite(nhfp->fd, (genericptr_t) &g.sstairs, sizeof (stairway));
save_stairs(nhfp);
bwrite(nhfp->fd, (genericptr_t) &g.updest, sizeof (dest_area));
bwrite(nhfp->fd, (genericptr_t) &g.dndest, sizeof (dest_area));
bwrite(nhfp->fd, (genericptr_t) &g.level.flags, sizeof g.level.flags);
@@ -496,6 +493,7 @@ xchar lev;
fobj = 0;
g.level.buriedobjlist = 0;
g.billobjs = 0;
stairway_free_all();
/* level.bonesinfo = 0; -- handled by savecemetery() */
}
save_engravings(nhfp);
@@ -668,6 +666,34 @@ struct obj *otmp;
}
}
static void
save_stairs(nhfp)
NHFILE *nhfp;
{
stairway *stway = g.stairs;
int buflen = (int) sizeof (stairway);
int len = 0;
while (stway) {
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
len += sizeof(buflen);
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
len += sizeof(stairway);
bwrite(nhfp->fd, (genericptr_t) stway, sizeof(stairway));
}
}
stway = stway->next;
}
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
buflen = -1;
len += sizeof(buflen);
bwrite(nhfp->fd, (genericptr_t) &buflen, sizeof buflen);
}
}
}
static void
saveobjchn(nhfp, otmp)
NHFILE *nhfp;
+9 -2
View File
@@ -362,6 +362,13 @@ register boolean nearshop;
{
coord mm;
stairway *stway = g.stairs;
while (stway) {
if (!stway->isladder && !stway->up && stway->tolev.dnum == u.uz.dnum)
break;
stway = stway->next;
}
if (nearshop) {
/* Create swarm around you, if you merely "stepped out" */
@@ -375,8 +382,8 @@ register boolean nearshop;
if (flags.verbose)
pline_The("Keystone Kops are after you!");
/* Create swarm near down staircase (hinders return to level) */
mm.x = xdnstair;
mm.y = ydnstair;
mm.x = stway->sx;
mm.y = stway->sy;
makekops(&mm);
/* Create swarm near shopkeeper (hinders return to shop) */
mm.x = shkp->mx;
+22 -83
View File
@@ -60,7 +60,6 @@ static void FDECL(create_object, (object *, struct mkroom *));
static void FDECL(create_altar, (altar *, struct mkroom *));
static boolean FDECL(search_door, (struct mkroom *,
xchar *, xchar *, XCHAR_P, int));
static void NDECL(fix_stair_rooms);
static void FDECL(create_corridor, (corridor *));
static struct mkroom *FDECL(build_room, (room *, struct mkroom *));
static void FDECL(light_region, (region *));
@@ -500,6 +499,7 @@ boolean extras;
struct mkroom *sroom;
timer_element *timer;
boolean ball_active = FALSE, ball_fliparea = FALSE;
stairway *stway;
/* nothing to do unless (flp & 1) or (flp & 2) or both */
if ((flp & 3) == 0)
@@ -537,29 +537,11 @@ boolean extras;
}
/* stairs and ladders */
if (flp & 1) {
if (xupstair)
yupstair = FlipY(yupstair);
if (xdnstair)
ydnstair = FlipY(ydnstair);
if (xupladder)
yupladder = FlipY(yupladder);
if (xdnladder)
ydnladder = FlipY(ydnladder);
if (g.sstairs.sx)
g.sstairs.sy = FlipY(g.sstairs.sy);
}
if (flp & 2) {
if (xupstair)
xupstair = FlipX(xupstair);
if (xdnstair)
xdnstair = FlipX(xdnstair);
if (xupladder)
xupladder = FlipX(xupladder);
if (xdnladder)
xdnladder = FlipX(xdnladder);
if (g.sstairs.sx)
g.sstairs.sx = FlipX(g.sstairs.sx);
for (stway = g.stairs; stway; stway = stway->next) {
if (flp & 1)
stway->sy = FlipY(stway->sy);
if (flp & 2)
stway->sx = FlipX(stway->sx);
}
/* traps */
@@ -2564,52 +2546,6 @@ schar ftyp, btyp;
return TRUE;
}
/*
* Disgusting hack: since special levels have their rooms filled before
* sorting the rooms, we have to re-arrange the speed values g.upstairs_room
* and g.dnstairs_room after the rooms have been sorted. On normal levels,
* stairs don't get created until _after_ sorting takes place.
*/
static void
fix_stair_rooms()
{
int i;
struct mkroom *croom;
if (xdnstair
&& !((g.dnstairs_room->lx <= xdnstair
&& xdnstair <= g.dnstairs_room->hx)
&& (g.dnstairs_room->ly <= ydnstair
&& ydnstair <= g.dnstairs_room->hy))) {
for (i = 0; i < g.nroom; i++) {
croom = &g.rooms[i];
if ((croom->lx <= xdnstair && xdnstair <= croom->hx)
&& (croom->ly <= ydnstair && ydnstair <= croom->hy)) {
g.dnstairs_room = croom;
break;
}
}
if (i == g.nroom)
panic("Couldn't find dnstair room in fix_stair_rooms!");
}
if (xupstair
&& !((g.upstairs_room->lx <= xupstair
&& xupstair <= g.upstairs_room->hx)
&& (g.upstairs_room->ly <= yupstair
&& yupstair <= g.upstairs_room->hy))) {
for (i = 0; i < g.nroom; i++) {
croom = &g.rooms[i];
if ((croom->lx <= xupstair && xupstair <= croom->hx)
&& (croom->ly <= yupstair && yupstair <= croom->hy)) {
g.upstairs_room = croom;
break;
}
}
if (i == g.nroom)
panic("Couldn't find upstair room in fix_stair_rooms!");
}
}
/*
* Corridors always start from a door. But it can end anywhere...
* Basically we search for door coordinates or for endpoints coordinates
@@ -2622,7 +2558,6 @@ corridor *c;
coord org, dest;
if (c->src.room == -1) {
fix_stair_rooms();
makecorridors(); /*makecorridors(c->src.door);*/
return;
}
@@ -3933,12 +3868,18 @@ boolean using_ladder;
if (using_ladder) {
levl[x][y].typ = LADDER;
if (up) {
xupladder = x;
yupladder = y;
d_level dest;
dest.dnum = u.uz.dnum;
dest.dlevel = u.uz.dlevel - 1;
stairway_add(x, y, TRUE, TRUE, &dest);
levl[x][y].ladder = LA_UP;
} else {
xdnladder = x;
ydnladder = y;
d_level dest;
dest.dnum = u.uz.dnum;
dest.dlevel = u.uz.dlevel + 1;
stairway_add(x, y, FALSE, TRUE, &dest);
levl[x][y].ladder = LA_DOWN;
}
} else {
@@ -5334,17 +5275,15 @@ ensure_way_out()
struct trap *ttmp = g.ftrap;
int x,y;
boolean ret = TRUE;
stairway *stway = g.stairs;
set_selection_floodfillchk(floodfillchk_match_accessible);
if (xupstair && !selection_getpoint(xupstair, yupstair, ov))
selection_floodfill(ov, xupstair, yupstair, TRUE);
if (xdnstair && !selection_getpoint(xdnstair, ydnstair, ov))
selection_floodfill(ov, xdnstair, ydnstair, TRUE);
if (xupladder && !selection_getpoint(xupladder, yupladder, ov))
selection_floodfill(ov, xupladder, yupladder, TRUE);
if (xdnladder && !selection_getpoint(xdnladder, ydnladder, ov))
selection_floodfill(ov, xdnladder, ydnladder, TRUE);
while (stway) {
if (stway->tolev.dnum == u.uz.dnum)
selection_floodfill(ov, stway->sx, stway->sy, TRUE);
stway = stway->next;
}
while (ttmp) {
if ((ttmp->ttyp == MAGIC_PORTAL || ttmp->ttyp == VIBRATING_SQUARE
+25 -6
View File
@@ -1260,6 +1260,17 @@ register int x, y;
make_angry_shk(mtmp, oldx, oldy);
}
static stairway *
stairway_find_forwiz(ladder, up)
boolean ladder, up;
{
stairway *stway = g.stairs;
while (stway && !(stway->isladder == ladder && stway->up == up && stway->tolev.dnum == u.uz.dnum))
stway = stway->next;
return stway;
}
/* place a monster at a random location, typically due to teleport */
/* return TRUE if successful, FALSE if not */
boolean
@@ -1268,6 +1279,7 @@ struct monst *mtmp; /* mx==0 implies migrating monster arrival */
boolean suppress_impossible;
{
register int x, y, trycount;
stairway *stway;
if (mtmp == u.usteed) {
tele();
@@ -1275,12 +1287,19 @@ boolean suppress_impossible;
}
if (mtmp->iswiz && mtmp->mx) { /* Wizard, not just arriving */
if (!In_W_tower(u.ux, u.uy, &u.uz))
x = xupstair, y = yupstair;
else if (!xdnladder) /* bottom level of tower */
x = xupladder, y = yupladder;
else
x = xdnladder, y = ydnladder;
if (!In_W_tower(u.ux, u.uy, &u.uz)) {
stway = stairway_find_forwiz(FALSE, TRUE);
x = stway->sx;
y = stway->sy;
} else if (!stairway_find_forwiz(TRUE, FALSE)) { /* bottom level of tower */
stway = stairway_find_forwiz(TRUE, TRUE);
x = stway->sx;
y = stway->sy;
} else {
stway = stairway_find_forwiz(TRUE, FALSE);
x = stway->sx;
y = stway->sy;
}
/* if the wiz teleports away to heal, try the up staircase,
to block the player's escaping before he's healed
(deliberately use `goodpos' rather than `rloc_pos_ok' here) */
+15 -19
View File
@@ -329,30 +329,26 @@ xchar *sx;
xchar *sy;
{
xchar x = 0, y = 0;
stairway *stway = g.stairs;
boolean stdir = !builds_up(&u.uz);
if (builds_up(&u.uz)) {
if (xdnstair) {
x = xdnstair;
y = ydnstair;
} else if (xdnladder) {
x = xdnladder;
y = ydnladder;
}
if ((stway = stairway_find_type_dir(FALSE, stdir)) != 0) {
x = stway->sx;
y = stway->sy;
} else if ((stway = stairway_find_type_dir(TRUE, stdir)) != 0) {
x = stway->sx;
y = stway->sy;
} else {
if (xupstair) {
x = xupstair;
y = yupstair;
} else if (xupladder) {
x = xupladder;
y = yupladder;
while (stway) {
if (stway->tolev.dnum != u.uz.dnum) {
x = stway->sx;
y = stway->sy;
break;
}
stway = stway->next;
}
}
if (!x && g.sstairs.sx) {
x = g.sstairs.sx;
y = g.sstairs.sy;
}
if (x && y) {
*sx = x;
*sy = y;
+7 -1
View File
@@ -2891,6 +2891,7 @@ struct obj *obj; /* wand or spell */
struct engr *e;
struct trap *ttmp;
char buf[BUFSZ];
stairway *stway = g.stairs;
/* some wands have special effects other than normal bhitpile */
/* drawbridge might change <u.ux,u.uy> */
@@ -2913,11 +2914,16 @@ struct obj *obj; /* wand or spell */
return TRUE; /* we've done our own bhitpile */
case WAN_OPENING:
case SPE_KNOCK:
while (stway) {
if (!stway->isladder && !stway->up && stway->tolev.dnum == u.uz.dnum)
break;
stway = stway->next;
}
/* up or down, but at closed portcullis only */
if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
open_drawbridge(xx, yy);
disclose = TRUE;
} else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
} else if (u.dz > 0 && stway && stway->sx == x && stway->sy == y
/* can't use the stairs down to quest level 2 until
leader "unlocks" them; give feedback if you try */
&& on_level(&u.uz, &qstart_level) && !ok_to_quest()) {