175 lines
7.6 KiB
C++
175 lines
7.6 KiB
C++
#include "Pawn.hpp"
|
|
|
|
/**
|
|
* Creates a new pawn with a specified color and position.
|
|
* @param color The color of the pawn.
|
|
* @param position The position of the pawn.
|
|
*/
|
|
Pawn::Pawn(ChessPieceColor color, ChessPiecePosition position) : ChessPiece(color, position) {
|
|
this->_char = this->_CHAR_PAWN;
|
|
this->_unicode = {"\u265F", "\u2659"};
|
|
}
|
|
|
|
/**
|
|
* Gets all chess piece positions the pawn can move next.
|
|
* The set of chess piece positions will be ignored, because the pawn has a fixed movement.
|
|
* @param chessboard A pointer to the chessboard.
|
|
* @param ignore A set of chess piece positions to be ignored.
|
|
* @return A set of chess piece positions the pawn can move next.
|
|
*/
|
|
std::set<ChessPiecePosition> Pawn::GetNextPositions(Chessboard* chessboard, std::set<ChessPiecePosition> ignore) {
|
|
std::set<ChessPiecePosition> positions;
|
|
ChessPiecePosition currentPosition = this->GetPosition();
|
|
ChessPiecePosition* nextPosition = ¤tPosition;
|
|
|
|
if (this->GetColor() == ChessPieceColor::Black) {
|
|
|
|
// 3.7.1. The pawn may move forward to the square immediately in front of it on the same file, provided that this square is unoccupied.
|
|
// 3.7.2. On its first move the pawn may move as in 3.7.1 or alternatively it may advance two squares along the same file, provided that both squares are unoccupied.
|
|
for (int move = 1; move <= 2; move++) {
|
|
nextPosition = nextPosition->NextBottom();
|
|
|
|
if (nextPosition) {
|
|
if (chessboard->IsEmptyField(nextPosition) == false) {
|
|
break;
|
|
}
|
|
|
|
if (move == 1) {
|
|
positions.insert(*nextPosition);
|
|
} else if (move == 2 && this->IsFirstMove()) {
|
|
positions.insert(*nextPosition);
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 3.7.3. the pawn may move to a square occupied by an opponent's piece diagonally in front of it on an adjacent file, capturing that piece.
|
|
for (std::string move : {"B1L1", "B1R1"}) {
|
|
nextPosition = ¤tPosition;
|
|
nextPosition = nextPosition->NextFromString(move);
|
|
|
|
if (nextPosition && chessboard->IsEmptyField(nextPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(nextPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor()) {
|
|
positions.insert(*nextPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3.7.3.1. A pawn occupying a square on the same rank as and on an adjacent file to an opponent's pawn which has just advanced two squares
|
|
// in one move from its original square may capture this opponent's pawn as though the latter had been moved only one square.
|
|
// 3.7.3.2. This capture is only legal on the move following this advance and is called an "en passant" capture.
|
|
if (chessboard->GetCountMoves() > 0) {
|
|
std::pair<ChessPiecePosition, ChessPiecePosition> lastMove = chessboard->GetLastMove();
|
|
std::string moveDifference = ChessPiecePosition::GetDifference(lastMove.first, lastMove.second);
|
|
ChessPiecePosition* leftPosition = currentPosition.NextLeft();
|
|
ChessPiecePosition* rightPosition = currentPosition.NextRight();
|
|
|
|
if (leftPosition && chessboard->IsEmptyField(leftPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(leftPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor() && chessPiece->IsPawn()) {
|
|
if (chessPiece->GetNumberOfMoves() == 1 && moveDifference == "T2" && chessPiece->GetPosition() == lastMove.second) {
|
|
ChessPiecePosition* bottomLeftPosition = currentPosition.NextFromString("B1L1");
|
|
|
|
if (bottomLeftPosition && chessboard->IsEmptyField(bottomLeftPosition)) {
|
|
positions.insert(*bottomLeftPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rightPosition && chessboard->IsEmptyField(rightPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(rightPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor() && chessPiece->IsPawn()) {
|
|
if (chessPiece->GetNumberOfMoves() == 1 && moveDifference == "T2" && chessPiece->GetPosition() == lastMove.second) {
|
|
ChessPiecePosition* bottomRightPosition = currentPosition.NextFromString("B1R1");
|
|
|
|
if (bottomRightPosition && chessboard->IsEmptyField(bottomRightPosition)) {
|
|
positions.insert(*bottomRightPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (this->GetColor() == ChessPieceColor::White) {
|
|
|
|
// 3.7.1. The pawn may move forward to the square immediately in front of it on the same file, provided that this square is unoccupied.
|
|
// 3.7.2. On its first move the pawn may move as in 3.7.1 or alternatively it may advance two squares along the same file, provided that both squares are unoccupied.
|
|
for (int move = 1; move <= 2; move++) {
|
|
nextPosition = nextPosition->NextTop();
|
|
|
|
if (nextPosition) {
|
|
if (chessboard->IsEmptyField(nextPosition) == false) {
|
|
break;
|
|
}
|
|
|
|
if (move == 1) {
|
|
positions.insert(*nextPosition);
|
|
} else if (move == 2 && this->IsFirstMove()) {
|
|
positions.insert(*nextPosition);
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 3.7.3. the pawn may move to a square occupied by an opponent's piece diagonally in front of it on an adjacent file, capturing that piece.
|
|
for (std::string move : {"T1L1", "T1R1"}) {
|
|
nextPosition = ¤tPosition;
|
|
nextPosition = nextPosition->NextFromString(move);
|
|
|
|
if (nextPosition && chessboard->IsEmptyField(nextPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(nextPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor()) {
|
|
positions.insert(*nextPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3.7.3.1. A pawn occupying a square on the same rank as and on an adjacent file to an opponent's pawn which has just advanced two squares
|
|
// in one move from its original square may capture this opponent's pawn as though the latter had been moved only one square.
|
|
// 3.7.3.2. This capture is only legal on the move following this advance and is called an "en passant" capture.
|
|
if (chessboard->GetCountMoves() > 0) {
|
|
std::pair<ChessPiecePosition, ChessPiecePosition> lastMove = chessboard->GetLastMove();
|
|
std::string moveDifference = ChessPiecePosition::GetDifference(lastMove.first, lastMove.second);
|
|
ChessPiecePosition* leftPosition = currentPosition.NextLeft();
|
|
ChessPiecePosition* rightPosition = currentPosition.NextRight();
|
|
|
|
if (leftPosition && chessboard->IsEmptyField(leftPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(leftPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor() && chessPiece->IsPawn()) {
|
|
if (chessPiece->GetNumberOfMoves() == 1 && moveDifference == "B2" && chessPiece->GetPosition() == lastMove.second) {
|
|
ChessPiecePosition* topLeftPosition = currentPosition.NextFromString("T1L1");
|
|
|
|
if (topLeftPosition && chessboard->IsEmptyField(topLeftPosition)) {
|
|
positions.insert(*topLeftPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rightPosition && chessboard->IsEmptyField(rightPosition) == false) {
|
|
ChessPiece* chessPiece = chessboard->GetChessPiece(rightPosition);
|
|
|
|
if (chessPiece->GetColor() != this->GetColor() && chessPiece->IsPawn()) {
|
|
if (chessPiece->GetNumberOfMoves() == 1 && moveDifference == "B2" && chessPiece->GetPosition() == lastMove.second) {
|
|
ChessPiecePosition* topRightPosition = currentPosition.NextFromString("T1R1");
|
|
|
|
if (topRightPosition && chessboard->IsEmptyField(topRightPosition)) {
|
|
positions.insert(*topRightPosition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return positions;
|
|
}
|