src/chess/pgn.c

Mon, 13 Jul 2026 22:23:00 +0200

author
Mike Becker <universe@uap-core.de>
date
Mon, 13 Jul 2026 22:23:00 +0200
changeset 142
780337e5cf6a
parent 140
e92ffe046659
child 143
e9159c70ff9e
permissions
-rw-r--r--

fix implementation of parse_pgn()

50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
1 /*
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
3 *
55
54ea19938d57 updated copyright and version info
Mike Becker <universe@uap-core.de>
parents: 54
diff changeset
4 * Copyright 2016 Mike Becker. All rights reserved.
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
5 *
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
8 *
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
11 *
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
15 *
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
27 *
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
28 */
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
29
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
30 #include "pgn.h"
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
31
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
32 #include <stdlib.h>
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
33 #include <ctype.h>
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
34 #include <string.h>
120
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
35 #include <sys/time.h>
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
36 #include <time.h>
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
37
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
38 enum {
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
39 pgn_error_missing_quote = 1,
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
40 pgn_error_missing_bracket,
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
41 pgn_error_missing_brace,
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
42 pgn_error_missing_dot,
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
43 pgn_error_move_syntax,
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
44 pgn_error_move_semantics,
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
45 pgn_error_result_syntax,
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
46 };
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
47
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
48 static const char* pgn_error_strings[] = {
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
49 "No Error.",
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
50 "Tag values must be enclosed in double-quotes.",
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
51 "Missing closing brace '}' for comment.",
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
52 "Tags must be enclosed in square brackets: '[Key \"Value\"]'.",
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
53 "Move numbers must be terminated with a dot (e.g. '13.' - not '13').",
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
54 "Move is syntactically incorrect.",
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
55 "Move is not valid according to chess rules.",
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
56 "Result syntax is incorrect. Expected 1-0, 0-1, 1/2-1/2, or *.",
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
57 };
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
58
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
59 const char* pgn_error_str(int code) {
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
60 return pgn_error_strings[code];
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
61 }
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
62
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
63 struct pgn_input {
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
64 union {
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
65 FILE *f;
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
66 const char *s;
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
67 } data;
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
68 int (*getc)(struct pgn_input *);
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
69 void (*backc)(struct pgn_input *);
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
70 };
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
71
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
72 static int pgngetc(struct pgn_input *pgn) {
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
73 return pgn->getc(pgn);
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
74 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
75
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
76 static void pgnbackc(struct pgn_input *pgn) {
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
77 pgn->backc(pgn);
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
78 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
79
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
80 static int pgnfgetc(struct pgn_input *pgn) {
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
81 return fgetc(pgn->data.f);
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
82 }
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
83
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
84 static void pgnfbackc(struct pgn_input *pgn) {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
85 fseek(pgn->data.f, -1, SEEK_CUR);
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
86 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
87
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
88 static void pgnsbackc(struct pgn_input *pgn) {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
89 --(pgn->data.s);
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
90 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
91
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
92 static int pgnsgetc(struct pgn_input *pgn) {
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
93 int c = *(unsigned char *) pgn->data.s;
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
94 pgn->data.s++;
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
95 return c;
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
96 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
97
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
98 static int read_pgn_(struct pgn_input pgndata, GameState *gamestate) {
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
99 int c, i;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
100
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
101 char result[8];
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
102
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
103 char tagkey[32];
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
104 char tagvalue[128];
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
105
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
106 /* read tag pairs */
82
e75865d90111 remove unnecessary loop variable
Mike Becker <universe@uap-core.de>
parents: 81
diff changeset
107 while (true) {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
108 while (isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
109 if (c == '1') {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
110 break;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
111 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
112 if (c != '[') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
113 return pgn_error_missing_bracket;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
114 }
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
115 while (isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
116 i = 0;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
117 do {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
118 tagkey[i++] = c;
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
119 } while (!isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
120 tagkey[i] = '\0';
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
121 while (isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
122 if (c != '"') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
123 return pgn_error_missing_quote;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
124 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
125 i = 0;
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
126 while ((c = pgngetc(&pgndata)) != '"') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
127 if (c == '\n' || c == EOF) {
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
128 return pgn_error_missing_quote;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
129 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
130 tagvalue[i++] = c;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
131 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
132 tagvalue[i] = '\0';
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
133 if (pgngetc(&pgndata) != ']') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
134 return pgn_error_missing_bracket;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
135 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
136
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
137 // TODO: read clock info
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
138 if (strcmp("Result", tagkey) == 0) {
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
139 // TODO: why are we parsing this? it is never used!
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
140 memcpy(result, tagvalue, 8);
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
141 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
142 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
143
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
144 /* read moves */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
145 if (pgngetc(&pgndata) != '.') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
146 return pgn_error_missing_dot;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
147 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
148
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
149 char movestr[10];
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
150 Move move;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
151 uint8_t curcol = WHITE;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
152
82
e75865d90111 remove unnecessary loop variable
Mike Becker <universe@uap-core.de>
parents: 81
diff changeset
153 while (true) {
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
154 /* move */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
155 while (isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
156 i = 0;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
157 do {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
158 movestr[i++] = c;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
159 if (i >= 10) {
81
82d3b044aa69 fix incorrect error value when a move string is too long in a PGN
Mike Becker <universe@uap-core.de>
parents: 80
diff changeset
160 return pgn_error_move_syntax;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
161 }
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
162 } while (!isspace(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
163 movestr[i] = '\0';
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
164 if (eval_move(gamestate, movestr, &move, curcol)
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
165 != VALID_MOVE_SYNTAX) {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
166 return pgn_error_move_syntax;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
167 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
168 if (validate_move(gamestate, &move) != VALID_MOVE_SEMANTICS) {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
169 return pgn_error_move_semantics;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
170 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
171 apply_move(gamestate, &move);
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
172
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
173 /* skip spaces */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
174 while (isspace(c = pgngetc(&pgndata)));
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
175
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
176 /* parse possible comment */
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
177 if (c == '{') {
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
178 // TODO: interpret comment (may contain clock info)
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
179 do {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
180 c = pgngetc(&pgndata);
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
181 } while (c != '}' && c != EOF);
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
182 if (c == EOF) {
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
183 return pgn_error_missing_brace;
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
184 }
88
e4a648fe6ce7 fix PGN parser
Mike Becker <universe@uap-core.de>
parents: 82
diff changeset
185 /* skip spaces */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
186 while (isspace(c = pgngetc(&pgndata)));
70
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
187 }
5427beba96d1 pgn parser can now handle comments (although it ignores them for now)
Mike Becker <universe@uap-core.de>
parents: 65
diff changeset
188
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
189 /* end of game data encountered */
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
190 if (c == EOF) {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
191 break;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
192 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
193 if (c == '1' || c == '0') {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
194 c = pgngetc(&pgndata);
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
195 // TODO: #842 - allow games to be continued if possible
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
196 if (c == '-') {
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
197 if (!gamestate->checkmate) {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
198 // TODO: maybe we should not parse this here;
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
199 // there is an unused result string from the STR
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
200 c = pgngetc(&pgndata);
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
201 if (c == '1') {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
202 gamestate->wresign = true;
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
203 } else if (c == '0') {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
204 gamestate->bresign = true;
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
205 } else {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
206 return pgn_error_result_syntax;
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
207 }
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
208 }
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
209 break;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
210 } else if (c == '/') {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
211 gamestate->remis = !gamestate->stalemate;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
212 break;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
213 } else {
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
214 /* oops, it was a move number, go back! */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
215 pgnbackc(&pgndata);
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
216 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
217 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
218
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
219 /* we have eaten the next valuable byte, so go back */
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
220 pgnbackc(&pgndata);
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
221
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
222 /* skip move number after black move */
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
223 if (curcol == BLACK) {
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
224 while (isdigit(c = pgngetc(&pgndata)));
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
225 if (c != '.') {
60
0c50aac49e55 adds error messages to PGN reader
Mike Becker <universe@uap-core.de>
parents: 59
diff changeset
226 return pgn_error_missing_dot;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
227 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
228 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
229 curcol = opponent_color(curcol);
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
230 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
231
59
3fa1de896666 fixes inappropriate use of EXIT_ macros + adds a sample PGN file
Mike Becker <universe@uap-core.de>
parents: 55
diff changeset
232 return 0;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
233 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
234
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
235 int read_pgn(FILE *stream, GameState *gamestate) {
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
236 return read_pgn_(
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
237 (struct pgn_input){
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
238 {.f = stream},
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
239 pgnfgetc,
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
240 pgnfbackc
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
241 }, gamestate);
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
242 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
243
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
244 int parse_pgn(const char *data, GameState *gamestate) {
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
245 return read_pgn_(
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
246 (struct pgn_input){
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
247 {.s = data},
142
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
248 pgnsgetc,
780337e5cf6a fix implementation of parse_pgn()
Mike Becker <universe@uap-core.de>
parents: 140
diff changeset
249 pgnsbackc
140
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
250 }, gamestate);
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
251 }
e92ffe046659 add parse_pgn function which can later be used for automated testing
Mike Becker <universe@uap-core.de>
parents: 133
diff changeset
252
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
253 static void pgn_insert_newlines(char *block) {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
254 size_t pos = 0;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
255 size_t last_space_pos = 0;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
256 size_t line_len = 0;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
257 while (block[pos] != '\0') {
118
0f2ffbc408ce prettier line breaking in exported PGNs
Mike Becker <universe@uap-core.de>
parents: 117
diff changeset
258 if (block[pos] == 0x1f) {
0f2ffbc408ce prettier line breaking in exported PGNs
Mike Becker <universe@uap-core.de>
parents: 117
diff changeset
259 block[pos++] = ' ';
0f2ffbc408ce prettier line breaking in exported PGNs
Mike Becker <universe@uap-core.de>
parents: 117
diff changeset
260 continue;
0f2ffbc408ce prettier line breaking in exported PGNs
Mike Becker <universe@uap-core.de>
parents: 117
diff changeset
261 }
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
262 if (block[pos] == ' ') {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
263 last_space_pos = pos;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
264 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
265 line_len++;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
266 if (line_len > 80) {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
267 block[last_space_pos] = '\n';
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
268 line_len = pos - last_space_pos;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
269 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
270 pos++;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
271 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
272 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
273
120
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
274 static const char *pgn_date(GameState *gamestate) {
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
275 static char date[16];
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
276 time_t dateseconds;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
277 if (gamestate->movecount == 0) {
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
278 struct timeval curtimestamp;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
279 gettimeofday(&curtimestamp, NULL);
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
280 dateseconds = curtimestamp.tv_sec;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
281 } else {
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
282 dateseconds = (time_t) gamestate->moves[0].timestamp.tv_sec;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
283 }
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
284 struct tm *tm = gmtime(&dateseconds);
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
285 if (tm == NULL) {
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
286 /* fallback - should never happen in reality */
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
287 strncpy(date, "????.??.??", sizeof(date));
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
288 } else {
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
289 int year = tm->tm_year + 1900;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
290 int month = tm->tm_mon + 1;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
291 int day = tm->tm_mday;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
292 #ifdef __GNUC__
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
293 /* this is required to tell GCC that it does not need to warn
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
294 * about the small buffer size of the date string.
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
295 */
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
296 if (year < 1900 || year > 9999) __builtin_unreachable();
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
297 if (month < 1 || month > 12) __builtin_unreachable();
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
298 if (day < 1 || day > 31) __builtin_unreachable();
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
299 #endif
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
300 snprintf(date, sizeof(date), "%04d.%02d.%02d",
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
301 year, month, day);
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
302 }
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
303 return date;
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
304 }
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
305
127
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
306 const char *pgn_player_name(GameState *gamestate, uint8_t color) {
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
307 const char *name = color == WHITE ? gamestate->wname : gamestate->bname;
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
308 return name[0] != '\0' ? name : "Anonymous";
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
309 }
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
310
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 127
diff changeset
311 void write_pgn(FILE* stream, GameState *gamestate, bool export_comments) {
120
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
312 /* STR tag pairs */
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
313 fprintf(stream, "[Event \"%s\"]\n", "terminal-chess game");
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
314 fprintf(stream, "[Site \"%s\"]\n", "Somewhere on Earth");
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
315 fprintf(stream, "[Date \"%s\"]\n", pgn_date(gamestate));
57577c9af5d3 add remaining missing STR tags to PGN exports
Mike Becker <universe@uap-core.de>
parents: 118
diff changeset
316 fprintf(stream, "[Round \"%s\"]\n", "-");
127
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
317 fprintf(stream, "[White \"%s\"]\n", pgn_player_name(gamestate, WHITE));
7258a46bf5ae ask for player names during PGN export
Mike Becker <universe@uap-core.de>
parents: 126
diff changeset
318 fprintf(stream, "[Black \"%s\"]\n", pgn_player_name(gamestate, BLACK));
102
463c648e6a9b change return type of write_pgn to void
Mike Becker <universe@uap-core.de>
parents: 101
diff changeset
319
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
320 char *result;
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
321 if (gamestate->stalemate || gamestate->remis) {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
322 result = "1/2-1/2";
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
323 } else if (gamestate->wresign) {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
324 result = "0-1";
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
325 } else if (gamestate->bresign) {
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
326 result = "1-0";
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
327 } else if (gamestate->checkmate) {
133
c58ae152733e simplify FEN generation and add current_color() function to rules
Mike Becker <universe@uap-core.de>
parents: 132
diff changeset
328 if (current_color(gamestate) == BLACK) {
c58ae152733e simplify FEN generation and add current_color() function to rules
Mike Becker <universe@uap-core.de>
parents: 132
diff changeset
329 result = "1-0";
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
330 } else {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
331 result = "0-1";
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
332 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
333 } else {
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
334 result = "*";
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
335 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
336 fprintf(stream, "[Result \"%s\"]\n\n", result);
126
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
337
d58b2abdd330 fix wrong game state when the waiting player resigns
Mike Becker <universe@uap-core.de>
parents: 121
diff changeset
338 // TODO: add optional clock info
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
339
64
4eda5df55f86 fixes castling not printed correctly to PGN
Mike Becker <universe@uap-core.de>
parents: 60
diff changeset
340 /* moves */
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
341 size_t moveblkcap = 4096;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
342 char *moveblk = malloc(moveblkcap);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
343 char *moveblkptr = moveblk;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
344 if (moveblk == NULL) {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
345 // TODO: error handling (for the entire function actually)
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
346 abort();
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
347 }
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 88
diff changeset
348 for (unsigned i = 0 ; i < gamestate->movecount ; i++) {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
349 /* reallocate move block buffer if needed */
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
350 {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
351 size_t moveblksize = moveblkptr - moveblk;
121
53f714ac783d fix critical OOM bug in PGN export
Mike Becker <universe@uap-core.de>
parents: 120
diff changeset
352 if (moveblksize + 128 > moveblkcap) {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
353 moveblkcap *= 2;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
354 char *newmoveblk = realloc(moveblk, moveblkcap);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
355 if (newmoveblk == NULL) {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
356 free(moveblk);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
357 abort();
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
358 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
359 moveblk = newmoveblk;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
360 moveblkptr = moveblk + moveblksize;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
361 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
362 }
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
363
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
364 int snpr; /* return value of printf calls */
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
365
98
9cb41383540f change move list from linked list to array (prepares game replays)
Mike Becker <universe@uap-core.de>
parents: 88
diff changeset
366 if (i % 2 == 0) {
118
0f2ffbc408ce prettier line breaking in exported PGNs
Mike Becker <universe@uap-core.de>
parents: 117
diff changeset
367 snpr = snprintf(moveblkptr, 16, "%d.\x1f%s",
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
368 1+i/2, gamestate->moves[i].string);
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
369 } else {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
370 snpr = snprintf(moveblkptr, 16, "%s",
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
371 gamestate->moves[i].string);
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
372 }
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
373 moveblkptr += snpr;
101
d4f19182fdc2 add clock times to PGN output
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
374
117
ee539a9691f0 add prompt whether PGN should be exported with comments
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
375 if (!export_comments) {
ee539a9691f0 add prompt whether PGN should be exported with comments
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
376 *(moveblkptr++) = ' ';
ee539a9691f0 add prompt whether PGN should be exported with comments
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
377 continue;
ee539a9691f0 add prompt whether PGN should be exported with comments
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
378 }
ee539a9691f0 add prompt whether PGN should be exported with comments
Mike Becker <universe@uap-core.de>
parents: 107
diff changeset
379
101
d4f19182fdc2 add clock times to PGN output
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
380 /* add clock times when the game was under time control */
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 127
diff changeset
381 if (gamestate->info.timecontrol) {
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
382 memcpy(moveblkptr, " {[%clk ", 8);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
383 moveblkptr += 8;
101
d4f19182fdc2 add clock times to PGN output
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
384 unsigned clkmv = i + 2; /* time for the next move! */
130
3fc6b1d6cbe9 implement optional delay - resolves #820
Mike Becker <universe@uap-core.de>
parents: 127
diff changeset
385 uint16_t clk = remaining_movetime2(gamestate, clkmv);
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
386 snpr = print_clk(clk, moveblkptr, true);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
387 moveblkptr += snpr;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
388 *(moveblkptr++) = ']';
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
389 *(moveblkptr++) = '}';
106
bdc9528d3e2b add elapsed move time commands to PGN exports
Mike Becker <universe@uap-core.de>
parents: 102
diff changeset
390
bdc9528d3e2b add elapsed move time commands to PGN exports
Mike Becker <universe@uap-core.de>
parents: 102
diff changeset
391 /* elapsed move time */
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
392 memcpy(moveblkptr, " {[%emt ", 8);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
393 moveblkptr += 8;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
394 uint16_t emt = gamestate->moves[i].movetime.tv_sec;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
395 snpr = print_clk(emt, moveblkptr, true);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
396 moveblkptr += snpr;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
397 *(moveblkptr++) = ']';
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
398 *(moveblkptr++) = '}';
101
d4f19182fdc2 add clock times to PGN output
Mike Becker <universe@uap-core.de>
parents: 98
diff changeset
399 }
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
400
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
401 *(moveblkptr++) = ' ';
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
402 }
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
403
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
404 if (result[0] != '*') {
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
405 size_t rlen = strlen(result);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
406 memcpy(moveblkptr, result, rlen);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
407 moveblkptr += rlen;
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
408 }
107
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
409 *(moveblkptr++) = '\n';
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
410 *moveblkptr = 0;
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
411
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
412 pgn_insert_newlines(moveblk);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
413 fputs(moveblk, stream);
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
414
36dd94278142 fix that PGN (with comments) can exceed 80 chars
Mike Becker <universe@uap-core.de>
parents: 106
diff changeset
415 free(moveblk);
50
41017d0a72c5 added pgn parser and writer (without comment support yet) + minor refactorings
Mike Becker <universe@uap-core.de>
parents:
diff changeset
416 }

mercurial