summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacksonmj <mj-pt@jacksonmj.co.uk>2012-05-17 00:01:48 (GMT)
committer jacksonmj <mj-pt@jacksonmj.co.uk>2012-05-17 20:56:21 (GMT)
commita11202313d5af4e6f88316743f54cba042e5d27c (patch)
treee3d2dc30836aa4d7b3aaa99ec6792088e3c865c7 /src
parent9a30a580d274dffc90833b1188241eca71fd8633 (diff)
downloadpowder-a11202313d5af4e6f88316743f54cba042e5d27c.zip
powder-a11202313d5af4e6f88316743f54cba042e5d27c.tar.gz
New flood_parts function, should fix crashing due to too much recursion
Diffstat (limited to 'src')
-rw-r--r--src/powder.c197
1 files changed, 133 insertions, 64 deletions
diff --git a/src/powder.c b/src/powder.c
index dfde225..6d92bc8 100644
--- a/src/powder.c
+++ b/src/powder.c
@@ -2918,11 +2918,18 @@ int flood_prop(int x, int y, size_t propoffset, void * propvalue, int proptype)
free(bitmap);
}
+#define PMAP_CMP_CONDUCTIVE(pmap, t) (((pmap)&0xFF)==(t) || (((pmap)&0xFF)==PT_SPRK && parts[(pmap)>>8].ctype==(t)))
+
int flood_parts(int x, int y, int fullc, int cm, int bm, int flags)
{
int c = fullc&0xFF;
int x1, x2, dy = (c<PT_NUM)?1:CELL;
int co = c;
+ int coord_stack_limit = XRES*YRES;
+ unsigned short (*coord_stack)[2] = malloc(sizeof(unsigned short)*2*coord_stack_limit);
+ int coord_stack_size = 0;
+ int created_something = 0;
+
if (c==SPC_PROP)
return 0;
if (cm==PT_INST&&co==PT_SPRK)
@@ -2958,84 +2965,146 @@ int flood_parts(int x, int y, int fullc, int cm, int bm, int flags)
if (((pmap[y][x]&0xFF)!=cm || bmap[y/CELL][x/CELL]!=bm )||( (flags&BRUSH_SPECIFIC_DELETE) && cm!=SLALT))
return 1;
- // go left as far as possible
- x1 = x2 = x;
- while (x1>=CELL)
+ coord_stack[coord_stack_size][0] = x;
+ coord_stack[coord_stack_size][1] = y;
+ 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--;
- }
- while (x2<XRES-CELL)
- {
- if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm)
+ // go right as far as possible
+ while (x2<XRES-CELL)
{
- break;
+ if ((pmap[y][x2+1]&0xFF)!=cm || bmap[y/CELL][(x2+1)/CELL]!=bm)
+ {
+ break;
+ }
+ x2++;
+ }
+ // fill span
+ for (x=x1; x<=x2; x++)
+ {
+ if (cm==PT_INST&&co==PT_SPRK)
+ {
+ if (create_part(-1, x, y, fullc)>=0)
+ created_something = 1;
+ }
+ else
+ {
+ if (create_parts(x, y, 0, 0, fullc, flags, 1))
+ created_something = 1;
+ }
}
- x2++;
- }
- // fill span
- for (x=x1; x<=x2; x++)
- {
+ // add vertically adjacent pixels to stack
if (cm==PT_INST&&co==PT_SPRK)
{
- if (create_part(-1,x, y, fullc)==-1)
- return 0;
- }
- else if (!create_parts(x, y, 0, 0, fullc, flags, 1))
- return 0;
- }
- // fill children
- if (cm==PT_INST&&co==PT_SPRK)//wire crossing for INST
- {
- if (y>=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)
- flood_parts(x1, y-2, fullc, cm, bm, flags);
- else if (y>=CELL+dy)
- for (x=x1; x<=x2; x++)
- if ((pmap[y-1][x]&0xFF)!=PT_SPRK)
+ //wire crossing for INST
+ 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)
{
- if (x==x1 || x==x2 || y>=YRES-CELL-1 ||
- (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)
- flood_parts(x, y-dy, fullc, cm, bm, flags);
-
+ 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-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)
- flood_parts(x1, y+2, fullc, cm, bm, flags);
- else if (y<YRES-CELL-dy)
- for (x=x1; x<=x2; x++)
- if ((pmap[y+1][x]&0xFF)!=PT_SPRK)
+ 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 (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)
- flood_parts(x, y+dy, fullc, cm, bm, flags);
+ 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 (y>=CELL+dy)
- for (x=x1; x<=x2; x++)
- if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm)
- if (!flood_parts(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 (!flood_parts(x, y+dy, fullc, cm, bm, flags))
- return 0;
- }
- if (!(cm==PT_INST&&co==PT_SPRK))
- return 1;
+ }
+ }
+ 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)
+ {
+ coord_stack[coord_stack_size][0] = x;
+ 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)
+ for (x=x1; x<=x2; x++)
+ if ((pmap[y+dy][x]&0xFF)==cm && bmap[(y+dy)/CELL][x/CELL]==bm)
+ {
+ coord_stack[coord_stack_size][0] = x;
+ coord_stack[coord_stack_size][1] = y+dy;
+ coord_stack_size++;
+ if (coord_stack_size>=coord_stack_limit)
+ return -1;
+ }
+ }
+ } while (coord_stack_size>0);
+ free(coord_stack);
+ return created_something;
}
int flood_water(int x, int y, int i, int originaly, int check)