Rewrite flood_water to use CoordStack and fix stack overflow, fixes #646
This commit is contained in:
parent
d61db0fd63
commit
2e154e5ff9
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#define FLAG_STAGNANT 0x1
|
#define FLAG_STAGNANT 0x1
|
||||||
#define FLAG_SKIPMOVE 0x2 // skip movement for one frame, only implemented for PHOT
|
#define FLAG_SKIPMOVE 0x2 // skip movement for one frame, only implemented for PHOT
|
||||||
#define FLAG_WATEREQUAL 0x4 //if a liquid was already checked during equalization
|
//#define FLAG_WATEREQUAL 0x4 //if a liquid was already checked during equalization
|
||||||
#define FLAG_MOVABLE 0x8 // compatibility with old saves (moving SPNG), only applies to SPNG
|
#define FLAG_MOVABLE 0x8 // compatibility with old saves (moving SPNG), only applies to SPNG
|
||||||
#define FLAG_PHOTDECO 0x8 // compatibility with old saves (decorated photons), only applies to PHOT. Having the same value as FLAG_MOVABLE is fine because they apply to different elements, and this saves space for future flags,
|
#define FLAG_PHOTDECO 0x8 // compatibility with old saves (decorated photons), only applies to PHOT. Having the same value as FLAG_MOVABLE is fine because they apply to different elements, and this saves space for future flags,
|
||||||
|
|
||||||
|
@ -866,63 +866,70 @@ int Simulation::FloodINST(int x, int y, int fullc, int cm)
|
|||||||
return created_something;
|
return created_something;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Simulation::flood_water(int x, int y, int i, int originaly, int check)
|
bool Simulation::flood_water(int x, int y, int i)
|
||||||
{
|
{
|
||||||
int x1 = 0,x2 = 0;
|
int x1, x2, originalY = y;
|
||||||
// go left as far as possible
|
int r = pmap[y][x];
|
||||||
x1 = x2 = x;
|
if (!r)
|
||||||
if (!pmap[y][x])
|
return false;
|
||||||
return 1;
|
|
||||||
|
|
||||||
while (x1>=CELL)
|
// Bitmap for checking where we've already looked
|
||||||
|
auto bitmapPtr = std::unique_ptr<char[]>(new char[XRES * YRES]);
|
||||||
|
char *bitmap = bitmapPtr.get();
|
||||||
|
std::fill(&bitmap[0], &bitmap[XRES * YRES], 0);
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
if ((elements[TYP(pmap[y][x1-1])].Falldown) != 2)
|
CoordStack cs;
|
||||||
|
cs.push(x, y);
|
||||||
|
do
|
||||||
{
|
{
|
||||||
|
cs.pop(x, y);
|
||||||
|
x1 = x2 = x;
|
||||||
|
while (x1 >= CELL)
|
||||||
|
{
|
||||||
|
if (elements[TYP(pmap[y][x1 - 1])].Falldown != 2 || bitmap[(y * XRES) + x1 - 1])
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
x1--;
|
x1--;
|
||||||
}
|
}
|
||||||
while (x2<XRES-CELL)
|
while (x2 < XRES-CELL)
|
||||||
{
|
|
||||||
if ((elements[TYP(pmap[y][x2+1])].Falldown) != 2)
|
|
||||||
{
|
{
|
||||||
|
if (elements[TYP(pmap[y][x2 + 1])].Falldown != 2 || bitmap[(y * XRES) + x1 - 1])
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
x2++;
|
x2++;
|
||||||
}
|
}
|
||||||
|
for (int x = x1; x <= x2; x++)
|
||||||
// fill span
|
|
||||||
for (x=x1; x<=x2; x++)
|
|
||||||
{
|
{
|
||||||
if (check)
|
// Check above, maybe around other sides too?
|
||||||
parts[ID(pmap[y][x])].flags &= ~FLAG_WATEREQUAL;//flag it as checked (different from the original particle's checked flag)
|
if (((y - 1) > originalY) && !pmap[y - 1][x] && eval_move(parts[i].type, x, y - 1, nullptr))
|
||||||
else
|
|
||||||
parts[ID(pmap[y][x])].flags |= FLAG_WATEREQUAL;
|
|
||||||
//check above, maybe around other sides too?
|
|
||||||
if ( ((y-1) > originaly) && !pmap[y-1][x] && eval_move(parts[i].type, x, y-1, NULL))
|
|
||||||
{
|
{
|
||||||
int oldx = (int)(parts[i].x + 0.5f);
|
int oldx = (int)(parts[i].x + 0.5f);
|
||||||
int oldy = (int)(parts[i].y + 0.5f);
|
int oldy = (int)(parts[i].y + 0.5f);
|
||||||
pmap[y-1][x] = pmap[oldy][oldx];
|
pmap[y - 1][x] = pmap[oldy][oldx];
|
||||||
pmap[oldy][oldx] = 0;
|
pmap[oldy][oldx] = 0;
|
||||||
parts[i].x = x;
|
parts[i].x = x;
|
||||||
parts[i].y = y-1;
|
parts[i].y = y - 1;
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// fill children
|
|
||||||
|
|
||||||
if (y>=CELL+1)
|
bitmap[(y * XRES) + x] = 1;
|
||||||
for (x=x1; x<=x2; x++)
|
}
|
||||||
if ((elements[TYP(pmap[y-1][x])].Falldown)==2 && (parts[ID(pmap[y-1][x])].flags & FLAG_WATEREQUAL) == check)
|
if (y >= CELL + 1)
|
||||||
if (!flood_water(x, y-1, i, originaly, check))
|
for (int x = x1; x <= x2; x++)
|
||||||
return 0;
|
if (elements[TYP(pmap[y - 1][x])].Falldown == 2 && !bitmap[((y - 1) * XRES) + x])
|
||||||
if (y<YRES-CELL-1)
|
cs.push(x, y - 1);
|
||||||
for (x=x1; x<=x2; x++)
|
if (y < YRES - CELL - 1)
|
||||||
if ((elements[TYP(pmap[y+1][x])].Falldown)==2 && (parts[ID(pmap[y+1][x])].flags & FLAG_WATEREQUAL) == check)
|
for (int x = x1; x <= x2; x++)
|
||||||
if (!flood_water(x, y+1, i, originaly, check))
|
if (elements[TYP(pmap[y + 1][x])].Falldown == 2 && !bitmap[((y + 1) * XRES) + x])
|
||||||
return 0;
|
cs.push(x, y + 1);
|
||||||
return 1;
|
} while (cs.getSize() > 0);
|
||||||
|
}
|
||||||
|
catch (std::exception &e)
|
||||||
|
{
|
||||||
|
std::cerr << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Simulation::SetEdgeMode(int newEdgeMode)
|
void Simulation::SetEdgeMode(int newEdgeMode)
|
||||||
@ -4651,7 +4658,7 @@ killed:
|
|||||||
// Checking stagnant is cool, but then it doesn't update when you change it later.
|
// Checking stagnant is cool, but then it doesn't update when you change it later.
|
||||||
if (water_equal_test && elements[t].Falldown == 2 && RNG::Ref().chance(1, 200))
|
if (water_equal_test && elements[t].Falldown == 2 && RNG::Ref().chance(1, 200))
|
||||||
{
|
{
|
||||||
if (!flood_water(x,y,i,y, parts[i].flags&FLAG_WATEREQUAL))
|
if (!flood_water(x, y, i))
|
||||||
goto movedone;
|
goto movedone;
|
||||||
}
|
}
|
||||||
// liquids and powders
|
// liquids and powders
|
||||||
|
@ -142,7 +142,7 @@ public:
|
|||||||
void kill_part(int i);
|
void kill_part(int i);
|
||||||
bool FloodFillPmapCheck(int x, int y, int type);
|
bool FloodFillPmapCheck(int x, int y, int type);
|
||||||
int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype);
|
int flood_prop(int x, int y, size_t propoffset, PropertyValue propvalue, StructProperty::PropertyType proptype);
|
||||||
int flood_water(int x, int y, int i, int originaly, int check);
|
bool flood_water(int x, int y, int i);
|
||||||
int FloodINST(int x, int y, int fullc, int cm);
|
int FloodINST(int x, int y, int fullc, int cm);
|
||||||
void detach(int i);
|
void detach(int i);
|
||||||
bool part_change_type(int i, int x, int y, int t);
|
bool part_change_type(int i, int x, int y, int t);
|
||||||
|
Reference in New Issue
Block a user