#include "board.hpp" #include "zobrist.hpp" #include #include Piece createPiece(PieceType type, bool color, bool moved) { Piece piece; piece.type = type; piece.color = color; piece.moved = moved; return piece; } int PositionToIndex(Position i) { return i.rank * 8 + i.file; } 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.oldCaslte = g->castle; // 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"); } } piece.moved = true; // 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, false}; 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; } assert(g->castle != ""); // caslte if (piece.type == KING && move.From.rank == (piece.color ? 0 : 7) && g->castle != "-" && (move.From.file + 2 == move.To.file || move.From.file - 2 == move.To.file)) { bool caslteSide = (move.From.file > move.To.file); // 0 queen side, 1 king side char castleCharacter = (caslteSide ? (piece.color ? 'K' : 'k') : (piece.color ? 'Q' : 'q')); std::string newCastleString = ""; if (g->castle.contains('Q') && 'Q' != castleCharacter) { newCastleString += 'Q'; }; if (g->castle.contains('K') && 'K' != castleCharacter) { newCastleString += 'K'; }; if (g->castle.contains('q') && 'q' != castleCharacter) { newCastleString += 'q'; }; if (g->castle.contains('k') && 'k' != castleCharacter) { newCastleString += 'k'; }; if (newCastleString == "") { newCastleString = "-"; }; g->castle = newCastleString; 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, false}; rook.moved = true; 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, false}; rook.moved = true; rook_pos = move.From; rook_pos.file += 1; g->pieces[PositionToIndex(rook_pos)] = rook; } }; // setting the moves g->pieces[PositionToIndex(move.To)] = piece; g->pieces[PositionToIndex(move.From)] = {false, NONEPIECE, false}; // 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->castle = undo.oldCaslte; if (--g->ThreeFoldMap[undo.zobristKey] <= 0) { g->ThreeFoldMap.erase(undo.zobristKey); } };