aboutsummaryrefslogtreecommitdiff
path: root/src/board/board.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/board/board.cpp')
-rw-r--r--src/board/board.cpp247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/board/board.cpp b/src/board/board.cpp
new file mode 100644
index 0000000..a76ec42
--- /dev/null
+++ b/src/board/board.cpp
@@ -0,0 +1,247 @@
+#include "board.hpp"
+#include "../moves.hpp"
+#include "zobrist/zobrist.hpp"
+#include <cassert>
+
+Piece createPiece(PieceType type, bool color) {
+ Piece piece;
+ piece.type = type;
+ piece.color = color;
+ return piece;
+}
+
+int PositionToIndex(Position i) { return i.rank * 8 + i.file; }
+
+Position FindKing(Game *b, bool white) {
+ for (int i = 0; i < 64; i++) {
+ Piece piece = b->pieces[i];
+
+ if (piece.type == KING && piece.color == white) {
+ return IndexToPosition(i);
+ }
+ }
+
+ assert(false && "King not found");
+ return {0, 0};
+}
+UndoMove MakeMove(Move move, Game *g) {
+ UndoMove undo = {};
+
+ undo.from = move.From;
+ undo.to = move.To;
+
+ undo.movedPiece = g->pieces[PositionToIndex(move.From)];
+ undo.capturedPiece = g->pieces[PositionToIndex(move.To)];
+
+ undo.oldTurn = g->turn;
+ undo.oldCanEnpassant = g->canEnpassant;
+ undo.oldEnPassant = g->enPassant;
+
+ undo.oldHalfMoveClock = g->halfMoveClock;
+ undo.oldMoveClock = g->MoveClock;
+
+ undo.oldState = g->state;
+
+ undo.OldwhiteCastleKing = g->whiteCastleKing;
+ undo.OldwhiteCastleQueen = g->whiteCastleQueen;
+ undo.OldblackCastleKing = g->blackCastleKing;
+ undo.OldblackCastleQueen = g->blackCastleQueen;
+
+ // play move
+ Piece piece = g->pieces[PositionToIndex(move.From)];
+ Piece piece2 = g->pieces[PositionToIndex(move.To)];
+
+ if (piece2.type != NONEPIECE) {
+ if (piece2.color == g->turn) {
+ assert(false && "capturing friendly piece error");
+ }
+ }
+
+ // clock
+ g->MoveClock++;
+ if (piece.type == PAWN || piece2.type != NONEPIECE) {
+ g->halfMoveClock = 0;
+ } else {
+ g->halfMoveClock++;
+ }
+
+ // Playing enpasstant
+ if (piece.type == PAWN && g->canEnpassant && move.To == g->enPassant) {
+ Position capturedPawn = move.To;
+ capturedPawn.rank += piece.color ? 1 : -1;
+ g->pieces[PositionToIndex(capturedPawn)] = {false, NONEPIECE};
+
+ undo.wasEnPassantCapture = true;
+ undo.enPassantCapturedSquare = capturedPawn;
+ undo.enPassantCapturedPiece = g->pieces[PositionToIndex(capturedPawn)];
+ }
+
+ g->canEnpassant = false;
+
+ // Adding enpassant
+ if (piece.type == PAWN) {
+ Position to = move.To;
+ to.rank -= (piece.color ? -2 : 2);
+ if (to == move.From) {
+ g->canEnpassant = true;
+ Position target = move.From;
+ target.rank += piece.color ? -1 : 1;
+ g->enPassant = target;
+ };
+ }
+
+ // Promotions
+ if (piece.type == PAWN && move.To.rank == (piece.color ? 0 : 7)) {
+ // TODO parse the promote type from uci isntead of ignoreting it
+ piece.type = move.promotion == NONEPIECE ? QUEEN : move.promotion;
+ }
+
+ // caslte
+ if (piece.type == KING && move.From.rank == (piece.color ? 0 : 7) &&
+ (move.From.file + 2 == move.To.file ||
+ move.From.file - 2 == move.To.file)) {
+
+ undo.wasCastle = true;
+ undo.CastledSide = (move.To.file > move.From.file);
+ if (move.From.file + 2 == move.To.file) {
+ Position rook_pos = move.To;
+ rook_pos.file += 1;
+ Piece rook = g->pieces[PositionToIndex(rook_pos)];
+ g->pieces[PositionToIndex(rook_pos)] = {false, NONEPIECE};
+ rook_pos = move.From;
+ rook_pos.file -= 1;
+ g->pieces[PositionToIndex(rook_pos)] = rook;
+ }
+ if (move.From.file - 2 == move.To.file) {
+ Position rook_pos = move.To;
+ rook_pos.file -= 1;
+ Piece rook = g->pieces[PositionToIndex(rook_pos)];
+ g->pieces[PositionToIndex(rook_pos)] = {false, NONEPIECE};
+ rook_pos = move.From;
+ rook_pos.file += 1;
+ g->pieces[PositionToIndex(rook_pos)] = rook;
+ }
+ };
+
+ // removing caslte rights
+ if (piece.type == KING) {
+ if (piece.color) {
+ g->whiteCastleKing = false;
+ g->whiteCastleQueen = false;
+ } else {
+ g->blackCastleKing = false;
+ g->blackCastleQueen = false;
+ }
+ }
+
+ // this part was written by ai
+ if (piece.type == ROOK) {
+ if (piece.color) { // White
+ if (move.From.rank == 7 && move.From.file == 0) // a1
+ g->whiteCastleQueen = false;
+
+ if (move.From.rank == 7 && move.From.file == 7) // h1
+ g->whiteCastleKing = false;
+ } else { // Black
+ if (move.From.rank == 0 && move.From.file == 0) // a8
+ g->blackCastleQueen = false;
+
+ if (move.From.rank == 0 && move.From.file == 7) // h8
+ g->blackCastleKing = false;
+ }
+ }
+
+ // this part is also written with ai
+ if (piece2.type == ROOK) {
+ if (piece2.color) { // White rook captured
+ if (move.To.rank == 7 && move.To.file == 0) // a1
+ g->whiteCastleQueen = false;
+
+ if (move.To.rank == 7 && move.To.file == 7) // h1
+ g->whiteCastleKing = false;
+ } else { // Black rook captured
+ if (move.To.rank == 0 && move.To.file == 0) // a8
+ g->blackCastleQueen = false;
+
+ if (move.To.rank == 0 && move.To.file == 7) // h8
+ g->blackCastleKing = false;
+ }
+ }
+
+ // playing the moves
+ g->pieces[PositionToIndex(move.To)] = piece;
+ g->pieces[PositionToIndex(move.From)] = {false, NONEPIECE};
+
+ // changing who turn it is
+ g->turn = !g->turn;
+
+ // 3 fold check
+ uint64_t key = GenerateZobristKey(g);
+
+ undo.zobristKey = key;
+
+ g->ThreeFoldMap[key]++;
+
+ if (g->ThreeFoldMap[key] >= 3) {
+ g->state = DRAW;
+ }
+
+ if (g->halfMoveClock >= 50) {
+ g->state = DRAW;
+ }
+
+ return undo;
+};
+void UnMakeMove(UndoMove undo, Game *g) {
+ g->pieces[PositionToIndex(undo.from)] = undo.movedPiece;
+
+ g->pieces[PositionToIndex(undo.to)] = undo.capturedPiece;
+
+ if (undo.wasEnPassantCapture) {
+ g->pieces[PositionToIndex(undo.enPassantCapturedSquare)] =
+ undo.enPassantCapturedPiece;
+ }
+
+ g->turn = undo.oldTurn;
+
+ g->canEnpassant = undo.oldCanEnpassant;
+ g->enPassant = undo.oldEnPassant;
+
+ g->halfMoveClock = undo.oldHalfMoveClock;
+ g->MoveClock = undo.oldMoveClock;
+
+ g->state = undo.oldState;
+
+ g->whiteCastleKing = undo.OldwhiteCastleKing;
+ g->whiteCastleQueen = undo.OldwhiteCastleQueen;
+ g->blackCastleKing = undo.OldblackCastleKing;
+ g->blackCastleQueen = undo.OldblackCastleQueen;
+
+ if (undo.wasCastle) {
+ if (undo.CastledSide) {
+ // rook f-file -> h-file
+ Position rookFrom = undo.to;
+ rookFrom.file -= 1; // f1/f8
+
+ Position rookTo = undo.to;
+ rookTo.file += 1; // h1/h8
+
+ g->pieces[PositionToIndex(rookTo)] = g->pieces[PositionToIndex(rookFrom)];
+ g->pieces[PositionToIndex(rookFrom)] = {false, NONEPIECE};
+ } else {
+ // rook d-file -> a-file
+ Position rookFrom = undo.to;
+ rookFrom.file += 1; // d1/d8
+
+ Position rookTo = undo.to;
+ rookTo.file -= 2; // a1/a8
+
+ g->pieces[PositionToIndex(rookTo)] = g->pieces[PositionToIndex(rookFrom)];
+ g->pieces[PositionToIndex(rookFrom)] = {false, NONEPIECE};
+ }
+ }
+ g->ThreeFoldMap[undo.zobristKey] -= 1;
+ if (g->ThreeFoldMap[undo.zobristKey] <= 0) {
+ g->ThreeFoldMap.erase(undo.zobristKey);
+ };
+};