From bd011e535911a72ccea5b11d0901080e75be4154 Mon Sep 17 00:00:00 2001 From: Peter Osterlund Date: Tue, 15 Jul 2014 09:30:16 +0000 Subject: [PATCH] DroidFish: Made it possible to change UCI options using an .ini file. --- .../src/org/petero/droidfish/DroidFish.java | 13 +++--- .../droidfish/engine/DroidComputerPlayer.java | 3 +- .../droidfish/engine/ExternalEngine.java | 8 +++- .../droidfish/engine/InternalStockFish.java | 16 ++++++- .../droidfish/engine/NetworkEngine.java | 9 +++- .../petero/droidfish/engine/UCIEngine.java | 5 ++- .../droidfish/engine/UCIEngineBase.java | 43 ++++++++++++++++++- .../engine/cuckoochess/CuckooChessEngine.java | 17 +++++++- 8 files changed, 99 insertions(+), 15 deletions(-) diff --git a/DroidFish/src/org/petero/droidfish/DroidFish.java b/DroidFish/src/org/petero/droidfish/DroidFish.java index 4be1744..d2915d8 100644 --- a/DroidFish/src/org/petero/droidfish/DroidFish.java +++ b/DroidFish/src/org/petero/droidfish/DroidFish.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011-2013 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com Copyright (C) 2012 Leo Mayer This program is free software: you can redistribute it and/or modify @@ -2128,16 +2128,17 @@ public class DroidFish extends Activity implements GUIInterface { return alert; } - private final static boolean internalEngine(String name) { + private final static boolean reservedEngineName(String name) { return "cuckoochess".equals(name) || - "stockfish".equals(name); + "stockfish".equals(name) || + name.endsWith(".ini"); } private final Dialog selectEngineDialog(final boolean abortOnCancel) { String[] fileNames = findFilesInDirectory(engineDir, new FileNameFilter() { @Override public boolean accept(String filename) { - return !internalEngine(filename); + return !reservedEngineName(filename); } }); final int numFiles = fileNames.length; @@ -2753,7 +2754,7 @@ public class DroidFish extends Activity implements GUIInterface { String[] fileNames = findFilesInDirectory(engineDir, new FileNameFilter() { @Override public boolean accept(String filename) { - if (internalEngine(filename)) + if (reservedEngineName(filename)) return false; return EngineUtil.isNetEngine(filename); } @@ -2827,7 +2828,7 @@ public class DroidFish extends Activity implements GUIInterface { if (engineName.contains("/")) { nameOk = false; errMsg = R.string.slash_not_allowed; - } else if (internalEngine(engineName) || file.exists()) { + } else if (reservedEngineName(engineName) || file.exists()) { nameOk = false; errMsg = R.string.engine_name_in_use; } diff --git a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java index 7ce74a3..661b99f 100644 --- a/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java +++ b/DroidFish/src/org/petero/droidfish/engine/DroidComputerPlayer.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -680,6 +680,7 @@ public class DroidComputerPlayer { case READ_OPTIONS: { if (readUCIOption(uci, s)) { uci.initOptions(engineOptions); + uci.applyIniFile(); uci.writeLineToEngine("ucinewgame"); uci.writeLineToEngine("isready"); engineState.setState(MainState.WAIT_READY); diff --git a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java index 2235abd..e18f2c1 100644 --- a/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/ExternalEngine.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -179,12 +179,16 @@ public class ExternalEngine extends UCIEngineBase { setOption("Hash", hashMB); gaviotaTbPath = engineOptions.getEngineGtbPath(false); setOption("GaviotaTbPath", gaviotaTbPath); - setOption("GaviotaTbCache", 8); syzygyPath = engineOptions.getEngineRtbPath(false); setOption("SyzygyPath", syzygyPath); optionsInitialized = true; } + @Override + protected File getOptionsFile() { + return new File(engineFileName.getAbsolutePath() + ".ini"); + } + /** Reduce too large hash sizes. */ private final int getHashMB(int hashMB) { if (hashMB > 16) { diff --git a/DroidFish/src/org/petero/droidfish/engine/InternalStockFish.java b/DroidFish/src/org/petero/droidfish/engine/InternalStockFish.java index 59b5c3f..4b4fb97 100644 --- a/DroidFish/src/org/petero/droidfish/engine/InternalStockFish.java +++ b/DroidFish/src/org/petero/droidfish/engine/InternalStockFish.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ import java.security.NoSuchAlgorithmException; import java.util.zip.GZIPInputStream; import android.content.Context; +import android.os.Environment; /** Stockfish engine running as process, started from assets resource. */ public class InternalStockFish extends ExternalEngine { @@ -39,6 +40,19 @@ public class InternalStockFish extends ExternalEngine { super(context, "", report); } + @Override + protected File getOptionsFile() { + File extDir = Environment.getExternalStorageDirectory(); + return new File(extDir, "uci/stockfish.ini"); + } + + @Override + protected boolean configurableOption(String name) { + if (name.equals("skill level")) + return false; + return true; + } + /** @inheritDoc */ @Override public final void setStrength(int strength) { diff --git a/DroidFish/src/org/petero/droidfish/engine/NetworkEngine.java b/DroidFish/src/org/petero/droidfish/engine/NetworkEngine.java index 1919d2f..30a5e20 100644 --- a/DroidFish/src/org/petero/droidfish/engine/NetworkEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/NetworkEngine.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2012 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2012-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ package org.petero.droidfish.engine; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -207,12 +208,16 @@ public class NetworkEngine extends UCIEngineBase { setOption("Hash", engineOptions.hashMB); gaviotaTbPath = engineOptions.getEngineGtbPath(true); setOption("GaviotaTbPath", gaviotaTbPath); - setOption("GaviotaTbCache", 8); syzygyPath = engineOptions.getEngineRtbPath(true); setOption("SyzygyPath", syzygyPath); optionsInitialized = true; } + @Override + protected File getOptionsFile() { + return new File(fileName + ".ini"); + } + /** @inheritDoc */ @Override public boolean optionsOk(EngineOptions engineOptions) { diff --git a/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java b/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java index 7637fa9..9bc43b9 100644 --- a/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/UCIEngine.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -34,6 +34,9 @@ public interface UCIEngine { /** Initialize default options. */ public void initOptions(EngineOptions engineOptions); + /** Read UCI options from .ini file and send them to the engine. */ + public void applyIniFile(); + /** Return true if engine options have correct values. * If false is returned, engine will be restarted. */ public boolean optionsOk(EngineOptions engineOptions); diff --git a/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java b/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java index e7374d3..304b7a9 100644 --- a/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java +++ b/DroidFish/src/org/petero/droidfish/engine/UCIEngineBase.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011-2012 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,9 +18,14 @@ package org.petero.droidfish.engine; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Locale; +import java.util.Map; +import java.util.Properties; import org.petero.droidfish.EngineOptions; import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine; @@ -70,6 +75,42 @@ public abstract class UCIEngineBase implements UCIEngine { isUCI = true; } + @Override + public final void applyIniFile() { + File optionsFile = getOptionsFile(); + Properties iniOptions = new Properties(); + FileInputStream is = null; + try { + is = new FileInputStream(optionsFile); + iniOptions.load(is); + } catch (IOException ex) { + } finally { + if (is != null) + try { is.close(); } catch (IOException ex) {} + } + for (Map.Entry ent : iniOptions.entrySet()) { + if (ent.getKey() instanceof String && ent.getValue() instanceof String) { + String key = ((String)ent.getKey()).toLowerCase(Locale.US); + String value = (String)ent.getValue(); + if (key.startsWith("uci_") || key.equals("hash") || key.equals("ponder") || + key.equals("multipv") || key.equals("gaviotatbpath") || + key.equals("syzygypath") || key.equals("threads") || key.equals("cores")) + continue; + if (!configurableOption(key)) + continue; + setOption(key, value); + } + } + } + + /** Get engine UCI options file. */ + protected abstract File getOptionsFile(); + + /** Return true if the UCI option can be changed by the user. */ + protected boolean configurableOption(String name) { + return true; + } + @Override public void shutDown() { if (processAlive) { diff --git a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java index 9e07cdf..dc5fd3f 100644 --- a/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java +++ b/DroidFish/src/org/petero/droidfish/engine/cuckoochess/CuckooChessEngine.java @@ -1,6 +1,6 @@ /* DroidFish - An Android chess program. - Copyright (C) 2011 Peter Österlund, peterosterlund2@gmail.com + Copyright (C) 2011-2014 Peter Österlund, peterosterlund2@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,11 +18,13 @@ package org.petero.droidfish.engine.cuckoochess; +import android.os.Environment; import chess.ChessParseError; import chess.ComputerPlayer; import chess.Move; import chess.Position; import chess.TextIO; +import java.io.File; import java.util.ArrayList; import java.util.Locale; @@ -73,6 +75,19 @@ public class CuckooChessEngine extends UCIEngineBase { engineThread.start(); } + @Override + protected File getOptionsFile() { + File extDir = Environment.getExternalStorageDirectory(); + return new File(extDir, "uci/cuckoochess.ini"); + } + + @Override + protected boolean configurableOption(String name) { + if (name.equals("strength")) + return false; + return true; + } + /** @inheritDoc */ @Override public boolean optionsOk(EngineOptions engineOptions) {