chessmcu/inc/Board.hpp
A.M. Rowsell fa9d534e94
docs: bringing in doxygen-awesome-css, added more inline documentation
The doxygen-awesome-css project is just a nice, simple, customizable
CSS system for making doxygen look less like 1992 and more like
2022. I need to spend a bunch of time tweaking it to make it
look good, and perhaps match it to the style already used at
chess.frzn.dev.

Added more inline Doxycomments, and also generated an image that
represents the logical layout of the boardGrid member variable,
showing the mirrored layout. This works well for our project
because of the way the serial data comes in.
2025-09-16 03:21:53 -04:00

123 lines
4 KiB
C++

// © 2025 A.M. Rowsell <amr@frzn.dev>
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, v. 2.0.
/** @file Board.hpp
* @brief The header file for the Board class
*
* This contains the class definition for the logical representation of the chessboard
* itself, as well as a few ancillary enums and forward declarations to make the code
* easier to read (hopefully). Unlike the Piece.hpp header, there's no inheritance
* or virtual functions so this "half" of the code is a bit simpler to follow.
*/
#ifndef BOARD_HPP
#define BOARD_HPP
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "Piece.hpp"
class Piece;
/** @enum Players
* @brief An enum for the white and black players
*/
enum Players { PL_WHITE, PL_BLACK };
struct Square;
/** @class Board Board.hpp inc/Board.hpp
* @brief This class abstracts the chess board itself
*
* The heart of the entire code is contained in the member variable boardGrid, which
* is a representation of the board. It's a 2D vector of Pieces, which are stored using
* smart pointers. When other functions want to view the board, they do so with the included
* getPieceAt() getters, which return raw pointers so ownership isn't transferred.
*
* Outside functions/methods can also change the state of the board with setPieceAt() which
* can allow one to move a piece (empty squares being nullptr) or add pieces to the Board when
* required.
*/
class Board {
private:
std::vector<std::vector<std::unique_ptr<Piece>>> boardGrid; /**< This holds the game state. It is a 2D vector of Piece types, or nullptr for empty squares @image html boardGrid.png "Logical diagram of boardGrid vector" */
Players playerTurn;
// let's get super object-oriented, baby
// these help the getters and setters access the boardGrid
// and also make them shorter and less duplicative
std::unique_ptr<Piece>& at(int r, int f) {
return boardGrid[r][f];
}
const std::unique_ptr<Piece> &at(int r, int f) const {
return boardGrid[r][f];
}
std::unique_ptr<Piece> &at(const Square& sq) {
return boardGrid[static_cast<int>(sq.rank)][static_cast<int>(sq.file)];
}
const std::unique_ptr<Piece> &at(const Square& sq) const {
return boardGrid[static_cast<int>(sq.rank)][static_cast<int>(sq.file)];
}
public:
Board();
virtual ~Board();
// These are to allow Piece to access Board in a controlled way
// instead of adding a friend declaration for every subclass
// ----- Getters -----
Piece* getPieceAt(int r, int f) {
return at(r, f).get();
}
const Piece* getPieceAt(int r, int f) const {
return at(r, f).get();
}
Piece* getPieceAt(const Square& sq) {
return at(sq).get();
}
const Piece* getPieceAt(const Square& sq) const {
return at(sq).get();
}
// ----- Setters -----
void setPieceAt(int r, int f, std::unique_ptr<Piece> piece) {
at(r, f) = std::move(piece);
}
void setPieceAt(const Square& sq, std::unique_ptr<Piece> piece) {
at(sq) = std::move(piece);
}
void clearSquare(int r, int f) {
at(r, f).reset();
}
void clearSquare(const Square& sq) {
at(sq).reset();
}
// ----- Utility -----
bool isSquareEmpty(int r, int f) const {
return at(r, f) == nullptr;
}
bool isSquareEmpty(const Square& sq) const {
return at(sq) == nullptr;
}
void setupInitialPosition();
void clearBoard();
void movePiece(Square from, Square to);
void nextTurn();
int setupFromFEN(std::string strFEN);
bool isInBounds(Square square) const;
// serial shift register stuff
uint64_t serialBoard = 0xFFFF00000000FFFF; // opening position
void deserializeBoard(uint64_t incomingBoard);
};
#endif // BOARD_HPP