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;
// Find the current state by looking at the current step and then the next 3 steps
for (int i = 0; i < 4; i++)
// Find the current state by looking at the current step and then the next 5 steps
for (int i = 0; i < 6; i++)
{
int j = solver.getPosition() + i;
@@ -152,10 +152,10 @@ public class PuzzleSolverOverlay extends Overlay
break;
}
Integer currentState = solver.getStep(j);
PuzzleState currentState = solver.getStep(j);
// 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;
solver.setPosition(j);
@@ -168,10 +168,10 @@ public class PuzzleSolverOverlay extends Overlay
}
// 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)
{
for (int i = 1; i < 4; i++)
for (int i = 1; i < 6; i++)
{
int j = solver.getPosition() - i;
@@ -180,9 +180,9 @@ public class PuzzleSolverOverlay extends Overlay
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;
shouldCache = true;
@@ -218,15 +218,15 @@ public class PuzzleSolverOverlay extends Overlay
// Display the next 4 steps
for (int j = 1; j < 5; j++)
{
Integer futureMove = solver.getStep(solver.getPosition() + j);
PuzzleState futureMove = solver.getStep(solver.getPosition() + j);
if (futureMove == null)
{
break;
}
int blankX = futureMove % DIMENSION;
int blankY = futureMove / DIMENSION;
int blankX = futureMove.getEmptyPiece() % DIMENSION;
int blankY = futureMove.getEmptyPiece() / DIMENSION;
int markerSize = DOT_MARKER_SIZE - j * 3;
@@ -242,23 +242,23 @@ public class PuzzleSolverOverlay extends Overlay
else
{
// Find the current blank tile position
Integer currentMove = solver.getStep(solver.getPosition());
PuzzleState currentMove = solver.getStep(solver.getPosition());
int lastBlankX = currentMove % DIMENSION;
int lastBlankY = currentMove / DIMENSION;
int lastBlankX = currentMove.getEmptyPiece() % DIMENSION;
int lastBlankY = currentMove.getEmptyPiece() / DIMENSION;
// Display the next 3 steps
for (int j = 1; j < 4; j++)
{
Integer futureMove = solver.getStep(solver.getPosition() + j);
PuzzleState futureMove = solver.getStep(solver.getPosition() + j);
if (futureMove == null)
{
break;
}
int blankX = futureMove % DIMENSION;
int blankY = futureMove / DIMENSION;
int blankX = futureMove.getEmptyPiece() % DIMENSION;
int blankY = futureMove.getEmptyPiece() / DIMENSION;
int xDelta = blankX - lastBlankX;
int yDelta = blankY - lastBlankY;
@@ -353,27 +353,7 @@ public class PuzzleSolverOverlay extends Overlay
itemIds[items.length] = BLANK_TILE_VALUE;
}
return 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);
return convertToSolverFormat(itemIds);
}
/**
@@ -413,6 +393,25 @@ public class PuzzleSolverOverlay extends Overlay
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()
{
if (downArrow == null)

View File

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

View File

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

View File

@@ -25,15 +25,12 @@
*/
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.PuzzleState;
import net.runelite.client.plugins.puzzlesolver.solver.heuristics.ManhattanDistance;
import net.runelite.client.plugins.puzzlesolver.solver.pathfinding.IDAStar;
import org.junit.Test;
import static net.runelite.client.plugins.puzzlesolver.solver.PuzzleSolver.DIMENSION;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class PuzzleSolverTest
@@ -97,27 +94,8 @@ public class PuzzleSolverTest
solver.run();
assertTrue(solver.hasSolution());
for (int i = 0; i < solver.getStepCount(); i++)
{
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]);
}
assertFalse(solver.hasFailed());
assertTrue(solver.getStep(solver.getStepCount() - 1).hasPieces(FINISHED_STATE));
}
}
}