add remaining missing STR tags to PGN exports default tip

Fri, 15 May 2026 12:18:34 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 15 May 2026 12:18:34 +0200
changeset 120
57577c9af5d3
parent 119
333a16b76adf

add remaining missing STR tags to PGN exports

resolves #814

src/chess/pgn.c file | annotate | diff | comparison | revisions
--- 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 <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <sys/time.h>
+#include <time.h>
 
 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";

mercurial