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:
+1
-1
@@ -706,4 +706,4 @@ get rid of 3.6.1 workaround needed to retain compatibility with 3.6.0 bones
|
||||
add an additional note to mextra.h and obj.h comments that reminds people to
|
||||
appropriately init new fields if they need to initialize to something
|
||||
other than zero
|
||||
|
||||
rework stairs structure into a linked list
|
||||
|
||||
+1
-18
@@ -75,16 +75,6 @@ struct dgn_topology { /* special dungeon levels for speed */
|
||||
#define sokoend_level (g.dungeon_topology.d_sokoend_level)
|
||||
/* clang-format on */
|
||||
|
||||
#define xdnstair (g.dnstair.sx)
|
||||
#define ydnstair (g.dnstair.sy)
|
||||
#define xupstair (g.upstair.sx)
|
||||
#define yupstair (g.upstair.sy)
|
||||
|
||||
#define xdnladder (g.dnladder.sx)
|
||||
#define ydnladder (g.dnladder.sy)
|
||||
#define xupladder (g.upladder.sx)
|
||||
#define yupladder (g.upladder.sy)
|
||||
|
||||
#define dunlev_reached(x) (g.dungeons[(x)->dnum].dunlev_ureached)
|
||||
|
||||
#include "quest.h"
|
||||
@@ -726,10 +716,7 @@ struct instance_globals {
|
||||
int y_maze_max;
|
||||
int otg_temp; /* used by object_to_glyph() [otg] */
|
||||
int in_doagain;
|
||||
stairway dnstair; /* stairs down */
|
||||
stairway upstair; /* stairs up */
|
||||
stairway dnladder; /* ladder down */
|
||||
stairway upladder; /* ladder up */
|
||||
stairway *stairs;
|
||||
int smeq[MAXNROFROOMS + 1];
|
||||
int doorindex;
|
||||
char *save_cm;
|
||||
@@ -754,7 +741,6 @@ struct instance_globals {
|
||||
number of shots, index of current one, validity check, shoot vs throw */
|
||||
struct multishot m_shot;
|
||||
dungeon dungeons[MAXDUNGEON]; /* ini'ed by init_dungeon() */
|
||||
stairway sstairs;
|
||||
dest_area updest;
|
||||
dest_area dndest;
|
||||
coord inv_pos;
|
||||
@@ -765,9 +751,6 @@ struct instance_globals {
|
||||
boolean mrg_to_wielded; /* weapon picked is merged with wielded one */
|
||||
struct plinemsg_type *plinemsg_types;
|
||||
char toplines[TBUFSZ];
|
||||
struct mkroom *upstairs_room;
|
||||
struct mkroom *dnstairs_room;
|
||||
struct mkroom *sstairs_room;
|
||||
coord bhitpos; /* place where throw or zap hits or stops */
|
||||
boolean in_steed_dismounting;
|
||||
coord doors[DOORMAX];
|
||||
|
||||
+3
-1
@@ -34,7 +34,9 @@ typedef struct s_level { /* special dungeon level element */
|
||||
typedef struct stairway { /* basic stairway identifier */
|
||||
xchar sx, sy; /* x / y location of the stair */
|
||||
d_level tolev; /* where does it go */
|
||||
char up; /* what type of stairway (up/down) */
|
||||
boolean up; /* up or down? */
|
||||
boolean isladder; /* ladder or stairway? */
|
||||
struct stairway *next;
|
||||
} stairway;
|
||||
|
||||
/* level region types */
|
||||
|
||||
@@ -630,6 +630,15 @@ E void FDECL(next_level, (BOOLEAN_P));
|
||||
E void FDECL(prev_level, (BOOLEAN_P));
|
||||
E void FDECL(u_on_newpos, (int, int));
|
||||
E void FDECL(u_on_rndspot, (int));
|
||||
E void FDECL(stairway_add, (int,int, BOOLEAN_P, BOOLEAN_P, d_level *));
|
||||
E void NDECL(stairway_print);
|
||||
E void NDECL(stairway_free_all);
|
||||
E stairway *FDECL(stairway_at, (int, int));
|
||||
E stairway *FDECL(stairway_find, (d_level *));
|
||||
E stairway *FDECL(stairway_find_from, (d_level *, BOOLEAN_P));
|
||||
E stairway *FDECL(stairway_find_dir, (BOOLEAN_P));
|
||||
E stairway *FDECL(stairway_find_type_dir, (BOOLEAN_P, BOOLEAN_P));
|
||||
E stairway *FDECL(stairway_find_special_dir, (BOOLEAN_P));
|
||||
E void FDECL(u_on_sstairs, (int));
|
||||
E void NDECL(u_on_upstairs);
|
||||
E void NDECL(u_on_dnstairs);
|
||||
|
||||
@@ -82,6 +82,7 @@ struct monst {
|
||||
xchar mx, my;
|
||||
xchar mux, muy; /* where the monster thinks you are */
|
||||
#define MTSZ 4
|
||||
/* mtrack[0..2] is used to keep extra data when migrating the monster */
|
||||
coord mtrack[MTSZ]; /* monster track */
|
||||
int mhp, mhpmax;
|
||||
unsigned mappearance; /* for undetected mimics and the wiz */
|
||||
|
||||
@@ -122,6 +122,8 @@ struct obj {
|
||||
long age; /* creation date */
|
||||
long owornmask;
|
||||
unsigned lua_ref_cnt; /* # of lua script references for this object */
|
||||
xchar omigr_from_dnum; /* where obj is migrating from */
|
||||
xchar omigr_from_dlevel; /* where obj is migrating from */
|
||||
struct oextra *oextra; /* pointer to oextra struct */
|
||||
};
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 24
|
||||
#define EDITLEVEL 25
|
||||
|
||||
/*
|
||||
* Development status possibilities.
|
||||
|
||||
@@ -243,6 +243,8 @@ enum screen_symbols {
|
||||
#define is_cmap_furniture(i) ((i) >= S_upstair && (i) <= S_fountain)
|
||||
#define is_cmap_water(i) ((i) == S_pool || (i) == S_water)
|
||||
#define is_cmap_lava(i) ((i) == S_lava)
|
||||
#define is_cmap_stairs(i) ((i) == S_upstair || (i) == S_dnstair || \
|
||||
(i) == S_upladder || (i) == S_dnladder)
|
||||
|
||||
|
||||
struct symdef {
|
||||
|
||||
+12
-34
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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(<mp, &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, <mp);
|
||||
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), <mp);
|
||||
break;
|
||||
case BR_PORTAL: /* max of 1 portal per level */
|
||||
for (trap = g.ftrap; trap; trap = trap->ntrap)
|
||||
|
||||
+31
-5
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user