| 39 pgn_error_missing_quote = 1, |
39 pgn_error_missing_quote = 1, |
| 40 pgn_error_missing_bracket, |
40 pgn_error_missing_bracket, |
| 41 pgn_error_missing_brace, |
41 pgn_error_missing_brace, |
| 42 pgn_error_missing_dot, |
42 pgn_error_missing_dot, |
| 43 pgn_error_move_syntax, |
43 pgn_error_move_syntax, |
| 44 pgn_error_move_semantics |
44 pgn_error_move_semantics, |
| |
45 pgn_error_result_syntax, |
| 45 }; |
46 }; |
| 46 |
47 |
| 47 static const char* pgn_error_strings[] = { |
48 static const char* pgn_error_strings[] = { |
| 48 "No Error.", |
49 "No Error.", |
| 49 "Tag values must be enclosed in double-quotes.", |
50 "Tag values must be enclosed in double-quotes.", |
| 50 "Missing closing brace '}' for comment.", |
51 "Missing closing brace '}' for comment.", |
| 51 "Tags must be enclosed in square brackets: '[Key \"Value\"]'.", |
52 "Tags must be enclosed in square brackets: '[Key \"Value\"]'.", |
| 52 "Move numbers must be terminated with a dot (e.g. '13.' - not '13').", |
53 "Move numbers must be terminated with a dot (e.g. '13.' - not '13').", |
| 53 "Move is syntactically incorrect.", |
54 "Move is syntactically incorrect.", |
| 54 "Move is not valid according to chess rules." |
55 "Move is not valid according to chess rules.", |
| |
56 "Result syntax is incorrect. Expected 1-0, 0-1, 1/2-1/2, or *.", |
| 55 }; |
57 }; |
| 56 |
58 |
| 57 const char* pgn_error_str(int code) { |
59 const char* pgn_error_str(int code) { |
| 58 return pgn_error_strings[code]; |
60 return pgn_error_strings[code]; |
| 59 } |
61 } |
| 95 tagvalue[i] = '\0'; |
97 tagvalue[i] = '\0'; |
| 96 if (fgetc(stream) != ']') { |
98 if (fgetc(stream) != ']') { |
| 97 return pgn_error_missing_bracket; |
99 return pgn_error_missing_bracket; |
| 98 } |
100 } |
| 99 |
101 |
| |
102 // TODO: read clock info |
| 100 if (strcmp("Result", tagkey) == 0) { |
103 if (strcmp("Result", tagkey) == 0) { |
| |
104 // TODO: why are we parsing this? it is never used! |
| 101 memcpy(result, tagvalue, 8); |
105 memcpy(result, tagvalue, 8); |
| 102 } |
106 } |
| 103 } |
107 } |
| 104 |
108 |
| 105 /* read moves */ |
109 /* read moves */ |
| 151 if (c == EOF) { |
155 if (c == EOF) { |
| 152 break; |
156 break; |
| 153 } |
157 } |
| 154 if (c == '1' || c == '0') { |
158 if (c == '1' || c == '0') { |
| 155 c = fgetc(stream); |
159 c = fgetc(stream); |
| |
160 // TODO: #842 - allow games to be continued if possible |
| 156 if (c == '-') { |
161 if (c == '-') { |
| 157 gamestate->resign = !gamestate->checkmate; |
162 if (!gamestate->checkmate) { |
| |
163 // TODO: maybe we should not parse this here; |
| |
164 // there is an unused result string from the STR |
| |
165 c = fgetc(stream); |
| |
166 if (c == '1') { |
| |
167 gamestate->wresign = true; |
| |
168 } else if (c == '0') { |
| |
169 gamestate->bresign = true; |
| |
170 } else { |
| |
171 return pgn_error_result_syntax; |
| |
172 } |
| |
173 } |
| 158 break; |
174 break; |
| 159 } else if (c == '/') { |
175 } else if (c == '/') { |
| 160 gamestate->remis = !gamestate->stalemate; |
176 gamestate->remis = !gamestate->stalemate; |
| 161 break; |
177 break; |
| 162 } else { |
178 } else { |
| 246 fprintf(stream, "[Black \"%s\"]\n", "Anonymous"); |
262 fprintf(stream, "[Black \"%s\"]\n", "Anonymous"); |
| 247 |
263 |
| 248 char *result; |
264 char *result; |
| 249 if (gamestate->stalemate || gamestate->remis) { |
265 if (gamestate->stalemate || gamestate->remis) { |
| 250 result = "1/2-1/2"; |
266 result = "1/2-1/2"; |
| 251 } else if (gamestate->checkmate || gamestate->resign) { |
267 } else if (gamestate->wresign) { |
| |
268 result = "0-1"; |
| |
269 } else if (gamestate->bresign) { |
| |
270 result = "1-0"; |
| |
271 } else if (gamestate->checkmate) { |
| 252 if (gamestate->movecount > 0) { |
272 if (gamestate->movecount > 0) { |
| 253 result = (last_move(gamestate).piece & COLOR_MASK) == WHITE ? |
273 result = (last_move(gamestate).piece & COLOR_MASK) == WHITE ? |
| 254 "1-0" : "0-1"; |
274 "1-0" : "0-1"; |
| 255 } else { |
275 } else { |
| 256 result = "0-1"; |
276 result = "0-1"; |
| 257 } |
277 } |
| 258 } else { |
278 } else { |
| 259 result = "*"; |
279 result = "*"; |
| 260 } |
280 } |
| 261 fprintf(stream, "[Result \"%s\"]\n\n", result); |
281 fprintf(stream, "[Result \"%s\"]\n\n", result); |
| |
282 |
| |
283 // TODO: add optional clock info |
| 262 |
284 |
| 263 /* moves */ |
285 /* moves */ |
| 264 size_t moveblkcap = 4096; |
286 size_t moveblkcap = 4096; |
| 265 char *moveblk = malloc(moveblkcap); |
287 char *moveblk = malloc(moveblkcap); |
| 266 char *moveblkptr = moveblk; |
288 char *moveblkptr = moveblk; |