src/chess/pgn.c

changeset 120
57577c9af5d3
parent 118
0f2ffbc408ce
equal deleted inserted replaced
119:333a16b76adf 120:57577c9af5d3
30 #include "pgn.h" 30 #include "pgn.h"
31 31
32 #include <stdlib.h> 32 #include <stdlib.h>
33 #include <ctype.h> 33 #include <ctype.h>
34 #include <string.h> 34 #include <string.h>
35 #include <sys/time.h>
36 #include <time.h>
35 37
36 enum { 38 enum {
37 pgn_error_missing_quote = 1, 39 pgn_error_missing_quote = 1,
38 pgn_error_missing_bracket, 40 pgn_error_missing_bracket,
39 pgn_error_missing_brace, 41 pgn_error_missing_brace,
198 } 200 }
199 pos++; 201 pos++;
200 } 202 }
201 } 203 }
202 204
205 static const char *pgn_date(GameState *gamestate) {
206 static char date[16];
207 time_t dateseconds;
208 if (gamestate->movecount == 0) {
209 struct timeval curtimestamp;
210 gettimeofday(&curtimestamp, NULL);
211 dateseconds = curtimestamp.tv_sec;
212 } else {
213 dateseconds = (time_t) gamestate->moves[0].timestamp.tv_sec;
214 }
215 struct tm *tm = gmtime(&dateseconds);
216 if (tm == NULL) {
217 /* fallback - should never happen in reality */
218 strncpy(date, "????.??.??", sizeof(date));
219 } else {
220 int year = tm->tm_year + 1900;
221 int month = tm->tm_mon + 1;
222 int day = tm->tm_mday;
223 #ifdef __GNUC__
224 /* this is required to tell GCC that it does not need to warn
225 * about the small buffer size of the date string.
226 */
227 if (year < 1900 || year > 9999) __builtin_unreachable();
228 if (month < 1 || month > 12) __builtin_unreachable();
229 if (day < 1 || day > 31) __builtin_unreachable();
230 #endif
231 snprintf(date, sizeof(date), "%04d.%02d.%02d",
232 year, month, day);
233 }
234 return date;
235 }
236
203 void write_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo, 237 void write_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo,
204 bool export_comments) { 238 bool export_comments) {
205 // TODO: tag pairs 239 /* STR tag pairs */
206 240 fprintf(stream, "[Event \"%s\"]\n", "terminal-chess game");
207 /* Result */ 241 fprintf(stream, "[Site \"%s\"]\n", "Somewhere on Earth");
242 fprintf(stream, "[Date \"%s\"]\n", pgn_date(gamestate));
243 fprintf(stream, "[Round \"%s\"]\n", "-");
244 // TODO: maybe allow players to enter their names before game starts
245 fprintf(stream, "[White \"%s\"]\n", "Anonymous");
246 fprintf(stream, "[Black \"%s\"]\n", "Anonymous");
247
208 char *result; 248 char *result;
209 if (gamestate->stalemate || gamestate->remis) { 249 if (gamestate->stalemate || gamestate->remis) {
210 result = "1/2-1/2"; 250 result = "1/2-1/2";
211 } else if (gamestate->checkmate || gamestate->resign) { 251 } else if (gamestate->checkmate || gamestate->resign) {
212 if (gamestate->movecount > 0) { 252 if (gamestate->movecount > 0) {

mercurial