From 391165409ddcf14b4a888b5aac90871999caa9a2 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Tue, 12 Jun 2012 18:41:36 +0100 Subject: [PATCH] TPT: New flood_parts function, should fix crashing due to too much recursion a11202313d --- src/simulation/Simulation.cpp | 220 ++++++++++++++++++++++------------ 1 file changed, 143 insertions(+), 77 deletions(-) diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 30b2fcc32..5bc64b9d7 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -345,11 +345,18 @@ Particle Simulation::Get(int x, int y) 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 c = fullc&0xFF; - int x1, x2, dy = 1; + int x1, x2, dy = (c=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=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 (create_part(-1,x, y, fullc)==-1) - return 0; + //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) + { + 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=coord_stack_limit) + return -1; + } + } + else if (y=coord_stack_limit) + return -1; + } + + } + } + } } - else if (!CreateParts(x, y, 0, 0, fullc, flags)) - 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) - FloodParts(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) - { - 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) - FloodParts(x, y-dy, fullc, cm, bm, flags); - - } - - 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=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=coord_stack_limit) + return -1; + } + } + } while (coord_stack_size>0); + free(coord_stack); + return created_something; } int Simulation::FloodWalls(int x, int y, int c, int cm, int bm, int flags)