summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLoic Guegan <manzerbredes@mailbox.org>2022-02-19 18:23:06 +0100
committerLoic Guegan <manzerbredes@mailbox.org>2022-02-19 18:23:06 +0100
commit5e78a4172da975ac227779456e670492217de206 (patch)
tree8f71add7ce8323b83b2810e6484a89c462835a00 /src
parentf60b684790ae7a726763e4c6f9122371c71d17e9 (diff)
Now SAN moves can be parsed
Diffstat (limited to 'src')
-rw-r--r--src/ChessArbiter.cpp109
-rw-r--r--src/ChessArbiter.hpp1
2 files changed, 110 insertions, 0 deletions
diff --git a/src/ChessArbiter.cpp b/src/ChessArbiter.cpp
index 18e1e1c..e747397 100644
--- a/src/ChessArbiter.cpp
+++ b/src/ChessArbiter.cpp
@@ -400,4 +400,113 @@ bool ChessArbiter::IsCheckMate() {
std::string ChessArbiter::GetSAN() { return (SAN); }
char ChessArbiter::GetCapture() { return (capture); }
+
+std::string ChessArbiter::ParseSAN(std::string SANMove) {
+ std::string src, dst;
+ char piece = ' ';
+ char hint = ' ';
+ bool isHintRank = false;
+
+ // First castling
+ if (SANMove[0] == 'O' || SANMove[0] == '0') {
+ char c3 = (SANMove.size() >= 3) ? SANMove[3] : '?';
+ // Long castle
+ if (c3 == '-') {
+ if (fen.player && IsCastlePossible(fen.player, true)) {
+ return ("e8c8");
+ } else if (IsCastlePossible(fen.player, true)) {
+ return ("e1c1");
+ }
+ } else {
+ if (fen.player && IsCastlePossible(fen.player, false)) {
+ return ("e8g8");
+ } else if (IsCastlePossible(fen.player, false)) {
+ return ("e1g1");
+ }
+ }
+ }
+
+ // First deduce dst square in the move
+ if (SANMove.size() > 0) {
+ // Pawn moves
+ if (std::islower(SANMove[0])) {
+ if (fen.player) {
+ piece = 'p';
+ } else {
+ piece = 'P';
+ }
+ // Not a capture
+ if (SANMove[1] != 'x') {
+ dst = SANMove.substr(0, 2);
+ } else {
+ dst = SANMove.substr(2, 2);
+ }
+ } else {
+ piece = SANMove[0];
+ char c1 = (SANMove.size() >= 2) ? SANMove[1] : '?';
+ char c2 = (SANMove.size() >= 3) ? SANMove[2] : '?';
+ char c3 = (SANMove.size() >= 4) ? SANMove[3] : '?';
+ if (c1 == 'x') {
+ dst = SANMove.substr(2, 2);
+ } else if (c2 == 'x') {
+ hint = c1;
+ dst = SANMove.substr(3, 2);
+ } else if (IS_DIGIT(c2)) {
+ dst = SANMove.substr(1, 2);
+ } else {
+ hint = c1;
+ dst = SANMove.substr(2, 2);
+ }
+ }
+ }
+ isHintRank = IS_DIGIT(hint);
+
+ // Now find src thanks to legal moves
+ std::vector<std::string> src_candidates;
+ for (std::string &move : ListLegalMoves(fen.player)) {
+ std::string current_src = move.substr(0, 2);
+ std::string current_dst = move.substr(2, 2);
+ if (current_dst == dst) {
+ src_candidates.push_back(current_src);
+ }
+ }
+
+ // Now filter the legals move
+ if (src_candidates.size() > 0) {
+ if (src_candidates.size() > 1) {
+ std::vector<std::string> src_candidates_filtered;
+ // Filter according to pieces:
+ for (std::string &cand : src_candidates) {
+ Piece p = board.GetPieceAt(cand); // This call never fails
+ if (std::toupper(p.piece) == piece) {
+ src_candidates_filtered.push_back(cand);
+ }
+ }
+ src_candidates = src_candidates_filtered;
+ src_candidates_filtered.clear();
+ // Last Filtering
+ if (src_candidates.size() > 1) {
+ for (std::string &cand : src_candidates) {
+ char cand_hint = cand[0];
+ if (isHintRank) {
+ cand_hint = cand[1];
+ }
+ if (hint == cand_hint) {
+ src_candidates_filtered.push_back(cand);
+ }
+ }
+ }
+ src_candidates = src_candidates_filtered;
+ }
+ src = src_candidates[0];
+ }
+
+ // Ensure that we return empty string if no matches
+ if(src.size()<=0){
+ return("");
+ }
+ // Else return "srcdst" string
+ return (src + dst);
+}
+
} // namespace chessarbiter \ No newline at end of file
diff --git a/src/ChessArbiter.hpp b/src/ChessArbiter.hpp
index 6d31073..e012b4a 100644
--- a/src/ChessArbiter.hpp
+++ b/src/ChessArbiter.hpp
@@ -65,5 +65,6 @@ public:
bool IsDrawByNoMoves();
bool IsDrawByRepetitions();
bool IsDraw();
+ std::string ParseSAN(std::string SANMove);
};
} // namespace chessarbiter