summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnicJov <contact.andrija@gmail.com>2020-12-04 13:17:00 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-06 15:51:34 +0100
commit01b62cc7f495e25f783b97a5b021067c817d65a5 (patch)
tree0f750fc9e2b90aef5528b286577b0022a252a335
parent694f68ab8694fb50cd177ae29e932ece50d9dbce (diff)
downloadserenity-01b62cc7f495e25f783b97a5b021067c817d65a5.zip
Chess: Added ability to resign and flip the board
This patch adds options to the app's menubar to resign the game and flip the board.
-rw-r--r--Games/Chess/ChessWidget.cpp21
-rw-r--r--Games/Chess/ChessWidget.h2
-rw-r--r--Games/Chess/main.cpp8
-rw-r--r--Libraries/LibChess/Chess.cpp39
-rw-r--r--Libraries/LibChess/Chess.h6
5 files changed, 76 insertions, 0 deletions
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<Gfx::Bitmap> 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<Square> 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<typename Callback>
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<Move> m_last_move;
int m_moves_since_capture { 0 };