1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 11:57:35 +00:00

Chess: Add En-passant

This commit is contained in:
Peter Elliott 2020-08-11 21:13:48 -06:00 committed by Andreas Kling
parent e91542a3cf
commit 9d40472721
4 changed files with 35 additions and 26 deletions

View file

@ -154,32 +154,30 @@ bool Chess::is_legal_no_check(const Move& move, Colour colour) const
return false; return false;
if (piece.type == Type::Pawn) { if (piece.type == Type::Pawn) {
// FIXME: Add en passant. int dir = (colour == Colour::White) ? +1 : -1;
if (colour == Colour::White) { unsigned start_rank = (colour == Colour::White) ? 1 : 6;
if (move.to.rank == move.from.rank + 1 && move.to.file == move.from.file && get_piece(move.to).type == Type::None) { unsigned other_start_rank = (colour == Colour::White) ? 6 : 1;
unsigned en_passant_rank = (colour == Colour::White) ? 4 : 3;
if (move.to.rank == move.from.rank + dir && move.to.file == move.from.file && get_piece(move.to).type == Type::None) {
// Regular pawn move. // Regular pawn move.
return true; return true;
} else if (move.to.rank == move.from.rank + 1 && (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1) } else if (move.to.rank == move.from.rank + dir && (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1)) {
&& get_piece(move.to).colour == Colour::Black) { Move en_passant_last_move = { { other_start_rank, move.to.file }, { en_passant_rank, move.to.file } };
if (get_piece(move.to).colour == opposing_colour(colour)) {
// Pawn capture. // Pawn capture.
return true; return true;
} else if (move.from.rank == 1 && move.to.rank == move.from.rank + 2 && move.to.file == move.from.file && get_piece(move.to).type == Type::None) { } else if (m_last_move.has_value() && move.from.rank == en_passant_rank && m_last_move.value() == en_passant_last_move
&& get_piece(en_passant_last_move.to) == Piece(opposing_colour(colour), Type::Pawn)) {
// En passant.
return true;
}
} else if (move.from.rank == start_rank && move.to.rank == move.from.rank + (2 * dir) && move.to.file == move.from.file
&& get_piece(move.to).type == Type::None && get_piece({ move.from.rank + dir, move.from.file }).type == Type::None) {
// 2 square pawn move from initial position. // 2 square pawn move from initial position.
return true; return true;
} }
} else if (colour == Colour::Black) {
if (move.to.rank == move.from.rank - 1 && move.to.file == move.from.file && get_piece(move.to).type == Type::None) {
// Regular pawn move.
return true;
} else if (move.to.rank == move.from.rank - 1 && (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1)
&& get_piece(move.to).colour == Colour::White) {
// Pawn capture.
return true;
} else if (move.from.rank == 6 && move.to.rank == move.from.rank - 2 && move.to.file == move.from.file && get_piece(move.to).type == Type::None) {
// 2 square pawn move from initial position.
return true;
}
}
return false; return false;
} else if (piece.type == Type::Knight) { } else if (piece.type == Type::Knight) {
int rank_delta = abs(move.to.rank - move.from.rank); int rank_delta = abs(move.to.rank - move.from.rank);
@ -308,6 +306,8 @@ bool Chess::apply_illegal_move(const Move& move, Colour colour)
// FIXME: pawn promotion // FIXME: pawn promotion
m_last_move = move;
if (move.from == Square("a1") || move.to == Square("a1") || move.from == Square("e1")) if (move.from == Square("a1") || move.to == Square("a1") || move.from == Square("e1"))
m_white_can_castle_queenside = false; m_white_can_castle_queenside = false;
if (move.from == Square("h1") || move.to == Square("h1") || move.from == Square("e1")) if (move.from == Square("h1") || move.to == Square("h1") || move.from == Square("e1"))
@ -347,6 +347,15 @@ bool Chess::apply_illegal_move(const Move& move, Colour colour)
} }
} }
if (get_piece(move.from).type == Type::Pawn && move.from.file != move.to.file && get_piece(move.to).type == Type::None) {
// En passant.
if (colour == Colour::White) {
set_piece({ move.to.rank - 1, move.to.file }, EmptyPiece);
} else {
set_piece({ move.to.rank + 1, move.to.file }, EmptyPiece);
}
}
set_piece(move.to, get_piece(move.from)); set_piece(move.to, get_piece(move.from));
set_piece(move.from, EmptyPiece); set_piece(move.from, EmptyPiece);

View file

@ -27,6 +27,7 @@
#pragma once #pragma once
#include <AK/IterationDecision.h> #include <AK/IterationDecision.h>
#include <AK/Optional.h>
#include <AK/StringView.h> #include <AK/StringView.h>
#include <AK/Traits.h> #include <AK/Traits.h>
@ -92,6 +93,7 @@ public:
, to(to) , to(to)
{ {
} }
bool operator==(const Move& other) const { return from == other.from && to == other.to; }
}; };
Chess(); Chess();
@ -103,6 +105,7 @@ public:
bool in_check(Colour colour) const; bool in_check(Colour colour) const;
bool apply_move(const Move&, Colour colour = Colour::None); bool apply_move(const Move&, Colour colour = Colour::None);
const Optional<Move>& last_move() const { return m_last_move; }
enum class Result { enum class Result {
CheckMate, CheckMate,
@ -124,6 +127,7 @@ private:
Piece m_board[8][8]; Piece m_board[8][8];
Colour m_turn { Colour::White }; Colour m_turn { Colour::White };
Optional<Move> m_last_move;
bool m_white_can_castle_kingside { true }; bool m_white_can_castle_kingside { true };
bool m_white_can_castle_queenside { true }; bool m_white_can_castle_queenside { true };

View file

@ -63,7 +63,7 @@ void ChessWidget::paint_event(GUI::PaintEvent& event)
painter.fill_rect(tile_rect, ((sq.rank % 2) == (sq.file % 2)) ? board_theme().dark_square_color : board_theme().light_square_color); painter.fill_rect(tile_rect, ((sq.rank % 2) == (sq.file % 2)) ? board_theme().dark_square_color : board_theme().light_square_color);
if (m_last_move.has_value() && (m_last_move.value().to == sq || m_last_move.value().from == sq)) { if (board().last_move().has_value() && (board().last_move().value().to == sq || board().last_move().value().from == sq)) {
painter.fill_rect(tile_rect, m_move_highlight_color); painter.fill_rect(tile_rect, m_move_highlight_color);
} }
@ -115,8 +115,6 @@ void ChessWidget::mouseup_event(GUI::MouseEvent& event)
auto target_square = mouse_to_square(event); auto target_square = mouse_to_square(event);
if (board().apply_move({ m_moving_square, target_square })) { if (board().apply_move({ m_moving_square, target_square })) {
m_last_move = Chess::Move(m_moving_square, target_square);
if (board().game_result() != Chess::Result::NotFinished) { if (board().game_result() != Chess::Result::NotFinished) {
set_drag_enabled(false); set_drag_enabled(false);
update(); update();
@ -204,7 +202,6 @@ void ChessWidget::reset()
{ {
m_board = Chess(); m_board = Chess();
m_drag_enabled = true; m_drag_enabled = true;
m_last_move = Optional<Chess::Move>();
update(); update();
} }

View file

@ -83,5 +83,4 @@ private:
Gfx::IntPoint m_drag_point; Gfx::IntPoint m_drag_point;
bool m_dragging_piece { false }; bool m_dragging_piece { false };
bool m_drag_enabled { true }; bool m_drag_enabled { true };
Optional<Chess::Move> m_last_move;
}; };