mirror of
https://github.com/peterosterlund2/droidfish.git
synced 2024-11-27 06:10:28 +01:00
Set engine strength using Elo value
Remove the Strength preferences setting. Add a new left drawer menu item to set the current engine strength in terms of Elo. Supported for all engines that implement the standard UCI options UCI_LimitStrength and UCI_Elo. Elo settings are remembered individually for each engine.
This commit is contained in:
parent
33dfafd18c
commit
7c75c83859
|
@ -48,6 +48,7 @@ import org.petero.droidfish.activities.util.PGNFile;
|
|||
import org.petero.droidfish.activities.util.PGNFile.GameInfo;
|
||||
import org.petero.droidfish.activities.Preferences;
|
||||
import org.petero.droidfish.book.BookOptions;
|
||||
import org.petero.droidfish.engine.DroidComputerPlayer.EloData;
|
||||
import org.petero.droidfish.engine.EngineUtil;
|
||||
import org.petero.droidfish.engine.UCIOptions;
|
||||
import org.petero.droidfish.gamelogic.DroidChessController;
|
||||
|
@ -136,6 +137,7 @@ import android.view.View.OnTouchListener;
|
|||
import android.view.WindowManager;
|
||||
import android.webkit.WebView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
|
@ -1094,8 +1096,7 @@ public class DroidFish extends Activity
|
|||
mEcoHints = getIntSetting("ecoHints", ECO_HINTS_AUTO);
|
||||
|
||||
String engine = settings.getString("engine", "stockfish");
|
||||
int strength = settings.getInt("strength", 1000);
|
||||
setEngineStrength(engine, strength);
|
||||
setEngine(engine);
|
||||
|
||||
mPonderMode = settings.getBoolean("ponderMode", false);
|
||||
if (!mPonderMode)
|
||||
|
@ -1308,16 +1309,16 @@ public class DroidFish extends Activity
|
|||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
private void setEngineStrength(String engine, int strength) {
|
||||
private void setEngine(String engine) {
|
||||
if (!storageAvailable()) {
|
||||
if (!"stockfish".equals(engine) && !"cuckoochess".equals(engine))
|
||||
engine = "stockfish";
|
||||
}
|
||||
ctrl.setEngineStrength(engine, strength);
|
||||
setEngineTitle(engine, strength);
|
||||
ctrl.setEngine(engine);
|
||||
setEngineTitle(engine, ctrl.eloData().getEloToUse());
|
||||
}
|
||||
|
||||
private void setEngineTitle(String engine, int strength) {
|
||||
private void setEngineTitle(String engine, int elo) {
|
||||
String eName = "";
|
||||
if (EngineUtil.isOpenExchangeEngine(engine)) {
|
||||
String engineFileName = new File(engine).getName();
|
||||
|
@ -1336,10 +1337,10 @@ public class DroidFish extends Activity
|
|||
eName = getString("cuckoochess".equals(engine) ?
|
||||
R.string.cuckoochess_engine :
|
||||
R.string.stockfish_engine);
|
||||
boolean analysis = (ctrl != null) && ctrl.analysisMode();
|
||||
if ((strength < 1000) && !analysis)
|
||||
eName = String.format(Locale.US, "%s: %d%%", eName, strength / 10);
|
||||
}
|
||||
if (ctrl != null && !ctrl.analysisMode())
|
||||
if (elo != Integer.MAX_VALUE)
|
||||
eName = String.format(Locale.US, "%s: %d", eName, elo);
|
||||
engineTitleText.setText(eName);
|
||||
}
|
||||
|
||||
|
@ -1363,10 +1364,9 @@ public class DroidFish extends Activity
|
|||
}
|
||||
|
||||
@Override
|
||||
public void updateEngineTitle() {
|
||||
public void updateEngineTitle(int elo) {
|
||||
String engine = settings.getString("engine", "stockfish");
|
||||
int strength = settings.getInt("strength", 1000);
|
||||
setEngineTitle(engine, strength);
|
||||
setEngineTitle(engine, elo);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1433,31 +1433,34 @@ public class DroidFish extends Activity
|
|||
}
|
||||
|
||||
private class DrawerItem {
|
||||
int id;
|
||||
int itemId; // Item string resource id
|
||||
DrawerItemId id;
|
||||
private int resId; // Item string resource id
|
||||
|
||||
DrawerItem(int id, int itemId) {
|
||||
DrawerItem(DrawerItemId id, int resId) {
|
||||
this.id = id;
|
||||
this.itemId = itemId;
|
||||
this.resId = resId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getString(itemId);
|
||||
return getString(resId);
|
||||
}
|
||||
}
|
||||
|
||||
static private final int ITEM_NEW_GAME = 0;
|
||||
static private final int ITEM_EDIT_BOARD = 1;
|
||||
static private final int ITEM_SETTINGS = 2;
|
||||
static private final int ITEM_FILE_MENU = 3;
|
||||
static private final int ITEM_RESIGN = 4;
|
||||
static private final int ITEM_FORCE_MOVE = 5;
|
||||
static private final int ITEM_DRAW = 6;
|
||||
static private final int ITEM_SELECT_BOOK = 7;
|
||||
static private final int ITEM_MANAGE_ENGINES = 8;
|
||||
static private final int ITEM_SET_COLOR_THEME = 9;
|
||||
static private final int ITEM_ABOUT = 10;
|
||||
private enum DrawerItemId {
|
||||
NEW_GAME,
|
||||
SET_STRENGTH,
|
||||
EDIT_BOARD,
|
||||
SETTINGS,
|
||||
FILE_MENU,
|
||||
RESIGN,
|
||||
FORCE_MOVE,
|
||||
DRAW,
|
||||
SELECT_BOOK,
|
||||
MANAGE_ENGINES,
|
||||
SET_COLOR_THEME,
|
||||
ABOUT,
|
||||
}
|
||||
|
||||
/** Initialize the drawer part of the user interface. */
|
||||
private void initDrawers() {
|
||||
|
@ -1466,14 +1469,15 @@ public class DroidFish extends Activity
|
|||
rightDrawer = findViewById(R.id.right_drawer);
|
||||
|
||||
final DrawerItem[] leftItems = new DrawerItem[] {
|
||||
new DrawerItem(ITEM_NEW_GAME, R.string.option_new_game),
|
||||
new DrawerItem(ITEM_EDIT_BOARD, R.string.option_edit_board),
|
||||
new DrawerItem(ITEM_FILE_MENU, R.string.option_file),
|
||||
new DrawerItem(ITEM_SELECT_BOOK, R.string.option_select_book),
|
||||
new DrawerItem(ITEM_MANAGE_ENGINES, R.string.option_manage_engines),
|
||||
new DrawerItem(ITEM_SET_COLOR_THEME, R.string.option_color_theme),
|
||||
new DrawerItem(ITEM_SETTINGS, R.string.option_settings),
|
||||
new DrawerItem(ITEM_ABOUT, R.string.option_about)
|
||||
new DrawerItem(DrawerItemId.NEW_GAME, R.string.option_new_game),
|
||||
new DrawerItem(DrawerItemId.SET_STRENGTH, R.string.set_engine_strength),
|
||||
new DrawerItem(DrawerItemId.EDIT_BOARD, R.string.option_edit_board),
|
||||
new DrawerItem(DrawerItemId.FILE_MENU, R.string.option_file),
|
||||
new DrawerItem(DrawerItemId.SELECT_BOOK, R.string.option_select_book),
|
||||
new DrawerItem(DrawerItemId.MANAGE_ENGINES, R.string.option_manage_engines),
|
||||
new DrawerItem(DrawerItemId.SET_COLOR_THEME, R.string.option_color_theme),
|
||||
new DrawerItem(DrawerItemId.SETTINGS, R.string.option_settings),
|
||||
new DrawerItem(DrawerItemId.ABOUT, R.string.option_about),
|
||||
};
|
||||
leftDrawer.setAdapter(new ArrayAdapter<>(this,
|
||||
R.layout.drawer_list_item,
|
||||
|
@ -1484,9 +1488,9 @@ public class DroidFish extends Activity
|
|||
});
|
||||
|
||||
final DrawerItem[] rightItems = new DrawerItem[] {
|
||||
new DrawerItem(ITEM_RESIGN, R.string.option_resign_game),
|
||||
new DrawerItem(ITEM_FORCE_MOVE, R.string.option_force_computer_move),
|
||||
new DrawerItem(ITEM_DRAW, R.string.option_draw)
|
||||
new DrawerItem(DrawerItemId.RESIGN, R.string.option_resign_game),
|
||||
new DrawerItem(DrawerItemId.FORCE_MOVE, R.string.option_force_computer_move),
|
||||
new DrawerItem(DrawerItemId.DRAW, R.string.option_draw),
|
||||
};
|
||||
rightDrawer.setAdapter(new ArrayAdapter<>(this,
|
||||
R.layout.drawer_list_item,
|
||||
|
@ -1504,7 +1508,7 @@ public class DroidFish extends Activity
|
|||
}
|
||||
|
||||
/** React to a selection in the left/right drawers. */
|
||||
private void handleDrawerSelection(int itemId) {
|
||||
private void handleDrawerSelection(DrawerItemId id) {
|
||||
drawerLayout.closeDrawer(Gravity.LEFT);
|
||||
drawerLayout.closeDrawer(Gravity.RIGHT);
|
||||
leftDrawer.clearChoices();
|
||||
|
@ -1512,30 +1516,33 @@ public class DroidFish extends Activity
|
|||
|
||||
setAutoMode(AutoMode.OFF);
|
||||
|
||||
switch (itemId) {
|
||||
case ITEM_NEW_GAME:
|
||||
switch (id) {
|
||||
case NEW_GAME:
|
||||
showDialog(NEW_GAME_DIALOG);
|
||||
break;
|
||||
case ITEM_EDIT_BOARD:
|
||||
case SET_STRENGTH:
|
||||
reShowDialog(SET_STRENGTH_DIALOG);
|
||||
break;
|
||||
case EDIT_BOARD:
|
||||
startEditBoard(ctrl.getFEN());
|
||||
break;
|
||||
case ITEM_SETTINGS: {
|
||||
case SETTINGS: {
|
||||
Intent i = new Intent(DroidFish.this, Preferences.class);
|
||||
startActivityForResult(i, RESULT_SETTINGS);
|
||||
break;
|
||||
}
|
||||
case ITEM_FILE_MENU:
|
||||
case FILE_MENU:
|
||||
if (storageAvailable())
|
||||
reShowDialog(FILE_MENU_DIALOG);
|
||||
break;
|
||||
case ITEM_RESIGN:
|
||||
case RESIGN:
|
||||
if (ctrl.humansTurn())
|
||||
ctrl.resignGame();
|
||||
break;
|
||||
case ITEM_FORCE_MOVE:
|
||||
case FORCE_MOVE:
|
||||
ctrl.stopSearch();
|
||||
break;
|
||||
case ITEM_DRAW:
|
||||
case DRAW:
|
||||
if (ctrl.humansTurn()) {
|
||||
if (ctrl.claimDrawIfPossible())
|
||||
ctrl.stopPonder();
|
||||
|
@ -1543,20 +1550,20 @@ public class DroidFish extends Activity
|
|||
DroidFishApp.toast(R.string.offer_draw, Toast.LENGTH_SHORT);
|
||||
}
|
||||
break;
|
||||
case ITEM_SELECT_BOOK:
|
||||
case SELECT_BOOK:
|
||||
if (storageAvailable())
|
||||
reShowDialog(SELECT_BOOK_DIALOG);
|
||||
break;
|
||||
case ITEM_MANAGE_ENGINES:
|
||||
case MANAGE_ENGINES:
|
||||
if (storageAvailable())
|
||||
reShowDialog(MANAGE_ENGINES_DIALOG);
|
||||
else
|
||||
reShowDialog(SELECT_ENGINE_DIALOG_NOMANAGE);
|
||||
break;
|
||||
case ITEM_SET_COLOR_THEME:
|
||||
case SET_COLOR_THEME:
|
||||
showDialog(SET_COLOR_THEME_DIALOG);
|
||||
break;
|
||||
case ITEM_ABOUT:
|
||||
case ABOUT:
|
||||
showDialog(ABOUT_DIALOG);
|
||||
break;
|
||||
}
|
||||
|
@ -2025,6 +2032,7 @@ public class DroidFish extends Activity
|
|||
static private final int DELETE_NETWORK_ENGINE_DIALOG = 25;
|
||||
static private final int CLIPBOARD_DIALOG = 26;
|
||||
static private final int SELECT_FEN_FILE_DIALOG = 27;
|
||||
static private final int SET_STRENGTH_DIALOG = 28;
|
||||
|
||||
/** Remove and show a dialog. */
|
||||
void reShowDialog(int id) {
|
||||
|
@ -2036,6 +2044,7 @@ public class DroidFish extends Activity
|
|||
protected Dialog onCreateDialog(int id) {
|
||||
switch (id) {
|
||||
case NEW_GAME_DIALOG: return newGameDialog();
|
||||
case SET_STRENGTH_DIALOG: return setStrengthDialog();
|
||||
case PROMOTE_DIALOG: return promoteDialog();
|
||||
case BOARD_MENU_DIALOG: return boardMenuDialog();
|
||||
case FILE_MENU_DIALOG: return fileMenuDialog();
|
||||
|
@ -2076,6 +2085,106 @@ public class DroidFish extends Activity
|
|||
return builder.create();
|
||||
}
|
||||
|
||||
private Dialog setStrengthDialog() {
|
||||
EloStrengthSetter m = new EloStrengthSetter();
|
||||
return m.getDialog();
|
||||
}
|
||||
|
||||
/** Handle user interface to set engine strength. */
|
||||
private class EloStrengthSetter {
|
||||
private final EloData eloData = ctrl.eloData();
|
||||
|
||||
private CheckBox checkBox;
|
||||
private TextView eloLabel;
|
||||
private EditText editTxt;
|
||||
private SeekBar seekBar;
|
||||
|
||||
private int progressToElo(int p) {
|
||||
return eloData.minElo + p;
|
||||
}
|
||||
|
||||
private int eloToProgress(int elo) {
|
||||
return elo - eloData.minElo;
|
||||
}
|
||||
|
||||
private void updateText(int elo) {
|
||||
String txt = Integer.valueOf(elo).toString();
|
||||
if (!txt.equals(editTxt.getText().toString())) {
|
||||
editTxt.setText(txt);
|
||||
editTxt.setSelection(txt.length());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateEnabledState(boolean enabled) {
|
||||
eloLabel.setEnabled(enabled);
|
||||
editTxt.setEnabled(enabled);
|
||||
seekBar.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public Dialog getDialog() {
|
||||
if (!eloData.canChangeStrength()) {
|
||||
DroidFishApp.toast(R.string.engine_cannot_reduce_strength, Toast.LENGTH_LONG);
|
||||
return null;
|
||||
}
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(DroidFish.this);
|
||||
builder.setTitle(R.string.set_engine_strength);
|
||||
View content = View.inflate(DroidFish.this, R.layout.set_strength, null);
|
||||
builder.setView(content);
|
||||
|
||||
checkBox = content.findViewById(R.id.strength_checkbox);
|
||||
eloLabel = content.findViewById(R.id.strength_elolabel);
|
||||
editTxt = content.findViewById(R.id.strength_edittext);
|
||||
seekBar = content.findViewById(R.id.strength_seekbar);
|
||||
|
||||
checkBox.setChecked(eloData.limitStrength);
|
||||
seekBar.setMax(eloToProgress(eloData.maxElo));
|
||||
seekBar.setProgress(eloToProgress(eloData.elo));
|
||||
updateText(eloData.elo);
|
||||
updateEnabledState(eloData.limitStrength);
|
||||
|
||||
checkBox.setOnCheckedChangeListener((button, isChecked) -> {
|
||||
updateEnabledState(isChecked);
|
||||
});
|
||||
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) { }
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) { }
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
updateText(progressToElo(progress));
|
||||
}
|
||||
});
|
||||
editTxt.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
String txt = editTxt.getText().toString();
|
||||
try {
|
||||
int elo = Integer.parseInt(txt);
|
||||
int p = eloToProgress(elo);
|
||||
if (p != seekBar.getProgress())
|
||||
seekBar.setProgress(p);
|
||||
updateText(progressToElo(p));
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) { }
|
||||
});
|
||||
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
boolean limitStrength = checkBox.isChecked();
|
||||
int elo = progressToElo(seekBar.getProgress());
|
||||
ctrl.setStrength(limitStrength, elo);
|
||||
});
|
||||
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
|
||||
private void startNewGame(int type) {
|
||||
if (type != 2) {
|
||||
int gameModeType = (type == 0) ? GameMode.PLAYER_WHITE : GameMode.PLAYER_BLACK;
|
||||
|
@ -2091,7 +2200,7 @@ public class DroidFish extends Activity
|
|||
ctrl.newGame(gameMode, tcData);
|
||||
ctrl.startGame();
|
||||
setBoardFlip(true);
|
||||
updateEngineTitle();
|
||||
updateEngineTitle(ctrl.eloData().getEloToUse()); // Game mode affects Elo setting
|
||||
}
|
||||
|
||||
private Dialog promoteDialog() {
|
||||
|
@ -2502,9 +2611,8 @@ public class DroidFish extends Activity
|
|||
editor.putString("engine", engine);
|
||||
editor.apply();
|
||||
dialog.dismiss();
|
||||
int strength = settings.getInt("strength", 1000);
|
||||
setEngineOptions(false);
|
||||
setEngineStrength(engine, strength);
|
||||
setEngine(engine);
|
||||
});
|
||||
builder.setOnCancelListener(dialog -> {
|
||||
if (!abortOnCancel)
|
||||
|
@ -2845,8 +2953,7 @@ public class DroidFish extends Activity
|
|||
int numPV = this.numPV;
|
||||
final int maxPV = ctrl.maxPV();
|
||||
if (gameMode.analysisMode()) {
|
||||
numPV = Math.min(numPV, maxPV);
|
||||
numPV = Math.max(numPV, 1);
|
||||
numPV = Math.min(Math.max(numPV, 1), maxPV);
|
||||
if (maxPV > 1) {
|
||||
lst.add(getString(R.string.num_variations)); actions.add(MULTIPV_SET);
|
||||
}
|
||||
|
@ -2988,11 +3095,9 @@ public class DroidFish extends Activity
|
|||
|
||||
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
public void onStopTrackingTouch(SeekBar seekBar) { }
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
public void onStartTrackingTouch(SeekBar seekBar) { }
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
int nPV = progressToNumPV(progress, maxPV);
|
||||
|
@ -3014,11 +3119,9 @@ public class DroidFish extends Activity
|
|||
}
|
||||
}
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
}
|
||||
public void afterTextChanged(Editable s) { }
|
||||
});
|
||||
|
||||
builder.setNegativeButton(R.string.cancel, null);
|
||||
|
@ -3349,9 +3452,8 @@ public class DroidFish extends Activity
|
|||
editor.putString("engine", engine);
|
||||
editor.apply();
|
||||
dialog.dismiss();
|
||||
int strength = settings.getInt("strength", 1000);
|
||||
setEngineOptions(false);
|
||||
setEngineStrength(engine, strength);
|
||||
setEngine(engine);
|
||||
}
|
||||
dialog.cancel();
|
||||
reShowDialog(NETWORK_ENGINE_DIALOG);
|
||||
|
|
|
@ -86,7 +86,7 @@ public interface GUIInterface {
|
|||
void setRemainingTime(int wTime, int bTime, int nextUpdate);
|
||||
|
||||
/** Update engine title text. */
|
||||
void updateEngineTitle();
|
||||
void updateEngineTitle(int elo);
|
||||
|
||||
/** Update title with the material difference. */
|
||||
void updateMaterialDifferenceTitle(Util.MaterialDiff diff);
|
||||
|
|
|
@ -91,9 +91,7 @@ public class SeekBarPreference extends Preference implements OnSeekBarChangeList
|
|||
builder.setView(selectPercentageBinding.getRoot());
|
||||
String title = "";
|
||||
String key = getKey();
|
||||
if (key.equals("strength")) {
|
||||
title = getContext().getString(R.string.edit_strength);
|
||||
} else if (key.equals("bookRandom")) {
|
||||
if (key.equals("bookRandom")) {
|
||||
title = getContext().getString(R.string.edit_randomization);
|
||||
}
|
||||
builder.setTitle(title);
|
||||
|
|
|
@ -109,7 +109,7 @@ public class DroidComputerPlayer {
|
|||
int movesToGo; // Number of moves to next time control
|
||||
|
||||
String engine; // Engine name (identifier)
|
||||
int strength; // Engine strength setting (0 - 1000)
|
||||
int elo; // Engine UCI_Elo setting, or Integer.MAX_VALUE for full strength
|
||||
int numPV; // Number of PV lines to compute
|
||||
|
||||
boolean ponderEnabled; // True if pondering enabled, for engine time management
|
||||
|
@ -145,14 +145,14 @@ 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 engine Chess engine to use for searching.
|
||||
* @param strength Engine strength setting.
|
||||
* @param elo Engine Elo strength setting.
|
||||
*/
|
||||
public static SearchRequest searchRequest(int id, long now,
|
||||
Position prevPos, ArrayList<Move> mList,
|
||||
Position currPos, boolean drawOffer,
|
||||
int wTime, int bTime, int wInc, int bInc, int movesToGo,
|
||||
boolean ponderEnabled, Move ponderMove,
|
||||
String engine, int strength) {
|
||||
String engine, int elo) {
|
||||
SearchRequest sr = new SearchRequest();
|
||||
sr.searchId = id;
|
||||
sr.startTime = now;
|
||||
|
@ -168,7 +168,7 @@ public class DroidComputerPlayer {
|
|||
sr.bInc = bInc;
|
||||
sr.movesToGo = movesToGo;
|
||||
sr.engine = engine;
|
||||
sr.strength = strength;
|
||||
sr.elo = elo;
|
||||
sr.numPV = 1;
|
||||
sr.ponderEnabled = ponderEnabled;
|
||||
sr.ponderMove = ponderMove;
|
||||
|
@ -204,7 +204,7 @@ public class DroidComputerPlayer {
|
|||
sr.isAnalyze = true;
|
||||
sr.wTime = sr.bTime = sr.wInc = sr.bInc = sr.movesToGo = 0;
|
||||
sr.engine = engine;
|
||||
sr.strength = 1000;
|
||||
sr.elo = Integer.MAX_VALUE;
|
||||
sr.numPV = numPV;
|
||||
sr.ponderEnabled = false;
|
||||
sr.ponderMove = null;
|
||||
|
@ -310,6 +310,56 @@ public class DroidComputerPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
public static class EloData {
|
||||
public boolean limitStrength = false; // True if engine strength reduction is enabled
|
||||
public int elo = 0; // Current strength setting
|
||||
public int minElo = 0; // Smallest possible Elo value
|
||||
public int maxElo = 0; // Largest possible Elo value
|
||||
|
||||
/** Return true if engine is able to change the playing strength. */
|
||||
public boolean canChangeStrength() {
|
||||
return minElo < maxElo;
|
||||
}
|
||||
|
||||
/** Get current Elo setting.
|
||||
* Return MAX_VALUE if reduced strength not enabled or not supported. */
|
||||
public int getEloToUse() {
|
||||
if (canChangeStrength() && limitStrength)
|
||||
return elo;
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return engine Elo strength data. */
|
||||
public synchronized EloData getEloData() {
|
||||
EloData ret = new EloData();
|
||||
UCIEngine uci = uciEngine;
|
||||
if (uci != null) {
|
||||
UCIOptions opts = uci.getUCIOptions();
|
||||
UCIOptions.OptionBase lsOpt = opts.getOption("UCI_LimitStrength");
|
||||
UCIOptions.OptionBase eloOpt = opts.getOption("UCI_Elo");
|
||||
if (lsOpt instanceof UCIOptions.CheckOption &&
|
||||
eloOpt instanceof UCIOptions.SpinOption) {
|
||||
ret.limitStrength = ((UCIOptions.CheckOption)lsOpt).value;
|
||||
UCIOptions.SpinOption eloSpin = (UCIOptions.SpinOption)eloOpt;
|
||||
ret.elo = eloSpin.value;
|
||||
ret.minElo = eloSpin.minValue;
|
||||
ret.maxElo = eloSpin.maxValue;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Set engine UCI strength parameters. */
|
||||
public void setStrength(int elo) {
|
||||
Map<String,String> opts = new TreeMap<>();
|
||||
boolean limitStrength = elo != Integer.MAX_VALUE;
|
||||
opts.put("UCI_LimitStrength", limitStrength ? "true" : "false");
|
||||
if (limitStrength)
|
||||
opts.put("UCI_Elo", String.valueOf(elo));
|
||||
setEngineUCIOptions(opts);
|
||||
}
|
||||
|
||||
/** Return all book moves, both as a formatted string and as a list of moves. */
|
||||
public final Pair<String, ArrayList<Move>> getBookHints(Position pos, boolean localized) {
|
||||
return book.getAllBookMoves(pos, localized);
|
||||
|
@ -571,7 +621,7 @@ public class DroidComputerPlayer {
|
|||
|
||||
// Set strength and MultiPV parameters
|
||||
clearInfo();
|
||||
uciEngine.setStrength(searchRequest.strength);
|
||||
uciEngine.setEloStrength(searchRequest.elo);
|
||||
if (maxPV > 1) {
|
||||
int num = Math.min(maxPV, searchRequest.numPV);
|
||||
uciEngine.setOption("MultiPV", num);
|
||||
|
@ -721,6 +771,7 @@ public class DroidComputerPlayer {
|
|||
uci.writeLineToEngine("ucinewgame");
|
||||
uci.writeLineToEngine("isready");
|
||||
engineState.setState(MainState.WAIT_READY);
|
||||
listener.notifyEngineInitialized();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -236,10 +236,6 @@ public class ExternalEngine extends UCIEngineBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrength(int strength) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLineFromEngine(int timeoutMillis) {
|
||||
String ret = inLines.readLine(timeoutMillis);
|
||||
|
|
|
@ -46,9 +46,9 @@ public class InternalStockFish extends ExternalEngine {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean configurableOption(String name) {
|
||||
protected boolean editableOption(String name) {
|
||||
name = name.toLowerCase(Locale.US);
|
||||
if (!super.configurableOption(name))
|
||||
if (!super.editableOption(name))
|
||||
return false;
|
||||
if (name.equals("skill level") || name.equals("write debug log") ||
|
||||
name.equals("write search log"))
|
||||
|
@ -56,11 +56,6 @@ public class InternalStockFish extends ExternalEngine {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setStrength(int strength) {
|
||||
setOption("Skill Level", strength/50);
|
||||
}
|
||||
|
||||
private long readCheckSum(File f) {
|
||||
try (InputStream is = new FileInputStream(f);
|
||||
DataInputStream dis = new DataInputStream(is)) {
|
||||
|
|
|
@ -228,10 +228,6 @@ public class NetworkEngine extends UCIEngineBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrength(int strength) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLineFromEngine(int timeoutMillis) {
|
||||
String ret = engineToGui.readLine(timeoutMillis);
|
||||
|
|
|
@ -67,8 +67,9 @@ public interface UCIEngine {
|
|||
/** Write a line to the engine. \n will be added automatically. */
|
||||
void writeLineToEngine(String data);
|
||||
|
||||
/** Set the engine strength, allowed values 0 - 1000. */
|
||||
void setStrength(int strength);
|
||||
/** Temporarily set the engine Elo strength to use for the next search.
|
||||
* Integer.MAX_VALUE means full strength. */
|
||||
void setEloStrength(int elo);
|
||||
|
||||
/** Set an engine integer option. */
|
||||
void setOption(String name, int value);
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Arrays;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.petero.droidfish.EngineOptions;
|
||||
import org.petero.droidfish.engine.cuckoochess.CuckooChessEngine;
|
||||
|
@ -80,14 +81,15 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
iniOptions.load(is);
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
Map<String,String> opts = new TreeMap<>();
|
||||
for (Map.Entry<Object,Object> 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 (configurableOption(key))
|
||||
setOption(key, value);
|
||||
opts.put(key, value);
|
||||
}
|
||||
}
|
||||
setUCIOptions(opts);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -125,12 +127,11 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
/** 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 if the UCI option can be edited in the "Engine Options" dialog. */
|
||||
protected boolean editableOption(String name) {
|
||||
name = name.toLowerCase(Locale.US);
|
||||
if (name.startsWith("uci_")) {
|
||||
String[] allowed = { "uci_limitstrength", "uci_elo" };
|
||||
return Arrays.asList(allowed).contains(name);
|
||||
return false;
|
||||
} else {
|
||||
String[] ignored = { "hash", "ponder", "multipv",
|
||||
"gaviotatbpath", "syzygypath" };
|
||||
|
@ -138,6 +139,17 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
}
|
||||
}
|
||||
|
||||
/** Return true if the UCI option can be modified by the user, either directly
|
||||
* from the "Engine Options" dialog or indirectly, for example from the
|
||||
* "Set Engine Strength" dialog. */
|
||||
private boolean configurableOption(String name) {
|
||||
if (editableOption(name))
|
||||
return true;
|
||||
name = name.toLowerCase(Locale.US);
|
||||
String[] configurable = { "uci_limitstrength", "uci_elo" };
|
||||
return Arrays.asList(configurable).contains(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown() {
|
||||
if (processAlive) {
|
||||
|
@ -221,7 +233,7 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
int maxV = Integer.parseInt(maxVal);
|
||||
if (minV <= defV && defV <= maxV)
|
||||
option = new UCIOptions.SpinOption(name, minV, maxV, defV);
|
||||
} catch (NumberFormatException ex) {
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
} else if (type.equals("combo")) {
|
||||
|
@ -241,8 +253,7 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
}
|
||||
|
||||
if (option != null) {
|
||||
if (!configurableOption(name))
|
||||
option.visible = false;
|
||||
option.visible = editableOption(name);
|
||||
options.addOption(option);
|
||||
}
|
||||
return option;
|
||||
|
@ -253,6 +264,21 @@ public abstract class UCIEngineBase implements UCIEngine {
|
|||
return options.contains(optName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setEloStrength(int elo) {
|
||||
String lsName = "UCI_LimitStrength";
|
||||
boolean limit = elo != Integer.MAX_VALUE;
|
||||
UCIOptions.OptionBase o = options.getOption(lsName);
|
||||
if (o instanceof UCIOptions.CheckOption) {
|
||||
// Don't use setOption() since this value reflects current search parameters,
|
||||
// not user specified strength settings, so should not be saved in .ini file.
|
||||
writeLineToEngine(String.format(Locale.US, "setoption name %s value %s",
|
||||
lsName, limit ? "true" : "false"));
|
||||
}
|
||||
if (limit)
|
||||
setOption("UCI_Elo", elo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setOption(String name, int value) {
|
||||
setOption(name, String.format(Locale.US, "%d", value));
|
||||
|
|
|
@ -41,7 +41,7 @@ public class UCIOptions implements Serializable, Cloneable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
public String name;
|
||||
public Type type;
|
||||
public boolean visible = true;
|
||||
public boolean visible = true; // True if visible in "Engine Options" dialog
|
||||
|
||||
@Override
|
||||
public OptionBase clone() throws CloneNotSupportedException {
|
||||
|
|
|
@ -74,9 +74,9 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean configurableOption(String name) {
|
||||
protected boolean editableOption(String name) {
|
||||
name = name.toLowerCase(Locale.US);
|
||||
if (!super.configurableOption(name))
|
||||
if (!super.editableOption(name))
|
||||
return false;
|
||||
if (name.equals("strength"))
|
||||
return false;
|
||||
|
@ -88,11 +88,6 @@ public class CuckooChessEngine extends UCIEngineBase {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setStrength(int strength) {
|
||||
setOption("strength", strength);
|
||||
}
|
||||
|
||||
private void mainLoop(LocalPipe is, LocalPipe os) {
|
||||
String line;
|
||||
while ((line = is.readLine()) != null) {
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.petero.droidfish.book.BookOptions;
|
|||
import org.petero.droidfish.book.EcoDb;
|
||||
import org.petero.droidfish.engine.DroidComputerPlayer;
|
||||
import org.petero.droidfish.engine.UCIOptions;
|
||||
import org.petero.droidfish.engine.DroidComputerPlayer.EloData;
|
||||
import org.petero.droidfish.engine.DroidComputerPlayer.SearchRequest;
|
||||
import org.petero.droidfish.engine.DroidComputerPlayer.SearchType;
|
||||
import org.petero.droidfish.gamelogic.Game.CommentInfo;
|
||||
|
@ -60,7 +61,6 @@ public class DroidChessController {
|
|||
private PGNOptions pgnOptions;
|
||||
|
||||
private String engine = "";
|
||||
private int strength = 1000;
|
||||
private int numPV = 1;
|
||||
|
||||
private SearchListener listener;
|
||||
|
@ -146,13 +146,15 @@ public class DroidChessController {
|
|||
if (!gameMode.playerWhite() || !gameMode.playerBlack())
|
||||
setPlayerNames(game); // If computer player involved, set player names
|
||||
updateGameMode();
|
||||
abortSearch();
|
||||
updateComputeThreads();
|
||||
gui.updateEngineTitle();
|
||||
updateGUI();
|
||||
gui.updateEngineTitle(getEloToUse()); // Game mode affects Elo setting
|
||||
restartSearch();
|
||||
}
|
||||
}
|
||||
|
||||
private int getEloToUse() {
|
||||
return eloData().getEloToUse();
|
||||
}
|
||||
|
||||
public final GameMode getGameMode() {
|
||||
return gameMode;
|
||||
}
|
||||
|
@ -179,28 +181,47 @@ public class DroidChessController {
|
|||
engineOptions = options;
|
||||
if (computerPlayer != null)
|
||||
computerPlayer.setEngineOptions(engineOptions);
|
||||
if (restart && (game != null)) {
|
||||
abortSearch();
|
||||
updateComputeThreads();
|
||||
updateGUI();
|
||||
}
|
||||
if (restart)
|
||||
restartSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set engine and engine strength. Restart computer thinking if appropriate.
|
||||
* @param engine Name of engine.
|
||||
* @param strength Engine strength, 0 - 1000. */
|
||||
public final synchronized void setEngineStrength(String engine, int strength) {
|
||||
boolean newEngine = !engine.equals(this.engine);
|
||||
if (newEngine || (strength != this.strength)) {
|
||||
this.engine = engine;
|
||||
this.strength = strength;
|
||||
private void restartSearch() {
|
||||
if (game != null) {
|
||||
abortSearch();
|
||||
updateComputeThreads();
|
||||
updateGUI();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set engine. Restart computer thinking if appropriate. */
|
||||
public final synchronized void setEngine(String engine) {
|
||||
if (!engine.equals(this.engine)) {
|
||||
this.engine = engine;
|
||||
restartSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set engine strength. Restart computer thinking if appropriate. */
|
||||
public final synchronized void setStrength(boolean limitStrength, int elo) {
|
||||
EloData d = eloData();
|
||||
int oldElo = d.getEloToUse();
|
||||
d.limitStrength = limitStrength;
|
||||
d.elo = elo;
|
||||
int newElo = d.getEloToUse();
|
||||
if (oldElo != newElo) {
|
||||
if (computerPlayer != null)
|
||||
computerPlayer.setStrength(newElo);
|
||||
restartSearch();
|
||||
gui.updateEngineTitle(newElo);
|
||||
}
|
||||
}
|
||||
|
||||
/** Return engine Elo strength data. */
|
||||
public final synchronized EloData eloData() {
|
||||
if (computerPlayer == null)
|
||||
return new EloData();
|
||||
return computerPlayer.getEloData();
|
||||
}
|
||||
|
||||
/** Set engine UCI options. */
|
||||
|
@ -233,8 +254,7 @@ public class DroidChessController {
|
|||
DataInputStream dis = new DataInputStream(bais)) {
|
||||
game.readFromStream(dis, version);
|
||||
game.tree.translateMoves();
|
||||
} catch (IOException ignore) {
|
||||
} catch (ChessParseError ignore) {
|
||||
} catch (IOException|ChessParseError ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,9 +403,7 @@ public class DroidChessController {
|
|||
if (humansTurn()) {
|
||||
int varNo = game.tree.addMove("--", "", 0, "", "");
|
||||
game.tree.goForward(varNo);
|
||||
abortSearch();
|
||||
updateComputeThreads();
|
||||
updateGUI();
|
||||
restartSearch();
|
||||
gui.setSelection(-1);
|
||||
}
|
||||
}
|
||||
|
@ -596,11 +614,8 @@ public class DroidChessController {
|
|||
clampedNumPV = Math.max(clampedNumPV, 1);
|
||||
boolean modified = clampedNumPV != this.numPV;
|
||||
this.numPV = numPV;
|
||||
if (modified) {
|
||||
abortSearch();
|
||||
updateComputeThreads();
|
||||
updateGUI();
|
||||
}
|
||||
if (modified)
|
||||
restartSearch();
|
||||
}
|
||||
|
||||
/** Request computer player to make a move immediately. */
|
||||
|
@ -757,7 +772,7 @@ public class DroidChessController {
|
|||
} else if (currTime < 999950) {
|
||||
statStrTmp.append(String.format(Locale.US, " t:%.1f", currTime / 1000.0));
|
||||
} else {
|
||||
statStrTmp.append(String.format(Locale.US, " t:%d", (int)((currTime + 500) / 1000)));
|
||||
statStrTmp.append(String.format(Locale.US, " t:%d", (currTime + 500) / 1000));
|
||||
}
|
||||
statStrTmp.append(" n:");
|
||||
appendWithPrefix(statStrTmp, currNodes);
|
||||
|
@ -900,18 +915,25 @@ public class DroidChessController {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void notifySearchResult(final int id, final String cmd, final Move ponder) {
|
||||
public void notifySearchResult(int id, String cmd, Move ponder) {
|
||||
new Thread(() -> gui.runOnUIThread(() -> makeComputerMove(id, cmd, ponder))).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEngineName(final String engineName) {
|
||||
public void notifyEngineName(String engineName) {
|
||||
gui.runOnUIThread(() -> {
|
||||
updatePlayerNames(engineName);
|
||||
gui.reportEngineName(engineName);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEngineInitialized() {
|
||||
gui.runOnUIThread(() -> {
|
||||
gui.updateEngineTitle(eloData().getEloToUse());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportEngineError(final String errMsg) {
|
||||
gui.runOnUIThread(() -> gui.reportEngineError(errMsg));
|
||||
|
@ -998,7 +1020,7 @@ public class DroidChessController {
|
|||
game.haveDrawOffer(),
|
||||
wTime, bTime, wInc, bInc, movesToGo,
|
||||
gui.ponderMode(), fPonderMove,
|
||||
engine, strength);
|
||||
engine, getEloToUse());
|
||||
computerPlayer.queueSearchRequest(sr);
|
||||
} else {
|
||||
computerPlayer.queueStartEngine(searchId, engine);
|
||||
|
@ -1033,8 +1055,9 @@ public class DroidChessController {
|
|||
String engine = "Computer";
|
||||
if (computerPlayer != null) {
|
||||
engine = computerPlayer.getEngineName();
|
||||
if (strength < 1000)
|
||||
engine += String.format(Locale.US, " (%.1f%%)", strength * 0.1);
|
||||
int elo = getEloToUse();
|
||||
if (elo != Integer.MAX_VALUE)
|
||||
engine += String.format(Locale.US, " (%d)", elo);
|
||||
}
|
||||
String player = gui.playerName();
|
||||
String white = gameMode.playerWhite() ? player : engine;
|
||||
|
@ -1045,8 +1068,9 @@ public class DroidChessController {
|
|||
|
||||
private synchronized void updatePlayerNames(String engineName) {
|
||||
if (game != null) {
|
||||
if (strength < 1000)
|
||||
engineName += String.format(Locale.US, " (%.1f%%)", strength * 0.1);
|
||||
int elo = getEloToUse();
|
||||
if (elo != Integer.MAX_VALUE)
|
||||
engineName += String.format(Locale.US, " (%d)", elo);
|
||||
String white = gameMode.playerWhite() ? game.tree.white : engineName;
|
||||
String black = gameMode.playerBlack() ? game.tree.black : engineName;
|
||||
game.tree.setPlayerNames(white, black);
|
||||
|
|
|
@ -84,4 +84,7 @@ public interface SearchListener {
|
|||
|
||||
/** Report engine error. */
|
||||
void reportEngineError(String errMsg);
|
||||
|
||||
/** Report that engine has been initialized. */
|
||||
void notifyEngineInitialized();
|
||||
}
|
||||
|
|
39
DroidFishApp/src/main/res/layout/set_strength.xml
Normal file
39
DroidFishApp/src/main/res/layout/set_strength.xml
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/strength_checkbox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/limit_strength"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/strength_elolabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:text="Elo:" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/strength_edittext"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1.0"
|
||||
android:inputType="number" />
|
||||
</LinearLayout>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/strength_seekbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp" />
|
||||
</LinearLayout>
|
|
@ -44,6 +44,7 @@
|
|||
android:gravity="center"
|
||||
android:textSize="14sp"
|
||||
android:tag="title"
|
||||
android:ellipsize="middle"
|
||||
android:text="@string/app_name" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
<string name="tools_menu">Прылады</string>
|
||||
<string name="load_save_menu">Загрузіць/Захаваць партыю</string>
|
||||
<string name="goto_move">Зрабіць ход</string>
|
||||
<string name="edit_strength">Змяніць ровень складанасці</string>
|
||||
<string name="edit_randomization">Змяніць рандамізацыю (выпадковасць)</string>
|
||||
<string name="invalid_number_format">Няправільны фармат ліку</string>
|
||||
<string name="side_to_move">Задаць кірунак ходу</string>
|
||||
|
@ -273,8 +272,6 @@
|
|||
<string name="prefs_playerNameFlip_title">Паварочваць дошку: гулец</string>
|
||||
<string name="prefs_playerNameFlip_summary">Скарыстаць імя гульца для аўтаматычнага павароту дошкі</string>
|
||||
<string name="prefs_engine_settings">Налады рухавічка</string>
|
||||
<string name="prefs_strength_title">Сіла гульні</string>
|
||||
<string name="prefs_strength_summary">Падтрымваецца толькі ўнутранымі рухавічкамі. Рэжым аналізу заўсёды скарыстае поўную сілу.</string>
|
||||
<string name="prefs_ponderMode_title">Разважанне</string>
|
||||
<string name="prefs_ponderMode_summary">Дазволіць рухавічку абдумванне падчас чакання ходу апанента. Падтрымваецца большасцю рухавічкоў.</string>
|
||||
<string name="prefs_hash_title">Хэш-табліца</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Um gegebenenfalls Strom zu sparen, ist es empfehlenswert, dass Sie diese Paramet
|
|||
<string name="tools_menu">Hilfsmittel</string>
|
||||
<string name="load_save_menu">Partie laden/speichern</string>
|
||||
<string name="goto_move">Gehe zu Zug</string>
|
||||
<string name="edit_strength">Spielstärke ändern</string>
|
||||
<string name="edit_randomization">Randomisierung ändern</string>
|
||||
<string name="invalid_number_format">Ungültiges Zahlenformat</string>
|
||||
<string name="side_to_move">Seite am Zug</string>
|
||||
|
@ -273,8 +272,6 @@ Um gegebenenfalls Strom zu sparen, ist es empfehlenswert, dass Sie diese Paramet
|
|||
<string name="prefs_playerNameFlip_title">Spielfeld nach Namen drehen</string>
|
||||
<string name="prefs_playerNameFlip_summary">Spielfeld in Abhängigkeit vom Spielernamen drehen</string>
|
||||
<string name="prefs_engine_settings">Engine-Einstellungen</string>
|
||||
<string name="prefs_strength_title">Spielstärke</string>
|
||||
<string name="prefs_strength_summary">Wird nur von internen Engines unterstützt. Im Analyse-Modus wird stets die volle Stärke verwendet.</string>
|
||||
<string name="prefs_ponderMode_title">Vorausberechnung</string>
|
||||
<string name="prefs_ponderMode_summary">Vorausberechnung von Zügen durch die Engine, wenn der Spieler am Zug ist (von den meisten Engines unterstützt)</string>
|
||||
<string name="prefs_hash_title">Hash-Tabelle</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Si está usted utilizando la batería, se recomienda que cambie los ajustes para
|
|||
<string name="tools_menu">Herramientas</string>
|
||||
<string name="load_save_menu">Cargar/Guardar Partida</string>
|
||||
<string name="goto_move">Ir a la jugada</string>
|
||||
<string name="edit_strength">Editar Fuerza de juego</string>
|
||||
<string name="edit_randomization">Editar Aleatoriedad</string>
|
||||
<string name="invalid_number_format"> Formato de número no válido</string>
|
||||
<string name="side_to_move">Turno de juego</string>
|
||||
|
@ -273,8 +272,6 @@ Si está usted utilizando la batería, se recomienda que cambie los ajustes para
|
|||
<string name="prefs_playerNameFlip_title">Invertir tablero : Jugador</string>
|
||||
<string name="prefs_playerNameFlip_summary">Utilizar el nombre del jugador para invertir el tablero automáticamente</string>
|
||||
<string name="prefs_engine_settings">Ajustes del Motor/Programa</string>
|
||||
<string name="prefs_strength_title">Fuerza/Nivel de Juego</string>
|
||||
<string name="prefs_strength_summary">Soportado únicamente por los motores internos. El modo análisis siempre utiliza fuerza máxima.</string>
|
||||
<string name="prefs_ponderMode_title">Pensar siempre</string>
|
||||
<string name="prefs_ponderMode_summary">Dejar calcular al motor mientras espera la jugada del oponente. Lo incorporan la mayoría de los motores.</string>
|
||||
<string name="prefs_hash_title">Tablas Hash</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Lorsque que vous êtes sur batterie, il est recommandé de changer les paramètr
|
|||
<string name="tools_menu">Outils</string>
|
||||
<string name="load_save_menu">Charger/Sauvegarder une partie</string>
|
||||
<string name="goto_move">Aller au coup</string>
|
||||
<string name="edit_strength">Modifier le niveau</string>
|
||||
<string name="edit_randomization">Modifier la randomisation</string>
|
||||
<string name="invalid_number_format">Format du nombre non valide</string>
|
||||
<string name="side_to_move">Camp au trait</string>
|
||||
|
@ -273,8 +272,6 @@ Lorsque que vous êtes sur batterie, il est recommandé de changer les paramètr
|
|||
<string name="prefs_playerNameFlip_title">Disposition de l\'échiquier: Joueur</string>
|
||||
<string name="prefs_playerNameFlip_summary">Utiliser le nom du joueur pour disposer automatiquement l\'échiquier</string>
|
||||
<string name="prefs_engine_settings">Paramètres du module</string>
|
||||
<string name="prefs_strength_title">Niveau de jeu</string>
|
||||
<string name="prefs_strength_summary">Supporté uniquement par les modules internes. Le mode Analyse utilisera toujours le niveau maximal.</string>
|
||||
<string name="prefs_ponderMode_title">Réflexion permanente</string>
|
||||
<string name="prefs_ponderMode_summary">Laisser le module actif lors du coup de l\'opposant. Supporté par la plupart des modules.</string>
|
||||
<string name="prefs_hash_title">Table de hachage</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Se l\'alimentazione è a batteria, è consigliabile modificare le impostazioni p
|
|||
<string name="tools_menu">Strumenti</string>
|
||||
<string name="load_save_menu">Apri/Salva partita</string>
|
||||
<string name="goto_move">Vai alla mossa</string>
|
||||
<string name="edit_strength">Imposta la Forza del motore</string>
|
||||
<string name="edit_randomization">Modifica la casualizzazione</string>
|
||||
<string name="invalid_number_format">Formato del numero non valido</string>
|
||||
<string name="side_to_move">Lato che muove</string>
|
||||
|
@ -273,8 +272,6 @@ Se l\'alimentazione è a batteria, è consigliabile modificare le impostazioni p
|
|||
<string name="prefs_playerNameFlip_title">Gira la scacchiera: Giocatore</string>
|
||||
<string name="prefs_playerNameFlip_summary">Usa il nome del giocatore per girare la scacchiera automaticamente</string>
|
||||
<string name="prefs_engine_settings">Impostazioni del motore</string>
|
||||
<string name="prefs_strength_title">Forza di gioco</string>
|
||||
<string name="prefs_strength_summary">Supportato solo dai motori interni. La modalità di analisi utilizza sempre la massima forza.</string>
|
||||
<string name="prefs_ponderMode_title">Sto riflettendo</string>
|
||||
<string name="prefs_ponderMode_summary">Lascia che il motore rifletta nell\'attesa della mossa dell\'avversario. Supportato dalla maggior parte dei motori.</string>
|
||||
<string name="prefs_hash_title">Tabella hash</string>
|
||||
|
|
|
@ -54,7 +54,6 @@ DroidFish는 백그라운드에 실행 중인 상태에서 다음과 같이 설
|
|||
<string name="tools_menu">도구</string>
|
||||
<string name="load_save_menu">게임 저장/불러오기</string>
|
||||
<string name="goto_move">이동으로 가기</string>
|
||||
<string name="edit_strength">강도 조정</string>
|
||||
<string name="edit_randomization">랜덤화 편집</string>
|
||||
<string name="invalid_number_format">잘못된 숫자 형식</string>
|
||||
<string name="side_to_move">이동할 사이드</string>
|
||||
|
@ -277,8 +276,6 @@ DroidFish는 백그라운드에 실행 중인 상태에서 다음과 같이 설
|
|||
<string name="prefs_playerNameFlip_title">플립 보드 : 플레이어</string>
|
||||
<string name="prefs_playerNameFlip_summary">자동 플립 보드를 위해 플레이어 이름을 사용합니다</string>
|
||||
<string name="prefs_engine_settings">엔진 설정</string>
|
||||
<string name="prefs_strength_title">플레이 강도</string>
|
||||
<string name="prefs_strength_summary">내장 엔진에서만 지원합니다. 분석 모드에서는 항상 최고 강도를 사용합니다.</string>
|
||||
<string name="prefs_ponderMode_title">숙고하기</string>
|
||||
<string name="prefs_ponderMode_summary">상대방의 이동을 기다리는 동안 엔진이 생각하도록 합니다. 대부분의 엔진에 의해 지원됩니다.</string>
|
||||
<string name="prefs_hash_title">해시 테이블</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Als uw telefoon op batterij werkt is het aan te raden om deze instellingen te wi
|
|||
<string name="tools_menu">Tools</string>
|
||||
<string name="load_save_menu">Laad/Bewaar Partij</string>
|
||||
<string name="goto_move">Ga naar zet</string>
|
||||
<string name="edit_strength">Speelsterkte bewerken</string>
|
||||
<string name="edit_randomization">Willekeurigheid bewerken</string>
|
||||
<string name="invalid_number_format">Ongeldig nummer formaat</string>
|
||||
<string name="side_to_move">Speler aan zet</string>
|
||||
|
@ -273,8 +272,6 @@ Als uw telefoon op batterij werkt is het aan te raden om deze instellingen te wi
|
|||
<string name="prefs_playerNameFlip_title">Draai bord:Speler</string>
|
||||
<string name="prefs_playerNameFlip_summary">Draai bord automatisch op spelers naam</string>
|
||||
<string name="prefs_engine_settings">Engine instellingen</string>
|
||||
<string name="prefs_strength_title">Speel sterkte</string>
|
||||
<string name="prefs_strength_summary">Alleen ondersteund door interne engines. Analyse gebruikt altijd de hoogste denksterkte.</string>
|
||||
<string name="prefs_ponderMode_title">Peinzen</string>
|
||||
<string name="prefs_ponderMode_summary">Laat de engine verder denken tijdens wachten op de zet van de tegenstander.</string>
|
||||
<string name="prefs_hash_title">Hashtabel</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Jeśli pracujesz na baterii, zalecana jest zmiana ustawień, w celu oszczędzani
|
|||
<string name="tools_menu">Narzędzia</string>
|
||||
<string name="load_save_menu">Załaduj/zapisz partię</string>
|
||||
<string name="goto_move">Idź do posunięcia</string>
|
||||
<string name="edit_strength">Edytuj siłę gry</string>
|
||||
<string name="edit_randomization">Zmień losowość</string>
|
||||
<string name="invalid_number_format">Niepoprawny format liczby</string>
|
||||
<string name="side_to_move">Strona na posunięciu</string>
|
||||
|
@ -273,8 +272,6 @@ Jeśli pracujesz na baterii, zalecana jest zmiana ustawień, w celu oszczędzani
|
|||
<string name="prefs_playerNameFlip_title">Obracanie szachownicy: gracz</string>
|
||||
<string name="prefs_playerNameFlip_summary">Używaj nazwy gracza, żeby obracać szachownicę automatycznie</string>
|
||||
<string name="prefs_engine_settings">Ustawienia silnika</string>
|
||||
<string name="prefs_strength_title">Siła gry</string>
|
||||
<string name="prefs_strength_summary">Wspierane wyłącznie przez lokalne silniki szachowe. Tryb analizy zawsze używa maksymalnej siły gry.</string>
|
||||
<string name="prefs_ponderMode_title">Namysł</string>
|
||||
<string name="prefs_ponderMode_summary">Silnik szachowy będzie liczył pozycję czekając na posunięcie przeciwnika. Wspierane przez większość silników.</string>
|
||||
<string name="prefs_hash_title">Tablica haszująca</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Se você está usando somente a bateria, recomenda-se que você mude as configur
|
|||
<string name="tools_menu">Ferramentas</string>
|
||||
<string name="load_save_menu">Carregar/Salvar partida</string>
|
||||
<string name="goto_move">Ir para o lance</string>
|
||||
<string name="edit_strength">Alterar nível</string>
|
||||
<string name="edit_randomization">Alterar aleatoriedade</string>
|
||||
<string name="invalid_number_format">Formato de número inválido</string>
|
||||
<string name="side_to_move">Lado a mover</string>
|
||||
|
@ -273,8 +272,6 @@ Se você está usando somente a bateria, recomenda-se que você mude as configur
|
|||
<string name="prefs_playerNameFlip_title">Inverter tabuleiro: jogador</string>
|
||||
<string name="prefs_playerNameFlip_summary">Usar o nome do jogador para virar o tabuleiro automaticamente</string>
|
||||
<string name="prefs_engine_settings">Configurações do software de Xadrez</string>
|
||||
<string name="prefs_strength_title">Nível de jogo</string>
|
||||
<string name="prefs_strength_summary">Somente suportado pelo software interno. Modo análise sempre usa força total.</string>
|
||||
<string name="prefs_ponderMode_title">Análise constante</string>
|
||||
<string name="prefs_ponderMode_summary">Deixar o software analisando enquanto espera o lance do oponente. Suportado pela maioria dos softwares.</string>
|
||||
<string name="prefs_hash_title">Tabela hash</string>
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
<string name="tools_menu">Инструменты</string>
|
||||
<string name="load_save_menu">Загрузить/Сохранить партию</string>
|
||||
<string name="goto_move">Сделать ход</string>
|
||||
<string name="edit_strength">Изменить уровень сложности</string>
|
||||
<string name="edit_randomization">Изменить рандомизацию (случайность)</string>
|
||||
<string name="invalid_number_format">Неправильный формат числа</string>
|
||||
<string name="side_to_move">Задать направление хода</string>
|
||||
|
@ -273,8 +272,6 @@
|
|||
<string name="prefs_playerNameFlip_title">Поворачивать доску: игрок</string>
|
||||
<string name="prefs_playerNameFlip_summary">Использовать имя игрока для автоматического поворота доски</string>
|
||||
<string name="prefs_engine_settings">Настройки движка</string>
|
||||
<string name="prefs_strength_title">Сила игры</string>
|
||||
<string name="prefs_strength_summary">Поддерживается только внутренними движками. Режим анализа всегда использует полную силу.</string>
|
||||
<string name="prefs_ponderMode_title">Размышление</string>
|
||||
<string name="prefs_ponderMode_summary">Позволить движку обдумывание во время ожидания хода оппонента. Поддерживается большинством движков.</string>
|
||||
<string name="prefs_hash_title">Хэш-таблица</string>
|
||||
|
|
|
@ -50,7 +50,6 @@ Pil gücüyle çalışıyorsanız, pil gücünden tasarruf etmek için ayarları
|
|||
<string name="tools_menu">Araçlar</string>
|
||||
<string name="load_save_menu">Oyun Yükle/Kaydet</string>
|
||||
<string name="goto_move">Harekete git</string>
|
||||
<string name="edit_strength">Gücü ayarla</string>
|
||||
<string name="edit_randomization">Rasgeleliği ayarla</string>
|
||||
<string name="invalid_number_format">Geçersiz sayı formatı</string>
|
||||
<string name="side_to_move">Hareket tarafı</string>
|
||||
|
@ -273,8 +272,6 @@ Pil gücüyle çalışıyorsanız, pil gücünden tasarruf etmek için ayarları
|
|||
<string name="prefs_playerNameFlip_title">Tahtayı Dödür: Oyuncu</string>
|
||||
<string name="prefs_playerNameFlip_summary">Tahtayı döndürmek için Oyuncu Adını kullan</string>
|
||||
<string name="prefs_engine_settings">Motor Ayarları</string>
|
||||
<string name="prefs_strength_title">Oynama zorluğu</string>
|
||||
<string name="prefs_strength_summary">Sadece dahili motorlar destekler. Analiz modu daima tam gücü kullanır.</string>
|
||||
<string name="prefs_ponderMode_title">Düşünme</string>
|
||||
<string name="prefs_ponderMode_summary">Rakibini beklerken bilgisayarın düşünmesine izin ver. Çoğu motor destekler.</string>
|
||||
<string name="prefs_hash_title">Hash Tablosu</string>
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
<string name="tools_menu">Інструменти</string>
|
||||
<string name="load_save_menu">Завантажити/Зберегти партію</string>
|
||||
<string name="goto_move">Зробити хід</string>
|
||||
<string name="edit_strength">Змінити рівень складності</string>
|
||||
<string name="edit_randomization">Змінити рандомізацію (випадковість)</string>
|
||||
<string name="invalid_number_format">Неправильний формат числа</string>
|
||||
<string name="side_to_move">Задати напрямок ходу</string>
|
||||
|
@ -273,8 +272,6 @@
|
|||
<string name="prefs_playerNameFlip_title">Повертати дошку: гравець</string>
|
||||
<string name="prefs_playerNameFlip_summary">Використовувати ім\'я гравця для автоматичного повороту дошки</string>
|
||||
<string name="prefs_engine_settings">Налаштування рушія</string>
|
||||
<string name="prefs_strength_title">Сила ігри</string>
|
||||
<string name="prefs_strength_summary">Підтримується тільки внутрішніми рушіями. Режим аналізу завжди використовує повну силу.</string>
|
||||
<string name="prefs_ponderMode_title">Розважання</string>
|
||||
<string name="prefs_ponderMode_summary">Дозволити рушію обдумування під час очікування ходу опонента. Підтримується більшістю рушіїв.</string>
|
||||
<string name="prefs_hash_title">Геш-таблиця</string>
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
<string name="tools_menu">工具</string>
|
||||
<string name="load_save_menu">加载/保存对局</string>
|
||||
<string name="goto_move">转到着法</string>
|
||||
<string name="edit_strength">编辑棋力</string>
|
||||
<string name="edit_randomization">编辑随机性</string>
|
||||
<string name="invalid_number_format">编号格式无效</string>
|
||||
<string name="side_to_move">轮走棋方</string>
|
||||
|
@ -273,8 +272,6 @@
|
|||
<string name="prefs_playerNameFlip_title">翻转棋盘: 棋手</string>
|
||||
<string name="prefs_playerNameFlip_summary">以棋手名字自动翻转棋盘</string>
|
||||
<string name="prefs_engine_settings">引擎设置</string>
|
||||
<string name="prefs_strength_title">对弈棋力</string>
|
||||
<string name="prefs_strength_summary">支持内置引擎。分析模式总是使用最强棋力</string>
|
||||
<string name="prefs_ponderMode_title">思考</string>
|
||||
<string name="prefs_ponderMode_summary">引擎在等待对手走棋时思考。支持大多数引擎</string>
|
||||
<string name="prefs_hash_title">哈希表</string>
|
||||
|
|
|
@ -50,7 +50,9 @@ If you are running on battery power, it is recommended that you change settings
|
|||
<string name="tools_menu">Tools</string>
|
||||
<string name="load_save_menu">Load/Save Game</string>
|
||||
<string name="goto_move">Goto move</string>
|
||||
<string name="edit_strength">Edit Strength</string>
|
||||
<string name="limit_strength">Limit Strength</string>
|
||||
<string name="set_engine_strength">Set Engine Strength</string>
|
||||
<string name="engine_cannot_reduce_strength">Engine cannot reduce playing strength</string>
|
||||
<string name="edit_randomization">Edit Randomization</string>
|
||||
<string name="invalid_number_format">Invalid number format</string>
|
||||
<string name="side_to_move">Side to Move</string>
|
||||
|
@ -273,8 +275,6 @@ If you are running on battery power, it is recommended that you change settings
|
|||
<string name="prefs_playerNameFlip_title">Flip Board: Player</string>
|
||||
<string name="prefs_playerNameFlip_summary">Use Player Name to flip board automatically</string>
|
||||
<string name="prefs_engine_settings">Engine Settings</string>
|
||||
<string name="prefs_strength_title">Playing Strength</string>
|
||||
<string name="prefs_strength_summary">Only supported by internal engines. Analysis mode always uses full strength.</string>
|
||||
<string name="prefs_ponderMode_title">Pondering</string>
|
||||
<string name="prefs_ponderMode_summary">Let engine think while waiting for opponent\'s move. Supported by most engines.</string>
|
||||
<string name="prefs_hash_title">Hash Table</string>
|
||||
|
|
|
@ -30,12 +30,6 @@
|
|||
</PreferenceCategory>
|
||||
<PreferenceCategory
|
||||
android:title="@string/prefs_engine_settings">
|
||||
<org.petero.droidfish.activities.util.SeekBarPreference
|
||||
android:key="strength"
|
||||
android:title="@string/prefs_strength_title"
|
||||
android:summary="@string/prefs_strength_summary"
|
||||
android:defaultValue="1000">
|
||||
</org.petero.droidfish.activities.util.SeekBarPreference>
|
||||
<CheckBoxPreference
|
||||
android:key="ponderMode"
|
||||
android:title="@string/prefs_ponderMode_title"
|
||||
|
|
51
README.md
51
README.md
|
@ -123,6 +123,29 @@ light bulb image) that toggles analysis mode. When analysis mode is disabled the
|
|||
game mode that was used before analysis mode was enabled is restored.
|
||||
|
||||
|
||||
# Playing strength
|
||||
|
||||
For engines that can reduce their playing strength using the UCI_LimitStrength
|
||||
and UCI_Elo options, it is possible to specify the engine playing strength by
|
||||
opening the *Left drawer menu* and selecting *Set Engine Strength*. Both
|
||||
built-in engines (*Stockfish* and *CuckooChess*) can reduce their playing
|
||||
strength.
|
||||
|
||||
The available Elo range can be different for different engines. If *Stockfish*
|
||||
is playing too strong even on the lowest setting, consider switching to the
|
||||
*CuckooChess* engine which is able to play at a much weaker level. At the lowest
|
||||
setting, *CuckooChess* plays random legal moves so it should be usable also for
|
||||
an absolute beginner.
|
||||
|
||||
The selected playing strength is shown in the title bar after the engine name.
|
||||
|
||||
Playing strength changes take effect the next time the engine starts to think
|
||||
about a move.
|
||||
|
||||
The playing strength setting is only used in game playing mode. When the engine
|
||||
is in analysis mode, full strength is always used.
|
||||
|
||||
|
||||
# The move list text area
|
||||
|
||||
The move list keeps a record of moves played during a game and during analysis.
|
||||
|
@ -737,34 +760,6 @@ what to do if a player runs out of time.
|
|||
|
||||
Time control changes take effect when a new game is started.
|
||||
|
||||
## Playing strength
|
||||
|
||||
For built-in engines (*Stockfish* and *CuckooChess*), it is possible to specify
|
||||
the playing strength in the *Engine Settings* section. The strength is specified
|
||||
as a percentage between 0% and 100%. You can specify the value either by
|
||||
dragging the slider, or by tapping the value and entering a new value in the
|
||||
dialog box.
|
||||
|
||||
For *Stockfish* the actual strength used is an integer value between 0 and 20,
|
||||
so the specified percentage value is divided by 5 and rounded down to an
|
||||
integer. Even at 0 strength *Stockfish* plays at a level that may be too high
|
||||
for a beginner.
|
||||
|
||||
For *CuckooChess* the specified percentage value is used without rounding and a
|
||||
smaller value causes the engine to make mistakes more often and to make bigger
|
||||
mistakes. At 0% strength the engine plays random legal moves so it should be
|
||||
usable also for an absolute beginner.
|
||||
|
||||
Playing strength changes take effect the next time the engine starts to think
|
||||
about a move.
|
||||
|
||||
The playing strength setting is only used in game playing mode. When the engine
|
||||
is in analysis mode, full strength is always used.
|
||||
|
||||
**Note!** For non built-in engines, the *Playing Strength* setting has no
|
||||
effect. It may however be possible to set the engine strength by modifying some
|
||||
of the engine UCI options.
|
||||
|
||||
## Hash table size
|
||||
|
||||
Use *Left drawer menu* -> *Settings* -> *Engine Settings* -> *Hash Table* to
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user