// // Created by hamac on 18.12.2024. // #include "Chessboard.h" #include "Utils.cpp" #include #include #include #include #include class Chessboard { private: /* Constants */ // Chars to display board // Corners const std::string topLeft = "┌"; const std::string topRight = "┐"; const std::string bottomLeft = "└"; const std::string bottomRight = "┘"; // Line chars const std::string horizontal = "─"; const std::string vertical = "│"; const std::string topIntersection = "┬"; const std::string bottomIntersection = "┴"; const std::string middleIntersection = "┼"; // White pieces const std::string whiteSquare = "\u25A1"; const std::string whiteKing = "\u2654"; const std::string whiteQueen = "\u2655"; const std::string whiteRook = "\u2656"; const std::string whiteBischop = "\u2657"; const std::string whiteKnight = "\u2658"; const std::string whitePawn = "\u2659"; // Black pieces const std::string blackSquare = "\u25A0"; const std::string blackKing = "\u265A"; const std::string blackQueen = "\u265B"; const std::string blackRook = "\u265C"; const std::string blackBischop = "\u265D"; const std::string blackKnight = "\u265E"; const std::string blackPawn = "\u265F"; /* class fields */ std::vector> currentBoard; // Starting formatting std::vector> startBoard = { {201, 202, 203, 204, 205, 203, 202, 201}, {200, 200, 200, 200, 200, 200, 200, 200}, {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1}, {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1}, {100, 100, 100, 100, 100, 100, 100, 100}, {101, 102, 103, 104, 105, 103, 102, 101} }; std::vector> emptyBoard = { {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1}, {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1}, {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1}, {1, 2, 1, 2, 1, 2, 1, 2}, {2, 1, 2, 1, 2, 1, 2, 1} }; // Saves turn order; true = white and false = black bool turnOrder = true; // ToDo: Max Size definieren? std::queue queue; /* methods */ // Method returns unicode for chess icon depending on the identifier std::string getChessIcon(int identifier) { switch (identifier) { case 1: return blackSquare; case 101: return blackRook; case 102: return blackKnight; case 103: return blackBischop; case 104: return blackQueen; case 105: return blackKing; case 100: return blackPawn; case 2: return whiteSquare; case 201: return whiteRook; case 202: return whiteKnight; case 203: return whiteBischop; case 204: return whiteQueen; case 205: return whiteKing; case 200: return whitePawn; default: return ""; } } static const std::unordered_map fileConvertion = { {0, 7}, {1, 6}, {2, 5}, {3, 4}, {4, 3}, {5, 2}, {6, 1}, {7, 0} }; void generateTopLine() { display += " " + horizontal + " " + topLeft; for (int col = 0; col < boardSize; ++col) { display += horizontal + horizontal + horizontal; if (col < boardSize - 1) display += topIntersection; } display += topRight + "\n"; } void generatePlayingField(const std::vector>& chessboard) { char desc = 56; for (int row = 0; row < boardSize; ++row) { display += " "; display += desc--; display += " " + vertical; for (int col = 0; col < boardSize; ++col) { display += " " + getChessIcon(chessboard[row][col]) + " " + vertical; } display += "\n"; // Horizontale Trennlinie (außer nach der letzten Zeile) if (row < boardSize - 1) { display += " " + horizontal + " " + vertical; for (int col = 0; col < boardSize; ++col) { display += horizontal + horizontal + horizontal; if (col < boardSize - 1) display += middleIntersection; } display += vertical + "\n"; } } } void generateBottomLine() { char desc = 65; display += " " + horizontal + " " + bottomLeft; for (int col = 0; col < boardSize; ++col) { display += horizontal + horizontal + horizontal; if (col < boardSize - 1) display += bottomIntersection; } display += bottomRight + "\n"; display += " " + vertical; for (int col = 0; col < boardSize; ++col) { display += " "; display += (desc++); display += " " + vertical; } } public: /* fields */ std::string display; int boardSize = 8; bool getTurnOrder() { return this->turnOrder; } void setTurnOrder(bool turnOrder) { this->turnOrder = turnOrder; } /* methods */ void setBoard(std::vector> board) { this->currentBoard = board; } std::vector> getBoard() { return this->currentBoard; } std::vector> getStartBoard() { return this->startBoard; } std::vector> getEmptyBoard() { return this->emptyBoard; } void draw () { draw(getStartBoard()); } void draw (const std::vector>& chessboard) { // Obere Rahmenlinie generateTopLine(); // Schachbrett mit vertikalen Linien generatePlayingField(chessboard); // Untere Rahmenlinie generateBottomLine(); setBoard(chessboard); std::cout << display << std::endl; } // ToDo: // Methode um mögliche Züge anzuzeigen // Rochade // Mate // Schachmate // En Passond // Restlichen moves // Angabe mit Menü Optionen als Zahlen // Figuren wählen mit Schachnotation int getCorrectPiece(char pieceIdentifier) { bool isWhite = getTurnOrder(); static const std::unordered_map pieceMap = { {'P', 200}, {'K', 205}, {'Q', 204}, {'N', 202}, {'R', 201}, {'B', 203} }; int piece = pieceMap.find(pieceIdentifier)->second; if (isWhite) { return piece - 100; } return piece; } std::pair convertPosition(const std::string &pos) { int y = pos[pos.size()-2] - 'a'; int x = fileConvertion.find((pos[pos.size()-1] - '0')-1)->second; return std::make_pair(x, y); } // void move(std::string move) { // ToDo: // add move to history queue std::vector splitMove; if (move.find('#') != std::string::npos) { // Schachmate // Finish game } else if (move.rfind("0-0", 0) == 0) { // Kleine Rochade // Check for Rochade } else if (move.rfind("0-0-0", 0) == 0) { // Große Rochade } // Standard move if (move.find('-')) { splitMove = Utils::split(move, '-'); } else if (move.find('x')) { splitMove = Utils::split(move, 'x'); } std::pair oldCoords= convertPosition(splitMove[0]); std::pair newCoords = convertPosition(splitMove[1]); std::vector> board = getBoard(); board[oldCoords.first][oldCoords.second] = getEmptyBoard()[oldCoords.first][oldCoords.second]; board[newCoords.first][newCoords.second] = getCorrectPiece(splitMove[0][0]); draw(board); // Notation // Start with current position - dash - new position // eg.: b1-c3 // Letter first than number // eg.: a5 // Pawn: e4 or p e4 (pawn) // R for rook // N for Knight // K for King // B for Bischop // Q for Queen // Special: // 0-0 short castle // 0-0-0 long castle // en passond: write square where pawn lands // capture: x // check: + // checkmate: # // draw/stalemate: 1/2-1/2 } // This method saves the current board state void saveBoard(Chessboard& chessboard) { } // This method loads a save state void loadBoard(int saveState) { // readJSONFile // } };