Fix crash in linkexit()
This commit is contained in:
parent
81c033d7dc
commit
b2bfca3ca1
6
lf.c
6
lf.c
|
@ -4508,7 +4508,7 @@ int genalignmentlist(flagpile_t *fp, char *buf) {
|
||||||
|
|
||||||
// for each G, N, E
|
// for each G, N, E
|
||||||
for (n = 0; n < 3; n++ ) {
|
for (n = 0; n < 3; n++ ) {
|
||||||
char candidate;
|
char candidate = '\0';
|
||||||
candidate = allaligns[n];
|
candidate = allaligns[n];
|
||||||
|
|
||||||
// does it match all flags?
|
// does it match all flags?
|
||||||
|
@ -4523,7 +4523,7 @@ int genalignmentlist(flagpile_t *fp, char *buf) {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
case AL_NONE:
|
case AL_NONE:
|
||||||
strcpy(this, retflag[i]->text);
|
strncpy(this, retflag[i]->text, BUFLEN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4539,7 +4539,7 @@ int genalignmentlist(flagpile_t *fp, char *buf) {
|
||||||
if (!strchr(localposs, candidate)) { // not already in list?
|
if (!strchr(localposs, candidate)) { // not already in list?
|
||||||
char letter[2];
|
char letter[2];
|
||||||
// this one is okay.
|
// this one is okay.
|
||||||
snprintf(letter, 1, "%c", candidate);
|
snprintf(letter, 2, "%c", candidate);
|
||||||
strcat(localposs, letter);
|
strcat(localposs, letter);
|
||||||
nposs++;
|
nposs++;
|
||||||
}
|
}
|
||||||
|
|
288
map.c
288
map.c
|
@ -4652,7 +4652,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
|
||||||
int nthings = 0,failed,nstairslinked = 0;
|
int nthings = 0,failed,nstairslinked = 0;
|
||||||
int nprevaults = 0;
|
int nprevaults = 0;
|
||||||
int db = B_TRUE;
|
int db = B_TRUE;
|
||||||
char dbtag[BUFLEN],dbbuf[BUFLEN];
|
char dbtag[BUFLEN],dbbuf[BIGBUFLEN];
|
||||||
|
|
||||||
snprintf(dbtag, BUFLEN, "[createmap.c]");
|
snprintf(dbtag, BUFLEN, "[createmap.c]");
|
||||||
|
|
||||||
|
@ -4819,7 +4819,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
|
||||||
snprintf(buf, BUFLEN, "%s (id #%d)",buf2, map->id);
|
snprintf(buf, BUFLEN, "%s (id #%d)",buf2, map->id);
|
||||||
map->name = strdup(buf);
|
map->name = strdup(buf);
|
||||||
|
|
||||||
snprintf(dbbuf, BUFLEN, "%s -about to check outline",dbtag);
|
snprintf(dbbuf, BIGBUFLEN, "%s -about to check outline",dbtag);
|
||||||
dblog(dbbuf);
|
dblog(dbbuf);
|
||||||
|
|
||||||
// get a list of what things are here based on the region's outline
|
// get a list of what things are here based on the region's outline
|
||||||
|
@ -6019,7 +6019,7 @@ void killregion(region_t *r) {
|
||||||
// if 'wantfilled' is set, only link to "filled" cells.
|
// if 'wantfilled' is set, only link to "filled" cells.
|
||||||
// return TRUE on failure.
|
// return TRUE on failure.
|
||||||
int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
||||||
int db = B_FALSE;
|
int db = B_TRUE;
|
||||||
int d, roomid,startd,endd;
|
int d, roomid,startd,endd;
|
||||||
int poss2[MAXCANDIDATES],nposs2;
|
int poss2[MAXCANDIDATES],nposs2;
|
||||||
int dist[MAXDIR_ORTH],hitsedge[MAXDIR_ORTH], sameroom[MAXDIR_ORTH];
|
int dist[MAXDIR_ORTH],hitsedge[MAXDIR_ORTH], sameroom[MAXDIR_ORTH];
|
||||||
|
@ -6030,6 +6030,8 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
||||||
int forcedir = D_NONE;
|
int forcedir = D_NONE;
|
||||||
|
|
||||||
if (ncellsadded) *ncellsadded = 0;
|
if (ncellsadded) *ncellsadded = 0;
|
||||||
|
node_t open[MAX_PATHFIND_ADJ];
|
||||||
|
node_t closed[MAX_PATHFIND_ADJ];
|
||||||
|
|
||||||
roomid = getroomid(startcell);
|
roomid = getroomid(startcell);
|
||||||
if (db) dblog(" calling linkexit() for cell at %d,%d in roomid %d", startcell->x, startcell->y, roomid);
|
if (db) dblog(" calling linkexit() for cell at %d,%d in roomid %d", startcell->x, startcell->y, roomid);
|
||||||
|
@ -6114,279 +6116,6 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mindist == 999) {
|
if (mindist == 999) {
|
||||||
/*
|
|
||||||
cell_t *turncell = NULL,*endcell = NULL;
|
|
||||||
cell_t *perpcell[MAX_MAPW*MAX_MAPH];
|
|
||||||
cell_t *perpturncell1[MAX_MAPW*MAX_MAPH];
|
|
||||||
int perpturndir1[MAX_MAPW*MAX_MAPH];
|
|
||||||
int nperpcells = 0;
|
|
||||||
int perpdir[2];
|
|
||||||
int startdir = D_NONE;
|
|
||||||
int turndir = D_NONE;
|
|
||||||
int startdist = 0;
|
|
||||||
int maxdist2 = -1;
|
|
||||||
int startposs[MAXDIR_ORTH];
|
|
||||||
int nstartposs = 0;
|
|
||||||
// no good directions.
|
|
||||||
if (db) dblog(" No directions lead to valid cells. Trying turns.");
|
|
||||||
|
|
||||||
|
|
||||||
if (forcedir != D_NONE) {
|
|
||||||
startdir = forcedir;
|
|
||||||
} else {
|
|
||||||
// starting at the LONGEST distance, traverse up each dir,
|
|
||||||
// branching off looking for rooms.
|
|
||||||
|
|
||||||
// if start cell is inside a room, find longest distance which
|
|
||||||
// doesn't go through the same room
|
|
||||||
if (db) dblog(" Selecting startdir to find turns.");
|
|
||||||
for (d = D_N; d <= D_W; d++) {
|
|
||||||
if (baddir[d]) {
|
|
||||||
if (db) dblog(" %s bad (baddir is set)", getdirname(d));
|
|
||||||
} else if (isroom(startcell)) {
|
|
||||||
if (!sameroom[d] && (dist[d] > maxdist2)) {
|
|
||||||
if (db) dblog(" %s ok (diff room and %d is best distance so far)",
|
|
||||||
getdirname(d), dist[d]);
|
|
||||||
maxdist2 = dist[d];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (db) dblog(" %s ok (start not room and %d is best distance so far)",
|
|
||||||
getdirname(d), dist[d]);
|
|
||||||
maxdist2 = dist[d];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// pick one randomly
|
|
||||||
for (d = D_N; d <= D_W; d++) {
|
|
||||||
if ((dist[d] == maxdist2) && !baddir[d]) {
|
|
||||||
startposs[nstartposs++] = d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (db) dblog(" %d possibilities found (maxdist2=%d).",nstartposs,maxdist2);
|
|
||||||
if (nstartposs) {
|
|
||||||
startdir = startposs[rnd(0,nstartposs-1)];
|
|
||||||
if (db) dblog(" Selected %s.",getdirname(startdir));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//assert((startdir >= D_N) && (startdir <= D_W));
|
|
||||||
if ((startdir < D_N) || (startdir > D_W)) {
|
|
||||||
// couldn't find any valid start dirs!
|
|
||||||
if (db) dblog(" Cannot find a valid startdir.");
|
|
||||||
return B_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// figure out perpendicular dirs
|
|
||||||
perpdir[0] = startdir - 1; if (perpdir[0] < D_N) perpdir[0] = D_W;
|
|
||||||
perpdir[1] = startdir + 1; if (perpdir[1] > D_W) perpdir[1] = D_N;
|
|
||||||
|
|
||||||
assert(perpdir[0] != startdir);
|
|
||||||
assert(perpdir[1] != startdir);
|
|
||||||
|
|
||||||
if (db) dblog(" Will walk %s (dist %d), checking %s and %s.", getdirname(startdir), maxdist,
|
|
||||||
getdirname(perpdir[0]), getdirname(perpdir[1]));
|
|
||||||
|
|
||||||
// check in startdir
|
|
||||||
c = getcellindir(startcell, startdir);
|
|
||||||
while (c && !turncell) {
|
|
||||||
int n;
|
|
||||||
cell_t *c2;
|
|
||||||
startdist++;
|
|
||||||
// don't bother checking left/right if this cell isn't okay to be cleared.
|
|
||||||
if (cellokforreachability(startcell, c, roomid, d, wantfilled, NULL)) {
|
|
||||||
// check left/right from this cell for rooms
|
|
||||||
for (n = 0; n <= 1; n++) {
|
|
||||||
int turndist = 0;
|
|
||||||
|
|
||||||
if (db) {
|
|
||||||
dblog("Travelling %s, checking %s from %d,%d.", getdirname(startdir),
|
|
||||||
getdirname(perpdir[n]), c->x, c->y);
|
|
||||||
}
|
|
||||||
c2 = getcellindir(c, perpdir[n]);
|
|
||||||
|
|
||||||
while (c2) {
|
|
||||||
int gotsolution = B_FALSE;
|
|
||||||
int rv;
|
|
||||||
turndist++;
|
|
||||||
|
|
||||||
assert((n >= 0) && (n <= 1));
|
|
||||||
perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns
|
|
||||||
perpturncell1[nperpcells] = c;
|
|
||||||
perpturndir1[nperpcells] = perpdir[n];
|
|
||||||
nperpcells++;
|
|
||||||
|
|
||||||
if (db) {
|
|
||||||
dblog_nocr("(%d,%d)",c2->x, c2->y);
|
|
||||||
}
|
|
||||||
rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL);
|
|
||||||
|
|
||||||
if (rv == B_FALSE) {
|
|
||||||
break;
|
|
||||||
} else if (rv == B_TRUE) {
|
|
||||||
gotsolution = B_TRUE;
|
|
||||||
} else if (turndist > 1) {
|
|
||||||
// check l/r too
|
|
||||||
int perpdir2[2],nn;
|
|
||||||
cell_t *pcell = NULL;
|
|
||||||
perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W;
|
|
||||||
perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N;
|
|
||||||
for (nn = 0; nn <= 1; nn++) {
|
|
||||||
pcell = getcellindir(c2, perpdir2[nn]);
|
|
||||||
if (pcell && adjcellokforreachability(pcell, roomid, perpdir2[nn], wantfilled)) {
|
|
||||||
// finished.
|
|
||||||
if (db) dblog(" Got to an empty cell next to us.");
|
|
||||||
gotsolution = B_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gotsolution) {
|
|
||||||
if (db) dblog(" Solution found: Walk %d %s, then %d %s.",
|
|
||||||
startdist, getdirname(startdir),
|
|
||||||
turndist, getdirname(perpdir[n]));
|
|
||||||
// walkable and not in this roomid. ok!
|
|
||||||
turncell = c;
|
|
||||||
endcell = c2;
|
|
||||||
turndir = perpdir[n];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check next cell
|
|
||||||
c2 = getcellindir(c2, perpdir[n]);
|
|
||||||
}
|
|
||||||
if (turncell) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// now keep going in main direction.
|
|
||||||
c = getcellindir(c, startdir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (turncell) {
|
|
||||||
// make a path up to the turn point.
|
|
||||||
if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir));
|
|
||||||
c = getcellindir(startcell, startdir);
|
|
||||||
while (c != turncell) {
|
|
||||||
breakwall(c, "turnset=1, making path from vault %d to corner", getroomid(startcell));
|
|
||||||
if (ncellsadded) (*ncellsadded)++;
|
|
||||||
c = getcellindir(c, startdir);
|
|
||||||
}
|
|
||||||
// clear the corner cell
|
|
||||||
breakwall(c, "turncell=1, this is the corner (from vault %d)",getroomid(startcell));
|
|
||||||
if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir));
|
|
||||||
// now turn and clear up to the next room/empty cell
|
|
||||||
c = getcellindir(c, turndir);
|
|
||||||
while (c != endcell) {
|
|
||||||
breakwall(c, "turncell=1, clearing from corner to end (from vault %d)", getroomid(startcell));
|
|
||||||
if (ncellsadded) (*ncellsadded)++;
|
|
||||||
c = getcellindir(c, turndir);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// We need to make 2 turns.
|
|
||||||
// for each perpcell[], look in startdir + diropposite(startdir)
|
|
||||||
int dir3[2],i,n;
|
|
||||||
cell_t *turncell2 = NULL;
|
|
||||||
int turndir2;
|
|
||||||
dir3[0] = startdir;
|
|
||||||
dir3[1] = diropposite(startdir);
|
|
||||||
if (db) dblog(" Need to make two turns. Searching %s and %s from each perpcell.", getdirname(dir3[0]),
|
|
||||||
getdirname(dir3[1]));
|
|
||||||
for (i = 0; i < nperpcells; i++) {
|
|
||||||
for (n = 0; n < 2; n++) {
|
|
||||||
cell_t *c2;
|
|
||||||
int turndist = 0;
|
|
||||||
|
|
||||||
if (db) dblog_nocr("looking %s from %d,%d: ", getdirname(dir3[n]),
|
|
||||||
perpcell[i]->x, perpcell[i]->y);
|
|
||||||
|
|
||||||
c2 = getcellindir(perpcell[i], dir3[n]);
|
|
||||||
while (c2) {
|
|
||||||
int gotsolution = B_FALSE;
|
|
||||||
int rv;
|
|
||||||
turndist++;
|
|
||||||
if (db) dblog_nocr("(%d,%d)",c2->x,c2->y);
|
|
||||||
|
|
||||||
rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL);
|
|
||||||
|
|
||||||
if (rv == B_FALSE) {
|
|
||||||
break;
|
|
||||||
} else if (rv == B_TRUE) {
|
|
||||||
gotsolution = B_TRUE;
|
|
||||||
} else if (turndist > 1) {
|
|
||||||
// check l/r too
|
|
||||||
int perpdir2[2],nn;
|
|
||||||
cell_t *pcell = NULL;
|
|
||||||
perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W;
|
|
||||||
perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N;
|
|
||||||
for (nn = 0; nn <= 1; nn++) {
|
|
||||||
pcell = getcellindir(c2, perpdir2[nn]);
|
|
||||||
if (pcell && adjcellokforreachability(pcell, roomid, perpdir2[nn], wantfilled)) {
|
|
||||||
// finished.
|
|
||||||
if (db) dblog(" Got to an empty cell next to us.");
|
|
||||||
gotsolution = B_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (gotsolution) {
|
|
||||||
turncell = perpturncell1[i];
|
|
||||||
turndir = perpturndir1[i];
|
|
||||||
turncell2 = perpcell[i];
|
|
||||||
turndir2 = dir3[n];
|
|
||||||
|
|
||||||
endcell = c2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check next cell
|
|
||||||
c2 = getcellindir(c2, dir3[n]);
|
|
||||||
} // end while c2
|
|
||||||
if (turncell2) break;
|
|
||||||
|
|
||||||
if (db) dblog("");
|
|
||||||
} // end for n=1-2
|
|
||||||
if (turncell2) break;
|
|
||||||
} // end foreach perpcell
|
|
||||||
|
|
||||||
// if we find a solution, fill in turncell2 and make path.
|
|
||||||
if (turncell2) {
|
|
||||||
if (db) dblog(" Twoturn solution found: Walk %s, then %s, then %s.",
|
|
||||||
getdirname(startdir), getdirname(turndir), getdirname(turndir2));
|
|
||||||
|
|
||||||
// make a path up to the turn point.
|
|
||||||
if (db) dblog(" Making path from vault to first corner, initdir=%s", getdirname(startdir));
|
|
||||||
c = getcellindir(startcell, startdir);
|
|
||||||
while (c != turncell) {
|
|
||||||
breakwall(c, "twoturn: path from vault %d to first corner 1", getroomid(startcell));
|
|
||||||
if (ncellsadded) (*ncellsadded)++;
|
|
||||||
c = getcellindir(c, startdir);
|
|
||||||
}
|
|
||||||
// clear the corner cell
|
|
||||||
breakwall(c, "twoturn: corner 1 (from vault %d)", getroomid(startcell));
|
|
||||||
// now turn and clear up to the next turn
|
|
||||||
if (db) dblog(" Making path from 1st corner to 2nd corner, turndir=%s", getdirname(turndir));
|
|
||||||
c = getcellindir(c, turndir);
|
|
||||||
while (c != turncell2) {
|
|
||||||
breakwall(c, "twoturn: path from 1st corner to 2nd corner (from vault %d)", getroomid(startcell));
|
|
||||||
if (ncellsadded) (*ncellsadded)++;
|
|
||||||
c = getcellindir(c, turndir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now turn and clear up to the next room/empty cell
|
|
||||||
if (db) dblog(" Making path from 2nd corner to rest of map, turndir=%s", getdirname(turndir2));
|
|
||||||
c = getcellindir(c, turndir2);
|
|
||||||
while (c != endcell) {
|
|
||||||
breakwall(c, "twoturn: path from 2nd corner to end (from vault %d)", getroomid(startcell));
|
|
||||||
if (ncellsadded) (*ncellsadded)++;
|
|
||||||
c = getcellindir(c, turndir2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (db) dblog(" Cannot find a way to link up.");
|
|
||||||
// debugging - a failure here during fix_reachability is fatal.
|
|
||||||
//if (wantfilled) {
|
|
||||||
// assert(0 == 1);
|
|
||||||
//}
|
|
||||||
return B_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int roomidx[MAXROOMS];
|
int roomidx[MAXROOMS];
|
||||||
cell_t *midcell[MAXROOMS];
|
cell_t *midcell[MAXROOMS];
|
||||||
int donesomething,a,i,foundpath;
|
int donesomething,a,i,foundpath;
|
||||||
|
@ -6437,8 +6166,6 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
||||||
for (a = 0 ; (a < m->nrooms) && !foundpath; a++) {
|
for (a = 0 ; (a < m->nrooms) && !foundpath; a++) {
|
||||||
int destroomid;
|
int destroomid;
|
||||||
int done = B_FALSE,i,n;
|
int done = B_FALSE,i,n;
|
||||||
node_t open[MAX_PATHFIND_ADJ];
|
|
||||||
node_t closed[MAX_PATHFIND_ADJ];
|
|
||||||
node_t *cur;
|
node_t *cur;
|
||||||
int nopen = 0,nclosed = 0;
|
int nopen = 0,nclosed = 0;
|
||||||
int okforreach;
|
int okforreach;
|
||||||
|
@ -6610,9 +6337,8 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
|
||||||
char reasontext[BUFLEN];
|
char reasontext[BUFLEN];
|
||||||
// work backwards from node[cur] (ie. targcell) following parents.
|
// work backwards from node[cur] (ie. targcell) following parents.
|
||||||
// populate path and return
|
// populate path and return
|
||||||
if (db) dblog("linkexit() - found path!\n");
|
snprintf(reasontext, BUFLEN, "astar pathfind link (from roomid %d)",roomid);
|
||||||
|
|
||||||
sprintf(reasontext, "astar pathfind link (from roomid %d)",roomid);
|
|
||||||
while (solnode) {
|
while (solnode) {
|
||||||
pathlen++;
|
pathlen++;
|
||||||
if (pathlen >= MAX_PATHFIND_STEPS) {
|
if (pathlen >= MAX_PATHFIND_STEPS) {
|
||||||
|
|
Loading…
Reference in New Issue