diff --git a/src/simulation/ElementDefs.h b/src/simulation/ElementDefs.h index 90c8316e4..e6d77b8b8 100644 --- a/src/simulation/ElementDefs.h +++ b/src/simulation/ElementDefs.h @@ -34,7 +34,7 @@ #define FLAG_STAGNANT 0x1 #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_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, diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 063956471..f007eaef5 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -866,63 +866,70 @@ int Simulation::FloodINST(int x, int y, int fullc, int cm) 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; - // go left as far as possible - x1 = x2 = x; - if (!pmap[y][x]) - return 1; + int x1, x2, originalY = y; + int r = pmap[y][x]; + if (!r) + return false; - while (x1>=CELL) - { - if ((elements[TYP(pmap[y][x1-1])].Falldown) != 2) - { - break; - } - x1--; - } - while (x2(new char[XRES * YRES]); + char *bitmap = bitmapPtr.get(); + std::fill(&bitmap[0], &bitmap[XRES * YRES], 0); - // fill span - for (x=x1; x<=x2; x++) + try { - if (check) - parts[ID(pmap[y][x])].flags &= ~FLAG_WATEREQUAL;//flag it as checked (different from the original particle's checked flag) - 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)) + CoordStack cs; + cs.push(x, y); + do { - int oldx = (int)(parts[i].x + 0.5f); - int oldy = (int)(parts[i].y + 0.5f); - pmap[y-1][x] = pmap[oldy][oldx]; - pmap[oldy][oldx] = 0; - parts[i].x = x; - parts[i].y = y-1; - return 0; - } - } - // fill children + 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; + x1--; + } + while (x2 < XRES-CELL) + { + if (elements[TYP(pmap[y][x2 + 1])].Falldown != 2 || bitmap[(y * XRES) + x1 - 1]) + break; + x2++; + } + for (int x = x1; x <= x2; x++) + { + // Check above, maybe around other sides too? + if (((y - 1) > originalY) && !pmap[y - 1][x] && eval_move(parts[i].type, x, y - 1, nullptr)) + { + int oldx = (int)(parts[i].x + 0.5f); + int oldy = (int)(parts[i].y + 0.5f); + pmap[y - 1][x] = pmap[oldy][oldx]; + pmap[oldy][oldx] = 0; + parts[i].x = x; + parts[i].y = y - 1; + return true; + } - if (y>=CELL+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 (!flood_water(x, y-1, i, originaly, check)) - return 0; - if (y= CELL + 1) + for (int x = x1; x <= x2; x++) + if (elements[TYP(pmap[y - 1][x])].Falldown == 2 && !bitmap[((y - 1) * XRES) + x]) + cs.push(x, y - 1); + if (y < YRES - CELL - 1) + for (int x = x1; x <= x2; x++) + if (elements[TYP(pmap[y + 1][x])].Falldown == 2 && !bitmap[((y + 1) * XRES) + x]) + cs.push(x, y + 1); + } while (cs.getSize() > 0); + } + catch (std::exception &e) + { + std::cerr << e.what() << std::endl; + return false; + } + return false; } 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. 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; } // liquids and powders diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 9a505796e..73a7d7461 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -142,7 +142,7 @@ public: void kill_part(int i); 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_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); void detach(int i); bool part_change_type(int i, int x, int y, int t);