Fix crash in linkexit()

This commit is contained in:
rob 2022-08-27 22:50:13 +10:00
parent 81c033d7dc
commit b2bfca3ca1
4 changed files with 1618 additions and 285 deletions

6
lf.c
View File

@ -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++;
} }

1605
log.txt Normal file

File diff suppressed because it is too large Load Diff

286
map.c
View File

@ -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) {

View File

@ -1604,8 +1604,10 @@ char getpctletter(float num, float max) {
int init(void) { int init(void) {
int i; int i;
long l;
// random numbers // random numbers
srand(time(NULL)); l = time(NULL);
srand(l);
//sranddev(); //sranddev();
// preset conditions // preset conditions