fountain and sink bookkeeping
This replaces most of commit 0ca2af4d8b
from a couple of days ago with something more robust. That change
actually introduced redundant code that caused fountain and/or sink
count to be off instead of preventing it.
Revise set_levltyp() to update level.flags.nfountains and
level.flags.nsinks if setting the type to or from fountain or sink.
A bunch of places that were setting levl[x][y].typ directly needed
to be revised to use set_levltyp() instead. set_levltyp() itself
hadn't been updated to handle LAVAWALL (to force such to be lit).
This commit is contained in:
@@ -1399,6 +1399,7 @@ extern void add_subroom(struct mkroom *, int, int, int, int, boolean, schar,
|
||||
extern void free_luathemes(boolean);
|
||||
extern void makecorridors(void);
|
||||
extern void add_door(coordxy, coordxy, struct mkroom *);
|
||||
extern void count_level_features(void);
|
||||
extern void clear_level_structures(void);
|
||||
extern void level_finalize_topology(void);
|
||||
extern void mklev(void);
|
||||
|
||||
@@ -96,6 +96,7 @@ enum levl_typ_types {
|
||||
#define ZAP_POS(typ) ((typ) >= POOL)
|
||||
#define SPACE_POS(typ) ((typ) > DOOR)
|
||||
#define IS_POOL(typ) ((typ) >= POOL && (typ) <= DRAWBRIDGE_UP)
|
||||
#define IS_LAVA(typ) ((typ) == LAVAPOOL || (typ) == LAVAWALL)
|
||||
#define IS_THRONE(typ) ((typ) == THRONE)
|
||||
#define IS_FOUNTAIN(typ) ((typ) == FOUNTAIN)
|
||||
#define IS_SINK(typ) ((typ) == SINK)
|
||||
|
||||
60
src/do.c
60
src/do.c
@@ -363,27 +363,26 @@ polymorph_sink(void)
|
||||
return;
|
||||
|
||||
sinklooted = levl[u.ux][u.uy].looted != 0;
|
||||
gl.level.flags.nsinks--;
|
||||
levl[u.ux][u.uy].doormask = 0; /* levl[][].flags */
|
||||
/* gl.level.flags.nsinks--; // set_levltyp() will update this */
|
||||
levl[u.ux][u.uy].flags = 0;
|
||||
switch (rn2(4)) {
|
||||
default:
|
||||
case 0:
|
||||
sym = S_fountain;
|
||||
levl[u.ux][u.uy].typ = FOUNTAIN;
|
||||
set_levltyp(u.ux, u.uy, FOUNTAIN); /* updates level.flags.nfountains */
|
||||
levl[u.ux][u.uy].blessedftn = 0;
|
||||
if (sinklooted)
|
||||
SET_FOUNTAIN_LOOTED(u.ux, u.uy);
|
||||
gl.level.flags.nfountains++;
|
||||
break;
|
||||
case 1:
|
||||
sym = S_throne;
|
||||
levl[u.ux][u.uy].typ = THRONE;
|
||||
set_levltyp(u.ux, u.uy, THRONE);
|
||||
if (sinklooted)
|
||||
levl[u.ux][u.uy].looted = T_LOOTED;
|
||||
break;
|
||||
case 2:
|
||||
sym = S_altar;
|
||||
levl[u.ux][u.uy].typ = ALTAR;
|
||||
set_levltyp(u.ux, u.uy, ALTAR);
|
||||
/* 3.6.3: this used to pass 'rn2(A_LAWFUL + 2) - 1' to
|
||||
Align2amask() but that evaluates its argument more than once */
|
||||
algn = rn2(3) - 1; /* -1 (A_Cha) or 0 (A_Neu) or +1 (A_Law) */
|
||||
@@ -392,7 +391,7 @@ polymorph_sink(void)
|
||||
break;
|
||||
case 3:
|
||||
sym = S_room;
|
||||
levl[u.ux][u.uy].typ = ROOM;
|
||||
set_levltyp(u.ux, u.uy, ROOM);
|
||||
make_grave(u.ux, u.uy, (char *) 0);
|
||||
if (levl[u.ux][u.uy].typ == GRAVE)
|
||||
sym = S_grave;
|
||||
@@ -413,29 +412,36 @@ static boolean
|
||||
teleport_sink(void)
|
||||
{
|
||||
coordxy cx, cy;
|
||||
int cnt = 0;
|
||||
struct trap *trp;
|
||||
struct engr *eng;
|
||||
unsigned alreadylooted;
|
||||
int trycnt = 0;
|
||||
|
||||
do {
|
||||
cx = rnd(COLNO - 1);
|
||||
cy = rn2(ROWNO);
|
||||
trp = t_at(cx, cy);
|
||||
eng = engr_at(cx, cy);
|
||||
} while ((levl[cx][cy].typ != ROOM || trp || eng || cansee(cx, cy))
|
||||
&& cnt++ < 200);
|
||||
#if 0 /* this isn't incorrect but it is extremely unlikely that spots
|
||||
* on the level's edge will be ROOM so picking such wastes tries */
|
||||
cx = rnd(COLNO - 1); /* 1..COLNO-1 */
|
||||
cy = rn2(ROWNO); /* 0..ROWNO-1 */
|
||||
#else /* use this instead */
|
||||
cx = 1 + rnd((COLNO - 1) - 2); /* 2..COLNO-2 */
|
||||
cy = 1 + rn2(ROWNO - 2); /* 1..ROWNO-2 */
|
||||
#endif
|
||||
if (levl[cx][cy].typ == ROOM
|
||||
&& !t_at(cx, cy) && !engr_at(cx, cy)
|
||||
&& (!cansee(cx, cy) || distu(cx, cy) > 3 * 3)) {
|
||||
/* this ends up having set_levltyp() count all sinks and
|
||||
fountains on the level twice but that is not a problem */
|
||||
alreadylooted = levl[u.ux][u.uy].looted;
|
||||
/* remove old sink */
|
||||
set_levltyp(u.ux, u.uy, ROOM); /* was SINK so updates nsinks */
|
||||
levl[u.ux][u.uy].looted = 0;
|
||||
newsym(u.ux, u.uy);
|
||||
/* create sink at new position */
|
||||
set_levltyp(cx, cy, SINK); /* now SINK so also updates nsinks */
|
||||
levl[cx][cy].looted = alreadylooted ? 1 : 0;
|
||||
newsym(cx, cy);
|
||||
return TRUE;
|
||||
}
|
||||
} while (++trycnt < 200);
|
||||
|
||||
if (levl[cx][cy].typ == ROOM && !trp && !eng) {
|
||||
/* create sink at new position */
|
||||
levl[cx][cy].typ = SINK;
|
||||
levl[cx][cy].looted = levl[u.ux][u.uy].looted;
|
||||
newsym(cx, cy);
|
||||
/* remove old sink */
|
||||
levl[u.ux][u.uy].typ = ROOM;
|
||||
levl[u.ux][u.uy].looted = 0;
|
||||
newsym(u.ux, u.uy);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,8 @@ gush(coordxy x, coordxy y, genericptr_t poolcnt)
|
||||
pline("Water gushes forth from the overflowing fountain!");
|
||||
|
||||
/* Put a pool at x, y */
|
||||
levl[x][y].typ = POOL, levl[x][y].flags = 0;
|
||||
set_levltyp(x, y, POOL);
|
||||
levl[x][y].flags = 0;
|
||||
/* No kelp! */
|
||||
del_engr_at(x, y);
|
||||
water_damage_chain(gl.level.objects[x][y], TRUE);
|
||||
@@ -226,9 +227,9 @@ dryup(coordxy x, coordxy y, boolean isyou)
|
||||
pline_The("fountain dries up!");
|
||||
}
|
||||
/* replace the fountain with ordinary floor */
|
||||
levl[x][y].typ = ROOM, levl[x][y].flags = 0;
|
||||
set_levltyp(x, y, ROOM); /* updates level.flags.nfountains */
|
||||
levl[x][y].flags = 0;
|
||||
levl[x][y].blessedftn = 0;
|
||||
gl.level.flags.nfountains--;
|
||||
/* The location is seen if the hero/monster is invisible
|
||||
or felt if the hero is blind. */
|
||||
newsym(x, y);
|
||||
@@ -430,9 +431,9 @@ dipfountain(register struct obj *obj)
|
||||
artiname(ART_EXCALIBUR), lady);
|
||||
}
|
||||
update_inventory();
|
||||
levl[u.ux][u.uy].typ = ROOM, levl[u.ux][u.uy].flags = 0;
|
||||
set_levltyp(u.ux, u.uy, ROOM); /* updates level.flags.nfountains */
|
||||
levl[u.ux][u.uy].flags = 0;
|
||||
newsym(u.ux, u.uy);
|
||||
gl.level.flags.nfountains--;
|
||||
if (in_town(u.ux, u.uy))
|
||||
(void) angry_guards(FALSE);
|
||||
return;
|
||||
@@ -543,11 +544,11 @@ breaksink(coordxy x, coordxy y)
|
||||
{
|
||||
if (cansee(x, y) || u_at(x, y))
|
||||
pline_The("pipes break! Water spurts out!");
|
||||
gl.level.flags.nsinks--;
|
||||
levl[x][y].typ = FOUNTAIN, levl[x][y].looted = 0;
|
||||
/* updates level.flags.nsinks and level.flags.nfountains */
|
||||
set_levltyp(x, y, FOUNTAIN);
|
||||
levl[x][y].looted = 0;
|
||||
levl[x][y].blessedftn = 0;
|
||||
SET_FOUNTAIN_LOOTED(x, y);
|
||||
gl.level.flags.nfountains++;
|
||||
newsym(x, y);
|
||||
}
|
||||
|
||||
|
||||
29
src/mklev.c
29
src/mklev.c
@@ -26,7 +26,7 @@ static void mktrap_victim(struct trap *);
|
||||
static struct mkroom *find_branch_room(coord *);
|
||||
static struct mkroom *pos_to_room(coordxy, coordxy);
|
||||
static boolean cardinal_nextto_room(struct mkroom *, coordxy, coordxy);
|
||||
static boolean place_niche(struct mkroom *, coordxy *, coordxy *, coordxy *);
|
||||
static boolean place_niche(struct mkroom *, int *, coordxy *, coordxy *);
|
||||
static void makeniche(int);
|
||||
static void make_niches(void);
|
||||
static int QSORTCALLBACK mkroom_cmp(const genericptr, const genericptr);
|
||||
@@ -599,7 +599,10 @@ cardinal_nextto_room(struct mkroom *aroom, coordxy x, coordxy y)
|
||||
}
|
||||
|
||||
static boolean
|
||||
place_niche(register struct mkroom *aroom, coordxy *dy, coordxy *xx, coordxy *yy)
|
||||
place_niche(
|
||||
struct mkroom *aroom,
|
||||
int *dy,
|
||||
coordxy *xx, coordxy *yy)
|
||||
{
|
||||
coord dd;
|
||||
|
||||
@@ -639,8 +642,8 @@ makeniche(int trap_type)
|
||||
{
|
||||
register struct mkroom *aroom;
|
||||
struct rm *rm;
|
||||
int vct = 8;
|
||||
coordxy dy, xx, yy;
|
||||
int dy, vct = 8;
|
||||
coordxy xx, yy;
|
||||
struct trap *ttmp;
|
||||
|
||||
while (vct--) {
|
||||
@@ -721,6 +724,24 @@ makevtele(void)
|
||||
makeniche(TELEP_TRAP);
|
||||
}
|
||||
|
||||
/* count the different features (sinks, fountains) in the level */
|
||||
void
|
||||
count_level_features(void)
|
||||
{
|
||||
coordxy x, y;
|
||||
|
||||
gl.level.flags.nfountains = gl.level.flags.nsinks = 0;
|
||||
for (y = 0; y < ROWNO; y++)
|
||||
for (x = 0; x < COLNO; x++) {
|
||||
int typ = levl[x][y].typ;
|
||||
|
||||
if (typ == FOUNTAIN)
|
||||
gl.level.flags.nfountains++;
|
||||
else if (typ == SINK)
|
||||
gl.level.flags.nsinks++;
|
||||
}
|
||||
}
|
||||
|
||||
/* clear out various globals that keep information on the current level.
|
||||
* some of this is only necessary for some types of levels (maze, normal,
|
||||
* special) but it's easier to put it all in one place than make sure
|
||||
|
||||
37
src/mkmaze.c
37
src/mkmaze.c
@@ -69,24 +69,36 @@ is_solid(coordxy x, coordxy y)
|
||||
|
||||
/* set map terrain type, handling lava lit, ice melt timers, etc */
|
||||
boolean
|
||||
set_levltyp(coordxy x, coordxy y, schar typ)
|
||||
set_levltyp(coordxy x, coordxy y, schar newtyp)
|
||||
{
|
||||
if (isok(x, y)) {
|
||||
if ((typ < MAX_TYPE) && CAN_OVERWRITE_TERRAIN(levl[x][y].typ)) {
|
||||
if (isok(x, y) && newtyp >= STONE && newtyp < MAX_TYPE) {
|
||||
if (CAN_OVERWRITE_TERRAIN(levl[x][y].typ)) {
|
||||
schar oldtyp = levl[x][y].typ;
|
||||
boolean was_ice = (levl[x][y].typ == ICE);
|
||||
|
||||
levl[x][y].typ = typ;
|
||||
levl[x][y].typ = newtyp;
|
||||
/* TODO?
|
||||
* if oldtyp used flags or horizontal differently from
|
||||
* from the way newtyp will use them, clear them.
|
||||
*/
|
||||
|
||||
if (typ == LAVAPOOL)
|
||||
if (IS_LAVA(newtyp))
|
||||
levl[x][y].lit = 1;
|
||||
|
||||
if (was_ice && typ != ICE)
|
||||
if (was_ice && newtyp != ICE)
|
||||
spot_stop_timers(x, y, MELT_ICE_AWAY);
|
||||
if ((IS_FOUNTAIN(oldtyp) != IS_FOUNTAIN(newtyp))
|
||||
|| (IS_SINK(oldtyp) != IS_SINK(newtyp)))
|
||||
count_level_features(); /* level.flags.nfountains,nsinks */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#ifdef EXTRA_SANITY_CHECKS
|
||||
} else {
|
||||
impossible("set_levltyp(%i,%i,%i) !isok", x, y, typ);
|
||||
impossible("set_levltyp(%d,%d,%d)%s%s",
|
||||
(int) x, (int) y, (int) newtyp,
|
||||
!isok(x, y) ? " not isok()" : "",
|
||||
(newtyp < STONE || newtyp >= MAX_TYPE) ? " bad type" : "");
|
||||
#endif /*EXTRA_SANITY_CHECKS*/
|
||||
}
|
||||
return FALSE;
|
||||
@@ -99,14 +111,17 @@ set_levltyp_lit(coordxy x, coordxy y, schar typ, schar lit)
|
||||
boolean ret = set_levltyp(x, y, typ);
|
||||
|
||||
if (ret && isok(x, y)) {
|
||||
/* LAVAPOOL handled in set_levltyp */
|
||||
if ((typ != LAVAPOOL) && (lit != SET_LIT_NOCHANGE)) {
|
||||
if (lit != SET_LIT_NOCHANGE) {
|
||||
#ifdef EXTRA_SANITY_CHECKS
|
||||
if (lit < SET_LIT_NOCHANGE || lit > 1)
|
||||
impossible("set_levltyp_lit(%i,%i,%i,%i)", x, y, typ, lit);
|
||||
impossible("set_levltyp_lit(%d,%d,%d,%d)",
|
||||
(int) x, (int) y, (int) typ, (int) lit);
|
||||
#endif /*EXTRA_SANITY_CHECKS*/
|
||||
if (lit == SET_LIT_RANDOM)
|
||||
if (IS_LAVA(typ))
|
||||
lit = 1;
|
||||
else if (lit == SET_LIT_RANDOM)
|
||||
lit = rn2(2);
|
||||
|
||||
levl[x][y].lit = lit;
|
||||
}
|
||||
}
|
||||
|
||||
16
src/objnam.c
16
src/objnam.c
@@ -3485,11 +3485,6 @@ wizterrainwish(struct _readobjnam_data *d)
|
||||
if (madeterrain) {
|
||||
feel_newsym(x, y); /* map the spot where the wish occurred */
|
||||
|
||||
if (oldtyp == FOUNTAIN && lev->typ != FOUNTAIN)
|
||||
gl.level.flags.nfountains--;
|
||||
else if (oldtyp == SINK && lev->typ != SINK)
|
||||
gl.level.flags.nsinks--;
|
||||
|
||||
/* hero started at <x,y> but might not be there anymore (create
|
||||
lava, decline to die, and get teleported away to safety) */
|
||||
if (u.uinwater && !is_pool(u.ux, u.uy)) {
|
||||
@@ -3509,14 +3504,9 @@ wizterrainwish(struct _readobjnam_data *d)
|
||||
}
|
||||
}
|
||||
|
||||
/* fixups for replaced terrain that aren't handled above;
|
||||
for fountain placed on fountain or sink placed on sink, the
|
||||
increment above gets canceled out by the decrement here;
|
||||
otherwise if fountain or sink was replaced, there's one less */
|
||||
if (IS_FOUNTAIN(oldtyp))
|
||||
gl.level.flags.nfountains--;
|
||||
else if (IS_SINK(oldtyp))
|
||||
gl.level.flags.nsinks--;
|
||||
/* fixups for replaced terrain that aren't handled above */
|
||||
if (IS_FOUNTAIN(oldtyp) || IS_SINK(oldtyp))
|
||||
count_level_features(); /* update level.flags.nfountains,nsinks */
|
||||
/* horizontal is overlaid by fountain->blessedftn, grave->disturbed */
|
||||
if (IS_FOUNTAIN(oldtyp) || IS_GRAVE(oldtyp)
|
||||
|| IS_WALL(oldtyp) || oldtyp == IRONBARS
|
||||
|
||||
24
src/sp_lev.c
24
src/sp_lev.c
@@ -32,7 +32,6 @@ static void flip_vault_guard(int, struct monst *,
|
||||
coordxy, coordxy, coordxy, coordxy);
|
||||
static void sel_set_wall_property(coordxy, coordxy, genericptr_t);
|
||||
static void set_wall_property(coordxy, coordxy, coordxy, coordxy, int);
|
||||
static void count_features(void);
|
||||
static void remove_boundary_syms(void);
|
||||
static void set_door_orientation(int, int);
|
||||
static boolean shared_with_room(int, int, struct mkroom *);
|
||||
@@ -989,25 +988,6 @@ set_wall_property(coordxy x1, coordxy y1, coordxy x2, coordxy y2, int prop)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the different features (sinks, fountains) in the level.
|
||||
*/
|
||||
static void
|
||||
count_features(void)
|
||||
{
|
||||
coordxy x, y;
|
||||
|
||||
gl.level.flags.nfountains = gl.level.flags.nsinks = 0;
|
||||
for (y = 0; y < ROWNO; y++)
|
||||
for (x = 0; x < COLNO; x++) {
|
||||
int typ = levl[x][y].typ;
|
||||
if (typ == FOUNTAIN)
|
||||
gl.level.flags.nfountains++;
|
||||
else if (typ == SINK)
|
||||
gl.level.flags.nsinks++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_boundary_syms(void)
|
||||
{
|
||||
@@ -6559,7 +6539,7 @@ lspo_finalize_level(lua_State *L UNUSED)
|
||||
if (L)
|
||||
flip_level_rnd(gc.coder->allow_flips, FALSE);
|
||||
|
||||
count_features();
|
||||
count_level_features();
|
||||
|
||||
if (L && gc.coder->solidify)
|
||||
solidify_map();
|
||||
@@ -7016,7 +6996,7 @@ load_special(const char *name)
|
||||
|
||||
flip_level_rnd(gc.coder->allow_flips, FALSE);
|
||||
|
||||
count_features();
|
||||
count_level_features();
|
||||
|
||||
if (gc.coder->solidify)
|
||||
solidify_map();
|
||||
|
||||
Reference in New Issue
Block a user