puzzlesolver: fix solution being reset when clicking the puzzle quickly

This commit is contained in:
Lotto
2018-02-24 00:38:41 +01:00
parent 31af43e9be
commit 3396c7ac45
4 changed files with 49 additions and 78 deletions

View File

@@ -142,8 +142,8 @@ public class PuzzleSolverOverlay extends Overlay
{ {
boolean foundPosition = false; boolean foundPosition = false;
// Find the current state by looking at the current step and then the next 3 steps // Find the current state by looking at the current step and then the next 5 steps
for (int i = 0; i < 4; i++) for (int i = 0; i < 6; i++)
{ {
int j = solver.getPosition() + i; int j = solver.getPosition() + i;
@@ -152,10 +152,10 @@ public class PuzzleSolverOverlay extends Overlay
break; break;
} }
Integer currentState = solver.getStep(j); PuzzleState currentState = solver.getStep(j);
// If this is false, player has moved the empty tile // If this is false, player has moved the empty tile
if (currentState != null && itemIds[currentState] == BLANK_TILE_VALUE) if (currentState != null && currentState.hasPieces(itemIds))
{ {
foundPosition = true; foundPosition = true;
solver.setPosition(j); solver.setPosition(j);
@@ -168,10 +168,10 @@ public class PuzzleSolverOverlay extends Overlay
} }
// If looking at the next steps didn't find the current state, // If looking at the next steps didn't find the current state,
// see if we can find the current state in the 3 previous steps // see if we can find the current state in the 5 previous steps
if (!foundPosition) if (!foundPosition)
{ {
for (int i = 1; i < 4; i++) for (int i = 1; i < 6; i++)
{ {
int j = solver.getPosition() - i; int j = solver.getPosition() - i;
@@ -180,9 +180,9 @@ public class PuzzleSolverOverlay extends Overlay
break; break;
} }
Integer currentState = solver.getStep(j); PuzzleState currentState = solver.getStep(j);
if (currentState != null && itemIds[currentState] == BLANK_TILE_VALUE) if (currentState != null && currentState.hasPieces(itemIds))
{ {
foundPosition = true; foundPosition = true;
shouldCache = true; shouldCache = true;
@@ -218,15 +218,15 @@ public class PuzzleSolverOverlay extends Overlay
// Display the next 4 steps // Display the next 4 steps
for (int j = 1; j < 5; j++) for (int j = 1; j < 5; j++)
{ {
Integer futureMove = solver.getStep(solver.getPosition() + j); PuzzleState futureMove = solver.getStep(solver.getPosition() + j);
if (futureMove == null) if (futureMove == null)
{ {
break; break;
} }
int blankX = futureMove % DIMENSION; int blankX = futureMove.getEmptyPiece() % DIMENSION;
int blankY = futureMove / DIMENSION; int blankY = futureMove.getEmptyPiece() / DIMENSION;
int markerSize = DOT_MARKER_SIZE - j * 3; int markerSize = DOT_MARKER_SIZE - j * 3;
@@ -242,23 +242,23 @@ public class PuzzleSolverOverlay extends Overlay
else else
{ {
// Find the current blank tile position // Find the current blank tile position
Integer currentMove = solver.getStep(solver.getPosition()); PuzzleState currentMove = solver.getStep(solver.getPosition());
int lastBlankX = currentMove % DIMENSION; int lastBlankX = currentMove.getEmptyPiece() % DIMENSION;
int lastBlankY = currentMove / DIMENSION; int lastBlankY = currentMove.getEmptyPiece() / DIMENSION;
// Display the next 3 steps // Display the next 3 steps
for (int j = 1; j < 4; j++) for (int j = 1; j < 4; j++)
{ {
Integer futureMove = solver.getStep(solver.getPosition() + j); PuzzleState futureMove = solver.getStep(solver.getPosition() + j);
if (futureMove == null) if (futureMove == null)
{ {
break; break;
} }
int blankX = futureMove % DIMENSION; int blankX = futureMove.getEmptyPiece() % DIMENSION;
int blankY = futureMove / DIMENSION; int blankY = futureMove.getEmptyPiece() / DIMENSION;
int xDelta = blankX - lastBlankX; int xDelta = blankX - lastBlankX;
int yDelta = blankY - lastBlankY; int yDelta = blankY - lastBlankY;
@@ -353,27 +353,7 @@ public class PuzzleSolverOverlay extends Overlay
itemIds[items.length] = BLANK_TILE_VALUE; itemIds[items.length] = BLANK_TILE_VALUE;
} }
return itemIds; return convertToSolverFormat(itemIds);
}
private void cacheItems(int[] items)
{
cachedItems = new int[items.length];
System.arraycopy(items, 0, cachedItems, 0, cachedItems.length);
}
private void solve(int[] items)
{
if (solverFuture != null)
{
solverFuture.cancel(true);
}
int[] puzzleItems = convertToSolverFormat(items);
PuzzleState puzzleState = new PuzzleState(puzzleItems);
solver = new PuzzleSolver(new IDAStar(new ManhattanDistance()), puzzleState);
solverFuture = executorService.submit(solver);
} }
/** /**
@@ -413,6 +393,25 @@ public class PuzzleSolverOverlay extends Overlay
return convertedItems; return convertedItems;
} }
private void cacheItems(int[] items)
{
cachedItems = new int[items.length];
System.arraycopy(items, 0, cachedItems, 0, cachedItems.length);
}
private void solve(int[] items)
{
if (solverFuture != null)
{
solverFuture.cancel(true);
}
PuzzleState puzzleState = new PuzzleState(items);
solver = new PuzzleSolver(new IDAStar(new ManhattanDistance()), puzzleState);
solverFuture = executorService.submit(solver);
}
private BufferedImage getDownArrow() private BufferedImage getDownArrow()
{ {
if (downArrow == null) if (downArrow == null)

View File

@@ -26,7 +26,6 @@
package net.runelite.client.plugins.puzzlesolver.solver; package net.runelite.client.plugins.puzzlesolver.solver;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.Pathfinder; import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.Pathfinder;
public class PuzzleSolver implements Runnable public class PuzzleSolver implements Runnable
@@ -36,7 +35,7 @@ public class PuzzleSolver implements Runnable
private Pathfinder pathfinder; private Pathfinder pathfinder;
private PuzzleState startState; private PuzzleState startState;
private List<Integer> solution; private List<PuzzleState> solution;
private int position; private int position;
private boolean failed = false; private boolean failed = false;
@@ -46,7 +45,7 @@ public class PuzzleSolver implements Runnable
this.startState = startState; this.startState = startState;
} }
public Integer getStep(int stepIdx) public PuzzleState getStep(int stepIdx)
{ {
if (stepIdx < 0 || stepIdx >= solution.size()) if (stepIdx < 0 || stepIdx >= solution.size())
{ {
@@ -84,17 +83,7 @@ public class PuzzleSolver implements Runnable
@Override @Override
public void run() public void run()
{ {
List<PuzzleState> solution = pathfinder.computePath(startState); solution = pathfinder.computePath(startState);
failed = solution == null;
if (solution != null)
{
this.solution = solution.stream()
.map(PuzzleState::getEmptyPiece)
.collect(Collectors.toList());
}
else
{
failed = true;
}
} }
} }

View File

@@ -153,6 +153,11 @@ public class PuzzleState
return parent; return parent;
} }
public boolean hasPieces(int[] pieces)
{
return Arrays.equals(pieces, this.pieces);
}
public int getPiece(int x, int y) public int getPiece(int x, int y)
{ {
return pieces[y * DIMENSION + x]; return pieces[y * DIMENSION + x];

View File

@@ -25,15 +25,12 @@
*/ */
package net.runelite.client.plugins.puzzlesolver; package net.runelite.client.plugins.puzzlesolver;
import java.util.List;
import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver; import net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver;
import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState; import net.runelite.client.plugins.puzzlesolver.solver.PuzzleState;
import net.runelite.client.plugins.puzzlesolver.solver.heuristics.ManhattanDistance; import net.runelite.client.plugins.puzzlesolver.solver.heuristics.ManhattanDistance;
import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStar; import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStar;
import org.junit.Test; import org.junit.Test;
import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
public class PuzzleSolverTest public class PuzzleSolverTest
@@ -97,27 +94,8 @@ public class PuzzleSolverTest
solver.run(); solver.run();
assertTrue(solver.hasSolution()); assertTrue(solver.hasSolution());
assertFalse(solver.hasFailed());
for (int i = 0; i < solver.getStepCount(); i++) assertTrue(solver.getStep(solver.getStepCount() - 1).hasPieces(FINISHED_STATE));
{
int futureMove = solver.getStep(i);
List<PuzzleState> moves = state.computeMoves();
for (PuzzleState move : moves)
{
if (move.getEmptyPiece() == futureMove)
{
state = move;
break;
}
}
}
for (int i = 0; i < FINISHED_STATE.length; i++)
{
assertEquals(state.getPiece(i % DIMENSION, i / DIMENSION), FINISHED_STATE[i]);
}
} }
} }
} }