#include "Board.h" #include #include #include #include #include #include "MoveGeneration.h" using namespace chessy; using namespace std; void Board::resetBoard(void) { whites[PieceType::PAWN] = 0x000000000000FF00; whites[PieceType::ROOK] = 0x0000000000000081; whites[PieceType::KNIGHT] = 0x0000000000000042; whites[PieceType::BISHOP] = 0x0000000000000024; whites[PieceType::QUEEN] = 0x0000000000000008; whites[PieceType::KING] = 0x0000000000000010; blacks[PieceType::PAWN] = 0x00FF000000000000; blacks[PieceType::ROOK] = 0x8100000000000000; blacks[PieceType::KNIGHT] = 0x4200000000000000; blacks[PieceType::BISHOP] = 0x2400000000000000; blacks[PieceType::QUEEN] = 0x0800000000000000; blacks[PieceType::KING] = 0x1000000000000000; } void Board::setEmpty(void) { whites[PieceType::PAWN] = 0; whites[PieceType::KNIGHT] = 0; whites[PieceType::BISHOP] = 0; whites[PieceType::ROOK] = 0; whites[PieceType::QUEEN] = 0; whites[PieceType::KING] = 0; blacks[PieceType::PAWN] = 0; blacks[PieceType::KNIGHT] = 0; blacks[PieceType::BISHOP] = 0; blacks[PieceType::ROOK] = 0; blacks[PieceType::QUEEN] = 0; blacks[PieceType::KING] = 0; } bool Board::tryToMove(Bitboard start, Bitboard end, Bitboard& b) { if (start & b) b = b ^ start ^ end; return false; } void Board::setBoard(const std::string& fenPosition) { int row = 7, column = 0; map boards { { 'p', &blacks[PieceType::PAWN] }, { 'n', &blacks[PieceType::KNIGHT] }, { 'b', &blacks[PieceType::BISHOP] }, { 'r', &blacks[PieceType::ROOK] }, { 'q', &blacks[PieceType::QUEEN] }, { 'k', &blacks[PieceType::KING] }, { 'P', &whites[PieceType::PAWN] }, { 'N', &whites[PieceType::KNIGHT] }, { 'B', &whites[PieceType::BISHOP] }, { 'R', &whites[PieceType::ROOK] }, { 'Q', &whites[PieceType::QUEEN] }, { 'K', &whites[PieceType::KING] } }; setEmpty(); for (auto character : fenPosition) { if (character >= '0' && character <= '9') { column += character - '0'; } else if (character == '/') { -- row; column = 0; } else { auto board = boards.find(character); if (board != boards.end()) { *(board->second) |= Bitboard::fromIndex({row, column}); } else { throw runtime_error("invalid piece type "s + character); } ++ column; } if (row < -1 || column > 8) throw runtime_error("invalid board string "s + fenPosition); } } // a bit hacky, sry std::string Board::getFenBoard(void) const { using namespace std; stringstream str; for (int row = 7; row >= 0; row--) { int counter = 0; for (int column = 0; column < 8; column++) { PieceType black = getBlackAtPosition({ row, column }); PieceType white = getWhiteAtPosition({ row, column }); //str << " " << Bitboard::fromIndex({row, column}) << " " << " ";; //str << "row,column,index: " << row << "," << column << "," << // int(Index(row, column).index) << " "; if (black == PieceType::EMPTY && white == PieceType::EMPTY) ++ counter; else if (counter > 0) { str << counter; counter = 0; } switch (black) { case PieceType::PAWN: str << 'p'; break; case PieceType::KNIGHT: str << 'n'; break; case PieceType::BISHOP: str << 'b'; break; case PieceType::ROOK: str << 'r'; break; case PieceType::QUEEN: str << 'q'; break; case PieceType::KING: str << 'k'; break; default: switch (white) { case PieceType::PAWN: str << 'P'; break; case PieceType::KNIGHT: str << 'N'; break; case PieceType::BISHOP: str << 'B'; break; case PieceType::ROOK: str << 'R'; break; case PieceType::QUEEN: str << 'Q'; break; case PieceType::KING: str << 'K'; break; default:; } } } if (counter > 0) str << counter; if (row != 0) str << "/"; } return str.str(); } PieceType Board::getWhiteAtPosition(Index i) const { Bitboard mask = Bitboard::fromIndex(i); for (int i = 0; i < 6; i++) if (whites[i] & mask) return (PieceType) i; return PieceType::EMPTY; } PieceType Board::getBlackAtPosition(Index i) const { Bitboard mask = Bitboard::fromIndex(i); for (int i = 0; i < 6; i++) if (blacks[i] & mask) return (PieceType) i; return PieceType::EMPTY; } PieceType Board::getAtPosition(Index i) const { PieceType b = getWhiteAtPosition(i); if (b != PieceType::EMPTY) return b; return getBlackAtPosition(i);; } void Board::move(const Move& move) { Bitboard start = Bitboard::fromIndex(move.origin); Bitboard end = Bitboard::fromIndex(move.destination); for (Bitboard& b : whites) if (b & end) { b ^= end; goto move; } for (Bitboard& b : blacks) if (b & end) { b ^= end; goto move; } move: for (Bitboard& b : whites) { if (b & end) b ^= end; if (b & start) { b &= ~start; b |= end; return; } } for (Bitboard& b : blacks) { if (b & start) { b &= ~start; b |= end; return; } } } void Board::removeAt(Index i) { Bitboard mask = ~Bitboard::fromIndex(i); for (Bitboard& b : whites) b &= mask; for (Bitboard& b : blacks) b &= mask; } Bitboard Board::getWhites(void) const { return whites[0] | whites[1] | whites[2] | whites[3] | whites[4] | whites[5]; } Bitboard Board::getBlacks(void) const { return blacks[0] | blacks[1] | blacks[2] | blacks[3] | blacks[4] | blacks[5]; } Bitboard Board::getOccupied(void) const { return getBlacks() | getWhites(); } Bitboard Board::getFree(void) const { return ~getOccupied(); } #include template bool Board::isCheck(void) const { constexpr Side enemy = otherSide(side); Index kingIndex = getKing().getLeastSignificantBit(); KnightMoveGenerator nmg{ kingIndex, 0 }; if (nmg.getBitboard() & getKnights()) return true; PrimitiveBishopMoveGenerator pbmg{ kingIndex, get(), get() }; if (pbmg.getBitboard() & (getBishops() | getQueens())) return true; PrimitiveRookMoveGenerator prmg{ kingIndex, get(), get() }; if (prmg.getBitboard() & (getRooks() | getQueens())) return true; if (side == WHITE_SIDE) { if (kingIndex.getRow() < 6) { if (kingIndex.getColumn() > 0) if (getKing().neOne() & getPawns()) return true; if (kingIndex.getColumn() < 7) if (getKing().nwOne() & getPawns()) return true; } } else { if (kingIndex.getRow() > 1) { if (kingIndex.getColumn() > 0) if (getKing().seOne() & getPawns()) return true; if (kingIndex.getColumn() < 7) if (getKing().swOne() & getPawns()) return true; } } KingMoveGenerator kmg{ getKing(), 0 }; if (kmg.getBitboard() & getKing()) return true; return false; } template bool Board::isCheck(void) const; template bool Board::isCheck(void) const;