diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 0780bea4c..d8b19bc37 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -1996,11 +1996,8 @@ void Simulation::clear_sim(void) SetEdgeMode(edgeMode); } -bool Simulation::IsObsticle(int x, int y, int type) +bool Simulation::IsWallBlocking(int x, int y, int type) { - if (pmap[y][x])// && (type != PT_SPRK || !(elements[pmap[y][x]&0xFF].Properties & PROP_CONDUCTS))) - return true; - if (bmap[y/CELL][x/CELL]) { int wall = bmap[y/CELL][x/CELL]; diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index fd65f8252..abcea157f 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -138,7 +138,7 @@ public: TPT_NO_INLINE int try_move(int i, int x, int y, int nx, int ny); TPT_NO_INLINE int eval_move(int pt, int nx, int ny, unsigned *rr); void init_can_move(); - bool IsObsticle(int x, int y, int type); + bool IsWallBlocking(int x, int y, int type); void create_cherenkov_photon(int pp); void create_gain_photon(int pp); TPT_NO_INLINE void kill_part(int i); diff --git a/src/simulation/elements/CRAY.cpp b/src/simulation/elements/CRAY.cpp index 525ba2f06..112dd498c 100644 --- a/src/simulation/elements/CRAY.cpp +++ b/src/simulation/elements/CRAY.cpp @@ -87,7 +87,7 @@ int Element_CRAY::update(UPDATE_FUNC_ARGS) break; } r = pmap[y+nyi+nyy][x+nxi+nxx]; - if (!sim->IsObsticle(x+nxi+nxx, y+nyi+nyy, parts[i].ctype) || (parts[i].ctype == PT_SPRK && sim->elements[r&0xFF].Properties & PROP_CONDUCTS) && !destroy) { // create, also set color if it has passed through FILT + if (!sim->IsWallBlocking(x+nxi+nxx, y+nyi+nyy, parts[i].ctype) && (!sim->pmap[y+nyi+nyy][x+nxi+nxx] || (parts[i].ctype == PT_SPRK && !destroy))) { // create, also set color if it has passed through FILT int nr; if (parts[i].ctype == PT_LIFE) nr = sim->create_part(-1, x+nxi+nxx, y+nyi+nyy, parts[i].ctype|(parts[i].tmp2<<8)); diff --git a/src/simulation/elements/PSTN.cpp b/src/simulation/elements/PSTN.cpp index 7d075a47b..6496483a4 100644 --- a/src/simulation/elements/PSTN.cpp +++ b/src/simulation/elements/PSTN.cpp @@ -160,6 +160,37 @@ int Element_PSTN::update(UPDATE_FUNC_ARGS) return 0; } +//#TPT-Directive ElementHeader Element_PSTN static int CanMoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int size, int amount) +int Element_PSTN::CanMoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int size, int amount) +{ + int posX, posY, r, spaces = 0, currentPos = 0; + if (amount == 0) + return 0; + for(posX = stackX, posY = stackY; currentPos < size + amount; posX += directionX, posY += directionY) { + if (!(posX < XRES && posY < YRES && posX >= 0 && posY >= 0)) { + break; + } + r = sim->pmap[posY][posX]; + if (sim->IsWallBlocking(posX, posY, 0)/* || (r&0xFF) == PT_INSL*/) + break; + if(!r) { + spaces++; + tempParts[currentPos++] = -1; + if(spaces >= amount) + break; + } else { + if(currentPos < size) + tempParts[currentPos++] = r>>8; + else + return spaces; + } + } + if (spaces) + return currentPos; + else + return 0; +} + //#TPT-Directive ElementHeader Element_PSTN static int MoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int size, int amount, bool retract, int callDepth = 0) int Element_PSTN::MoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int size, int amount, bool retract, int callDepth) { @@ -167,8 +198,32 @@ int Element_PSTN::MoveStack(Simulation * sim, int stackX, int stackY, int direct int posX, posY, r, spaces = 0, currentPos = 0; r = sim->pmap[stackY][stackX]; if(!callDepth && (r&0xFF) == PT_FRME) { - int biggestMove = amount; + int ret = amount; int newY = !!directionX, newX = !!directionY; + if (!retract) + { + //check if we can push all the FRME + for(int c = 0; c < MAX_FRAME; c++) { + posY = stackY + (c*newY); + posX = stackX + (c*newX); + if (posX < XRES && posY < YRES && posX >= 0 && posY >= 0 && (sim->pmap[posY][posX]&0xFF) == PT_FRME) { + int val = CanMoveStack(sim, posX+directionX, posY+directionY, directionX, directionY, size, amount); + if(val < amount) + amount = val; + } else + break; + } + for(int c = 1; c < MAX_FRAME; c++) { + posY = stackY - (c*newY); + posX = stackX - (c*newX); + if (posX < XRES && posY < YRES && posX >= 0 && posY >= 0 && (sim->pmap[posY][posX]&0xFF) == PT_FRME) { + int val = CanMoveStack(sim, posX+directionX, posY+directionY, directionX, directionY, size, amount); + if(val < amount) + amount = val; + } else + break; + } + } //If the piston is pushing frame, iterate out from the centre to the edge and push everything resting on frame for(int c = 0; c < MAX_FRAME; c++) { posY = stackY + (c*newY); @@ -177,9 +232,9 @@ int Element_PSTN::MoveStack(Simulation * sim, int stackX, int stackY, int direct r = sim->pmap[posY][posX]; if((r&0xFF) == PT_FRME) { int val = MoveStack(sim, posX, posY, directionX, directionY, size, amount, retract, 1); - if(val < biggestMove) - biggestMove = val; - } else + if(c == 0) + ret = val; + } else break; } } @@ -189,14 +244,12 @@ int Element_PSTN::MoveStack(Simulation * sim, int stackX, int stackY, int direct if (posX < XRES && posY < YRES && posX >= 0 && posY >= 0) { r = sim->pmap[posY][posX]; if((r&0xFF) == PT_FRME) { - int val = MoveStack(sim, posX, posY, directionX, directionY, size, amount, retract, 1); - if(val < biggestMove) - biggestMove = val; - } else + MoveStack(sim, posX, posY, directionX, directionY, size, amount, retract, 1); + } else break; } } - return biggestMove; + return ret; } if(retract){ bool foundEnd = false; @@ -225,27 +278,10 @@ int Element_PSTN::MoveStack(Simulation * sim, int stackX, int stackY, int direct return amount; } if(!foundParts && foundEnd) - return amount; + return amount; } else { - for(posX = stackX, posY = stackY; currentPos < size + amount; posX += directionX, posY += directionY) { - if (!(posX < XRES && posY < YRES && posX >= 0 && posY >= 0)) { - break; - } - r = sim->pmap[posY][posX]; - if(!r) { - spaces++; - tempParts[currentPos++] = -1; - if(spaces >= amount) - break; - } else { - foundParts = true; - if(currentPos < size) - tempParts[currentPos++] = r>>8; - else - break; - } - } - if(foundParts && spaces){ + currentPos = CanMoveStack(sim, stackX, stackY, directionX, directionY, size, amount); + if(currentPos){ //Move particles int possibleMovement = 0; for(int j = currentPos-1; j >= 0; j--) {