mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2025-12-11 16:42: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!!! PGN view option: game continuation (for training)
|
||||||
// FIXME!!! Remove invalid playerActions in PGN import (should be done in verifyChildren)
|
// FIXME!!! Remove invalid playerActions in PGN import (should be done in verifyChildren)
|
||||||
// FIXME!!! Implement bookmark mechanism for positions in pgn files
|
// 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!!! 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
|
// FIXME!!! Add support for all time controls defined by the PGN standard
|
||||||
@@ -511,9 +512,8 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
if (ctrl != null) {
|
if (ctrl != null)
|
||||||
ctrl.shutdownEngine();
|
ctrl.shutdownEngine();
|
||||||
}
|
|
||||||
setNotification(false);
|
setNotification(false);
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
@@ -1552,7 +1552,7 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||||||
for (int i = 0; i < pvMovesTmp.size(); i++) {
|
for (int i = 0; i < pvMovesTmp.size(); i++) {
|
||||||
ArrayList<Move> pv = pvMovesTmp.get(i);
|
ArrayList<Move> pv = pvMovesTmp.get(i);
|
||||||
StringBuilder preComment = new StringBuilder();
|
StringBuilder preComment = new StringBuilder();
|
||||||
if (pvStrs.length > i) {
|
if (i < pvStrs.length) {
|
||||||
String[] tmp = pvStrs[i].split(" ");
|
String[] tmp = pvStrs[i].split(" ");
|
||||||
for (int j = 0; j < 2; j++) {
|
for (int j = 0; j < 2; j++) {
|
||||||
if (j < tmp.length) {
|
if (j < tmp.length) {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public interface GUIInterface {
|
|||||||
/** Update the displayed board position. */
|
/** Update the displayed board position. */
|
||||||
public void setPosition(Position pos, String variantInfo, List<Move> variantMoves);
|
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);
|
public void setSelection(int sq);
|
||||||
|
|
||||||
final static class GameStatus {
|
final static class GameStatus {
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ public class CtgBook implements IOpeningBook {
|
|||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
final private static int tbl[] = {
|
private final static int tbl[] = {
|
||||||
0x3100d2bf, 0x3118e3de, 0x34ab1372, 0x2807a847,
|
0x3100d2bf, 0x3118e3de, 0x34ab1372, 0x2807a847,
|
||||||
0x1633f566, 0x2143b359, 0x26d56488, 0x3b9e6f59,
|
0x1633f566, 0x2143b359, 0x26d56488, 0x3b9e6f59,
|
||||||
0x37755656, 0x3089ca7b, 0x18e92d85, 0x0cd0e9d8,
|
0x37755656, 0x3089ca7b, 0x18e92d85, 0x0cd0e9d8,
|
||||||
@@ -290,7 +290,7 @@ public class CtgBook implements IOpeningBook {
|
|||||||
0x274c7e7c, 0x1e8be65c, 0x2fa0b0bb, 0x1eb6c371
|
0x274c7e7c, 0x1e8be65c, 0x2fa0b0bb, 0x1eb6c371
|
||||||
};
|
};
|
||||||
|
|
||||||
final private static int getHashValue(byte[] encodedPos) {
|
private final static int getHashValue(byte[] encodedPos) {
|
||||||
int hash = 0;
|
int hash = 0;
|
||||||
int tmp = 0;
|
int tmp = 0;
|
||||||
for (int i = 0; i < encodedPos.length; i++) {
|
for (int i = 0; i < encodedPos.length; i++) {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public final class DroidBook {
|
|||||||
rndGen.setSeed(System.currentTimeMillis());
|
rndGen.setSeed(System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set opening book options. */
|
||||||
public final void setOptions(BookOptions options) {
|
public final void setOptions(BookOptions options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
if (CtgBook.canHandle(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) {
|
public final Pair<String,ArrayList<Move>> getAllBookMoves(Position pos) {
|
||||||
StringBuilder ret = new StringBuilder();
|
StringBuilder ret = new StringBuilder();
|
||||||
ArrayList<Move> bookMoveList = new ArrayList<Move>();
|
ArrayList<Move> bookMoveList = new ArrayList<Move>();
|
||||||
|
|||||||
@@ -46,11 +46,13 @@ public class DroidComputerPlayer {
|
|||||||
private DroidBook book;
|
private DroidBook book;
|
||||||
private boolean newGame = false;
|
private boolean newGame = false;
|
||||||
private String engine = "";
|
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 int numCPUs = 1;
|
||||||
|
|
||||||
private boolean havePonderHit = false;
|
private boolean havePonderHit = false;
|
||||||
|
|
||||||
|
/** Constructor. Starts engine process if not already started. */
|
||||||
public DroidComputerPlayer(String engine) {
|
public DroidComputerPlayer(String engine) {
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
startEngine();
|
startEngine();
|
||||||
@@ -58,28 +60,9 @@ public class DroidComputerPlayer {
|
|||||||
book = DroidBook.getInstance();
|
book = DroidBook.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final synchronized void startEngine() {
|
/** Set engine and engine strength.
|
||||||
boolean useCuckoo = engine.equals("cuckoochess");
|
* @param engine Name of engine.
|
||||||
if (uciEngine == null) {
|
* @param strength Engine strength, 0 - 1000. */
|
||||||
if (useCuckoo) {
|
|
||||||
uciEngine = new CuckooChessEngine();
|
|
||||||
} else {
|
|
||||||
uciEngine = new NativePipedProcess();
|
|
||||||
}
|
|
||||||
uciEngine.initialize();
|
|
||||||
uciEngine.writeLineToEngine("uci");
|
|
||||||
readUCIOptions();
|
|
||||||
int nThreads = getNumCPUs();
|
|
||||||
if (nThreads > 8) nThreads = 8;
|
|
||||||
numCPUs = nThreads;
|
|
||||||
if (!useCuckoo)
|
|
||||||
uciEngine.setOption("Hash", 16);
|
|
||||||
uciEngine.setOption("Ponder", false);
|
|
||||||
uciEngine.writeLineToEngine("ucinewgame");
|
|
||||||
syncReady();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final synchronized void setEngineStrength(String engine, int strength) {
|
public final synchronized void setEngineStrength(String engine, int strength) {
|
||||||
if (!engine.equals(this.engine)) {
|
if (!engine.equals(this.engine)) {
|
||||||
shutdownEngine();
|
shutdownEngine();
|
||||||
@@ -90,10 +73,17 @@ public class DroidComputerPlayer {
|
|||||||
uciEngine.setStrength(strength);
|
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() {
|
public final synchronized int getMaxPV() {
|
||||||
return maxPV;
|
return maxPV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set engine multi-PV mode. */
|
||||||
public final synchronized void setNumPV(int numPV) {
|
public final synchronized void setNumPV(int numPV) {
|
||||||
if ((uciEngine != null) && (maxPV > 1)) {
|
if ((uciEngine != null) && (maxPV > 1)) {
|
||||||
int num = Math.min(maxPV, numPV);
|
int num = Math.min(maxPV, numPV);
|
||||||
@@ -101,64 +91,17 @@ public class DroidComputerPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getNumCPUs() {
|
/** Set opening book options. */
|
||||||
int nCPUsFromProc = 1;
|
|
||||||
try {
|
|
||||||
FileReader fr = new FileReader("/proc/stat");
|
|
||||||
BufferedReader inBuf = new BufferedReader(fr, 8192);
|
|
||||||
String line;
|
|
||||||
int nCPUs = 0;
|
|
||||||
while ((line = inBuf.readLine()) != null) {
|
|
||||||
if ((line.length() >= 4) && line.startsWith("cpu") && Character.isDigit(line.charAt(3)))
|
|
||||||
nCPUs++;
|
|
||||||
}
|
|
||||||
inBuf.close();
|
|
||||||
if (nCPUs < 1) nCPUs = 1;
|
|
||||||
nCPUsFromProc = nCPUs;
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
int nCPUsFromOS = NativePipedProcess.getNPhysicalProcessors();
|
|
||||||
return Math.max(nCPUsFromProc, nCPUsFromOS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setListener(SearchListener listener) {
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setBookOptions(BookOptions options) {
|
public final void setBookOptions(BookOptions options) {
|
||||||
book.setOptions(options);
|
book.setOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readUCIOptions() {
|
/** Return all book moves, both as a formatted string and as a list of moves. */
|
||||||
int timeout = 1000;
|
public final Pair<String, ArrayList<Move>> getBookHints(Position pos) {
|
||||||
maxPV = 1;
|
return book.getAllBookMoves(pos);
|
||||||
while (true) {
|
|
||||||
String s = uciEngine.readLineFromEngine(timeout);
|
|
||||||
String[] tokens = tokenize(s);
|
|
||||||
if (tokens[0].equals("uciok"))
|
|
||||||
break;
|
|
||||||
else if (tokens[0].equals("id")) {
|
|
||||||
if (tokens[1].equals("name")) {
|
|
||||||
engineName = "";
|
|
||||||
for (int i = 2; i < tokens.length; i++) {
|
|
||||||
if (engineName.length() > 0)
|
|
||||||
engineName += " ";
|
|
||||||
engineName += tokens[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ((tokens.length > 2) && tokens[2].toLowerCase().equals("multipv")) {
|
|
||||||
try {
|
|
||||||
for (int i = 3; i < tokens.length; i++) {
|
|
||||||
if (tokens[i].equals("max") && (i+1 < tokens.length)) {
|
|
||||||
maxPV = Math.max(maxPV, Integer.parseInt(tokens[i+1]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException nfe) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get engine reported name, including strength setting. */
|
||||||
public synchronized String getEngineName() {
|
public synchronized String getEngineName() {
|
||||||
if (uciEngine != null)
|
if (uciEngine != null)
|
||||||
return engineName + uciEngine.addStrengthToName();
|
return engineName + uciEngine.addStrengthToName();
|
||||||
@@ -166,26 +109,12 @@ public class DroidComputerPlayer {
|
|||||||
return engineName;
|
return engineName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert a string to tokens by splitting at whitespace characters. */
|
|
||||||
private final String[] tokenize(String cmdLine) {
|
|
||||||
cmdLine = cmdLine.trim();
|
|
||||||
return cmdLine.split("\\s+");
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void syncReady() {
|
|
||||||
uciEngine.writeLineToEngine("isready");
|
|
||||||
while (true) {
|
|
||||||
String s = uciEngine.readLineFromEngine(1000);
|
|
||||||
if (s.equals("readyok"))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clear transposition table. */
|
/** Clear transposition table. */
|
||||||
public final void clearTT() {
|
public final void clearTT() {
|
||||||
newGame = true;
|
newGame = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sends "ucinewgame" to engine if clearTT() has previously been called. */
|
||||||
public final void maybeNewGame() {
|
public final void maybeNewGame() {
|
||||||
if (newGame) {
|
if (newGame) {
|
||||||
newGame = false;
|
newGame = false;
|
||||||
@@ -196,6 +125,14 @@ public class DroidComputerPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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. */
|
/** Stop the engine process. */
|
||||||
public final synchronized void shutdownEngine() {
|
public final synchronized void shutdownEngine() {
|
||||||
if (uciEngine != null) {
|
if (uciEngine != null) {
|
||||||
@@ -204,13 +141,6 @@ public class DroidComputerPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
* 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
|
* The command can be a valid move string, in which case the move is played
|
||||||
@@ -316,6 +246,146 @@ public class DroidComputerPlayer {
|
|||||||
return new Pair<String,Move>(bestMove, nextPonderMove);
|
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) {
|
||||||
|
if (useCuckoo) {
|
||||||
|
uciEngine = new CuckooChessEngine();
|
||||||
|
} else {
|
||||||
|
uciEngine = new NativePipedProcess();
|
||||||
|
}
|
||||||
|
uciEngine.initialize();
|
||||||
|
uciEngine.writeLineToEngine("uci");
|
||||||
|
readUCIOptions();
|
||||||
|
int nThreads = getNumCPUs();
|
||||||
|
if (nThreads > 8) nThreads = 8;
|
||||||
|
numCPUs = nThreads;
|
||||||
|
if (!useCuckoo)
|
||||||
|
uciEngine.setOption("Hash", 16);
|
||||||
|
uciEngine.setOption("Ponder", false);
|
||||||
|
uciEngine.writeLineToEngine("ucinewgame");
|
||||||
|
syncReady();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getNumCPUs() {
|
||||||
|
int nCPUsFromProc = 1;
|
||||||
|
try {
|
||||||
|
FileReader fr = new FileReader("/proc/stat");
|
||||||
|
BufferedReader inBuf = new BufferedReader(fr, 8192);
|
||||||
|
String line;
|
||||||
|
int nCPUs = 0;
|
||||||
|
while ((line = inBuf.readLine()) != null) {
|
||||||
|
if ((line.length() >= 4) && line.startsWith("cpu") && Character.isDigit(line.charAt(3)))
|
||||||
|
nCPUs++;
|
||||||
|
}
|
||||||
|
inBuf.close();
|
||||||
|
if (nCPUs < 1) nCPUs = 1;
|
||||||
|
nCPUsFromProc = nCPUs;
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
int nCPUsFromOS = NativePipedProcess.getNPhysicalProcessors();
|
||||||
|
return Math.max(nCPUsFromProc, nCPUsFromOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void readUCIOptions() {
|
||||||
|
int timeout = 1000;
|
||||||
|
maxPV = 1;
|
||||||
|
while (true) {
|
||||||
|
String s = uciEngine.readLineFromEngine(timeout);
|
||||||
|
String[] tokens = tokenize(s);
|
||||||
|
if (tokens[0].equals("uciok"))
|
||||||
|
break;
|
||||||
|
else if (tokens[0].equals("id")) {
|
||||||
|
if (tokens[1].equals("name")) {
|
||||||
|
engineName = "";
|
||||||
|
for (int i = 2; i < tokens.length; i++) {
|
||||||
|
if (engineName.length() > 0)
|
||||||
|
engineName += " ";
|
||||||
|
engineName += tokens[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ((tokens.length > 2) && tokens[2].toLowerCase().equals("multipv")) {
|
||||||
|
try {
|
||||||
|
for (int i = 3; i < tokens.length; i++) {
|
||||||
|
if (tokens[i].equals("max") && (i+1 < tokens.length)) {
|
||||||
|
maxPV = Math.max(maxPV, Integer.parseInt(tokens[i+1]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException nfe) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convert a string to tokens by splitting at whitespace characters. */
|
||||||
|
private final String[] tokenize(String cmdLine) {
|
||||||
|
cmdLine = cmdLine.trim();
|
||||||
|
return cmdLine.split("\\s+");
|
||||||
|
}
|
||||||
|
|
||||||
|
private final void syncReady() {
|
||||||
|
uciEngine.writeLineToEngine("isready");
|
||||||
|
while (true) {
|
||||||
|
String s = uciEngine.readLineFromEngine(1000);
|
||||||
|
if (s.equals("readyok"))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Wait for engine to respond with bestMove and ponderMove.
|
/** Wait for engine to respond with bestMove and ponderMove.
|
||||||
* While waiting, monitor and report search info. */
|
* While waiting, monitor and report search info. */
|
||||||
private final Pair<String,String> monitorEngine(Position pos, Move ponderMove) {
|
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".
|
/** Check if a draw claim is allowed, possibly after playing "move".
|
||||||
* @param move The move that may have to be made before claiming draw.
|
* @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.
|
* @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;
|
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;
|
private DroidComputerPlayer computerPlayer;
|
||||||
TimeControl timeController;
|
TimeControl timeController;
|
||||||
private boolean gamePaused;
|
private boolean gamePaused;
|
||||||
|
/** If true, add new moves as mainline moves. */
|
||||||
private boolean addFirst;
|
private boolean addFirst;
|
||||||
|
|
||||||
PgnToken.PgnTokenReceiver gameTextListener;
|
PgnToken.PgnTokenReceiver gameTextListener;
|
||||||
@@ -50,6 +51,7 @@ public class Game {
|
|||||||
newGame();
|
newGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** De-serialize from byte array. */
|
||||||
final void fromByteArray(byte[] data) {
|
final void fromByteArray(byte[] data) {
|
||||||
tree.fromByteArray(data);
|
tree.fromByteArray(data);
|
||||||
updateTimeControl(true);
|
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) {
|
public final void setAddFirst(boolean addFirst) {
|
||||||
this.addFirst = addFirst;
|
this.addFirst = addFirst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets start position and discards the whole game tree. */
|
||||||
final void setPos(Position pos) {
|
final void setPos(Position pos) {
|
||||||
tree.setStartPos(new Position(pos));
|
tree.setStartPos(new Position(pos));
|
||||||
updateTimeControl(false);
|
updateTimeControl(false);
|
||||||
@@ -217,6 +221,7 @@ public class Game {
|
|||||||
return nVar > 0;
|
return nVar > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get number of variations in current game position. */
|
||||||
public final int numVariations() {
|
public final int numVariations() {
|
||||||
if (tree.currentNode == tree.rootNode)
|
if (tree.currentNode == tree.rootNode)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -226,6 +231,7 @@ public class Game {
|
|||||||
return nChildren;
|
return nChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get current variation in current position. */
|
||||||
public final int currVariation() {
|
public final int currVariation() {
|
||||||
if (tree.currentNode == tree.rootNode)
|
if (tree.currentNode == tree.rootNode)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -235,6 +241,7 @@ public class Game {
|
|||||||
return defChild;
|
return defChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Go to a new variation in the game tree. */
|
||||||
public final void changeVariation(int delta) {
|
public final void changeVariation(int delta) {
|
||||||
if (tree.currentNode == tree.rootNode)
|
if (tree.currentNode == tree.rootNode)
|
||||||
return;
|
return;
|
||||||
@@ -249,6 +256,7 @@ public class Game {
|
|||||||
updateTimeControl(true);
|
updateTimeControl(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Move current variation up/down in the game tree. */
|
||||||
public final void moveVariation(int delta) {
|
public final void moveVariation(int delta) {
|
||||||
if (tree.currentNode == tree.rootNode)
|
if (tree.currentNode == tree.rootNode)
|
||||||
return;
|
return;
|
||||||
@@ -264,6 +272,7 @@ public class Game {
|
|||||||
updateTimeControl(true);
|
updateTimeControl(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Delete whole game sub-tree rooted at current position. */
|
||||||
public final void removeSubTree() {
|
public final void removeSubTree() {
|
||||||
if (getLastMove() != null) {
|
if (getLastMove() != null) {
|
||||||
tree.goBack();
|
tree.goBack();
|
||||||
@@ -323,10 +332,14 @@ public class Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void goNode(Node node) {
|
/** Go to given node in game tree.
|
||||||
tree.goNode(node);
|
* @return True if current node changed, false otherwise. */
|
||||||
|
public final boolean goNode(Node node) {
|
||||||
|
if (!tree.goNode(node))
|
||||||
|
return false;
|
||||||
pendingDrawOffer = false;
|
pendingDrawOffer = false;
|
||||||
updateTimeControl(true);
|
updateTimeControl(true);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void newGame() {
|
public final void newGame() {
|
||||||
|
|||||||
@@ -657,13 +657,17 @@ public class GameTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Go to given node in game tree. */
|
/** Go to given node in game tree.
|
||||||
public final void goNode(Node node) {
|
* @return True if current node changed, false otherwise. */
|
||||||
|
public final boolean goNode(Node node) {
|
||||||
|
if (node == currentNode)
|
||||||
|
return false;
|
||||||
ArrayList<Integer> path = node.getPathFromRoot();
|
ArrayList<Integer> path = node.getPathFromRoot();
|
||||||
while (currentNode != rootNode)
|
while (currentNode != rootNode)
|
||||||
goBack();
|
goBack();
|
||||||
for (Integer c : path)
|
for (Integer c : path)
|
||||||
goForward(c);
|
goForward(c);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** List of possible continuation moves. */
|
/** List of possible continuation moves. */
|
||||||
@@ -1388,6 +1392,7 @@ public class GameTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set PGN header tags and values. */
|
||||||
void setHeaders(Map<String,String> headers) {
|
void setHeaders(Map<String,String> headers) {
|
||||||
for (Entry<String, String> entry : headers.entrySet()) {
|
for (Entry<String, String> entry : headers.entrySet()) {
|
||||||
String tag = entry.getKey();
|
String tag = entry.getKey();
|
||||||
@@ -1417,6 +1422,7 @@ public class GameTree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get PGN header tags and values. */
|
||||||
void getHeaders(Map<String,String> headers) {
|
void getHeaders(Map<String,String> headers) {
|
||||||
headers.put("Event", event);
|
headers.put("Event", event);
|
||||||
headers.put("Site", site);
|
headers.put("Site", site);
|
||||||
|
|||||||
@@ -667,7 +667,8 @@ public class GameTreeTest extends TestCase {
|
|||||||
for (int i = 0; i < 5; i++) gt.goForward(-1);
|
for (int i = 0; i < 5; i++) gt.goForward(-1);
|
||||||
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
||||||
Node na6 = gt.currentNode;
|
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));
|
assertEquals("*e4 e5 Nf3 Nc6 Bb5 a6", getMoveListAsString(gt));
|
||||||
gt.goNode(na6);
|
gt.goNode(na6);
|
||||||
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
assertEquals("e4 e5 Nf3 Nc6 Bb5 a6*", getMoveListAsString(gt));
|
||||||
|
|||||||
Reference in New Issue
Block a user