// © 2025 A.M. Rowsell // 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. #include "Piece.hpp" Piece::~Piece() { return; } // because the Piece class is instantiated in another class using // unique_ptr, non-pure virtual functions apparently *must* // have definitions, or the linker freaks out // so this is just a stub that does nothing. it doesn't matter // because only the derived class versions should be called. std::vector Piece::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; return moveList; } std::vector King::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; const int directions[8][2] = { {-1, 0}, // Up {-1, -1}, // up-left {-1, 1}, // up-right {1, 0}, // Down {1, -1}, // down-left {1, 1}, // down-right {0, -1}, // Left {0, 1} // Right }; return moveList; } std::vector Rook::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; const int directions[4][2] = { {-1, 0}, // Up {1, 0}, // Down {0, -1}, // Left {0, 1} // Right }; for (auto& dir : directions) { int r = from.rank + dir[0]; int f = from.file + dir[1]; while (r >= 0 && r < 8 && f >= 0 && f < 8) { const auto& target = board.boardGrid[r][f]; auto ra = static_cast (r); auto fi = static_cast (f); Square targetSquare = {ra, fi}; if (!target) { moveList.push_back({from, targetSquare}); } else if (target && target->getColour() != this->getColour()) { moveList.push_back({from, targetSquare}); break; } else { break; } r += dir[0]; f += dir[1]; } } return moveList; } std::vector Queen::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; return moveList; } std::vector Knight::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; return moveList; } std::vector Bishop::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; return moveList; } std::vector Pawn::getLegalMoves(const Square &from, const Board &board) const { std::vector moveList; const int directions[2][4][2] = { { // black {-1, 0}, // Up {-2, 0}, // 2up first move {-1, 1}, // attack to right {-1, -1} // attack to left }, { // white {1, 0}, // down {2, 0}, // 2down first move {1, 1}, // attack to right {1, -1} // attack to left } }; if (this->getColour() == PIECE_BLACK) { // go through black options for (auto &dir : directions[0]) { int r = from.rank + dir[0]; int f = from.file + dir[1]; if (r >= 0 && r < 8 && f >= 0 && f < 8) { // no need for a while loop as we only have finite moves in limited directions const auto& target = board.boardGrid[r][f]; auto ra = static_cast (r); auto fi = static_cast (f); Square targetSquare = {ra, fi}; if (dir[0] == -2 && !this->checkIfMoved()) { // then 2 is potentially legal if (!target && !(board.boardGrid[r + 1][f])) // check both squares for pieces of any colour moveList.push_back({from, targetSquare}); else break; } else if (abs(dir[1]) == 1) { // attempted capture (diagonal) if (target && target->getColour() != this->getColour()) { // legal capture moveList.push_back({from, targetSquare}); } else { break; } } else { // normal one square forward if (!target) moveList.push_back({from, targetSquare}); } // now check if we are on 8th rank, for promotion } } } else if (this->getColour() == PIECE_WHITE) { for (auto &dir : directions[1]) { // go through white options int r = from.rank + dir[0]; int f = from.file + dir[1]; if (r >= 0 && r < 8 && f >= 0 && f < 8) { // no need for a while loop as we only have finite moves in limited directions const auto& target = board.boardGrid[r][f]; auto ra = static_cast (r); auto fi = static_cast (f); Square targetSquare = {ra, fi}; if (dir[0] == 2 && !this->checkIfMoved()) { // then 2 is potentially legal if (!target && !(boardGrid[r - 1][f])) moveList.push_back({from, targetSquare}); else break; } else if (abs(dir[1]) == 1) { // attempted capture (diagonal) if (target && target->getColour() != this->getColour()) { // can only move there if it's a capture // legal capture moveList.push_back({from, targetSquare}); } else { break; } } else { // normal one square forward if (!target) moveList.push_back({from, targetSquare}); } // now check if we are on 8th rank, for promotion } } } return moveList; }