diff options
Diffstat (limited to 'src/board/board.cpp')
| -rw-r--r-- | src/board/board.cpp | 247 |
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); + }; +}; |
