# HG changeset patch # User Mike Becker # Date 1778840314 -7200 # Node ID 57577c9af5d30233c8aedcc8cfb32a39f9aa410c # Parent 333a16b76adf08a536eca828915dc7f26cb3b8d6 add remaining missing STR tags to PGN exports resolves #814 diff -r 333a16b76adf -r 57577c9af5d3 src/chess/pgn.c --- a/src/chess/pgn.c Thu May 14 10:17:23 2026 +0200 +++ b/src/chess/pgn.c Fri May 15 12:18:34 2026 +0200 @@ -32,6 +32,8 @@ #include #include #include +#include +#include enum { pgn_error_missing_quote = 1, @@ -200,11 +202,49 @@ } } +static const char *pgn_date(GameState *gamestate) { + static char date[16]; + time_t dateseconds; + if (gamestate->movecount == 0) { + struct timeval curtimestamp; + gettimeofday(&curtimestamp, NULL); + dateseconds = curtimestamp.tv_sec; + } else { + dateseconds = (time_t) gamestate->moves[0].timestamp.tv_sec; + } + struct tm *tm = gmtime(&dateseconds); + if (tm == NULL) { + /* fallback - should never happen in reality */ + strncpy(date, "????.??.??", sizeof(date)); + } else { + int year = tm->tm_year + 1900; + int month = tm->tm_mon + 1; + int day = tm->tm_mday; +#ifdef __GNUC__ + /* this is required to tell GCC that it does not need to warn + * about the small buffer size of the date string. + */ + if (year < 1900 || year > 9999) __builtin_unreachable(); + if (month < 1 || month > 12) __builtin_unreachable(); + if (day < 1 || day > 31) __builtin_unreachable(); +#endif + snprintf(date, sizeof(date), "%04d.%02d.%02d", + year, month, day); + } + return date; +} + void write_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo, bool export_comments) { - // TODO: tag pairs + /* STR tag pairs */ + fprintf(stream, "[Event \"%s\"]\n", "terminal-chess game"); + fprintf(stream, "[Site \"%s\"]\n", "Somewhere on Earth"); + fprintf(stream, "[Date \"%s\"]\n", pgn_date(gamestate)); + fprintf(stream, "[Round \"%s\"]\n", "-"); + // TODO: maybe allow players to enter their names before game starts + fprintf(stream, "[White \"%s\"]\n", "Anonymous"); + fprintf(stream, "[Black \"%s\"]\n", "Anonymous"); - /* Result */ char *result; if (gamestate->stalemate || gamestate->remis) { result = "1/2-1/2";