mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-12 17:12:40 +01:00
DroidFish: Use the SearchListener interface to communicate the search result (best move + ponder move) back to the DroidChessController.
This commit is contained in:
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import org.petero.droidfish.BookOptions;
|
import org.petero.droidfish.BookOptions;
|
||||||
import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine;
|
import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine;
|
||||||
|
import org.petero.droidfish.gamelogic.Game;
|
||||||
import org.petero.droidfish.gamelogic.Move;
|
import org.petero.droidfish.gamelogic.Move;
|
||||||
import org.petero.droidfish.gamelogic.MoveGen;
|
import org.petero.droidfish.gamelogic.MoveGen;
|
||||||
import org.petero.droidfish.gamelogic.Pair;
|
import org.petero.droidfish.gamelogic.Pair;
|
||||||
@@ -63,33 +64,11 @@ public class DroidComputerPlayer {
|
|||||||
book = DroidBook.getInstance();
|
book = DroidBook.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set engine and engine strength.
|
|
||||||
* @param engine Name of engine.
|
|
||||||
* @param strength Engine strength, 0 - 1000. */
|
|
||||||
public final synchronized void setEngineStrength(String engine, int strength) {
|
|
||||||
if (!engine.equals(this.engine)) {
|
|
||||||
shutdownEngine();
|
|
||||||
this.engine = engine;
|
|
||||||
startEngine();
|
|
||||||
}
|
|
||||||
this.strength = strength;
|
|
||||||
if (uciEngine != null)
|
|
||||||
uciEngine.setStrength(strength);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return maximum number of PVs supported by engine. */
|
/** Return maximum number of PVs supported by engine. */
|
||||||
public final synchronized int getMaxPV() {
|
public final synchronized int getMaxPV() {
|
||||||
return maxPV;
|
return maxPV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set engine multi-PV mode. */
|
|
||||||
public final synchronized void setNumPV(int numPV) {
|
|
||||||
if ((uciEngine != null) && (maxPV > 1)) {
|
|
||||||
int num = Math.min(maxPV, numPV);
|
|
||||||
uciEngine.setOption("MultiPV", num);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set opening book options. */
|
/** Set opening book options. */
|
||||||
public final void setBookOptions(BookOptions options) {
|
public final void setBookOptions(BookOptions options) {
|
||||||
book.setOptions(options);
|
book.setOptions(options);
|
||||||
@@ -141,15 +120,18 @@ public class DroidComputerPlayer {
|
|||||||
* @param ponderEnabled True if pondering is enabled in the GUI. Can affect time management.
|
* @param ponderEnabled True if pondering is enabled in the GUI. Can affect time management.
|
||||||
* @param ponderMove Move to ponder, or null for non-ponder search.
|
* @param ponderMove Move to ponder, or null for non-ponder search.
|
||||||
* @param engineThreads Number of engine threads to use, if supported by engine.
|
* @param engineThreads Number of engine threads to use, if supported by engine.
|
||||||
* @return The computer player command, and the next ponder move.
|
* @param engine Chess engine to use for searching.
|
||||||
|
* @param strength Engine strength setting.
|
||||||
*/
|
*/
|
||||||
public final Pair<String,Move> doSearch(Position prevPos, ArrayList<Move> mList,
|
public final void doSearch(Position prevPos, ArrayList<Move> mList,
|
||||||
Position currPos, boolean drawOffer,
|
Position currPos, boolean drawOffer,
|
||||||
int wTime, int bTime, int inc, int movesToGo,
|
int wTime, int bTime, int inc, int movesToGo,
|
||||||
boolean ponderEnabled, Move ponderMove,
|
boolean ponderEnabled, Move ponderMove,
|
||||||
int engineThreads) {
|
int engineThreads,
|
||||||
if (listener != null)
|
String engine, int strength, Game g) {
|
||||||
listener.notifyBookInfo("", null);
|
setEngineStrength(engine, strength);
|
||||||
|
setNumPV(1);
|
||||||
|
listener.notifyBookInfo("", null);
|
||||||
|
|
||||||
if (ponderMove != null)
|
if (ponderMove != null)
|
||||||
mList.add(ponderMove);
|
mList.add(ponderMove);
|
||||||
@@ -171,7 +153,8 @@ public class DroidComputerPlayer {
|
|||||||
Move bookMove = book.getBookMove(currPos);
|
Move bookMove = book.getBookMove(currPos);
|
||||||
if (bookMove != null) {
|
if (bookMove != null) {
|
||||||
if (canClaimDraw(currPos, posHashList, posHashListSize, bookMove) == "") {
|
if (canClaimDraw(currPos, posHashList, posHashListSize, bookMove) == "") {
|
||||||
return new Pair<String,Move>(TextIO.moveToString(currPos, bookMove, false), null);
|
listener.notifySearchResult(g, TextIO.moveToString(currPos, bookMove, false), null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,12 +162,14 @@ public class DroidComputerPlayer {
|
|||||||
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(currPos);
|
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(currPos);
|
||||||
moves = MoveGen.removeIllegal(currPos, moves);
|
moves = MoveGen.removeIllegal(currPos, moves);
|
||||||
if (moves.size() == 0) {
|
if (moves.size() == 0) {
|
||||||
return new Pair<String,Move>("", null); // User set up a position where computer has no valid moves.
|
listener.notifySearchResult(g, "", null); // User set up a position where computer has no valid moves.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (moves.size() == 1) {
|
if (moves.size() == 1) {
|
||||||
Move bestMove = moves.get(0);
|
Move bestMove = moves.get(0);
|
||||||
if (canClaimDraw(currPos, posHashList, posHashListSize, bestMove) == "") {
|
if (canClaimDraw(currPos, posHashList, posHashListSize, bestMove) == "") {
|
||||||
return new Pair<String,Move>(TextIO.moveToUCIString(bestMove), null);
|
listener.notifySearchResult(g, TextIO.moveToUCIString(bestMove), null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,7 +216,7 @@ public class DroidComputerPlayer {
|
|||||||
if (drawOffer && !statIsMate && (statScore <= -300)) {
|
if (drawOffer && !statIsMate && (statScore <= -300)) {
|
||||||
bestMove = "draw accept";
|
bestMove = "draw accept";
|
||||||
}
|
}
|
||||||
return new Pair<String,Move>(bestMove, nextPonderMove);
|
listener.notifySearchResult(g, bestMove, nextPonderMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean shouldStop = false;
|
public boolean shouldStop = false;
|
||||||
@@ -250,16 +235,21 @@ public class DroidComputerPlayer {
|
|||||||
* @param currPos Position to analyze.
|
* @param currPos Position to analyze.
|
||||||
* @param drawOffer True if other side have offered draw.
|
* @param drawOffer True if other side have offered draw.
|
||||||
* @param engineThreads Number of threads to use, or 0 for default value.
|
* @param engineThreads Number of threads to use, or 0 for default value.
|
||||||
|
* @param engine Chess engine to use for searching
|
||||||
|
* @param numPV Multi-PV mode.
|
||||||
*/
|
*/
|
||||||
public final void analyze(Position prevPos, ArrayList<Move> mList, Position currPos,
|
public final void analyze(Position prevPos, ArrayList<Move> mList, Position currPos,
|
||||||
boolean drawOffer, int engineThreads) {
|
boolean drawOffer, int engineThreads,
|
||||||
|
String engine, int numPV) {
|
||||||
|
setEngineStrength(engine, 1000);
|
||||||
|
setNumPV(numPV);
|
||||||
if (shouldStop)
|
if (shouldStop)
|
||||||
return;
|
return;
|
||||||
if (listener != null) {
|
{
|
||||||
Pair<String, ArrayList<Move>> bi = getBookHints(currPos);
|
Pair<String, ArrayList<Move>> bi = getBookHints(currPos);
|
||||||
listener.notifyBookInfo(bi.first, bi.second);
|
listener.notifyBookInfo(bi.first, bi.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no legal moves, there is nothing to analyze
|
// If no legal moves, there is nothing to analyze
|
||||||
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(currPos);
|
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(currPos);
|
||||||
moves = MoveGen.removeIllegal(currPos, moves);
|
moves = MoveGen.removeIllegal(currPos, moves);
|
||||||
@@ -287,6 +277,28 @@ public class DroidComputerPlayer {
|
|||||||
monitorEngine(currPos, null);
|
monitorEngine(currPos, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set engine and engine strength.
|
||||||
|
* @param engine Name of engine.
|
||||||
|
* @param strength Engine strength, 0 - 1000. */
|
||||||
|
private final synchronized void setEngineStrength(String engine, int strength) {
|
||||||
|
if (!engine.equals(this.engine)) {
|
||||||
|
shutdownEngine();
|
||||||
|
this.engine = engine;
|
||||||
|
startEngine();
|
||||||
|
}
|
||||||
|
this.strength = strength;
|
||||||
|
if (uciEngine != null)
|
||||||
|
uciEngine.setStrength(strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set engine multi-PV mode. */
|
||||||
|
private final synchronized void setNumPV(int numPV) {
|
||||||
|
if ((uciEngine != null) && (maxPV > 1)) {
|
||||||
|
int num = Math.min(maxPV, numPV);
|
||||||
|
uciEngine.setOption("MultiPV", num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final synchronized void startEngine() {
|
private final synchronized void startEngine() {
|
||||||
boolean useCuckoo = engine.equals("cuckoochess");
|
boolean useCuckoo = engine.equals("cuckoochess");
|
||||||
if (uciEngine == null) {
|
if (uciEngine == null) {
|
||||||
@@ -572,8 +584,6 @@ public class DroidComputerPlayer {
|
|||||||
|
|
||||||
/** Notify GUI about search statistics. */
|
/** Notify GUI about search statistics. */
|
||||||
private final synchronized void notifyGUI(Position pos, Move ponderMove) {
|
private final synchronized void notifyGUI(Position pos, Move ponderMove) {
|
||||||
if (listener == null)
|
|
||||||
return;
|
|
||||||
if (depthModified) {
|
if (depthModified) {
|
||||||
listener.notifyDepth(statCurrDepth);
|
listener.notifyDepth(statCurrDepth);
|
||||||
depthModified = false;
|
depthModified = false;
|
||||||
|
|||||||
@@ -713,6 +713,11 @@ public class DroidChessController {
|
|||||||
public void prefsChanged() {
|
public void prefsChanged() {
|
||||||
setSearchInfo();
|
setSearchInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifySearchResult(Game g, String cmd, Move ponder) {
|
||||||
|
makeComputerMove(g, cmd, ponder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void updateBookHints() {
|
private final void updateBookHints() {
|
||||||
@@ -927,36 +932,11 @@ public class DroidChessController {
|
|||||||
final Move fPonderMove = ponder ? ponderMove : null;
|
final Move fPonderMove = ponder ? ponderMove : null;
|
||||||
computerThread = new Thread(new Runnable() {
|
computerThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
computerPlayer.setEngineStrength(engine, strength);
|
computerPlayer.doSearch(ph.first, ph.second, currPos, haveDrawOffer,
|
||||||
computerPlayer.setNumPV(1);
|
wTime, bTime, inc, fMovesToGo,
|
||||||
final Pair<String,Move> pair =
|
gui.ponderMode(), fPonderMove,
|
||||||
computerPlayer.doSearch(ph.first, ph.second, currPos, haveDrawOffer,
|
gui.engineThreads(),
|
||||||
wTime, bTime, inc, fMovesToGo,
|
engine, strength, g);
|
||||||
gui.ponderMode(), fPonderMove,
|
|
||||||
gui.engineThreads());
|
|
||||||
final String cmd = pair.first;
|
|
||||||
final Move ponder = pair.second;
|
|
||||||
final SearchStatus localSS = ss;
|
|
||||||
gui.runOnUIThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
synchronized (shutdownEngineLock) {
|
|
||||||
if (!localSS.searchResultWanted)
|
|
||||||
return;
|
|
||||||
Position oldPos = new Position(g.currPos());
|
|
||||||
g.processString(cmd);
|
|
||||||
ponderMove = ponder;
|
|
||||||
updateGameMode();
|
|
||||||
gui.computerMoveMade();
|
|
||||||
listener.clearSearchInfo();
|
|
||||||
stopComputerThinking();
|
|
||||||
stopAnalysis(); // To force analysis to restart for new position
|
|
||||||
updateComputeThreads(true);
|
|
||||||
setSelection();
|
|
||||||
setAnimMove(oldPos, g.getLastMove(), true);
|
|
||||||
updateGUI();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
listener.clearSearchInfo();
|
listener.clearSearchInfo();
|
||||||
@@ -965,6 +945,30 @@ public class DroidChessController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final void makeComputerMove(final Game g, final String cmd, final Move ponder) {
|
||||||
|
final SearchStatus localSS = ss;
|
||||||
|
gui.runOnUIThread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
synchronized (shutdownEngineLock) {
|
||||||
|
if (!localSS.searchResultWanted)
|
||||||
|
return;
|
||||||
|
Position oldPos = new Position(g.currPos());
|
||||||
|
g.processString(cmd);
|
||||||
|
ponderMove = ponder;
|
||||||
|
updateGameMode();
|
||||||
|
gui.computerMoveMade();
|
||||||
|
listener.clearSearchInfo();
|
||||||
|
stopComputerThinking();
|
||||||
|
stopAnalysis(); // To force analysis to restart for new position
|
||||||
|
updateComputeThreads(true);
|
||||||
|
setSelection();
|
||||||
|
setAnimMove(oldPos, g.getLastMove(), true);
|
||||||
|
updateGUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private final synchronized boolean stopComputerThinking() {
|
private final synchronized boolean stopComputerThinking() {
|
||||||
if (computerThread != null) {
|
if (computerThread != null) {
|
||||||
computerPlayer.stopSearch();
|
computerPlayer.stopSearch();
|
||||||
@@ -990,12 +994,9 @@ public class DroidChessController {
|
|||||||
final boolean alive = game.tree.getGameState() == GameState.ALIVE;
|
final boolean alive = game.tree.getGameState() == GameState.ALIVE;
|
||||||
analysisThread = new Thread(new Runnable() {
|
analysisThread = new Thread(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (alive) {
|
if (alive)
|
||||||
computerPlayer.setEngineStrength(engine, 1000);
|
|
||||||
computerPlayer.setNumPV(numPV);
|
|
||||||
computerPlayer.analyze(ph.first, ph.second, currPos, haveDrawOffer,
|
computerPlayer.analyze(ph.first, ph.second, currPos, haveDrawOffer,
|
||||||
gui.engineThreads());
|
gui.engineThreads(), engine, numPV);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
listener.clearSearchInfo();
|
listener.clearSearchInfo();
|
||||||
|
|||||||
@@ -77,4 +77,6 @@ public interface SearchListener {
|
|||||||
public void notifyPV(Position pos, ArrayList<PvInfo> pvInfo, boolean isPonder);
|
public void notifyPV(Position pos, ArrayList<PvInfo> pvInfo, boolean isPonder);
|
||||||
public void notifyStats(int nodes, int nps, int time);
|
public void notifyStats(int nodes, int nps, int time);
|
||||||
public void notifyBookInfo(String bookInfo, List<Move> moveList);
|
public void notifyBookInfo(String bookInfo, List<Move> moveList);
|
||||||
|
|
||||||
|
public void notifySearchResult(Game g, String cmd, Move ponder);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user