DroidFish: Use the SearchListener interface to communicate the search result (best move + ponder move) back to the DroidChessController.

This commit is contained in:
Peter Osterlund 2011-12-28 20:11:48 +00:00
parent 6165005464
commit 9d7d30b293
3 changed files with 87 additions and 74 deletions

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
import org.petero.droidfish.BookOptions;
import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine;
import org.petero.droidfish.gamelogic.Game;
import org.petero.droidfish.gamelogic.Move;
import org.petero.droidfish.gamelogic.MoveGen;
import org.petero.droidfish.gamelogic.Pair;
@ -63,33 +64,11 @@ public class DroidComputerPlayer {
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. */
public final synchronized int getMaxPV() {
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. */
public final void setBookOptions(BookOptions 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 ponderMove Move to ponder, or null for non-ponder search.
* @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,
Position currPos, boolean drawOffer,
int wTime, int bTime, int inc, int movesToGo,
boolean ponderEnabled, Move ponderMove,
int engineThreads) {
if (listener != null)
listener.notifyBookInfo("", null);
public final void doSearch(Position prevPos, ArrayList<Move> mList,
Position currPos, boolean drawOffer,
int wTime, int bTime, int inc, int movesToGo,
boolean ponderEnabled, Move ponderMove,
int engineThreads,
String engine, int strength, Game g) {
setEngineStrength(engine, strength);
setNumPV(1);
listener.notifyBookInfo("", null);
if (ponderMove != null)
mList.add(ponderMove);
@ -171,7 +153,8 @@ public class DroidComputerPlayer {
Move bookMove = book.getBookMove(currPos);
if (bookMove != null) {
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);
moves = MoveGen.removeIllegal(currPos, moves);
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) {
Move bestMove = moves.get(0);
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)) {
bestMove = "draw accept";
}
return new Pair<String,Move>(bestMove, nextPonderMove);
listener.notifySearchResult(g, bestMove, nextPonderMove);
}
public boolean shouldStop = false;
@ -250,16 +235,21 @@ public class DroidComputerPlayer {
* @param currPos Position to analyze.
* @param drawOffer True if other side have offered draw.
* @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,
boolean drawOffer, int engineThreads) {
boolean drawOffer, int engineThreads,
String engine, int numPV) {
setEngineStrength(engine, 1000);
setNumPV(numPV);
if (shouldStop)
return;
if (listener != null) {
{
Pair<String, ArrayList<Move>> bi = getBookHints(currPos);
listener.notifyBookInfo(bi.first, bi.second);
}
// If no legal moves, there is nothing to analyze
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(currPos);
moves = MoveGen.removeIllegal(currPos, moves);
@ -287,6 +277,28 @@ public class DroidComputerPlayer {
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() {
boolean useCuckoo = engine.equals("cuckoochess");
if (uciEngine == null) {
@ -572,8 +584,6 @@ public class DroidComputerPlayer {
/** Notify GUI about search statistics. */
private final synchronized void notifyGUI(Position pos, Move ponderMove) {
if (listener == null)
return;
if (depthModified) {
listener.notifyDepth(statCurrDepth);
depthModified = false;

View File

@ -713,6 +713,11 @@ public class DroidChessController {
public void prefsChanged() {
setSearchInfo();
}
@Override
public void notifySearchResult(Game g, String cmd, Move ponder) {
makeComputerMove(g, cmd, ponder);
}
}
private final void updateBookHints() {
@ -927,36 +932,11 @@ public class DroidChessController {
final Move fPonderMove = ponder ? ponderMove : null;
computerThread = new Thread(new Runnable() {
public void run() {
computerPlayer.setEngineStrength(engine, strength);
computerPlayer.setNumPV(1);
final Pair<String,Move> pair =
computerPlayer.doSearch(ph.first, ph.second, currPos, haveDrawOffer,
wTime, bTime, inc, fMovesToGo,
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();
}
}
});
computerPlayer.doSearch(ph.first, ph.second, currPos, haveDrawOffer,
wTime, bTime, inc, fMovesToGo,
gui.ponderMode(), fPonderMove,
gui.engineThreads(),
engine, strength, g);
}
});
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() {
if (computerThread != null) {
computerPlayer.stopSearch();
@ -990,12 +994,9 @@ public class DroidChessController {
final boolean alive = game.tree.getGameState() == GameState.ALIVE;
analysisThread = new Thread(new Runnable() {
public void run() {
if (alive) {
computerPlayer.setEngineStrength(engine, 1000);
computerPlayer.setNumPV(numPV);
if (alive)
computerPlayer.analyze(ph.first, ph.second, currPos, haveDrawOffer,
gui.engineThreads());
}
gui.engineThreads(), engine, numPV);
}
});
listener.clearSearchInfo();

View File

@ -77,4 +77,6 @@ public interface SearchListener {
public void notifyPV(Position pos, ArrayList<PvInfo> pvInfo, boolean isPonder);
public void notifyStats(int nodes, int nps, int time);
public void notifyBookInfo(String bookInfo, List<Move> moveList);
public void notifySearchResult(Game g, String cmd, Move ponder);
}