// // Created by hamac on 18.12.2024. // #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 = "□"; const std::string whiteKing = "♔"; const std::string whiteQueen = "♕"; const std::string whiteRook = "♖"; const std::string whiteBischop = "♗"; const std::string whiteKnight = "♘"; const std::string whitePawn = "♙"; // Black pieces const std::string blackSquare = "■"; const std::string blackKing = "♚"; const std::string blackQueen = "♛"; const std::string blackRook = "♜"; const std::string blackBischop = "♝"; const std::string blackKnight = "♞"; const std::string blackPawn = "♟"; /* class fields */ std::vector> currentBoard; // Starting formatting std::vector> startBoard = { {'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r'}, {'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'}, {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}, {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}, {'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'}, {'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R'}, }; // ToDo: Mathematisch sicherlich weg rationalisierbar std::vector> emptyBoard = { {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}, {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}, {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'}, {'w', 'x', 'w', 'x' ,'w', 'x', 'w', 'x'}, {'x', 'w', 'x', 'w', 'x', 'w', 'x', 'w'} }; // 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(char identifier) { switch (identifier) { case 'x': return blackSquare; case 'r': return blackRook; case 'n': return blackKnight; case 'b': return blackBischop; case 'q': return blackQueen; case 'k': return blackKing; case 'p': return blackPawn; case 'w': return whiteSquare; case 'R': return whiteRook; case 'N': return whiteKnight; case 'B': return whiteBischop; case 'Q': return whiteQueen; case 'K': return whiteKing; case 'P': return whitePawn; default: return ""; } } 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 char getCorrectPiece(char pieceIdentifier) { bool isWhite = getTurnOrder(); if (!isWhite) return pieceIdentifier + 32; return pieceIdentifier; } std::pair convertPosition(const std::string &pos) { static const std::unordered_map fileConvertion = { {0, 7}, {1, 6}, {2, 5}, {3, 4}, {4, 3}, {5, 2}, {6, 1}, {7, 0} }; 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 // } };