TPT: New flood_parts function, should fix crashing due to too much recursion a11202313d

This commit is contained in:
Simon Robertshaw
2012-06-12 18:41:36 +01:00
parent 10f51cb586
commit 391165409d

View File

@@ -345,11 +345,18 @@ Particle Simulation::Get(int x, int y)
return Particle(); return Particle();
} }
#define PMAP_CMP_CONDUCTIVE(pmap, t) (((pmap)&0xFF)==(t) || (((pmap)&0xFF)==PT_SPRK && parts[(pmap)>>8].ctype==(t)))
int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags) int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags)
{ {
int c = fullc&0xFF; int c = fullc&0xFF;
int x1, x2, dy = 1; int x1, x2, dy = (c<PT_NUM)?1:CELL;
int co = c; int co = c;
int coord_stack_limit = XRES*YRES;
unsigned short (*coord_stack)[2] = (short unsigned int (*)[2])malloc(sizeof(unsigned short)*2*coord_stack_limit);
int coord_stack_size = 0;
int created_something = 0;
if (c==SPC_PROP) if (c==SPC_PROP)
return 0; return 0;
if (cm==PT_INST&&co==PT_SPRK) if (cm==PT_INST&&co==PT_SPRK)
@@ -362,8 +369,6 @@ int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags)
cm = pmap[y][x]&0xFF; cm = pmap[y][x]&0xFF;
if (!cm) if (!cm)
return 0; return 0;
//if ((flags&BRUSH_REPLACEMODE) && cm!=SLALT)
// return 0;
} }
else else
cm = 0; cm = 0;
@@ -381,89 +386,150 @@ int Simulation::FloodParts(int x, int y, int fullc, int cm, int bm, int flags)
else else
bm = 0; bm = 0;
} }
if (((pmap[y][x]&0xFF)!=cm || bmap[y/CELL][x/CELL]!=bm )/*||( (flags&BRUSH_SPECIFIC_DELETE) && cm!=SLALT)*/) if (((pmap[y][x]&0xFF)!=cm || bmap[y/CELL][x/CELL]!=bm ))
return 1; return 1;
// go left as far as possible coord_stack[coord_stack_size][0] = x;
x1 = x2 = x; coord_stack[coord_stack_size][1] = y;
while (x1>=CELL) coord_stack_size++;
do
{ {
if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm) coord_stack_size--;
x = coord_stack[coord_stack_size][0];
y = coord_stack[coord_stack_size][1];
x1 = x2 = x;
// go left as far as possible
while (x1>=CELL)
{ {
break; if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm)
{
break;
}
x1--;
} }
x1--; // go right as far as possible
} while (x2<XRES-CELL)
while (x2<XRES-CELL)
{
if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm)
{ {
break; if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm)
{
break;
}
x2++;
} }
x2++; // fill span
} for (x=x1; x<=x2; x++)
{
// fill span if (cm==PT_INST&&co==PT_SPRK)
for (x=x1; x<=x2; x++) {
{ if (create_part(-1, x, y, fullc)>=0)
created_something = 1;
}
else
{
if (CreateParts(x, y, 0, 0, fullc, flags))
created_something = 1;
}
}
// add vertically adjacent pixels to stack
if (cm==PT_INST&&co==PT_SPRK) if (cm==PT_INST&&co==PT_SPRK)
{ {
if (create_part(-1,x, y, fullc)==-1) //wire crossing for INST
return 0; if (y>=CELL+1 && x1==x2 &&
PMAP_CMP_CONDUCTIVE(pmap[y-1][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-1][x1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-1][x1+1], PT_INST) &&
!PMAP_CMP_CONDUCTIVE(pmap[y-2][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y-2][x1], PT_INST) && !PMAP_CMP_CONDUCTIVE(pmap[y-2][x1+1], PT_INST))
{
// travelling vertically up, skipping a horizontal line
if ((pmap[y-2][x1]&0xFF)==PT_INST)
{
coord_stack[coord_stack_size][0] = x1;
coord_stack[coord_stack_size][1] = y-2;
coord_stack_size++;
if (coord_stack_size>=coord_stack_limit)
return -1;
}
}
else if (y>=CELL+1)
{
for (x=x1; x<=x2; x++)
{
if ((pmap[y-1][x]&0xFF)==PT_INST)
{
if (x==x1 || x==x2 || y>=YRES-CELL-1 || !PMAP_CMP_CONDUCTIVE(pmap[y+1][x], PT_INST))
{
// if at the end of a horizontal section, or if it's a T junction
coord_stack[coord_stack_size][0] = x;
coord_stack[coord_stack_size][1] = y-1;
coord_stack_size++;
if (coord_stack_size>=coord_stack_limit)
return -1;
}
}
}
}
if (y<YRES-CELL-1 && x1==x2 &&
PMAP_CMP_CONDUCTIVE(pmap[y+1][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+1][x1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+1][x1+1], PT_INST) &&
!PMAP_CMP_CONDUCTIVE(pmap[y+2][x1-1], PT_INST) && PMAP_CMP_CONDUCTIVE(pmap[y+2][x1], PT_INST) && !PMAP_CMP_CONDUCTIVE(pmap[y+2][x1+1], PT_INST))
{
// travelling vertically down, skipping a horizontal line
if ((pmap[y+2][x1]&0xFF)==PT_INST)
{
coord_stack[coord_stack_size][0] = x1;
coord_stack[coord_stack_size][1] = y+2;
coord_stack_size++;
if (coord_stack_size>=coord_stack_limit)
return -1;
}
}
else if (y<YRES-CELL-1)
{
for (x=x1; x<=x2; x++)
{
if ((pmap[y+1][x]&0xFF)==PT_INST)
{
if (x==x1 || x==x2 || y<0 || !PMAP_CMP_CONDUCTIVE(pmap[y-1][x], PT_INST))
{
// if at the end of a horizontal section, or if it's a T junction
coord_stack[coord_stack_size][0] = x;
coord_stack[coord_stack_size][1] = y+1;
coord_stack_size++;
if (coord_stack_size>=coord_stack_limit)
return -1;
}
}
}
}
} }
else if (!CreateParts(x, y, 0, 0, fullc, flags)) else
return 0; {
} if (y>=CELL+dy)
// fill children for (x=x1; x<=x2; x++)
if (cm==PT_INST&&co==PT_SPRK)//wire crossing for INST if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm)
{ {
if (y>=CELL+dy && x1==x2 && coord_stack[coord_stack_size][0] = x;
((pmap[y-1][x1-1]&0xFF)==PT_INST||(pmap[y-1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1]&0xFF)==PT_INST||(pmap[y-1][x1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1+1]&0xFF)==PT_INST || (pmap[y-1][x1+1]&0xFF)==PT_SPRK) && coord_stack[coord_stack_size][1] = y-dy;
(pmap[y-2][x1-1]&0xFF)!=PT_INST && ((pmap[y-2][x1]&0xFF)==PT_INST ||(pmap[y-2][x1]&0xFF)==PT_SPRK) && (pmap[y-2][x1+1]&0xFF)!=PT_INST) coord_stack_size++;
FloodParts(x1, y-2, fullc, cm, bm, flags); if (coord_stack_size>=coord_stack_limit)
else if (y>=CELL+dy) return -1;
for (x=x1; x<=x2; x++) }
if ((pmap[y-1][x]&0xFF)!=PT_SPRK) if (y<YRES-CELL-dy)
{ for (x=x1; x<=x2; x++)
if (x==x1 || x==x2 || y>=YRES-CELL-1 || if ((pmap[y+dy][x]&0xFF)==cm && bmap[(y+dy)/CELL][x/CELL]==bm)
(pmap[y-1][x-1]&0xFF)==PT_INST || (pmap[y-1][x+1]&0xFF)==PT_INST || {
(pmap[y+1][x-1]&0xFF)==PT_INST || ((pmap[y+1][x]&0xFF)!=PT_INST&&(pmap[y+1][x]&0xFF)!=PT_SPRK) || (pmap[y+1][x+1]&0xFF)==PT_INST) coord_stack[coord_stack_size][0] = x;
FloodParts(x, y-dy, fullc, cm, bm, flags); coord_stack[coord_stack_size][1] = y+dy;
coord_stack_size++;
} if (coord_stack_size>=coord_stack_limit)
return -1;
if (y<YRES-CELL-dy && x1==x2 && }
((pmap[y+1][x1-1]&0xFF)==PT_INST||(pmap[y+1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y+1][x1]&0xFF)==PT_INST||(pmap[y+1][x1]&0xFF)==PT_SPRK) && ((pmap[y+1][x1+1]&0xFF)==PT_INST || (pmap[y+1][x1+1]&0xFF)==PT_SPRK) && }
(pmap[y+2][x1-1]&0xFF)!=PT_INST && ((pmap[y+2][x1]&0xFF)==PT_INST ||(pmap[y+2][x1]&0xFF)==PT_SPRK) && (pmap[y+2][x1+1]&0xFF)!=PT_INST) } while (coord_stack_size>0);
FloodParts(x1, y+2, fullc, cm, bm, flags); free(coord_stack);
else if (y<YRES-CELL-dy) return created_something;
for (x=x1; x<=x2; x++)
if ((pmap[y+1][x]&0xFF)!=PT_SPRK)
{
if (x==x1 || x==x2 || y<0 ||
(pmap[y+1][x-1]&0xFF)==PT_INST || (pmap[y+1][x+1]&0xFF)==PT_INST ||
(pmap[y-1][x-1]&0xFF)==PT_INST || ((pmap[y-1][x]&0xFF)!=PT_INST&&(pmap[y-1][x]&0xFF)!=PT_SPRK) || (pmap[y-1][x+1]&0xFF)==PT_INST)
FloodParts(x, y+dy, fullc, cm, bm, flags);
}
}
else
{
if (y>=CELL+dy)
for (x=x1; x<=x2; x++)
if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm)
if (!FloodParts(x, y-dy, fullc, cm, bm, flags))
return 0;
if (y<YRES-CELL-dy)
for (x=x1; x<=x2; x++)
if ((pmap[y+dy][x]&0xFF)==cm && bmap[(y+dy)/CELL][x/CELL]==bm)
if (!FloodParts(x, y+dy, fullc, cm, bm, flags))
return 0;
}
if (!(cm==PT_INST&&co==PT_SPRK))
return 1;
return 0;
} }
int Simulation::FloodWalls(int x, int y, int c, int cm, int bm, int flags) int Simulation::FloodWalls(int x, int y, int c, int cm, int bm, int flags)