pull request #888 - latent shop creation bug
Pull request from copperwater: if a theme room produced a room with one door that effectively opened on a 'hallway' leading to the core of that room, it would be considered to be eligible to become a shop. But if the only spot available for the shopkeeper to move away from the spot in front of the door was another spot in the hallway, there would be no possibility to get out of the way, either to let someone in, or if the hero arrived by teleport or trap, to let hero out. | -- | ---..[rest |##+12..of the | ---..room] | -- Shopkeeper would move back and forth between 1 and 2, always blocking access between the door and the rest of the room. Currently no rooms get generated with that shape. I haven't tried to force one in order to verify the fix. Fixes #888
This commit is contained in:
79
src/mkroom.c
79
src/mkroom.c
@@ -27,6 +27,7 @@ static struct permonst *morguemon(void);
|
||||
static struct permonst *squadmon(void);
|
||||
static void save_room(NHFILE *, struct mkroom *);
|
||||
static void rest_room(NHFILE *, struct mkroom *);
|
||||
static boolean invalid_shop_shape(struct mkroom *sroom);
|
||||
|
||||
#define sq(x) ((x) * (x))
|
||||
|
||||
@@ -150,6 +151,10 @@ mkshop(void)
|
||||
|
||||
gottype:
|
||||
for (sroom = &g.rooms[0];; sroom++) {
|
||||
/* return from this loop: cannot find any eligible room to be a shop
|
||||
* continue: sroom is ineligible
|
||||
* break: sroom is eligible
|
||||
*/
|
||||
if (sroom->hx < 0)
|
||||
return;
|
||||
if (sroom - g.rooms >= g.nroom) {
|
||||
@@ -160,8 +165,12 @@ mkshop(void)
|
||||
continue;
|
||||
if (has_dnstairs(sroom) || has_upstairs(sroom))
|
||||
continue;
|
||||
if (sroom->doorct == 1 || (wizard && ep && sroom->doorct != 0))
|
||||
break;
|
||||
if (sroom->doorct == 1 || (wizard && ep && sroom->doorct != 0)) {
|
||||
if (invalid_shop_shape(sroom))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sroom->rlit) {
|
||||
coordxy x, y;
|
||||
@@ -1009,4 +1018,70 @@ cmap_to_type(int sym)
|
||||
return typ;
|
||||
}
|
||||
|
||||
/* With the introduction of themed rooms, there are certain room shapes that may
|
||||
* generate a door, the square just inside the door, and only one other ROOM
|
||||
* square touching that one. E.g.
|
||||
* ---
|
||||
* ---..
|
||||
* +....
|
||||
* ---..
|
||||
* ---
|
||||
* This means that if the room becomes a shop, the shopkeeper will move between
|
||||
* those two squares nearest the door without ever allowing the player to get
|
||||
* past them.
|
||||
* Before approving sroom as a shop, check for this circumstance, and if it
|
||||
* exists, don't consider it as valid for a shop.
|
||||
*
|
||||
* Note that the invalidity of the shape derives from the position of its door
|
||||
* already being chosen. It's quite possible that if the door were somewhere
|
||||
* else on the perimeter of this room, it would work fine as a shop.*/
|
||||
static boolean
|
||||
invalid_shop_shape(struct mkroom *sroom)
|
||||
{
|
||||
coordxy x, y;
|
||||
coordxy doorx = g.doors[sroom->fdoor].x;
|
||||
coordxy doory = g.doors[sroom->fdoor].y;
|
||||
coordxy insidex, insidey, insidect = 0;
|
||||
|
||||
/* First, identify squares inside the room and next to the door. */
|
||||
for (x = max(doorx - 1, sroom->lx);
|
||||
x <= min(doorx + 1, sroom->hx); x++) {
|
||||
for (y = max(doory - 1, sroom->ly);
|
||||
y <= min(doory + 1, sroom->hy); y++) {
|
||||
if (levl[x][y].typ == ROOM) {
|
||||
insidex = x;
|
||||
insidey = y;
|
||||
insidect++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (insidect < 1) {
|
||||
impossible("invalid_shop_shape: no squares inside door?");
|
||||
return TRUE;
|
||||
}
|
||||
/* if insidect > 1, then the shopkeeper already has alternate
|
||||
* squares to move to so we don't need to check further. */
|
||||
if (insidect == 1) {
|
||||
/* But if it is 1, scan all adjacent squares for other squares
|
||||
* that are part of this room. */
|
||||
insidect = 0;
|
||||
for (x = max(insidex - 1, sroom->lx);
|
||||
x <= min(insidex + 1, sroom->hx); x++) {
|
||||
for (y = max(insidey - 1, sroom->ly);
|
||||
y <= min(insidey + 1, sroom->hy); y++) {
|
||||
if (x == insidex && y == insidey)
|
||||
continue;
|
||||
if (levl[x][y].typ == ROOM)
|
||||
insidect++;
|
||||
}
|
||||
}
|
||||
if (insidect == 1) {
|
||||
/* shopkeeper standing just inside the door can only move
|
||||
* to one other square; this cannot be a shop. */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*mkroom.c*/
|
||||
|
||||
Reference in New Issue
Block a user