mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-21 02:08:12 +03:00
Chess: Add En-passant
This commit is contained in:
parent
e91542a3cf
commit
9d40472721
Notes:
sideshowbarker
2024-07-19 03:35:35 +09:00
Author: https://github.com/petelliott Commit: https://github.com/SerenityOS/serenity/commit/9d404727218 Pull-request: https://github.com/SerenityOS/serenity/pull/3099 Reviewed-by: https://github.com/stelar7
@ -154,32 +154,30 @@ bool Chess::is_legal_no_check(const Move& move, Colour colour) const
|
||||
return false;
|
||||
|
||||
if (piece.type == Type::Pawn) {
|
||||
// FIXME: Add en passant.
|
||||
if (colour == Colour::White) {
|
||||
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::Black) {
|
||||
int dir = (colour == Colour::White) ? +1 : -1;
|
||||
unsigned start_rank = (colour == Colour::White) ? 1 : 6;
|
||||
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.
|
||||
return true;
|
||||
} else if (move.to.rank == move.from.rank + dir && (move.to.file == move.from.file + 1 || move.to.file == move.from.file - 1)) {
|
||||
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.
|
||||
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) {
|
||||
// 2 square pawn move from initial position.
|
||||
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.
|
||||
} 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.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (piece.type == Type::Knight) {
|
||||
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
|
||||
|
||||
m_last_move = move;
|
||||
|
||||
if (move.from == Square("a1") || move.to == Square("a1") || move.from == Square("e1"))
|
||||
m_white_can_castle_queenside = false;
|
||||
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.from, EmptyPiece);
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/IterationDecision.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Traits.h>
|
||||
|
||||
@ -92,6 +93,7 @@ public:
|
||||
, to(to)
|
||||
{
|
||||
}
|
||||
bool operator==(const Move& other) const { return from == other.from && to == other.to; }
|
||||
};
|
||||
|
||||
Chess();
|
||||
@ -103,6 +105,7 @@ public:
|
||||
bool in_check(Colour colour) const;
|
||||
|
||||
bool apply_move(const Move&, Colour colour = Colour::None);
|
||||
const Optional<Move>& last_move() const { return m_last_move; }
|
||||
|
||||
enum class Result {
|
||||
CheckMate,
|
||||
@ -124,6 +127,7 @@ private:
|
||||
|
||||
Piece m_board[8][8];
|
||||
Colour m_turn { Colour::White };
|
||||
Optional<Move> m_last_move;
|
||||
|
||||
bool m_white_can_castle_kingside { true };
|
||||
bool m_white_can_castle_queenside { true };
|
||||
|
@ -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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -115,8 +115,6 @@ void ChessWidget::mouseup_event(GUI::MouseEvent& event)
|
||||
auto target_square = mouse_to_square(event);
|
||||
|
||||
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) {
|
||||
set_drag_enabled(false);
|
||||
update();
|
||||
@ -204,7 +202,6 @@ void ChessWidget::reset()
|
||||
{
|
||||
m_board = Chess();
|
||||
m_drag_enabled = true;
|
||||
m_last_move = Optional<Chess::Move>();
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -83,5 +83,4 @@ private:
|
||||
Gfx::IntPoint m_drag_point;
|
||||
bool m_dragging_piece { false };
|
||||
bool m_drag_enabled { true };
|
||||
Optional<Chess::Move> m_last_move;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user