summaryrefslogtreecommitdiff
path: root/src/Fen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Fen.cpp')
-rw-r--r--src/Fen.cpp170
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