diff options
Diffstat (limited to 'src/Fen.cpp')
| -rw-r--r-- | src/Fen.cpp | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/src/Fen.cpp b/src/Fen.cpp new file mode 100644 index 0000000..32c66a2 --- /dev/null +++ b/src/Fen.cpp @@ -0,0 +1,170 @@ +#include "Fen.hpp" + +namespace chessarbiter { + +std::string FENParser::normalize_rank(std::string fen_rank) { + std::string normalized; + for (char &c : fen_rank) { + if (IS_DIGIT(c)) { + for (char i = 0; i < (c - '0'); i++) { + normalized += ' '; + } + } else { + normalized += c; + } + } + return (normalized); +} + +char FENParser::NextToken(std::string fen, char loc) { + while (loc < fen.size() && IS_BLANK(fen[loc])) { + loc++; + } + return (loc); +} + +char FENParser::NextRank(std::string fen, char loc) { + loc++; + while (loc < fen.size() && fen[loc] != '/' && fen[loc] != ' ') { + loc++; + } + return (loc); +} + +std::string FENParser::Serialize(FEN fen) { + std::string s; + char skip = 0; + char rank = 0; + for (char &c : fen.board) { + rank++; + if (c == ' ') { + skip++; + } else { + if (skip > 0) { + s += std::to_string(skip); + skip = 0; + } + s += c; + } + if (rank == 8) { + if (skip != 0) { + s += std::to_string(skip); + skip = 0; + } + s += '/'; + rank = 0; + } + } + + // Remove last / + s = s.substr(0, s.size() - 1); + s += " "; + + // Player + if (fen.player) { + s += "b "; + } else { + s += "w "; + } + + // Castle + if (!(fen.white_castle_short || fen.white_castle_long || + fen.black_castle_short || fen.black_castle_long)) { + s += "-"; + } else { + if (fen.white_castle_short) { + s += "K"; + } + if (fen.white_castle_long) { + s += "Q"; + } + if (fen.black_castle_short) { + s += "k"; + } + if (fen.black_castle_long) { + s += "q"; + } + } + + // Remaining + s += " " + fen.en_passant + " " + std::to_string(fen.halfmove) + " " + + std::to_string(fen.move); + + return (s); +} + +FEN FENParser::Parse(std::string fen) { + FEN parsed; + + // Parse board + char loc = 0; + for (char rank = 0; rank < 8; rank++) { + char newloc = NextRank(fen, loc); + parsed.board += normalize_rank(fen.substr(loc, newloc - loc)); + loc = newloc + 1; + } + + // Parse player to move + loc = NextToken(fen, loc); + parsed.player = fen[loc] == 'b'; + + // Parse castling + loc = NextToken(fen, loc + 1); + char length = 0; + char cur_loc = loc; + while (!IS_BLANK(fen[cur_loc])) { + length++; + cur_loc++; + } + parsed.white_castle_short = false; + parsed.white_castle_long = false; + parsed.black_castle_short = false; + parsed.black_castle_long = false; + std::string castle = fen.substr(loc, length); + for (char i = 0; i < length; i++) { + switch (fen[loc + i]) { + case 'K': + parsed.white_castle_short = true; + break; + case 'Q': + parsed.white_castle_long = true; + break; + case 'k': + parsed.black_castle_short = true; + break; + case 'q': + parsed.black_castle_long = true; + break; + } + } + + // Parse en passant + loc = NextToken(fen, loc + length); + if (fen[loc] != '-') { + parsed.en_passant = fen.substr(loc, 2); + loc++; + } + loc++; + + // Parse half move counter + loc = NextToken(fen, loc); + std::string halfmove; + while (!IS_BLANK(fen[loc])) { + halfmove += fen[loc]; + loc++; + } + parsed.halfmove = stoi(halfmove); + + // Parse move counter + loc = NextToken(fen, loc); + std::string move; + while (loc < fen.size() && !IS_BLANK(fen[loc])) { + move += fen[loc]; + loc++; + } + parsed.move = stoi(move); + + return (parsed); +} + +} // namespace chessarbiter
\ No newline at end of file |
