summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLoic Guegan <manzerbredes@mailbox.org>2022-01-30 10:00:28 +0100
committerLoic Guegan <manzerbredes@mailbox.org>2022-01-30 10:00:28 +0100
commit159d5334128ff0bb90a8e4e85739dc8bc44baad8 (patch)
treec6af2ddd2fe5f7b9cc5cc93f3ce46d78e50afeec /src
parent851f31e7ae3c090e6769099128e7adae931286d0 (diff)
- Add drawing methods to the API
- Improve tests
Diffstat (limited to 'src')
-rw-r--r--src/Board.cpp16
-rw-r--r--src/ChessArbiter.cpp49
-rw-r--r--src/ChessArbiter.hpp15
3 files changed, 65 insertions, 15 deletions
diff --git a/src/Board.cpp b/src/Board.cpp
index afd32e3..0e88423 100644
--- a/src/Board.cpp
+++ b/src/Board.cpp
@@ -74,14 +74,11 @@ std::string Board::GetKingLocation(bool isBlack) {
void Board::Move(std::string move) {
std::string src(move.substr(0, 2));
std::string dst(move.substr(2, 2));
- if (!IsEmpty(src)) {
- if (!IsEmpty(dst)) {
- RemovePiece(dst);
- }
- for (Piece &p : pieces) {
- if (p.coord == src) {
- p.coord = dst;
- }
+ for (Piece &p : pieces) {
+ if (p.coord == src) {
+ RemovePiece(dst); // Remove piece on dst if exists
+ p.coord = dst;
+ break;
}
}
}
@@ -116,6 +113,9 @@ bool Board::IsMovePossible(std::string move) {
}
// Check colors on dst square
+ // Seems that checking that is empty
+ // instead of catching NoPieceFound exception is
+ // more performant
if (!IsEmpty(dst)) {
Piece dstp = GetPieceAt(dst);
if (srcp.isBlack == dstp.isBlack)
diff --git a/src/ChessArbiter.cpp b/src/ChessArbiter.cpp
index 37dd5e2..1d1379d 100644
--- a/src/ChessArbiter.cpp
+++ b/src/ChessArbiter.cpp
@@ -5,8 +5,10 @@ ChessArbiter::ChessArbiter()
: wPawn(1), wRook(5), wKnight(3), wBishop(3), wQueen(9), wKing(0) {}
void ChessArbiter::Setup(std::string fen) {
+ positions.clear();
SetFEN(fen);
fen_last = this->fen;
+ positions[this->fen.board] = 1;
}
void ChessArbiter::SetFEN(FEN fen) { SetFEN(FENParser::Serialize(fen)); }
@@ -114,6 +116,13 @@ bool ChessArbiter::Play(std::string move) {
return (false);
}
+ // Update position map (repetitions draw)
+ if (positions.count(fen.board) == 0) {
+ positions[fen.board] = 1;
+ } else {
+ positions[fen.board] += 1;
+ }
+
return (true);
}
return (false);
@@ -292,16 +301,48 @@ bool ChessArbiter::IsPlayable() {
return (false);
}
+bool ChessArbiter::IsDrawByFiftyMoveRule() { return (fen.halfmove >= 100); }
+
+bool ChessArbiter::IsDrawByNoMoves() {
+ if (!IsCheck(fen.player)) {
+ std::vector<std::string> moves = ListLegalMoves(fen.player);
+ for (std::string &move : moves) {
+ if (Play(move)) {
+ positions[fen.board]--; // If move work, remove its position
+ SetFEN(fen_last);
+ return (false);
+ }
+ }
+ return (true);
+ }
+ return (false);
+}
+
+bool ChessArbiter::IsDrawByRepetitions() {
+ for (auto const &[key, val] : positions) {
+ if (val >= 3) {
+ return (true);
+ }
+ }
+ return (false);
+}
+
+bool ChessArbiter::IsDraw() {
+ return (IsDrawByFiftyMoveRule() || IsDrawByNoMoves() ||
+ IsDrawByRepetitions());
+}
+
bool ChessArbiter::IsCheckMate() {
if (IsCheck(fen.player)) {
std::vector<std::string> moves = ListLegalMoves(fen.player);
- for(std::string &move: moves){
- if(Play(move)){
+ for (std::string &move : moves) {
+ if (Play(move)) {
+ positions[fen.board]--; // If move work, remove its position
SetFEN(fen_last);
- return(false);
+ return (false);
}
}
- return(true);
+ return (true);
}
return (false);
}
diff --git a/src/ChessArbiter.hpp b/src/ChessArbiter.hpp
index 5739904..488ca7c 100644
--- a/src/ChessArbiter.hpp
+++ b/src/ChessArbiter.hpp
@@ -1,6 +1,7 @@
#include "Board.hpp"
#include "Fen.hpp"
#include <iostream>
+#include <unordered_map>
namespace chessarbiter {
class ChessArbiter {
@@ -8,12 +9,15 @@ class ChessArbiter {
FEN fen;
FEN fen_last; // To undo a move
int wPawn, wRook, wKnight, wBishop, wQueen, wKing;
+ /// @brief Use to compute occurences of positions
+ std::unordered_map<std::string, char> positions;
+ /// @brief FEN methods used internally
+ void SetFEN(std::string);
+ void SetFEN(FEN);
public:
ChessArbiter();
void Setup(std::string);
- void SetFEN(std::string);
- void SetFEN(FEN);
std::string GetFEN();
/// @brief Check which player is going to play
bool IsBlackTurn();
@@ -27,7 +31,7 @@ public:
std::string GetBoard();
/// @brief Get current position evaluation according to player's material
int GetMaterialScore();
- /// @brief Check if position is legal
+ /// @brief Check if position is legal to be played
bool IsPlayable();
/// @brief Get pieces captures by a player
std::string GetCaptures(bool);
@@ -36,5 +40,10 @@ public:
/// @brief Check if a specific castle is possible by a player
bool IsCastlePossible(bool, bool);
bool IsCheckMate();
+ /// @brief Draws check
+ bool IsDrawByFiftyMoveRule();
+ bool IsDrawByNoMoves();
+ bool IsDrawByRepetitions();
+ bool IsDraw();
};
} // namespace chessarbiter \ No newline at end of file