mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-10 16:12:41 +01:00
DroidFish: Some code re-organization.
This commit is contained in:
@@ -107,6 +107,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
||||
// FIXME!!! PGN view option: game continuation (for training)
|
||||
// FIXME!!! Remove invalid playerActions in PGN import (should be done in verifyChildren)
|
||||
// FIXME!!! Implement bookmark mechanism for positions in pgn files
|
||||
// FIXME!!! Display chess notation in local language
|
||||
|
||||
// FIXME!!! Computer clock should stop if phone turned off (computer stops thinking if unplugged)
|
||||
// FIXME!!! Add support for all time controls defined by the PGN standard
|
||||
@@ -511,9 +512,8 @@ public class DroidFish extends Activity implements GUIInterface {
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (ctrl != null) {
|
||||
if (ctrl != null)
|
||||
ctrl.shutdownEngine();
|
||||
}
|
||||
setNotification(false);
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -1552,7 +1552,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
||||
for (int i = 0; i < pvMovesTmp.size(); i++) {
|
||||
ArrayList<Move> pv = pvMovesTmp.get(i);
|
||||
StringBuilder preComment = new StringBuilder();
|
||||
if (pvStrs.length > i) {
|
||||
if (i < pvStrs.length) {
|
||||
String[] tmp = pvStrs[i].split(" ");
|
||||
for (int j = 0; j < 2; j++) {
|
||||
if (j < tmp.length) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public interface GUIInterface {
|
||||
/** Update the displayed board position. */
|
||||
public void setPosition(Position pos, String variantInfo, List<Move> variantMoves);
|
||||
|
||||
/** Mark square i as selected. Set to -1 to clear selection. */
|
||||
/** Mark square sq as selected. Set to -1 to clear selection. */
|
||||
public void setSelection(int sq);
|
||||
|
||||
final static class GameStatus {
|
||||
|
||||
@@ -271,7 +271,7 @@ public class CtgBook implements IOpeningBook {
|
||||
return page;
|
||||
}
|
||||
|
||||
final private static int tbl[] = {
|
||||
private final static int tbl[] = {
|
||||
0x3100d2bf, 0x3118e3de, 0x34ab1372, 0x2807a847,
|
||||
0x1633f566, 0x2143b359, 0x26d56488, 0x3b9e6f59,
|
||||
0x37755656, 0x3089ca7b, 0x18e92d85, 0x0cd0e9d8,
|
||||
@@ -290,7 +290,7 @@ public class CtgBook implements IOpeningBook {
|
||||
0x274c7e7c, 0x1e8be65c, 0x2fa0b0bb, 0x1eb6c371
|
||||
};
|
||||
|
||||
final private static int getHashValue(byte[] encodedPos) {
|
||||
private final static int getHashValue(byte[] encodedPos) {
|
||||
int hash = 0;
|
||||
int tmp = 0;
|
||||
for (int i = 0; i < encodedPos.length; i++) {
|
||||
|
||||
@@ -74,6 +74,7 @@ public final class DroidBook {
|
||||
rndGen.setSeed(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/** Set opening book options. */
|
||||
public final void setOptions(BookOptions options) {
|
||||
this.options = options;
|
||||
if (CtgBook.canHandle(options))
|
||||
@@ -136,7 +137,7 @@ public final class DroidBook {
|
||||
}
|
||||
}
|
||||
|
||||
/** Return a string describing all book moves. */
|
||||
/** Return all book moves, both as a formatted string and as a list of moves. */
|
||||
public final Pair<String,ArrayList<Move>> getAllBookMoves(Position pos) {
|
||||
StringBuilder ret = new StringBuilder();
|
||||
ArrayList<Move> bookMoveList = new ArrayList<Move>();
|
||||
|
||||
@@ -46,11 +46,13 @@ public class DroidComputerPlayer {
|
||||
private DroidBook book;
|
||||
private boolean newGame = false;
|
||||
private String engine = "";
|
||||
private int maxPV = 1; // >1 if multiPV mode is supported
|
||||
/** >1 if multiPV mode is supported. */
|
||||
private int maxPV = 1;
|
||||
private int numCPUs = 1;
|
||||
|
||||
private boolean havePonderHit = false;
|
||||
|
||||
/** Constructor. Starts engine process if not already started. */
|
||||
public DroidComputerPlayer(String engine) {
|
||||
this.engine = engine;
|
||||
startEngine();
|
||||
@@ -58,6 +60,245 @@ 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();
|
||||
}
|
||||
if (uciEngine != null)
|
||||
uciEngine.setStrength(strength);
|
||||
}
|
||||
|
||||
/** Set search listener. */
|
||||
public final void setListener(SearchListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
/** 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);
|
||||
}
|
||||
|
||||
/** Return all book moves, both as a formatted string and as a list of moves. */
|
||||
public final Pair<String, ArrayList<Move>> getBookHints(Position pos) {
|
||||
return book.getAllBookMoves(pos);
|
||||
}
|
||||
|
||||
/** Get engine reported name, including strength setting. */
|
||||
public synchronized String getEngineName() {
|
||||
if (uciEngine != null)
|
||||
return engineName + uciEngine.addStrengthToName();
|
||||
else
|
||||
return engineName;
|
||||
}
|
||||
|
||||
/** Clear transposition table. */
|
||||
public final void clearTT() {
|
||||
newGame = true;
|
||||
}
|
||||
|
||||
/** Sends "ucinewgame" to engine if clearTT() has previously been called. */
|
||||
public final void maybeNewGame() {
|
||||
if (newGame) {
|
||||
newGame = false;
|
||||
if (uciEngine != null) {
|
||||
uciEngine.writeLineToEngine("ucinewgame");
|
||||
syncReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends "ponderhit" command to engine. */
|
||||
public final synchronized void ponderHit(Position pos, Move ponderMove) {
|
||||
havePonderHit = true;
|
||||
uciEngine.writeLineToEngine("ponderhit");
|
||||
pvModified = true;
|
||||
notifyGUI(pos, ponderMove);
|
||||
}
|
||||
|
||||
/** Stop the engine process. */
|
||||
public final synchronized void shutdownEngine() {
|
||||
if (uciEngine != null) {
|
||||
uciEngine.shutDown();
|
||||
uciEngine = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a search and return a command from the computer player.
|
||||
* The command can be a valid move string, in which case the move is played
|
||||
* and the turn goes over to the other player. The command can also be a special
|
||||
* command, such as "draw" and "resign".
|
||||
* @param pos An earlier position from the game
|
||||
* @param mList List of moves to go from the earlier position to the current position.
|
||||
* This list makes it possible for the computer to correctly handle draw
|
||||
* by repetition/50 moves.
|
||||
* @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.
|
||||
*/
|
||||
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);
|
||||
|
||||
if (ponderMove != null)
|
||||
mList.add(ponderMove);
|
||||
|
||||
havePonderHit = false;
|
||||
|
||||
// Set up for draw detection
|
||||
long[] posHashList = new long[mList.size()+1];
|
||||
int posHashListSize = 0;
|
||||
Position p = new Position(prevPos);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
for (int i = 0; i < mList.size(); i++) {
|
||||
posHashList[posHashListSize++] = p.zobristHash();
|
||||
p.makeMove(mList.get(i), ui);
|
||||
}
|
||||
|
||||
if (ponderMove == null) {
|
||||
// If we have a book move, play it.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// If only one legal move, play it without searching
|
||||
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.
|
||||
}
|
||||
if (moves.size() == 1) {
|
||||
Move bestMove = moves.get(0);
|
||||
if (canClaimDraw(currPos, posHashList, posHashListSize, bestMove) == "") {
|
||||
return new Pair<String,Move>(TextIO.moveToUCIString(bestMove), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder posStr = new StringBuilder();
|
||||
posStr.append("position fen ");
|
||||
posStr.append(TextIO.toFEN(prevPos));
|
||||
int nMoves = mList.size();
|
||||
if (nMoves > 0) {
|
||||
posStr.append(" moves");
|
||||
for (int i = 0; i < nMoves; i++) {
|
||||
posStr.append(" ");
|
||||
posStr.append(TextIO.moveToUCIString(mList.get(i)));
|
||||
}
|
||||
}
|
||||
maybeNewGame();
|
||||
uciEngine.setOption("Ponder", ponderEnabled);
|
||||
uciEngine.setOption("UCI_AnalyseMode", false);
|
||||
uciEngine.setOption("Threads", engineThreads > 0 ? engineThreads : numCPUs);
|
||||
uciEngine.writeLineToEngine(posStr.toString());
|
||||
if (wTime < 1) wTime = 1;
|
||||
if (bTime < 1) bTime = 1;
|
||||
StringBuilder goStr = new StringBuilder(96);
|
||||
goStr.append(String.format("go wtime %d btime %d", wTime, bTime));
|
||||
if (inc > 0)
|
||||
goStr.append(String.format(" winc %d binc %d", inc, inc));
|
||||
if (movesToGo > 0)
|
||||
goStr.append(String.format(" movestogo %d", movesToGo));
|
||||
if (ponderMove != null)
|
||||
goStr.append(" ponder");
|
||||
uciEngine.writeLineToEngine(goStr.toString());
|
||||
|
||||
Pair<String,String> pair = monitorEngine(currPos, ponderMove);
|
||||
String bestMove = pair.first;
|
||||
Move nextPonderMove = TextIO.UCIstringToMove(pair.second);
|
||||
|
||||
// Claim draw if appropriate
|
||||
if (statScore <= 0) {
|
||||
String drawClaim = canClaimDraw(currPos, posHashList, posHashListSize, TextIO.UCIstringToMove(bestMove));
|
||||
if (drawClaim != "")
|
||||
bestMove = drawClaim;
|
||||
}
|
||||
// Accept draw offer if engine is losing
|
||||
if (drawOffer && !statIsMate && (statScore <= -300)) {
|
||||
bestMove = "draw accept";
|
||||
}
|
||||
return new Pair<String,Move>(bestMove, nextPonderMove);
|
||||
}
|
||||
|
||||
public boolean shouldStop = false;
|
||||
|
||||
/** Tell engine to stop searching. */
|
||||
public final synchronized void stopSearch() {
|
||||
shouldStop = true;
|
||||
if (uciEngine != null)
|
||||
uciEngine.writeLineToEngine("stop");
|
||||
havePonderHit = false;
|
||||
}
|
||||
|
||||
/** Start analyzing a position.
|
||||
* @param prevPos Position corresponding to last irreversible move.
|
||||
* @param mList List of moves from prevPos to currPos.
|
||||
* @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.
|
||||
*/
|
||||
public final void analyze(Position prevPos, ArrayList<Move> mList, Position currPos,
|
||||
boolean drawOffer, int engineThreads) {
|
||||
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);
|
||||
if (moves.size() == 0)
|
||||
return;
|
||||
|
||||
StringBuilder posStr = new StringBuilder();
|
||||
posStr.append("position fen ");
|
||||
posStr.append(TextIO.toFEN(prevPos));
|
||||
int nMoves = mList.size();
|
||||
if (nMoves > 0) {
|
||||
posStr.append(" moves");
|
||||
for (int i = 0; i < nMoves; i++) {
|
||||
posStr.append(" ");
|
||||
posStr.append(TextIO.moveToUCIString(mList.get(i)));
|
||||
}
|
||||
}
|
||||
maybeNewGame();
|
||||
uciEngine.writeLineToEngine(posStr.toString());
|
||||
uciEngine.setOption("UCI_AnalyseMode", true);
|
||||
uciEngine.setOption("Threads", engineThreads > 0 ? engineThreads : numCPUs);
|
||||
String goStr = String.format("go infinite");
|
||||
uciEngine.writeLineToEngine(goStr);
|
||||
|
||||
monitorEngine(currPos, null);
|
||||
}
|
||||
|
||||
private final synchronized void startEngine() {
|
||||
boolean useCuckoo = engine.equals("cuckoochess");
|
||||
if (uciEngine == null) {
|
||||
@@ -80,27 +321,6 @@ public class DroidComputerPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void setEngineStrength(String engine, int strength) {
|
||||
if (!engine.equals(this.engine)) {
|
||||
shutdownEngine();
|
||||
this.engine = engine;
|
||||
startEngine();
|
||||
}
|
||||
if (uciEngine != null)
|
||||
uciEngine.setStrength(strength);
|
||||
}
|
||||
|
||||
public final synchronized int getMaxPV() {
|
||||
return maxPV;
|
||||
}
|
||||
|
||||
public final synchronized void setNumPV(int numPV) {
|
||||
if ((uciEngine != null) && (maxPV > 1)) {
|
||||
int num = Math.min(maxPV, numPV);
|
||||
uciEngine.setOption("MultiPV", num);
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNumCPUs() {
|
||||
int nCPUsFromProc = 1;
|
||||
try {
|
||||
@@ -121,15 +341,7 @@ public class DroidComputerPlayer {
|
||||
return Math.max(nCPUsFromProc, nCPUsFromOS);
|
||||
}
|
||||
|
||||
public final void setListener(SearchListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public final void setBookOptions(BookOptions options) {
|
||||
book.setOptions(options);
|
||||
}
|
||||
|
||||
private void readUCIOptions() {
|
||||
private final void readUCIOptions() {
|
||||
int timeout = 1000;
|
||||
maxPV = 1;
|
||||
while (true) {
|
||||
@@ -159,13 +371,6 @@ public class DroidComputerPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized String getEngineName() {
|
||||
if (uciEngine != null)
|
||||
return engineName + uciEngine.addStrengthToName();
|
||||
else
|
||||
return engineName;
|
||||
}
|
||||
|
||||
/** Convert a string to tokens by splitting at whitespace characters. */
|
||||
private final String[] tokenize(String cmdLine) {
|
||||
cmdLine = cmdLine.trim();
|
||||
@@ -181,141 +386,6 @@ public class DroidComputerPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear transposition table. */
|
||||
public final void clearTT() {
|
||||
newGame = true;
|
||||
}
|
||||
|
||||
public final void maybeNewGame() {
|
||||
if (newGame) {
|
||||
newGame = false;
|
||||
if (uciEngine != null) {
|
||||
uciEngine.writeLineToEngine("ucinewgame");
|
||||
syncReady();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Stop the engine process. */
|
||||
public final synchronized void shutdownEngine() {
|
||||
if (uciEngine != null) {
|
||||
uciEngine.shutDown();
|
||||
uciEngine = null;
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void ponderHit(Position pos, Move ponderMove) {
|
||||
havePonderHit = true;
|
||||
uciEngine.writeLineToEngine("ponderhit");
|
||||
pvModified = true;
|
||||
notifyGUI(pos, ponderMove);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a search and return a command from the computer player.
|
||||
* The command can be a valid move string, in which case the move is played
|
||||
* and the turn goes over to the other player. The command can also be a special
|
||||
* command, such as "draw" and "resign".
|
||||
* @param pos An earlier position from the game
|
||||
* @param mList List of moves to go from the earlier position to the current position.
|
||||
* This list makes it possible for the computer to correctly handle draw
|
||||
* by repetition/50 moves.
|
||||
* @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.
|
||||
*/
|
||||
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);
|
||||
|
||||
if (ponderMove != null)
|
||||
mList.add(ponderMove);
|
||||
|
||||
havePonderHit = false;
|
||||
|
||||
// Set up for draw detection
|
||||
long[] posHashList = new long[mList.size()+1];
|
||||
int posHashListSize = 0;
|
||||
Position p = new Position(prevPos);
|
||||
UndoInfo ui = new UndoInfo();
|
||||
for (int i = 0; i < mList.size(); i++) {
|
||||
posHashList[posHashListSize++] = p.zobristHash();
|
||||
p.makeMove(mList.get(i), ui);
|
||||
}
|
||||
|
||||
if (ponderMove == null) {
|
||||
// If we have a book move, play it.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// If only one legal move, play it without searching
|
||||
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.
|
||||
}
|
||||
if (moves.size() == 1) {
|
||||
Move bestMove = moves.get(0);
|
||||
if (canClaimDraw(currPos, posHashList, posHashListSize, bestMove) == "") {
|
||||
return new Pair<String,Move>(TextIO.moveToUCIString(bestMove), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder posStr = new StringBuilder();
|
||||
posStr.append("position fen ");
|
||||
posStr.append(TextIO.toFEN(prevPos));
|
||||
int nMoves = mList.size();
|
||||
if (nMoves > 0) {
|
||||
posStr.append(" moves");
|
||||
for (int i = 0; i < nMoves; i++) {
|
||||
posStr.append(" ");
|
||||
posStr.append(TextIO.moveToUCIString(mList.get(i)));
|
||||
}
|
||||
}
|
||||
maybeNewGame();
|
||||
uciEngine.setOption("Ponder", ponderEnabled);
|
||||
uciEngine.setOption("UCI_AnalyseMode", false);
|
||||
uciEngine.setOption("Threads", engineThreads > 0 ? engineThreads : numCPUs);
|
||||
uciEngine.writeLineToEngine(posStr.toString());
|
||||
if (wTime < 1) wTime = 1;
|
||||
if (bTime < 1) bTime = 1;
|
||||
StringBuilder goStr = new StringBuilder(96);
|
||||
goStr.append(String.format("go wtime %d btime %d", wTime, bTime));
|
||||
if (inc > 0)
|
||||
goStr.append(String.format(" winc %d binc %d", inc, inc));
|
||||
if (movesToGo > 0)
|
||||
goStr.append(String.format(" movestogo %d", movesToGo));
|
||||
if (ponderMove != null)
|
||||
goStr.append(" ponder");
|
||||
uciEngine.writeLineToEngine(goStr.toString());
|
||||
|
||||
Pair<String,String> pair = monitorEngine(currPos, ponderMove);
|
||||
String bestMove = pair.first;
|
||||
Move nextPonderMove = TextIO.UCIstringToMove(pair.second);
|
||||
|
||||
// Claim draw if appropriate
|
||||
if (statScore <= 0) {
|
||||
String drawClaim = canClaimDraw(currPos, posHashList, posHashListSize, TextIO.UCIstringToMove(bestMove));
|
||||
if (drawClaim != "")
|
||||
bestMove = drawClaim;
|
||||
}
|
||||
// Accept draw offer if engine is losing
|
||||
if (drawOffer && !statIsMate && (statScore <= -300)) {
|
||||
bestMove = "draw accept";
|
||||
}
|
||||
return new Pair<String,Move>(bestMove, nextPonderMove);
|
||||
}
|
||||
|
||||
/** Wait for engine to respond with bestMove and ponderMove.
|
||||
* While waiting, monitor and report search info. */
|
||||
private final Pair<String,String> monitorEngine(Position pos, Move ponderMove) {
|
||||
@@ -355,49 +425,6 @@ public class DroidComputerPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
public final Pair<String, ArrayList<Move>> getBookHints(Position pos) {
|
||||
Pair<String, ArrayList<Move>> bi = book.getAllBookMoves(pos);
|
||||
return new Pair<String, ArrayList<Move>>(bi.first, bi.second);
|
||||
}
|
||||
|
||||
public boolean shouldStop = false;
|
||||
|
||||
public final void analyze(Position prevPos, ArrayList<Move> mList, Position currPos,
|
||||
boolean drawOffer, int engineThreads) {
|
||||
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);
|
||||
if (moves.size() == 0)
|
||||
return;
|
||||
|
||||
StringBuilder posStr = new StringBuilder();
|
||||
posStr.append("position fen ");
|
||||
posStr.append(TextIO.toFEN(prevPos));
|
||||
int nMoves = mList.size();
|
||||
if (nMoves > 0) {
|
||||
posStr.append(" moves");
|
||||
for (int i = 0; i < nMoves; i++) {
|
||||
posStr.append(" ");
|
||||
posStr.append(TextIO.moveToUCIString(mList.get(i)));
|
||||
}
|
||||
}
|
||||
maybeNewGame();
|
||||
uciEngine.writeLineToEngine(posStr.toString());
|
||||
uciEngine.setOption("UCI_AnalyseMode", true);
|
||||
uciEngine.setOption("Threads", engineThreads > 0 ? engineThreads : numCPUs);
|
||||
String goStr = String.format("go infinite");
|
||||
uciEngine.writeLineToEngine(goStr);
|
||||
|
||||
monitorEngine(currPos, null);
|
||||
}
|
||||
|
||||
/** Check if a draw claim is allowed, possibly after playing "move".
|
||||
* @param move The move that may have to be made before claiming draw.
|
||||
* @return The draw string that claims the draw, or empty string if draw claim not valid.
|
||||
@@ -583,11 +610,4 @@ public class DroidComputerPlayer {
|
||||
statsModified = false;
|
||||
}
|
||||
}
|
||||
|
||||
public final synchronized void stopSearch() {
|
||||
shouldStop = true;
|
||||
if (uciEngine != null)
|
||||
uciEngine.writeLineToEngine("stop");
|
||||
havePonderHit = false;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@ public class Game {
|
||||
private DroidComputerPlayer computerPlayer;
|
||||
TimeControl timeController;
|
||||
private boolean gamePaused;
|
||||
/** If true, add new moves as mainline moves. */
|
||||
private boolean addFirst;
|
||||
|
||||
PgnToken.PgnTokenReceiver gameTextListener;
|
||||
@@ -50,6 +51,7 @@ public class Game {
|
||||
newGame();
|
||||
}
|
||||
|
||||
/** De-serialize from byte array. */
|
||||
final void fromByteArray(byte[] data) {
|
||||
tree.fromByteArray(data);
|
||||
updateTimeControl(true);
|
||||
@@ -66,10 +68,12 @@ public class Game {
|
||||
}
|
||||
}
|
||||
|
||||
/** Set whether new moves are entered as mainline moves or variations. */
|
||||
public final void setAddFirst(boolean addFirst) {
|
||||
this.addFirst = addFirst;
|
||||
}
|
||||
|
||||
/** Sets start position and discards the whole game tree. */
|
||||
final void setPos(Position pos) {
|
||||
tree.setStartPos(new Position(pos));
|
||||
updateTimeControl(false);
|
||||
@@ -217,6 +221,7 @@ public class Game {
|
||||
return nVar > 0;
|
||||
}
|
||||
|
||||
/** Get number of variations in current game position. */
|
||||
public final int numVariations() {
|
||||
if (tree.currentNode == tree.rootNode)
|
||||
return 1;
|
||||
@@ -226,6 +231,7 @@ public class Game {
|
||||
return nChildren;
|
||||
}
|
||||
|
||||
/** Get current variation in current position. */
|
||||
public final int currVariation() {
|
||||
if (tree.currentNode == tree.rootNode)
|
||||
return 0;
|
||||
@@ -235,6 +241,7 @@ public class Game {
|
||||
return defChild;
|
||||
}
|
||||
|
||||
/** Go to a new variation in the game tree. */
|
||||
public final void changeVariation(int delta) {
|
||||
if (tree.currentNode == tree.rootNode)
|
||||
return;
|
||||
@@ -249,6 +256,7 @@ public class Game {
|
||||
updateTimeControl(true);
|
||||
}
|
||||
|
||||
/** Move current variation up/down in the game tree. */
|
||||
public final void moveVariation(int delta) {
|
||||
if (tree.currentNode == tree.rootNode)
|
||||
return;
|
||||
@@ -264,6 +272,7 @@ public class Game {
|
||||
updateTimeControl(true);
|
||||
}
|
||||
|
||||
/** Delete whole game sub-tree rooted at current position. */
|
||||
public final void removeSubTree() {
|
||||
if (getLastMove() != null) {
|
||||
tree.goBack();
|
||||
@@ -323,10 +332,14 @@ public class Game {
|
||||
}
|
||||
}
|
||||
|
||||
public final void goNode(Node node) {
|
||||
tree.goNode(node);
|
||||
/** Go to given node in game tree.
|
||||
* @return True if current node changed, false otherwise. */
|
||||
public final boolean goNode(Node node) {
|
||||
if (!tree.goNode(node))
|
||||
return false;
|
||||
pendingDrawOffer = false;
|
||||
updateTimeControl(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
public final void newGame() {
|
||||
|
||||
@@ -657,13 +657,17 @@ public class GameTree {
|
||||
}
|
||||
}
|
||||
|
||||
/** Go to given node in game tree. */
|
||||
public final void goNode(Node node) {
|
||||
/** Go to given node in game tree.
|
||||
* @return True if current node changed, false otherwise. */
|
||||
public final boolean goNode(Node node) {
|
||||
if (node == currentNode)
|
||||
return false;
|
||||
ArrayList<Integer> path = node.getPathFromRoot();
|
||||
while (currentNode != rootNode)
|
||||
goBack();
|
||||
for (Integer c : path)
|
||||
goForward(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** List of possible continuation moves. */
|
||||
@@ -1388,6 +1392,7 @@ public class GameTree {
|
||||
}
|
||||
}
|
||||
|
||||
/** Set PGN header tags and values. */
|
||||
void setHeaders(Map<String,String> headers) {
|
||||
for (Entry<String, String> entry : headers.entrySet()) {
|
||||
String tag = entry.getKey();
|
||||
@@ -1417,6 +1422,7 @@ public class GameTree {
|
||||
}
|
||||
}
|
||||
|
||||
/** Get PGN header tags and values. */
|
||||
void getHeaders(Map<String,String> headers) {
|
||||
headers.put("Event", event);
|
||||
headers.put("Site", site);
|
||||
|
||||
@@ -667,7 +667,8 @@ public class GameTreeTest extends TestCase {
|
||||
for (int i = 0; i < 5; i++) gt.goForward(-1);
|
||||
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
||||
Node na6 = gt.currentNode;
|
||||
gt.goNode(gt.rootNode);
|
||||
assertTrue(gt.goNode(gt.rootNode));
|
||||
assertFalse(gt.goNode(gt.rootNode));
|
||||
assertEquals("*e4 e5 Nf3 Nc6 Bb5 a6", getMoveListAsString(gt));
|
||||
gt.goNode(na6);
|
||||
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
||||
|
||||
Reference in New Issue
Block a user