123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- #include "ChessGame.h"
- #include <sstream>
- #include <stdexcept>
- using namespace chessy;
- MoveInfo::MoveInfo(Move move, const ChessGame& cg) :
- move{ move }, movedPiece{ cg.getBoard().getAtPosition(move.origin) },
- enPassantTarget{ 0 }
- {
- }
- ChessGame::ChessGame(void)
- {
- board.resetBoard();
- }
- ChessGame::ChessGame(const std::string& fenString)
- {
- loadFromFen(fenString);
- }
- bool ChessGame::isValidMove(const Move& move) const
- {
- return false;
- }
- std::vector<Move> ChessGame::getValidMoves(void) const
- {
- std::vector<Move> ret;
- return ret;
- }
- void ChessGame::move(Move move)
- {
- MoveInfo mi;
- mi.move = move;
- mi.movedPiece = board.getAtPosition(move.origin);
- doMove(mi);
- }
- void ChessGame::loadFromFen(const std::string& fenString)
- {
- using namespace std;
- stringstream tokenizer (fenString);
- string board;
- string turn;
- string castling;
- string enPassant;
- string halfmoves;
- string moveCount;
- tokenizer >> board;
- tokenizer >> turn;
- tokenizer >> castling;
- tokenizer >> enPassant;
- tokenizer >> halfmoves;
- tokenizer >> moveCount;
- this->board.setBoard(board);
- this->enPassant = Index {enPassant};
- if (turn == "w"s) this->turn = WHITE_SIDE;
- else if (turn == "b"s) this->turn = BLACK_SIDE;
- else throw runtime_error("invalid turn "s + turn);
- castlingRights = 0;
- if (castling != "-")
- for (auto character : castling) {
- switch (character) {
- case 'k':
- setCanCastleKingSide(WHITE_SIDE, true);
- break;
- case 'q':
- setCanCastleQueenSide(WHITE_SIDE, true);
- break;
- case 'K':
- setCanCastleKingSide(BLACK_SIDE, true);
- break;
- case 'Q':
- setCanCastleQueenSide(BLACK_SIDE, true);
- break;
- default:
- throw runtime_error("invalid castling right: "s + character);
- }
- }
- if (enPassant == "-"s) {
- this->enPassant = -1;
- }
- else {
- if (enPassant.size() != 2 || (enPassant[1] != '3' && enPassant[1] != '6'))
- throw runtime_error("invalid en passant string: "s + enPassant);
- this->enPassant = Index{ enPassant };
- }
- try {
- reversibleHalfMoves = stoi(halfmoves);
- }
- catch(...) {
- throw runtime_error("invalid number of halfmoves: "s + halfmoves);
- }
- try {
- this->moveCount = stoi(moveCount);
- }
- catch(...) {
- throw runtime_error("invalid number of moves: "s + halfmoves);
- }
- }
- std::string ChessGame::generateFen(void) const
- {
- using namespace std;
- string board = this->board.getFenBoard();
- string turn = this->turn == WHITE_SIDE ? "w"s : "b"s;
- string castlingRights =
- (getCanCastleKingSide(BLACK_SIDE) ? "K"s : ""s) +
- (getCanCastleQueenSide(BLACK_SIDE)? "Q"s : ""s) +
- (getCanCastleKingSide(WHITE_SIDE) ? "k"s : ""s) +
- (getCanCastleQueenSide(WHITE_SIDE) ? "q"s : ""s);
- if (castlingRights.empty())
- castlingRights = "-"s;
- string enPassant;
- if (this->enPassant == -1) {
- enPassant = "-"s;
- }
- else {
- enPassant = this->enPassant.getName();
- }
- string halfmoves = to_string(reversibleHalfMoves);
- string mCount = to_string(moveCount);
- return board + " " + turn + " " + castlingRights + " " + enPassant + " " + halfmoves +
- " " + mCount;
- }
- UndoInfo ChessGame::doMove(const MoveInfo& mi)
- {
- UndoInfo ui;
- ui.castlingRights = castlingRights;
- if (mi.movedPiece == KING) {
- setCanCastleKingSide(turn, false);
- setCanCastleQueenSide(turn, false);
- }
- ui.type = mi.movedPiece;
- Bitboard& b = board.getBitboards(turn)[ui.type];
- ui.before = b;
- Bitboard target = Bitboard::fromIndex(mi.move.destination);
- b &= ~Bitboard::fromIndex(mi.move.origin);
- b |= target;
- ui.captured = PieceType::EMPTY;
- for (int i = 0; i < 6; i++) {
- Bitboard& e = board.getBitboards(otherSide(turn))[i];
- if (target & e) {
- ui.captured = static_cast<PieceType>(i);
- ui.beforeCaptured = e;
- e ^= target;
- break;
- }
- }
- turn = otherSide(turn);
- moveCount++;
- ui.reversibleHalfMoves = reversibleHalfMoves;
- if(mi.movedPiece != PAWN &&
- board.getAtPosition(mi.move.destination) != EMPTY) {
- reversibleHalfMoves++;
- }
- return ui;
- }
- void ChessGame::undoMove(const UndoInfo& ui)
- {
- turn = otherSide(turn);
- Bitboard& b = board.getBitboards(turn)[ui.type];
- b = ui.before;
- if (ui.captured != PieceType::EMPTY)
- board.getBitboards(otherSide(turn))[ui.captured] = ui.beforeCaptured;
- moveCount--;
- reversibleHalfMoves = ui.reversibleHalfMoves;
- castlingRights = ui.castlingRights;
- }
|