diff --git a/Games/Chess/ChessWidget.cpp b/Games/Chess/ChessWidget.cpp index 1c965bcf2c..053d0c7e55 100644 --- a/Games/Chess/ChessWidget.cpp +++ b/Games/Chess/ChessWidget.cpp @@ -288,3 +288,24 @@ void ChessWidget::maybe_input_engine_move() update(); }); } + +void ChessWidget::flip_board() +{ + m_side = Chess::opposing_colour(m_side); + update(); +} + +void ChessWidget::resign() +{ + if (m_engine && m_board.turn() != m_side) { + GUI::MessageBox::show(window(), "You can only resign on your turn.", "Resign", GUI::MessageBox::Type::Information); + return; + } + + board().set_resigned(m_board.turn()); + + set_drag_enabled(false); + update(); + const String msg = m_board.result_to_string(m_board.game_result()); + GUI::MessageBox::show(window(), msg, "Game Over", GUI::MessageBox::Type::Information); +} diff --git a/Games/Chess/ChessWidget.h b/Games/Chess/ChessWidget.h index 7dd53b2edb..657caeefbd 100644 --- a/Games/Chess/ChessWidget.h +++ b/Games/Chess/ChessWidget.h @@ -61,6 +61,8 @@ public: void set_drag_enabled(bool e) { m_drag_enabled = e; } RefPtr get_piece_graphic(const Chess::Piece& piece) const; + void resign(); + void flip_board(); void reset(); struct BoardTheme { diff --git a/Games/Chess/main.cpp b/Games/Chess/main.cpp index 198ec54289..97a5de81f7 100644 --- a/Games/Chess/main.cpp +++ b/Games/Chess/main.cpp @@ -85,6 +85,14 @@ int main(int argc, char** argv) auto menubar = GUI::MenuBar::construct(); auto& app_menu = menubar->add_menu("Chess"); + app_menu.add_action(GUI::Action::create("Resign", { Mod_None, Key_F3 }, [&](auto&) { + widget.resign(); + })); + app_menu.add_action(GUI::Action::create("Flip Board", { Mod_None, Key_F4 }, [&](auto&) { + widget.flip_board(); + })); + app_menu.add_separator(); + app_menu.add_action(GUI::Action::create("New game", { Mod_None, Key_F2 }, [&](auto&) { widget.reset(); })); diff --git a/Libraries/LibChess/Chess.cpp b/Libraries/LibChess/Chess.cpp index 8c65f34b42..7a10049a39 100644 --- a/Libraries/LibChess/Chess.cpp +++ b/Libraries/LibChess/Chess.cpp @@ -512,6 +512,9 @@ Move Board::random_move(Colour colour) const Board::Result Board::game_result() const { + if (m_resigned != Colour::None) + return (m_resigned == Colour::White) ? Result::WhiteResign : Result::BlackResign; + bool sufficient_material = false; bool no_more_pieces_allowed = false; Optional bishop; @@ -684,4 +687,40 @@ bool Board::operator==(const Board& other) const return turn() == other.turn(); } +void Board::set_resigned(Chess::Colour c) +{ + m_resigned = c; +} + +String Board::result_to_string(Result r) const +{ + switch (r) { + case Result::CheckMate: + if (m_turn == Chess::Colour::White) + return "Black wins by Checkmate"; + else + return "White wins by Checkmate"; + case Result::WhiteResign: + return "Black wins by Resignation"; + case Result::BlackResign: + return "White wins by Resignation"; + case Result::StaleMate: + return "Draw by Stalemate"; + case Chess::Board::Result::FiftyMoveRule: + return "Draw by 50 move rule"; + case Chess::Board::Result::SeventyFiveMoveRule: + return "Draw by 75 move rule"; + case Chess::Board::Result::ThreeFoldRepetition: + return "Draw by threefold repetition"; + case Chess::Board::Result::FiveFoldRepetition: + return "Draw by fivefold repetition"; + case Chess::Board::Result::InsufficientMaterial: + return "Draw by insufficient material"; + case Chess::Board::Result::NotFinished: + return "Game not finished"; + default: + ASSERT_NOT_REACHED(); + } +} + } diff --git a/Libraries/LibChess/Chess.h b/Libraries/LibChess/Chess.h index d10c6ff758..787a6ed4b2 100644 --- a/Libraries/LibChess/Chess.h +++ b/Libraries/LibChess/Chess.h @@ -135,6 +135,8 @@ public: enum class Result { CheckMate, StaleMate, + WhiteResign, + BlackResign, FiftyMoveRule, SeventyFiveMoveRule, ThreeFoldRepetition, @@ -143,6 +145,8 @@ public: NotFinished, }; + String result_to_string(Result) const; + template void generate_moves(Callback callback, Colour colour = Colour::None) const; Move random_move(Colour colour = Colour::None) const; @@ -150,6 +154,7 @@ public: Colour game_winner() const; int game_score() const; bool game_finished() const; + void set_resigned(Colour); int material_imbalance() const; Colour turn() const { return m_turn; } @@ -164,6 +169,7 @@ private: Piece m_board[8][8]; Colour m_turn { Colour::White }; + Colour m_resigned { Colour::None }; Optional m_last_move; int m_moves_since_capture { 0 };