mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-27 14:15:16 +01:00
DroidFish: Made it possible to edit UCI options while the engine is
thinking. The changes take effect the next time the engine stops thinking.
This commit is contained in:
parent
2ca80fc19d
commit
7026555cbe
|
@ -86,7 +86,7 @@ public class ButtonActions {
|
|||
for (UIAction a : menuActions) {
|
||||
if (a != null) {
|
||||
haveActions = true;
|
||||
if (a.enabled())
|
||||
if (a.enabled())
|
||||
haveEnabledActions = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2897,8 +2897,6 @@ public class DroidFish extends Activity implements GUIInterface {
|
|||
|
||||
/** Return true if engine UCI options can be set now. */
|
||||
private final boolean canSetEngineOptions() {
|
||||
if (!ctrl.computerIdle())
|
||||
return false;
|
||||
UCIOptions uciOpts = ctrl.getUCIOptions();
|
||||
if (uciOpts == null)
|
||||
return false;
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.petero.droidfish.engine;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.petero.droidfish.EngineOptions;
|
||||
import org.petero.droidfish.book.BookOptions;
|
||||
|
@ -46,7 +47,9 @@ public class DroidComputerPlayer {
|
|||
private final Context context;
|
||||
private final SearchListener listener;
|
||||
private final DroidBook book;
|
||||
private EngineOptions engineOptions;
|
||||
private EngineOptions engineOptions = new EngineOptions();
|
||||
/** Pending UCI options to send when engine becomes idle. */
|
||||
private Map<String,String> pendingOptions = new TreeMap<String,String>();
|
||||
|
||||
/** Set when "ucinewgame" needs to be sent. */
|
||||
private boolean newGame = false;
|
||||
|
@ -226,8 +229,8 @@ public class DroidComputerPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
private EngineState engineState;
|
||||
private SearchRequest searchRequest;
|
||||
private EngineState engineState = new EngineState();
|
||||
private SearchRequest searchRequest = null;
|
||||
private Thread engineMonitor;
|
||||
|
||||
/** Constructor. Starts engine process if not already started. */
|
||||
|
@ -235,9 +238,6 @@ public class DroidComputerPlayer {
|
|||
this.context = context;
|
||||
this.listener = listener;
|
||||
book = DroidBook.getInstance();
|
||||
engineOptions = new EngineOptions();
|
||||
engineState = new EngineState();
|
||||
searchRequest = null;
|
||||
}
|
||||
|
||||
/** Return true if computer player is consuming CPU time. */
|
||||
|
@ -253,16 +253,30 @@ public class DroidComputerPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
/** Return true if computer player is in IDLE state. */
|
||||
public final synchronized boolean computerIdle() {
|
||||
return engineState.state == MainState.IDLE;
|
||||
/** Return true if computer player has been loaded. */
|
||||
public final synchronized boolean computerLoaded() {
|
||||
return (engineState.state != MainState.READ_OPTIONS) &&
|
||||
(engineState.state != MainState.DEAD);
|
||||
}
|
||||
|
||||
|
||||
public final synchronized UCIOptions getUCIOptions() {
|
||||
UCIEngine uci = uciEngine;
|
||||
if (uci == null)
|
||||
return null;
|
||||
return uci.getUCIOptions();
|
||||
UCIOptions opts = uci.getUCIOptions();
|
||||
if (opts == null)
|
||||
return null;
|
||||
try {
|
||||
opts = opts.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
for (Map.Entry<String,String> e : pendingOptions.entrySet()) {
|
||||
UCIOptions.OptionBase o = opts.getOption(e.getKey());
|
||||
if (o != null)
|
||||
o.setFromString(e.getValue());
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
/** Return maximum number of PVs supported by engine. */
|
||||
|
@ -279,11 +293,27 @@ public class DroidComputerPlayer {
|
|||
engineOptions = options;
|
||||
}
|
||||
|
||||
/** Send pending UCI option changes to the engine. */
|
||||
private synchronized boolean applyPendingOptions() {
|
||||
if (pendingOptions.isEmpty())
|
||||
return false;
|
||||
boolean modified = false;
|
||||
UCIEngine uci = uciEngine;
|
||||
if (uci != null)
|
||||
modified = uci.setUCIOptions(pendingOptions);
|
||||
pendingOptions.clear();
|
||||
return modified;
|
||||
}
|
||||
|
||||
public synchronized void setEngineUCIOptions(Map<String,String> uciOptions) {
|
||||
if (engineState.state == MainState.IDLE) {
|
||||
pendingOptions.putAll(uciOptions);
|
||||
boolean modified = true;
|
||||
if (engineState.state == MainState.IDLE)
|
||||
modified = applyPendingOptions();
|
||||
if (modified) {
|
||||
UCIEngine uci = uciEngine;
|
||||
if (uci != null)
|
||||
uci.setUCIOptions(uciOptions);
|
||||
uci.saveIniFile(getUCIOptions());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,8 +327,8 @@ public class DroidComputerPlayer {
|
|||
return engineName;
|
||||
}
|
||||
|
||||
/** Clear transposition table. Takes effect when next search started. */
|
||||
public final synchronized void clearTT() {
|
||||
/** Sends "ucinewgame". Takes effect when next search started. */
|
||||
public final synchronized void uciNewGame() {
|
||||
newGame = true;
|
||||
}
|
||||
|
||||
|
@ -508,7 +538,7 @@ public class DroidComputerPlayer {
|
|||
return;
|
||||
}
|
||||
|
||||
// Send "ucinewgame" (clear hash table) if needed
|
||||
// Send "ucinewgame" if needed
|
||||
if (newGame) {
|
||||
uciEngine.writeLineToEngine("ucinewgame");
|
||||
uciEngine.writeLineToEngine("isready");
|
||||
|
@ -517,6 +547,13 @@ public class DroidComputerPlayer {
|
|||
return;
|
||||
}
|
||||
|
||||
// Apply pending UCI option changes
|
||||
if (applyPendingOptions()) {
|
||||
uciEngine.writeLineToEngine("isready");
|
||||
engineState.setState(MainState.WAIT_READY);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if only engine start was requested
|
||||
boolean isSearch = sr.isSearch;
|
||||
boolean isAnalyze = sr.isAnalyze;
|
||||
|
@ -681,6 +718,7 @@ public class DroidComputerPlayer {
|
|||
switch (engineState.state) {
|
||||
case READ_OPTIONS: {
|
||||
if (readUCIOption(uci, s)) {
|
||||
pendingOptions.clear();
|
||||
uci.initOptions(engineOptions);
|
||||
uci.applyIniFile();
|
||||
uci.writeLineToEngine("ucinewgame");
|
||||
|
|
|
@ -52,9 +52,7 @@ public class InternalStockFish extends ExternalEngine {
|
|||
if (!super.configurableOption(name))
|
||||
return false;
|
||||
if (name.equals("skill level") || name.equals("write debug log") ||
|
||||
name.equals("write search log") || name.equals("search log filename") ||
|
||||
name.equals("book file") || name.equals("best book move") ||
|
||||
name.equals("ownbook"))
|
||||
name.equals("write search log"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,10 @@ public interface UCIEngine {
|
|||
public void applyIniFile();
|
||||
|
||||
/** Set engine UCI options. */
|
||||
public void setUCIOptions(Map<String,String> uciOptions);
|
||||
public boolean setUCIOptions(Map<String,String> uciOptions);
|
||||
|
||||
/** Save non-default UCI option values to file. */
|
||||
public void saveIniFile(UCIOptions options);
|
||||
|
||||
/** Get engine UCI options. */
|
||||
public UCIOptions getUCIOptions();
|
||||
|
|
|
@ -35,7 +35,7 @@ import android.content.Context;
|
|||
public abstract class UCIEngineBase implements UCIEngine {
|
||||
|
||||
private boolean processAlive;
|
||||
UCIOptions options;
|
||||
private UCIOptions options;
|
||||
protected boolean isUCI;
|
||||
|
||||
public static UCIEngine getEngine(Context context, String engine,
|
||||
|
@ -99,7 +99,7 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void setUCIOptions(Map<String,String> uciOptions) {
|
||||
public final boolean setUCIOptions(Map<String,String> uciOptions) {
|
||||
boolean modified = false;
|
||||
for (Map.Entry<String,String> ent : uciOptions.entrySet()) {
|
||||
String key = ((String)ent.getKey()).toLowerCase(Locale.US);
|
||||
|
@ -107,23 +107,26 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
if (configurableOption(key))
|
||||
modified |= setOption(key, value);
|
||||
}
|
||||
if (modified) { // Save .ini file
|
||||
Properties iniOptions = new Properties();
|
||||
for (String name : options.getOptionNames()) {
|
||||
UCIOptions.OptionBase o = options.getOption(name);
|
||||
if (configurableOption(name) && o.modified())
|
||||
iniOptions.put(o.name, o.getStringValue());
|
||||
}
|
||||
File optionsFile = getOptionsFile();
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(optionsFile);
|
||||
iniOptions.store(os, null);
|
||||
} catch (IOException ex) {
|
||||
} finally {
|
||||
if (os != null)
|
||||
try { os.close(); } catch (IOException ex) {}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void saveIniFile(UCIOptions options) {
|
||||
Properties iniOptions = new Properties();
|
||||
for (String name : options.getOptionNames()) {
|
||||
UCIOptions.OptionBase o = options.getOption(name);
|
||||
if (configurableOption(name) && o.modified())
|
||||
iniOptions.put(o.name, o.getStringValue());
|
||||
}
|
||||
File optionsFile = getOptionsFile();
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
os = new FileOutputStream(optionsFile);
|
||||
iniOptions.store(os, null);
|
||||
} catch (IOException ex) {
|
||||
} finally {
|
||||
if (os != null)
|
||||
try { os.close(); } catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class UCIOptions implements Serializable {
|
||||
public class UCIOptions implements Serializable, Cloneable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private ArrayList<String> names;
|
||||
private Map<String, OptionBase> options;
|
||||
|
@ -19,12 +19,17 @@ public class UCIOptions implements Serializable {
|
|||
STRING
|
||||
}
|
||||
|
||||
public abstract static class OptionBase implements Serializable {
|
||||
public abstract static class OptionBase implements Serializable, Cloneable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public String name;
|
||||
public Type type;
|
||||
public boolean visible = true;
|
||||
|
||||
@Override
|
||||
public OptionBase clone() throws CloneNotSupportedException {
|
||||
return (OptionBase)super.clone();
|
||||
}
|
||||
|
||||
/** Return true if current value != default value. */
|
||||
abstract public boolean modified();
|
||||
|
||||
|
@ -204,7 +209,22 @@ public class UCIOptions implements Serializable {
|
|||
options = new TreeMap<String, OptionBase>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UCIOptions clone() throws CloneNotSupportedException {
|
||||
UCIOptions copy = new UCIOptions();
|
||||
|
||||
copy.names = new ArrayList<String>();
|
||||
copy.names.addAll(names);
|
||||
|
||||
copy.options = new TreeMap<String, OptionBase>();
|
||||
for (Map.Entry<String, OptionBase> e : options.entrySet())
|
||||
copy.options.put(e.getKey(), e.getValue().clone());
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
names.clear();
|
||||
options.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ public class DroidChessController {
|
|||
computerPlayer.queueStartEngine(searchId, engine);
|
||||
searchId++;
|
||||
game = new Game(gameTextListener, tcData);
|
||||
computerPlayer.clearTT();
|
||||
computerPlayer.uciNewGame();
|
||||
setPlayerNames(game);
|
||||
updateGameMode();
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ public class DroidChessController {
|
|||
gameTextListener.clear();
|
||||
updateGameMode();
|
||||
abortSearch();
|
||||
computerPlayer.clearTT();
|
||||
computerPlayer.uciNewGame();
|
||||
updateComputeThreads();
|
||||
gui.setSelection(-1);
|
||||
updateGUI();
|
||||
|
@ -297,13 +297,10 @@ public class DroidChessController {
|
|||
return (computerPlayer != null) && computerPlayer.computerBusy();
|
||||
}
|
||||
|
||||
/** Return true if computer player is in IDLE state. */
|
||||
public final synchronized boolean computerIdle() {
|
||||
return (computerPlayer != null) && computerPlayer.computerIdle();
|
||||
}
|
||||
|
||||
/** Return engine UCI options if an engine has been loaded and has
|
||||
* reported its UCI options. */
|
||||
public final synchronized UCIOptions getUCIOptions() {
|
||||
if (!computerIdle() || computerPlayer == null)
|
||||
if (computerPlayer == null || !computerPlayer.computerLoaded())
|
||||
return null;
|
||||
return computerPlayer.getUCIOptions();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user