DroidFish: Display chess moves using localized piece names.

This commit is contained in:
Peter Osterlund 2012-08-19 10:05:42 +00:00
parent 986d30991d
commit 5c161d2101
22 changed files with 271 additions and 111 deletions

View File

@ -48,7 +48,7 @@ public final class MoveGen {
/** /**
* Generate and return a list of pseudo-legal moves. * Generate and return a list of pseudo-legal moves.
* Pseudo-legal means that the moves doesn't necessarily defend from check threats. * Pseudo-legal means that the moves don't necessarily defend from check threats.
*/ */
public final MoveList pseudoLegalMoves(Position pos) { public final MoveList pseudoLegalMoves(Position pos) {
MoveList moveList = getMoveListObj(); MoveList moveList = getMoveListObj();

View File

@ -108,7 +108,7 @@ wenn Sie es nicht aktiv nutzen.\
<string name="filename">Dateiname:</string> <string name="filename">Dateiname:</string>
<string name="halfmove">Halbzug:</string> <string name="halfmove">Halbzug:</string>
<string name="fullmove">Zugnummer:</string> <string name="fullmove">Zugnummer:</string>
<string name="filter_text">Filtertext</string> <string name="filter_text">Suche…</string>
<string name="value_percent">Wert (%):</string> <string name="value_percent">Wert (%):</string>
<string name="header_event">Ereignis:</string> <string name="header_event">Ereignis:</string>
<string name="header_site">Ort:</string> <string name="header_site">Ort:</string>
@ -171,6 +171,7 @@ wenn Sie es nicht aktiv nutzen.\
<string name="uci_protocol_error">UCI-Protokollfehler</string> <string name="uci_protocol_error">UCI-Protokollfehler</string>
<string name="start_new_game">Neue Partie starten?</string> <string name="start_new_game">Neue Partie starten?</string>
<string name="strength_cuckoo_hint">Nutzen Sie die CuckooChess-Engine für eine noch geringere Spielstärke.</string> <string name="strength_cuckoo_hint">Nutzen Sie die CuckooChess-Engine für eine noch geringere Spielstärke.</string>
<string name="piece_names">B S L T D K</string>
<string name="err_too_few_spaces">Zuwenig Felder</string> <string name="err_too_few_spaces">Zuwenig Felder</string>
<string name="err_invalid_piece">Unzulässige Figur</string> <string name="err_invalid_piece">Unzulässige Figur</string>
<string name="err_invalid_side">Unzulässige Seite</string> <string name="err_invalid_side">Unzulässige Seite</string>

View File

@ -169,6 +169,7 @@ Si está usted utilizando la batería, se recomienda que cambie los ajustes para
<string name="uci_protocol_error">Fallo en el protocolo UCI</string> <string name="uci_protocol_error">Fallo en el protocolo UCI</string>
<string name="start_new_game">¿Empezar nueva partida?</string> <string name="start_new_game">¿Empezar nueva partida?</string>
<string name="strength_cuckoo_hint">Utilice el motor CuckooChess para rebajar aún más el nivel de juego.</string> <string name="strength_cuckoo_hint">Utilice el motor CuckooChess para rebajar aún más el nivel de juego.</string>
<string name="piece_names">P C A T D R</string>
<string name="err_too_few_spaces">Pocos espacios</string> <string name="err_too_few_spaces">Pocos espacios</string>
<string name="err_invalid_piece">Pieza incorrecta</string> <string name="err_invalid_piece">Pieza incorrecta</string>
<string name="err_invalid_side">Lado incorrecto</string> <string name="err_invalid_side">Lado incorrecto</string>

View File

@ -107,7 +107,7 @@ não estiver usando o programa diretamente.\</string>
<string name="filename">Arquivo:</string> <string name="filename">Arquivo:</string>
<string name="halfmove">Relógio para meio-lance:</string> <string name="halfmove">Relógio para meio-lance:</string>
<string name="fullmove">Contador de lances completos:</string> <string name="fullmove">Contador de lances completos:</string>
<string name="filter_text">Pesquisar...</string> <string name="filter_text">Pesquisar</string>
<string name="value_percent">Valor(%):</string> <string name="value_percent">Valor(%):</string>
<string name="header_event">Evento:</string> <string name="header_event">Evento:</string>
<string name="header_site">Site:</string> <string name="header_site">Site:</string>
@ -170,6 +170,7 @@ não estiver usando o programa diretamente.\</string>
<string name="uci_protocol_error">Erro de protocolo UCI</string> <string name="uci_protocol_error">Erro de protocolo UCI</string>
<string name="start_new_game">Iniciar nova partida?</string> <string name="start_new_game">Iniciar nova partida?</string>
<string name="strength_cuckoo_hint">Use o CuckooChess para um nível ainda menor.</string> <string name="strength_cuckoo_hint">Use o CuckooChess para um nível ainda menor.</string>
<string name="piece_names">P C B T D R</string>
<string name="err_too_few_spaces">Poucos espaços</string> <string name="err_too_few_spaces">Poucos espaços</string>
<string name="err_invalid_piece">Peça inválida</string> <string name="err_invalid_piece">Peça inválida</string>
<string name="err_invalid_side">Lado inválido</string> <string name="err_invalid_side">Lado inválido</string>
@ -238,7 +239,7 @@ não estiver usando o programa diretamente.\</string>
<string name="prefs_fullScreenMode_summary">Modo tela cheia oculta a barra de notificações</string> <string name="prefs_fullScreenMode_summary">Modo tela cheia oculta a barra de notificações</string>
<string name="prefs_wakeLock_title">Desabilita apagar a tela automaticamente</string> <string name="prefs_wakeLock_title">Desabilita apagar a tela automaticamente</string>
<string name="prefs_drawSquareLabels_title">Rótulos nas casas</string> <string name="prefs_drawSquareLabels_title">Rótulos nas casas</string>
<string name="prefs_drawSquareLabels_summary">Mostrar rótulos nas casas: a-h e 1-8</string> <string name="prefs_drawSquareLabels_summary">Mostrar rótulos nas casas: ah e 18</string>
<string name="prefs_scrollSensitivity_title">Velocidade do movimento</string> <string name="prefs_scrollSensitivity_title">Velocidade do movimento</string>
<string name="prefs_scrollSensitivity_summary">Velocidade do movimento para navegação em partida</string> <string name="prefs_scrollSensitivity_summary">Velocidade do movimento para navegação em partida</string>
<string name="prefs_invertScrollDirection_title">Inverter direção do movimento</string> <string name="prefs_invertScrollDirection_title">Inverter direção do movimento</string>

View File

@ -159,6 +159,7 @@
<string name="uci_protocol_error">Ошибка UCI протокола</string> <string name="uci_protocol_error">Ошибка UCI протокола</string>
<string name="start_new_game">Начать новую партию?</string> <string name="start_new_game">Начать новую партию?</string>
<string name="strength_cuckoo_hint">Использовать движок CuckooChess для наименьшего уровня сложности.</string> <string name="strength_cuckoo_hint">Использовать движок CuckooChess для наименьшего уровня сложности.</string>
<string name="piece_names">П К С Л Ф Кр</string>
<string name="err_too_few_spaces">Слишком малое пространство</string> <string name="err_too_few_spaces">Слишком малое пространство</string>
<string name="err_invalid_piece">Неверная фигура</string> <string name="err_invalid_piece">Неверная фигура</string>
<string name="err_invalid_side">Неверное местоположение</string> <string name="err_invalid_side">Неверное местоположение</string>

View File

@ -10,6 +10,7 @@
<string name="thinking_arrows_default">2</string> <string name="thinking_arrows_default">2</string>
<string name="scroll_sensitivity_default">2</string> <string name="scroll_sensitivity_default">2</string>
<string name="book_line_length_default">1000000</string> <string name="book_line_length_default">1000000</string>
<string name="viewPieceType_default">1</string>
<string name="cpu_warning">\ <string name="cpu_warning">\
<b>CPU Usage</b>\n\ <b>CPU Usage</b>\n\
If you leave DroidFish running in the background and <i>GameMode</i> is set to \ If you leave DroidFish running in the background and <i>GameMode</i> is set to \
@ -185,6 +186,7 @@ you are not actively using the program.\
<string name="invalid_network_port">Invalid network port</string> <string name="invalid_network_port">Invalid network port</string>
<string name="start_new_game">Start New Game?</string> <string name="start_new_game">Start New Game?</string>
<string name="strength_cuckoo_hint">Use the CuckooChess engine for even lower strength.</string> <string name="strength_cuckoo_hint">Use the CuckooChess engine for even lower strength.</string>
<string name="piece_names">P N B R Q K</string>
<string name="err_too_few_spaces">Too few spaces</string> <string name="err_too_few_spaces">Too few spaces</string>
<string name="err_invalid_piece">Invalid piece</string> <string name="err_invalid_piece">Invalid piece</string>
<string name="err_invalid_side">Invalid side</string> <string name="err_invalid_side">Invalid side</string>
@ -323,6 +325,8 @@ you are not actively using the program.\
<string name="prefs_viewNAG_summary">Include numeric annotation glyphs (NAGs), such as ! and ?</string> <string name="prefs_viewNAG_summary">Include numeric annotation glyphs (NAGs), such as ! and ?</string>
<string name="prefs_viewHeaders_title">Headers</string> <string name="prefs_viewHeaders_title">Headers</string>
<string name="prefs_viewHeaders_summary">Show PGN header lines</string> <string name="prefs_viewHeaders_summary">Show PGN header lines</string>
<string name="prefs_viewPieceType_title">Pieces</string>
<string name="prefs_viewPieceType_summary">Control how chess pieces are displayed</string>
<string name="prefs_pgn_import">PGN import</string> <string name="prefs_pgn_import">PGN import</string>
<string name="prefs_importVariations_title">Variations</string> <string name="prefs_importVariations_title">Variations</string>
<string name="prefs_importVariations_summary">Include non-mainline moves</string> <string name="prefs_importVariations_summary">Include non-mainline moves</string>
@ -376,6 +380,14 @@ you are not actively using the program.\
<item>6</item> <item>6</item>
<item>8</item> <item>8</item>
</string-array> </string-array>
<string-array name="viewPieceType_texts">
<item>English letters</item>
<item>Local language letters</item>
</string-array>
<string-array name="viewPieceType_values">
<item>0</item>
<item>1</item>
</string-array>
<string-array name="engine_hash_texts"> <string-array name="engine_hash_texts">
<item>16 MB</item> <item>16 MB</item>
<item>32 MB</item> <item>32 MB</item>

View File

@ -513,6 +513,14 @@
android:summary="@string/prefs_viewHeaders_summary" android:summary="@string/prefs_viewHeaders_summary"
android:defaultValue="false"> android:defaultValue="false">
</CheckBoxPreference> </CheckBoxPreference>
<ListPreference
android:key="viewPieceType"
android:title="@string/prefs_viewPieceType_title"
android:summary="@string/prefs_viewPieceType_summary"
android:entryValues="@array/viewPieceType_values"
android:entries="@array/viewPieceType_texts"
android:defaultValue="@string/viewPieceType_default">
</ListPreference>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
android:title="@string/prefs_pgn_import"> android:title="@string/prefs_pgn_import">

View File

@ -126,7 +126,6 @@ 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!!! Add support for "Chess Leipzig" font // FIXME!!! Add support for "Chess Leipzig" font
// FIXME!!! Implement figurine notation // FIXME!!! Implement figurine notation
@ -253,7 +252,7 @@ public class DroidFish extends Activity implements GUIInterface {
public void run() { public void run() {
pgnOptions.view.variations = toggleBooleanPref("viewVariations"); pgnOptions.view.variations = toggleBooleanPref("viewVariations");
gameTextListener.clear(); gameTextListener.clear();
ctrl.prefsChanged(); ctrl.prefsChanged(false);
} }
}); });
addAction(new UIAction() { addAction(new UIAction() {
@ -264,7 +263,7 @@ public class DroidFish extends Activity implements GUIInterface {
public void run() { public void run() {
pgnOptions.view.comments = toggleBooleanPref("viewComments"); pgnOptions.view.comments = toggleBooleanPref("viewComments");
gameTextListener.clear(); gameTextListener.clear();
ctrl.prefsChanged(); ctrl.prefsChanged(false);
} }
}); });
addAction(new UIAction() { addAction(new UIAction() {
@ -275,7 +274,7 @@ public class DroidFish extends Activity implements GUIInterface {
public void run() { public void run() {
pgnOptions.view.headers = toggleBooleanPref("viewHeaders"); pgnOptions.view.headers = toggleBooleanPref("viewHeaders");
gameTextListener.clear(); gameTextListener.clear();
ctrl.prefsChanged(); ctrl.prefsChanged(false);
} }
}); });
addAction(new UIAction() { addAction(new UIAction() {
@ -352,6 +351,7 @@ public class DroidFish extends Activity implements GUIInterface {
custom3ButtonActions = new ButtonActions("custom3", CUSTOM3_BUTTON_DIALOG, custom3ButtonActions = new ButtonActions("custom3", CUSTOM3_BUTTON_DIALOG,
R.string.select_action); R.string.select_action);
TextIO.setPieceNames(getString(R.string.piece_names));
initUI(true); initUI(true);
gameTextListener = new PgnScreenText(pgnOptions); gameTextListener = new PgnScreenText(pgnOptions);
@ -808,6 +808,8 @@ public class DroidFish extends Activity implements GUIInterface {
pgnOptions.view.comments = settings.getBoolean("viewComments", true); pgnOptions.view.comments = settings.getBoolean("viewComments", true);
pgnOptions.view.nag = settings.getBoolean("viewNAG", true); pgnOptions.view.nag = settings.getBoolean("viewNAG", true);
pgnOptions.view.headers = settings.getBoolean("viewHeaders", false); pgnOptions.view.headers = settings.getBoolean("viewHeaders", false);
final int oldViewPieceType = pgnOptions.view.pieceType;
pgnOptions.view.pieceType = getIntSetting("viewPieceType", PGNOptions.PT_LOCAL);
pgnOptions.imp.variations = settings.getBoolean("importVariations", true); pgnOptions.imp.variations = settings.getBoolean("importVariations", true);
pgnOptions.imp.comments = settings.getBoolean("importComments", true); pgnOptions.imp.comments = settings.getBoolean("importComments", true);
pgnOptions.imp.nag = settings.getBoolean("importNAG", true); pgnOptions.imp.nag = settings.getBoolean("importNAG", true);
@ -821,7 +823,7 @@ public class DroidFish extends Activity implements GUIInterface {
cb.setColors(); cb.setColors();
gameTextListener.clear(); gameTextListener.clear();
ctrl.prefsChanged(); ctrl.prefsChanged(oldViewPieceType != pgnOptions.view.pieceType);
} }
private void updateButtons() { private void updateButtons() {
@ -1829,7 +1831,7 @@ public class DroidFish extends Activity implements GUIInterface {
ColorTheme.instance().setTheme(settings, item); ColorTheme.instance().setTheme(settings, item);
cb.setColors(); cb.setColors();
gameTextListener.clear(); gameTextListener.clear();
ctrl.prefsChanged(); ctrl.prefsChanged(false);
dialog.dismiss(); dialog.dismiss();
} }
}); });

View File

@ -20,11 +20,15 @@ package org.petero.droidfish;
/** Settings controlling PGN import/export */ /** Settings controlling PGN import/export */
public class PGNOptions { public class PGNOptions {
public static final int PT_ENGLISH = 0; // Piece type english letters
public static final int PT_LOCAL = 1; // Piece type local language letters
public static class Viewer { public static class Viewer {
public boolean variations; public boolean variations;
public boolean comments; public boolean comments;
public boolean nag; public boolean nag;
public boolean headers; public boolean headers;
public int pieceType;
} }
public static class Import { public static class Import {
public boolean variations; public boolean variations;
@ -39,6 +43,7 @@ public class PGNOptions {
public boolean clockInfo; public boolean clockInfo;
public boolean pgnPromotions; public boolean pgnPromotions;
public boolean moveNrAfterNag; public boolean moveNrAfterNag;
public int pieceType;
} }
public Viewer view; public Viewer view;
@ -50,5 +55,6 @@ public class PGNOptions {
imp = new Import(); imp = new Import();
exp = new Export(); exp = new Export();
exp.moveNrAfterNag = true; exp.moveNrAfterNag = true;
exp.pieceType = PT_ENGLISH;
} }
} }

View File

@ -114,7 +114,8 @@ public final class DroidBook {
} }
/** Return all book moves, both as a formatted string and as a list of moves. */ /** Return all book moves, both as a formatted string and as a list of moves. */
public final synchronized Pair<String,ArrayList<Move>> getAllBookMoves(Position pos) { public final synchronized Pair<String,ArrayList<Move>> getAllBookMoves(Position pos,
boolean localized) {
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
ArrayList<Move> bookMoveList = new ArrayList<Move>(); ArrayList<Move> bookMoveList = new ArrayList<Move>();
List<BookEntry> bookMoves = getBook().getBookEntries(pos); List<BookEntry> bookMoves = getBook().getBookEntries(pos);
@ -150,7 +151,7 @@ public final class DroidBook {
for (BookEntry be : bookMoves) { for (BookEntry be : bookMoves) {
Move m = be.move; Move m = be.move;
bookMoveList.add(m); bookMoveList.add(m);
String moveStr = TextIO.moveToString(pos, m, false); String moveStr = TextIO.moveToString(pos, m, false, localized);
if (first) if (first)
first = false; first = false;
else else

View File

@ -275,8 +275,8 @@ public class DroidComputerPlayer {
} }
/** Return all book moves, both as a formatted string and as a list of moves. */ /** Return all book moves, both as a formatted string and as a list of moves. */
public final Pair<String, ArrayList<Move>> getBookHints(Position pos) { public final Pair<String, ArrayList<Move>> getBookHints(Position pos, boolean localized) {
return book.getAllBookMoves(pos); return book.getAllBookMoves(pos, localized);
} }
/** Get engine reported name. */ /** Get engine reported name. */
@ -371,7 +371,9 @@ public class DroidComputerPlayer {
Move bookMove = book.getBookMove(sr.currPos); Move bookMove = book.getBookMove(sr.currPos);
if (bookMove != null) { if (bookMove != null) {
if (canClaimDraw(sr.currPos, posHashList, posHashListSize, bookMove) == "") { if (canClaimDraw(sr.currPos, posHashList, posHashListSize, bookMove) == "") {
listener.notifySearchResult(sr.searchId, TextIO.moveToString(sr.currPos, bookMove, false), null); listener.notifySearchResult(sr.searchId,
TextIO.moveToString(sr.currPos, bookMove, false, false),
null);
return; return;
} }
} }
@ -803,7 +805,7 @@ public class DroidComputerPlayer {
} else if (canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) { } else if (canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) {
drawStr = "draw rep"; drawStr = "draw rep";
} else if (move != null) { } else if (move != null) {
String strMove = TextIO.moveToString(pos, move, false); String strMove = TextIO.moveToString(pos, move, false, false);
posHashList[posHashListSize++] = pos.zobristHash(); posHashList[posHashListSize++] = pos.zobristHash();
UndoInfo ui = new UndoInfo(); UndoInfo ui = new UndoInfo();
pos.makeMove(move, ui); pos.makeMove(move, ui);

View File

@ -184,15 +184,22 @@ public class DroidChessController {
} }
/** Notify controller that preferences has changed. */ /** Notify controller that preferences has changed. */
public final synchronized void prefsChanged() { public final synchronized void prefsChanged(boolean translateMoves) {
if (game == null)
translateMoves = false;
if (translateMoves)
game.tree.translateMoves();
updateBookHints(); updateBookHints();
updateMoveList(); updateMoveList();
listener.prefsChanged(searchId); listener.prefsChanged(searchId, translateMoves);
if (translateMoves)
updateGUI();
} }
/** De-serialize from byte array. */ /** De-serialize from byte array. */
public final synchronized void fromByteArray(byte[] data) { public final synchronized void fromByteArray(byte[] data) {
game.fromByteArray(data); game.fromByteArray(data);
game.tree.translateMoves();
} }
/** Serialize to byte array. */ /** Serialize to byte array. */
@ -221,6 +228,7 @@ public class DroidChessController {
// Try read as PGN instead // Try read as PGN instead
if (!newGame.readPGN(fenPgn, pgnOptions)) if (!newGame.readPGN(fenPgn, pgnOptions))
throw e; throw e;
newGame.tree.translateMoves();
} }
searchId++; searchId++;
game = newGame; game = newGame;
@ -554,7 +562,7 @@ public class DroidChessController {
public final synchronized CommentInfo getComments() { public final synchronized CommentInfo getComments() {
Node cur = game.tree.currentNode; Node cur = game.tree.currentNode;
CommentInfo ret = new CommentInfo(); CommentInfo ret = new CommentInfo();
ret.move = cur.moveStr; ret.move = cur.moveStrLocal;
ret.preComment = cur.preComment; ret.preComment = cur.preComment;
ret.postComment = cur.postComment; ret.postComment = cur.postComment;
ret.nag = cur.nag; ret.nag = cur.nag;
@ -571,11 +579,17 @@ public class DroidChessController {
updateGUI(); updateGUI();
} }
/** Return true if localized piece names should be used. */
private final boolean localPt() {
return pgnOptions.view.pieceType == PGNOptions.PT_LOCAL;
}
/** Engine search information receiver. */ /** Engine search information receiver. */
private final class SearchListener implements org.petero.droidfish.gamelogic.SearchListener { private final class SearchListener implements org.petero.droidfish.gamelogic.SearchListener {
private int currDepth = 0; private int currDepth = 0;
private int currMoveNr = 0; private int currMoveNr = 0;
private String currMove = ""; private Move currMove = null;
private String currMoveStr = "";
private int currNodes = 0; private int currNodes = 0;
private int currNps = 0; private int currNps = 0;
private int currTime = 0; private int currTime = 0;
@ -586,8 +600,10 @@ public class DroidChessController {
private Move ponderMove = null; private Move ponderMove = null;
private ArrayList<PvInfo> pvInfoV = new ArrayList<PvInfo>(); private ArrayList<PvInfo> pvInfoV = new ArrayList<PvInfo>();
private int pvInfoSearchId = -1; // Search ID corresponding to pvInfoV
public final void clearSearchInfo(int id) { public final void clearSearchInfo(int id) {
pvInfoSearchId = -1;
ponderMove = null; ponderMove = null;
pvInfoV.clear(); pvInfoV.clear();
currDepth = 0; currDepth = 0;
@ -620,7 +636,7 @@ public class DroidChessController {
buf.append(pvi.pvStr); buf.append(pvi.pvStr);
} }
final String statStr = (currDepth > 0) ? final String statStr = (currDepth > 0) ?
String.format("d:%d %d:%s t:%.2f n:%d nps:%d", currDepth, currMoveNr, currMove, String.format("d:%d %d:%s t:%.2f n:%d nps:%d", currDepth, currMoveNr, currMoveStr,
currTime / 1000.0, currNodes, currNps) currTime / 1000.0, currNodes, currNps)
: ""; : "";
final String newPV = buf.toString(); final String newPV = buf.toString();
@ -652,7 +668,8 @@ public class DroidChessController {
@Override @Override
public void notifyCurrMove(int id, Position pos, Move m, int moveNr) { public void notifyCurrMove(int id, Position pos, Move m, int moveNr) {
currMove = TextIO.moveToString(pos, m, false); currMove = m;
currMoveStr = TextIO.moveToString(pos, m, false, localPt());
currMoveNr = moveNr; currMoveNr = moveNr;
setSearchInfo(id); setSearchInfo(id);
} }
@ -661,6 +678,7 @@ public class DroidChessController {
@Override @Override
public void notifyPV(int id, Position pos, ArrayList<PvInfo> pvInfo, Move ponderMove) { public void notifyPV(int id, Position pos, ArrayList<PvInfo> pvInfo, Move ponderMove) {
this.ponderMove = ponderMove; this.ponderMove = ponderMove;
this.pvInfoSearchId = id;
pvInfoV = (ArrayList<PvInfo>) pvInfo.clone(); pvInfoV = (ArrayList<PvInfo>) pvInfo.clone();
for (PvInfo pv : pvInfo) { for (PvInfo pv : pvInfo) {
currTime = pv.time; currTime = pv.time;
@ -671,7 +689,7 @@ public class DroidChessController {
Position tmpPos = new Position(pos); Position tmpPos = new Position(pos);
UndoInfo ui = new UndoInfo(); UndoInfo ui = new UndoInfo();
if (ponderMove != null) { if (ponderMove != null) {
String moveStr = TextIO.moveToString(tmpPos, ponderMove, false); String moveStr = TextIO.moveToString(tmpPos, ponderMove, false, localPt());
buf.append(String.format(" [%s]", moveStr)); buf.append(String.format(" [%s]", moveStr));
tmpPos.makeMove(ponderMove, ui); tmpPos.makeMove(ponderMove, ui);
} }
@ -680,7 +698,7 @@ public class DroidChessController {
break; break;
if (!TextIO.isValid(tmpPos, m)) if (!TextIO.isValid(tmpPos, m))
break; break;
String moveStr = TextIO.moveToString(tmpPos, m, false); String moveStr = TextIO.moveToString(tmpPos, m, false, localPt());
buf.append(String.format(" %s", moveStr)); buf.append(String.format(" %s", moveStr));
tmpPos.makeMove(m, ui); tmpPos.makeMove(m, ui);
} }
@ -706,9 +724,16 @@ public class DroidChessController {
setSearchInfo(id); setSearchInfo(id);
} }
public void prefsChanged(int id) { public void prefsChanged(int id, boolean translateMoves) {
if (translateMoves && (id == pvInfoSearchId)) {
Position pos = game.currPos();
if (currMove != null)
notifyCurrMove(id, pos, currMove, currMoveNr);
notifyPV(id, pos, pvInfoV, ponderMove);
} else {
setSearchInfo(id); setSearchInfo(id);
} }
}
@Override @Override
public void notifySearchResult(final int id, final String cmd, final Move ponder) { public void notifySearchResult(final int id, final String cmd, final Move ponder) {
@ -758,7 +783,7 @@ public class DroidChessController {
private final void updateBookHints() { private final void updateBookHints() {
if (humansTurn()) { if (humansTurn()) {
Pair<String, ArrayList<Move>> bi = computerPlayer.getBookHints(game.currPos()); Pair<String, ArrayList<Move>> bi = computerPlayer.getBookHints(game.currPos(), localPt());
listener.notifyBookInfo(searchId, bi.first, bi.second); listener.notifyBookInfo(searchId, bi.first, bi.second);
} }
} }
@ -906,8 +931,7 @@ public class DroidChessController {
*/ */
private final boolean doMove(Move move) { private final boolean doMove(Move move) {
Position pos = game.currPos(); Position pos = game.currPos();
ArrayList<Move> moves = new MoveGen().pseudoLegalMoves(pos); ArrayList<Move> moves = new MoveGen().legalMoves(pos);
moves = MoveGen.removeIllegal(pos, moves);
int promoteTo = move.promoteTo; int promoteTo = move.promoteTo;
for (Move m : moves) { for (Move m : moves) {
if ((m.from == move.from) && (m.to == move.to)) { if ((m.from == move.from) && (m.to == move.to)) {
@ -917,7 +941,7 @@ public class DroidChessController {
return false; return false;
} }
if (m.promoteTo == promoteTo) { if (m.promoteTo == promoteTo) {
String strMove = TextIO.moveToString(pos, m, false); String strMove = TextIO.moveToString(pos, m, false, false, moves);
game.processString(strMove); game.processString(strMove);
return true; return true;
} }
@ -943,7 +967,7 @@ public class DroidChessController {
} }
} else { } else {
if ((s.state == GameState.DRAW_REP) || (s.state == GameState.DRAW_50)) if ((s.state == GameState.DRAW_REP) || (s.state == GameState.DRAW_50))
s.drawInfo = game.getDrawInfo(); s.drawInfo = game.getDrawInfo(localPt());
} }
gui.setStatus(s); gui.setStatus(s);
updateMoveList(); updateMoveList();
@ -957,7 +981,7 @@ public class DroidChessController {
if (i > 0) sb.append(' '); if (i > 0) sb.append(' ');
if (i == game.tree.currentNode.defaultChild) if (i == game.tree.currentNode.defaultChild)
sb.append(Util.boldStart); sb.append(Util.boldStart);
sb.append(TextIO.moveToString(pos, prevVarList.get(i), false)); sb.append(TextIO.moveToString(pos, prevVarList.get(i), false, localPt()));
if (i == game.tree.currentNode.defaultChild) if (i == game.tree.currentNode.defaultChild)
sb.append(Util.boldStop); sb.append(Util.boldStop);
} }
@ -985,6 +1009,7 @@ public class DroidChessController {
tmpOptions.exp.playerAction = false; tmpOptions.exp.playerAction = false;
tmpOptions.exp.clockInfo = false; tmpOptions.exp.clockInfo = false;
tmpOptions.exp.moveNrAfterNag = false; tmpOptions.exp.moveNrAfterNag = false;
tmpOptions.exp.pieceType = pgnOptions.view.pieceType;
gameTextListener.clear(); gameTextListener.clear();
game.tree.pgnTreeWalker(tmpOptions, gameTextListener); game.tree.pgnTreeWalker(tmpOptions, gameTextListener);
} }

View File

@ -185,8 +185,8 @@ public class Game {
} }
} }
public final String getDrawInfo() { public final String getDrawInfo(boolean localized) {
return tree.getGameStateInfo(); return tree.getGameStateInfo(localized);
} }
/** /**
@ -404,7 +404,7 @@ public class Game {
if (valid) { if (valid) {
String playerAction = rep ? "draw rep" : "draw 50"; String playerAction = rep ? "draw rep" : "draw 50";
if (m != null) if (m != null)
playerAction += " " + TextIO.moveToString(pos, m, false); playerAction += " " + TextIO.moveToString(pos, m, false, false);
addToGameTree(new Move(0, 0, 0), playerAction); addToGameTree(new Move(0, 0, 0), playerAction);
} else { } else {
pendingDrawOffer = true; pendingDrawOffer = true;

View File

@ -218,10 +218,38 @@ public class GameTree {
} }
} }
/** Update moveStrLocal in all game nodes. */
public final void translateMoves() {
List<Integer> currPath = new ArrayList<Integer>();
while (currentNode != rootNode) {
Node child = currentNode;
goBack();
int childNum = currentNode.children.indexOf(child);
currPath.add(childNum);
}
translateMovesHelper();
for (int i = currPath.size() - 1; i >= 0; i--)
goForward(currPath.get(i), false);
}
private final void translateMovesHelper() {
ArrayList<Move> moves = MoveGen.instance.legalMoves(currentPos);
currentNode.verifyChildren(currentPos, moves);
int nc = currentNode.children.size();
for (int i = 0; i < nc; i++) {
Node child = currentNode.children.get(i);
child.moveStrLocal = TextIO.moveToString(currentPos, child.move, false, true, moves);
goForward(i, false);
translateMovesHelper();
goBack();
}
}
/** Export game tree in PGN format. */ /** Export game tree in PGN format. */
public final String toPGN(PGNOptions options) { public final String toPGN(PGNOptions options) {
PgnText pgnText = new PgnText(); PgnText pgnText = new PgnText();
options.exp.pgnPromotions = true; options.exp.pgnPromotions = true;
options.exp.pieceType = PGNOptions.PT_ENGLISH;
pgnTreeWalker(options, pgnText); pgnTreeWalker(options, pgnText);
return pgnText.getPgnString(); return pgnText.getPgnString();
} }
@ -235,7 +263,7 @@ public class GameTree {
while (currentNode != rootNode) { while (currentNode != rootNode) {
Node child = currentNode; Node child = currentNode;
goBack(); goBack();
int childNum = variations().indexOf(child); int childNum = currentNode.children.indexOf(child);
currPath.add(childNum); currPath.add(childNum);
} }
while (variations().size() > 0) while (variations().size() > 0)
@ -692,11 +720,17 @@ public class GameTree {
int idx = currentNode.children.size(); int idx = currentNode.children.size();
Node node = new Node(currentNode, moveStr, playerAction, Integer.MIN_VALUE, nag, preComment, postComment); Node node = new Node(currentNode, moveStr, playerAction, Integer.MIN_VALUE, nag, preComment, postComment);
Move move = TextIO.UCIstringToMove(moveStr); Move move = TextIO.UCIstringToMove(moveStr);
if (move == null) ArrayList<Move> moves = null;
move = TextIO.stringToMove(currentPos, moveStr); if (move == null) {
moves = MoveGen.instance.legalMoves(currentPos);
move = TextIO.stringToMove(currentPos, moveStr, moves);
}
if (move == null) if (move == null)
return -1; return -1;
node.moveStr = TextIO.moveToString(currentPos, move, false); if (moves == null)
moves = MoveGen.instance.legalMoves(currentPos);
node.moveStr = TextIO.moveToString(currentPos, move, false, false, moves);
node.moveStrLocal = TextIO.moveToString(currentPos, move, false, true, moves);
node.move = move; node.move = move;
node.ui = new UndoInfo(); node.ui = new UndoInfo();
currentNode.children.add(node); currentNode.children.add(node);
@ -831,7 +865,7 @@ public class GameTree {
} }
/** Get additional info affecting gameState. A player "draw" or "resign" command. */ /** Get additional info affecting gameState. A player "draw" or "resign" command. */
final String getGameStateInfo() { final String getGameStateInfo(boolean localized) {
String ret = ""; String ret = "";
String action = currentNode.playerAction; String action = currentNode.playerAction;
if (action.startsWith("draw rep ")) { if (action.startsWith("draw rep ")) {
@ -840,6 +874,25 @@ public class GameTree {
if (action.startsWith("draw 50 ")) { if (action.startsWith("draw 50 ")) {
ret = action.substring(8).trim(); ret = action.substring(8).trim();
} }
if (localized) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ret.length(); i++) {
int p = Piece.EMPTY;
switch (ret.charAt(i)) {
case 'Q': p = Piece.WQUEEN; break;
case 'R': p = Piece.WROOK; break;
case 'B': p = Piece.WBISHOP; break;
case 'N': p = Piece.WKNIGHT; break;
case 'K': p = Piece.WKING; break;
case 'P': p = Piece.WPAWN; break;
}
if (p == Piece.EMPTY)
sb.append(ret.charAt(i));
else
sb.append(TextIO.pieceToCharLocalized(p));
}
ret = sb.toString();
}
return ret; return ret;
} }
@ -930,7 +983,8 @@ public class GameTree {
* The root node is special in that it doesn't have a move. * The root node is special in that it doesn't have a move.
*/ */
public static class Node { public static class Node {
String moveStr; // String representation of move leading to this node. Empty string root node. String moveStr; // String representation of move leading to this node. Empty string in root node.
String moveStrLocal; // Localized version of moveStr
Move move; // Computed on demand for better PGN parsing performance. Move move; // Computed on demand for better PGN parsing performance.
// Subtrees of invalid moves will be dropped when detected. // Subtrees of invalid moves will be dropped when detected.
// Always valid for current node. // Always valid for current node.
@ -948,6 +1002,7 @@ public class GameTree {
public Node() { public Node() {
this.moveStr = ""; this.moveStr = "";
this.moveStrLocal = "";
this.move = null; this.move = null;
this.ui = null; this.ui = null;
this.playerAction = ""; this.playerAction = "";
@ -963,6 +1018,7 @@ public class GameTree {
public Node(Node parent, String moveStr, String playerAction, int remainingTime, int nag, public Node(Node parent, String moveStr, String playerAction, int remainingTime, int nag,
String preComment, String postComment) { String preComment, String postComment) {
this.moveStr = moveStr; this.moveStr = moveStr;
this.moveStrLocal = moveStr;
this.move = null; this.move = null;
this.ui = null; this.ui = null;
this.playerAction = playerAction; this.playerAction = playerAction;
@ -981,12 +1037,18 @@ public class GameTree {
/** nodePos must represent the same position as this Node object. */ /** nodePos must represent the same position as this Node object. */
private final boolean verifyChildren(Position nodePos) { private final boolean verifyChildren(Position nodePos) {
return verifyChildren(nodePos, null);
}
private final boolean verifyChildren(Position nodePos, ArrayList<Move> moves) {
boolean anyToRemove = false; boolean anyToRemove = false;
for (Node child : children) { for (Node child : children) {
if (child.move == null) { if (child.move == null) {
Move move = TextIO.stringToMove(nodePos, child.moveStr); if (moves == null)
moves = MoveGen.instance.legalMoves(nodePos);
Move move = TextIO.stringToMove(nodePos, child.moveStr, moves);
if (move != null) { if (move != null) {
child.moveStr = TextIO.moveToString(nodePos, move, false); child.moveStr = TextIO.moveToString(nodePos, move, false, false, moves);
child.moveStrLocal = TextIO.moveToString(nodePos, move, false, true, moves);
child.move = move; child.move = move;
child.ui = new UndoInfo(); child.ui = new UndoInfo();
} else { } else {
@ -1053,6 +1115,7 @@ public class GameTree {
static final void readFromStream(DataInputStream dis, Node node) throws IOException { static final void readFromStream(DataInputStream dis, Node node) throws IOException {
while (true) { while (true) {
node.moveStr = dis.readUTF(); node.moveStr = dis.readUTF();
node.moveStrLocal = node.moveStr;
int from = dis.readByte(); int from = dis.readByte();
if (from >= 0) { if (from >= 0) {
int to = dis.readByte(); int to = dis.readByte();
@ -1105,7 +1168,7 @@ public class GameTree {
} }
} }
/** Export this node in PGN format. */ /** Export this node in PGN (or display text) format. */
private final boolean addPgnDataOneNode(PgnToken.PgnTokenReceiver out, MoveNumber mn, private final boolean addPgnDataOneNode(PgnToken.PgnTokenReceiver out, MoveNumber mn,
boolean needMoveNr, PGNOptions options) { boolean needMoveNr, PGNOptions options) {
if ((preComment.length() > 0) && options.exp.comments) { if ((preComment.length() > 0) && options.exp.comments) {
@ -1125,8 +1188,12 @@ public class GameTree {
out.processToken(this, PgnToken.PERIOD, null); out.processToken(this, PgnToken.PERIOD, null);
} }
} }
String str = moveStr; String str;
if (options.exp.pgnPromotions && (move != null) && (move.promoteTo != Piece.EMPTY)) { if (options.exp.pieceType == PGNOptions.PT_LOCAL) {
str = moveStrLocal;
} else {
str = moveStr;
if (options.exp.pgnPromotions && (move != null) && (move.promoteTo != Piece.EMPTY))
str = TextIO.pgnPromotion(str); str = TextIO.pgnPromotion(str);
} }
out.processToken(this, PgnToken.SYMBOL, str); out.processToken(this, PgnToken.SYMBOL, str);
@ -1261,6 +1328,7 @@ public class GameTree {
moveAdded = false; moveAdded = false;
} }
nodeToAdd.moveStr = tok.token; nodeToAdd.moveStr = tok.token;
nodeToAdd.moveStrLocal = tok.token;
moveAdded = true; moveAdded = true;
} }
break; break;

View File

@ -31,9 +31,16 @@ public class MoveGen {
instance = new MoveGen(); instance = new MoveGen();
} }
/** Generate and return a list of legal moves. */
public final ArrayList<Move> legalMoves(Position pos) {
ArrayList<Move> moveList = pseudoLegalMoves(pos);
moveList = MoveGen.removeIllegal(pos, moveList);
return moveList;
}
/** /**
* Generate and return a list of pseudo-legal moves. * Generate and return a list of pseudo-legal moves.
* Pseudo-legal means that the moves doesn't necessarily defend from check threats. * Pseudo-legal means that the moves don't necessarily defend from check threats.
*/ */
public final ArrayList<Move> pseudoLegalMoves(Position pos) { public final ArrayList<Move> pseudoLegalMoves(Position pos) {
ArrayList<Move> moveList = getMoveListObj(); ArrayList<Move> moveList = getMoveListObj();

View File

@ -37,21 +37,6 @@ public interface SearchListener {
ArrayList<Move> pv; ArrayList<Move> pv;
String pvStr = ""; String pvStr = "";
public PvInfo(PvInfo pvi) {
depth = pvi.depth;
score = pvi.score;
time = pvi.time;
nodes = pvi.nodes;
nps = pvi.nps;
isMate = pvi.isMate;
upperBound = pvi.upperBound;
lowerBound = pvi.lowerBound;
pv = new ArrayList<Move>(pvi.pv.size());
for (int i = 0; i < pvi.pv.size(); i++)
pv.add(pvi.pv.get(i));
pvStr = pvi.pvStr;
}
public PvInfo(int depth, int score, int time, int nodes, int nps, public PvInfo(int depth, int score, int time, int nodes, int nps,
boolean isMate, boolean upperBound, boolean lowerBound, ArrayList<Move> pv) { boolean isMate, boolean upperBound, boolean lowerBound, ArrayList<Move> pv) {
this.depth = depth; this.depth = depth;

View File

@ -25,12 +25,22 @@ import org.petero.droidfish.R;
/** /**
* * Handle conversion of positions and moves to/from text format.
* @author petero * @author petero
*/ */
public class TextIO { public class TextIO {
static public final String startPosFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; static public final String startPosFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
/** Localized version of "P N B R Q K". */
private static String[] pieceNames = null;
/** Set localized piece names. */
public static final void setPieceNames(String pieceNames) {
String[] pn = pieceNames.split(" ");
if (pn.length == 6)
TextIO.pieceNames = pn;
}
/** Parse a FEN string and return a chess Position object. */ /** Parse a FEN string and return a chess Position object. */
public static final Position readFEN(String fen) throws ChessParseError { public static final Position readFEN(String fen) throws ChessParseError {
Position pos = new Position(); Position pos = new Position();
@ -312,15 +322,15 @@ public class TextIO {
* @param pos The chess position. * @param pos The chess position.
* @param move The executed move. * @param move The executed move.
* @param longForm If true, use long notation, eg Ng1-f3. * @param longForm If true, use long notation, eg Ng1-f3.
* Otherwise, use short notation, eg Nf3 * Otherwise, use short notation, eg Nf3.
* @param localized If true, use localized piece names.
*/ */
public static final String moveToString(Position pos, Move move, boolean longForm) { public static final String moveToString(Position pos, Move move, boolean longForm,
ArrayList<Move> moves = MoveGen.instance.pseudoLegalMoves(pos); boolean localized) {
moves = MoveGen.removeIllegal(pos, moves); return moveToString(pos, move, longForm, localized, null);
return moveToString(pos, move, longForm, moves);
} }
private static final String moveToString(Position pos, Move move, boolean longForm, public static final String moveToString(Position pos, Move move, boolean longForm,
List<Move> moves) { boolean localized, List<Move> moves) {
if ((move == null) || move.equals(new Move(0, 0, 0))) if ((move == null) || move.equals(new Move(0, 0, 0)))
return "--"; return "--";
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
@ -342,7 +352,12 @@ public class TextIO {
} }
} }
if (ret.length() == 0) { if (ret.length() == 0) {
if (pieceNames == null)
localized = false;
int p = pos.getPiece(move.from); int p = pos.getPiece(move.from);
if (localized)
ret.append(pieceToCharLocalized(p));
else
ret.append(pieceToChar(p)); ret.append(pieceToChar(p));
int x1 = Position.getX(move.from); int x1 = Position.getX(move.from);
int y1 = Position.getY(move.from); int y1 = Position.getY(move.from);
@ -361,6 +376,8 @@ public class TextIO {
int numSameTarget = 0; int numSameTarget = 0;
int numSameFile = 0; int numSameFile = 0;
int numSameRow = 0; int numSameRow = 0;
if (moves == null)
moves = MoveGen.instance.legalMoves(pos);
int mSize = moves.size(); int mSize = moves.size();
for (int mi = 0; mi < mSize; mi++) { for (int mi = 0; mi < mSize; mi++) {
Move m = moves.get(mi); Move m = moves.get(mi);
@ -389,9 +406,13 @@ public class TextIO {
} }
ret.append((char) (x2 + 'a')); ret.append((char) (x2 + 'a'));
ret.append((char) (y2 + '1')); ret.append((char) (y2 + '1'));
if (move.promoteTo != Piece.EMPTY) if (move.promoteTo != Piece.EMPTY) {
if (localized)
ret.append(pieceToCharLocalized(move.promoteTo));
else
ret.append(pieceToChar(move.promoteTo)); ret.append(pieceToChar(move.promoteTo));
} }
}
UndoInfo ui = new UndoInfo(); UndoInfo ui = new UndoInfo();
pos.makeMove(move, ui); pos.makeMove(move, ui);
boolean givesCheck = MoveGen.inCheck(pos); boolean givesCheck = MoveGen.inCheck(pos);
@ -453,6 +474,10 @@ public class TextIO {
* information as long as it matches exactly one valid move. * information as long as it matches exactly one valid move.
*/ */
public static final Move stringToMove(Position pos, String strMove) { public static final Move stringToMove(Position pos, String strMove) {
return stringToMove(pos, strMove, null);
}
public static final Move stringToMove(Position pos, String strMove,
ArrayList<Move> moves) {
if (strMove.equals("--")) if (strMove.equals("--"))
return new Move(0, 0, 0); return new Move(0, 0, 0);
@ -530,8 +555,8 @@ public class TextIO {
info.promPiece = Piece.EMPTY; info.promPiece = Piece.EMPTY;
} }
ArrayList<Move> moves = MoveGen.instance.pseudoLegalMoves(pos); if (moves == null)
moves = MoveGen.removeIllegal(pos, moves); moves = MoveGen.instance.legalMoves(pos);
ArrayList<Move> matches = new ArrayList<Move>(2); ArrayList<Move> matches = new ArrayList<Move>(2);
for (int i = 0; i < moves.size(); i++) { for (int i = 0; i < moves.size(); i++) {
@ -717,6 +742,17 @@ public class TextIO {
return ""; return "";
} }
public final static String pieceToCharLocalized(int p) {
switch (p) {
case Piece.WQUEEN: case Piece.BQUEEN: return pieceNames[4];
case Piece.WROOK: case Piece.BROOK: return pieceNames[3];
case Piece.WBISHOP: case Piece.BBISHOP: return pieceNames[2];
case Piece.WKNIGHT: case Piece.BKNIGHT: return pieceNames[1];
case Piece.WKING: case Piece.BKING: return pieceNames[5];
}
return "";
}
private final static int charToPiece(boolean white, char c) { private final static int charToPiece(boolean white, char c) {
switch (c) { switch (c) {
case 'Q': case 'q': return white ? Piece.WQUEEN : Piece.BQUEEN; case 'Q': case 'q': return white ? Piece.WQUEEN : Piece.BQUEEN;

View File

@ -60,7 +60,7 @@ public class BookTest extends TestCase {
public void testGetAllBookMoves() throws ChessParseError { public void testGetAllBookMoves() throws ChessParseError {
Position pos = TextIO.readFEN(TextIO.startPosFEN); Position pos = TextIO.readFEN(TextIO.startPosFEN);
DroidBook book = DroidBook.getInstance(); DroidBook book = DroidBook.getInstance();
String moveListString = book.getAllBookMoves(pos).first; String moveListString = book.getAllBookMoves(pos, false).first;
String[] strMoves = moveListString.split(":[0-9]* "); String[] strMoves = moveListString.split(":[0-9]* ");
assertTrue(strMoves.length > 1); assertTrue(strMoves.length > 1);
for (String strMove : strMoves) { for (String strMove : strMoves) {

View File

@ -140,7 +140,7 @@ public class GameTest extends TestCase {
game.setPos(TextIO.readFEN(fen)); game.setPos(TextIO.readFEN(fen));
game.processString("draw 50 Nc3"); game.processString("draw 50 Nc3");
assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Draw claim valid assertEquals(Game.GameState.DRAW_50, game.getGameState()); // Draw claim valid
assertEquals("Nc3", game.getDrawInfo()); assertEquals("Nc3", game.getDrawInfo(false));
game.setPos(TextIO.readFEN(fen)); game.setPos(TextIO.readFEN(fen));
game.processString("draw 50 a6"); game.processString("draw 50 a6");

View File

@ -225,7 +225,7 @@ public class GameTreeTest extends TestCase {
for (int i = 0; i < vars.size(); i++) { for (int i = 0; i < vars.size(); i++) {
if (i > 0) if (i > 0)
ret.append(' '); ret.append(' ');
String moveStr = TextIO.moveToString(gt.currentPos, vars.get(i), false); String moveStr = TextIO.moveToString(gt.currentPos, vars.get(i), false, false);
ret.append(moveStr); ret.append(moveStr);
} }
return ret.toString(); return ret.toString();
@ -477,7 +477,7 @@ public class GameTreeTest extends TestCase {
assertEquals("A \"good\" player", gt.white); assertEquals("A \"good\" player", gt.white);
assertEquals("e4", getVariationsAsString(gt)); assertEquals("e4", getVariationsAsString(gt));
// Test for broken PGN headers: [White "A "good" player"] // Test for broken PGN headers: [White "A "good old" player"]
res = gt.readPGN("[White \"A \"good old\" player\"]\ne4", options); res = gt.readPGN("[White \"A \"good old\" player\"]\ne4", options);
assertEquals(true, res); assertEquals(true, res);
assertEquals("A \"good old\" player", gt.white); assertEquals("A \"good old\" player", gt.white);

View File

@ -195,7 +195,7 @@ public class MoveGenTest extends TestCase {
} }
ArrayList<String> strMoves = new ArrayList<String>(); ArrayList<String> strMoves = new ArrayList<String>();
for (Move m : moves) { for (Move m : moves) {
String mStr = TextIO.moveToString(pos, m, true); String mStr = TextIO.moveToString(pos, m, true, false);
strMoves.add(mStr); strMoves.add(mStr);
// System.out.println(mStr); // System.out.println(mStr);
} }

View File

@ -123,6 +123,10 @@ public class TextIOTest extends TestCase {
return wasError; return wasError;
} }
private final static String moveToString(Position pos, Move move, boolean longForm) {
return TextIO.moveToString(pos, move, longForm, false);
}
/** /**
* Test of moveToString method, of class TextIO. * Test of moveToString method, of class TextIO.
*/ */
@ -132,39 +136,39 @@ public class TextIOTest extends TestCase {
Move move = new Move(Position.getSquare(4, 1), Position.getSquare(4, 3), Move move = new Move(Position.getSquare(4, 1), Position.getSquare(4, 3),
Piece.EMPTY); Piece.EMPTY);
boolean longForm = true; boolean longForm = true;
String result = TextIO.moveToString(pos, move, longForm); String result = moveToString(pos, move, longForm);
assertEquals("e2-e4", result); assertEquals("e2-e4", result);
move = new Move(Position.getSquare(6, 0), Position.getSquare(5, 2), Piece.EMPTY); move = new Move(Position.getSquare(6, 0), Position.getSquare(5, 2), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Ng1-f3", result); assertEquals("Ng1-f3", result);
move = new Move(Position.getSquare(4, 7), Position.getSquare(2, 7), move = new Move(Position.getSquare(4, 7), Position.getSquare(2, 7),
Piece.EMPTY); Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("O-O-O", result); assertEquals("O-O-O", result);
String fen = "1r3k2/2P5/8/8/8/4K3/8/8 w - - 0 1"; String fen = "1r3k2/2P5/8/8/8/4K3/8/8 w - - 0 1";
pos = TextIO.readFEN(fen); pos = TextIO.readFEN(fen);
assertEquals(fen, TextIO.toFEN(pos)); assertEquals(fen, TextIO.toFEN(pos));
move = new Move(Position.getSquare(2,6), Position.getSquare(1,7), Piece.WROOK); move = new Move(Position.getSquare(2,6), Position.getSquare(1,7), Piece.WROOK);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("c7xb8R+", result); assertEquals("c7xb8R+", result);
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WKNIGHT); move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WKNIGHT);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("c7-c8N", result); assertEquals("c7-c8N", result);
move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WQUEEN); move = new Move(Position.getSquare(2,6), Position.getSquare(2,7), Piece.WQUEEN);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("c7-c8Q+", result); assertEquals("c7-c8Q+", result);
// Test null move // Test null move
pos = TextIO.readFEN(TextIO.startPosFEN); pos = TextIO.readFEN(TextIO.startPosFEN);
Move nullMove = new Move(0, 0, 0); Move nullMove = new Move(0, 0, 0);
result = TextIO.moveToString(pos, nullMove, false); result = moveToString(pos, nullMove, false);
assertEquals("--", result); assertEquals("--", result);
result = TextIO.moveToString(pos, nullMove, true); result = moveToString(pos, nullMove, true);
assertEquals("--", result); assertEquals("--", result);
} }
@ -176,19 +180,19 @@ public class TextIOTest extends TestCase {
boolean longForm = true; boolean longForm = true;
Move move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK); Move move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WROOK);
String result = TextIO.moveToString(pos, move, longForm); String result = moveToString(pos, move, longForm);
assertEquals("b7-b8R+", result); // check assertEquals("b7-b8R+", result); // check
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WQUEEN); move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WQUEEN);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("b7-b8Q#", result); // check mate assertEquals("b7-b8Q#", result); // check mate
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WKNIGHT); move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WKNIGHT);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("b7-b8N", result); assertEquals("b7-b8N", result);
move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WBISHOP); move = new Move(Position.getSquare(1, 6), Position.getSquare(1, 7), Piece.WBISHOP);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("b7-b8B", result); // stalemate assertEquals("b7-b8B", result); // stalemate
} }
@ -202,43 +206,43 @@ public class TextIOTest extends TestCase {
boolean longForm = false; boolean longForm = false;
Move move = new Move(Position.getSquare(4,5), Position.getSquare(4,3), Piece.EMPTY); Move move = new Move(Position.getSquare(4,5), Position.getSquare(4,3), Piece.EMPTY);
String result = TextIO.moveToString(pos, move, longForm); String result = moveToString(pos, move, longForm);
assertEquals("Qee4", result); // File disambiguation needed assertEquals("Qee4", result); // File disambiguation needed
move = new Move(Position.getSquare(2,5), Position.getSquare(4,3), Piece.EMPTY); move = new Move(Position.getSquare(2,5), Position.getSquare(4,3), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Qc6e4", result); // Full disambiguation needed assertEquals("Qc6e4", result); // Full disambiguation needed
move = new Move(Position.getSquare(2,3), Position.getSquare(4,3), Piece.EMPTY); move = new Move(Position.getSquare(2,3), Position.getSquare(4,3), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Q4e4", result); // Row disambiguation needed assertEquals("Q4e4", result); // Row disambiguation needed
move = new Move(Position.getSquare(2,3), Position.getSquare(2,0), Piece.EMPTY); move = new Move(Position.getSquare(2,3), Position.getSquare(2,0), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Qc1+", result); // No disambiguation needed assertEquals("Qc1+", result); // No disambiguation needed
move = new Move(Position.getSquare(0,1), Position.getSquare(0,0), Piece.BQUEEN); move = new Move(Position.getSquare(0,1), Position.getSquare(0,0), Piece.BQUEEN);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("a1Q", result); // Normal promotion assertEquals("a1Q", result); // Normal promotion
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BQUEEN); move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BQUEEN);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("axb1Q#", result); // Capture promotion and check mate assertEquals("axb1Q#", result); // Capture promotion and check mate
move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BKNIGHT); move = new Move(Position.getSquare(0,1), Position.getSquare(1,0), Piece.BKNIGHT);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("axb1N", result); // Capture promotion assertEquals("axb1N", result); // Capture promotion
move = new Move(Position.getSquare(3,6), Position.getSquare(4,4), Piece.EMPTY); move = new Move(Position.getSquare(3,6), Position.getSquare(4,4), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Ne5", result); // Other knight pinned, no disambiguation needed assertEquals("Ne5", result); // Other knight pinned, no disambiguation needed
move = new Move(Position.getSquare(7,6), Position.getSquare(7,4), Piece.EMPTY); move = new Move(Position.getSquare(7,6), Position.getSquare(7,4), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("h5", result); // Regular pawn move assertEquals("h5", result); // Regular pawn move
move = new Move(Position.getSquare(5,7), Position.getSquare(3,7), Piece.EMPTY); move = new Move(Position.getSquare(5,7), Position.getSquare(3,7), Piece.EMPTY);
result = TextIO.moveToString(pos, move, longForm); result = moveToString(pos, move, longForm);
assertEquals("Rfd8", result); // File disambiguation needed assertEquals("Rfd8", result); // File disambiguation needed
} }