mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 17:47:44 +00:00
Chess: Add ability to export game as PGN file
This patch adds an option to the menubar for exporting the current game as a PGN file. This file can then be read by other chess programs (and ours eventually) to replay the game or analyze it. The implementation is mostly PGN spec compliant, however the code could use some more work. Particularly the `const_cast`s... But it's a start. :^) Fixup: Chess: Fixed hard-coded home path in unveil() call Fixup: Chess: Removed castling flags from Move struct The castling detection logic is done inside Move::to_algebraic() now, removing the need for is_castle_short and is_castle_long flags inside of the Move struct.
This commit is contained in:
parent
01b62cc7f4
commit
fe1628746c
5 changed files with 205 additions and 11 deletions
|
@ -27,9 +27,12 @@
|
|||
#include "ChessWidget.h"
|
||||
#include "PromotionDialog.h"
|
||||
#include <AK/String.h>
|
||||
#include <LibCore/DateTime.h>
|
||||
#include <LibCore/File.h>
|
||||
#include <LibGUI/MessageBox.h>
|
||||
#include <LibGUI/Painter.h>
|
||||
#include <LibGfx/Font.h>
|
||||
#include <unistd.h>
|
||||
|
||||
ChessWidget::ChessWidget(const StringView& set)
|
||||
{
|
||||
|
@ -289,6 +292,57 @@ void ChessWidget::maybe_input_engine_move()
|
|||
});
|
||||
}
|
||||
|
||||
bool ChessWidget::export_pgn(const StringView& export_path) const
|
||||
{
|
||||
auto file_or_error = Core::File::open(export_path, Core::File::WriteOnly);
|
||||
if (file_or_error.is_error()) {
|
||||
warnln("Couldn't open '{}': {}", export_path, file_or_error.error());
|
||||
return false;
|
||||
}
|
||||
auto& file = *file_or_error.value();
|
||||
|
||||
// Tag Pair Section
|
||||
file.write("[Event \"Casual Game\"]\n");
|
||||
file.write("[Site \"SerenityOS Chess\"]\n");
|
||||
file.write(String::formatted("[Date \"{}\"]\n", Core::DateTime::now().to_string("%Y.%m.%d")));
|
||||
file.write("[Round \"1\"]\n");
|
||||
|
||||
String username(getlogin());
|
||||
const String player1 = (!username.is_empty() ? username : "?");
|
||||
const String player2 = (!m_engine.is_null() ? "SerenityOS ChessEngine" : "?");
|
||||
file.write(String::formatted("[White \"{}\"]\n", m_side == Chess::Colour::White ? player1 : player2));
|
||||
file.write(String::formatted("[Black \"{}\"]\n", m_side == Chess::Colour::Black ? player1 : player2));
|
||||
|
||||
file.write(String::formatted("[Result \"{}\"]\n", Chess::Board::result_to_points(m_board.game_result(), m_board.turn())));
|
||||
file.write("[WhiteElo \"?\"]\n");
|
||||
file.write("[BlackElo \"?\"]\n");
|
||||
file.write("[Variant \"Standard\"]\n");
|
||||
file.write("[TimeControl \"-\"]\n");
|
||||
file.write("[Annotator \"SerenityOS Chess\"]\n");
|
||||
file.write("\n");
|
||||
|
||||
// Movetext Section
|
||||
for (size_t i = 0, move_no = 1; i < m_board.moves().size(); i += 2, move_no++) {
|
||||
const String white = m_board.moves().at(i).to_algebraic();
|
||||
|
||||
if (i + 1 < m_board.moves().size()) {
|
||||
const String black = m_board.moves().at(i + 1).to_algebraic();
|
||||
file.write(String::formatted("{}. {} {} ", move_no, white, black));
|
||||
} else {
|
||||
file.write(String::formatted("{}. {} ", move_no, white));
|
||||
}
|
||||
}
|
||||
|
||||
file.write("{ ");
|
||||
file.write(Chess::Board::result_to_string(m_board.game_result(), m_board.turn()));
|
||||
file.write(" } ");
|
||||
file.write(Chess::Board::result_to_points(m_board.game_result(), m_board.turn()));
|
||||
file.write("\n");
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChessWidget::flip_board()
|
||||
{
|
||||
m_side = Chess::opposing_colour(m_side);
|
||||
|
@ -306,6 +360,6 @@ void ChessWidget::resign()
|
|||
|
||||
set_drag_enabled(false);
|
||||
update();
|
||||
const String msg = m_board.result_to_string(m_board.game_result());
|
||||
const String msg = Chess::Board::result_to_string(m_board.game_result(), m_board.turn());
|
||||
GUI::MessageBox::show(window(), msg, "Game Over", GUI::MessageBox::Type::Information);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue