| 30 #include "pgn.h" |
30 #include "pgn.h" |
| 31 #include <ctype.h> |
31 #include <ctype.h> |
| 32 #include <stdlib.h> |
32 #include <stdlib.h> |
| 33 #include <string.h> |
33 #include <string.h> |
| 34 |
34 |
| |
35 enum { |
| |
36 pgn_error_missing_quote = 1, |
| |
37 pgn_error_missing_bracket, |
| |
38 pgn_error_missing_dot, |
| |
39 pgn_error_move_syntax, |
| |
40 pgn_error_move_semantics |
| |
41 }; |
| |
42 |
| |
43 static const char* pgn_error_strings[] = { |
| |
44 "No Error.", |
| |
45 "Tag values must be enclosed in double-quotes.", |
| |
46 "Tags must be enclosed in square brackets: '[Key \"Value\"]'.", |
| |
47 "Move numbers must be terminated with a dot (e.g. '13.' - not '13').", |
| |
48 "Move is syntactically incorrect.", |
| |
49 "Move is not valid according to chess rules." |
| |
50 }; |
| |
51 |
| |
52 const char* pgn_error_str(int code) { |
| |
53 return pgn_error_strings[code]; |
| |
54 } |
| |
55 |
| 35 int read_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo) { |
56 int read_pgn(FILE* stream, GameState *gamestate, GameInfo *gameinfo) { |
| 36 int c, i; |
57 int c, i; |
| 37 |
58 |
| 38 char result[8]; |
59 char result[8]; |
| 39 |
60 |
| 47 if (c == '1') { |
68 if (c == '1') { |
| 48 readmoves = 1; |
69 readmoves = 1; |
| 49 break; |
70 break; |
| 50 } |
71 } |
| 51 if (c != '[') { |
72 if (c != '[') { |
| 52 return 1; |
73 return pgn_error_missing_bracket; |
| 53 } |
74 } |
| 54 while (isspace(c = fgetc(stream))); |
75 while (isspace(c = fgetc(stream))); |
| 55 i = 0; |
76 i = 0; |
| 56 do { |
77 do { |
| 57 tagkey[i++] = c; |
78 tagkey[i++] = c; |
| 58 } while (!isspace(c = fgetc(stream))); |
79 } while (!isspace(c = fgetc(stream))); |
| 59 tagkey[i] = '\0'; |
80 tagkey[i] = '\0'; |
| 60 while (isspace(c = fgetc(stream))); |
81 while (isspace(c = fgetc(stream))); |
| 61 if (c != '"') { |
82 if (c != '"') { |
| 62 return 1; |
83 return pgn_error_missing_quote; |
| 63 } |
84 } |
| 64 i = 0; |
85 i = 0; |
| 65 while ((c = fgetc(stream)) != '"') { |
86 while ((c = fgetc(stream)) != '"') { |
| 66 if (c == '\n') { |
87 if (c == '\n' || c == EOF) { |
| 67 return 1; |
88 return pgn_error_missing_quote; |
| 68 } |
89 } |
| 69 tagvalue[i++] = c; |
90 tagvalue[i++] = c; |
| 70 } |
91 } |
| 71 tagvalue[i] = '\0'; |
92 tagvalue[i] = '\0'; |
| 72 if (fgetc(stream) != ']') { |
93 if (fgetc(stream) != ']') { |
| 73 return 1; |
94 return pgn_error_missing_bracket; |
| 74 } |
95 } |
| 75 |
96 |
| 76 if (strcmp("Result", tagkey) == 0) { |
97 if (strcmp("Result", tagkey) == 0) { |
| 77 memcpy(result, tagvalue, 8); |
98 memcpy(result, tagvalue, 8); |
| 78 } |
99 } |
| 79 } |
100 } |
| 80 |
101 |
| 81 // read moves |
102 // read moves |
| 82 if (fgetc(stream) != '.') { |
103 if (fgetc(stream) != '.') { |
| 83 return 1; |
104 return pgn_error_missing_dot; |
| 84 } |
105 } |
| 85 |
106 |
| 86 char movestr[10]; |
107 char movestr[10]; |
| 87 Move move; |
108 Move move; |
| 88 uint8_t curcol = WHITE; |
109 uint8_t curcol = WHITE; |
| 98 } |
119 } |
| 99 } while (!isspace(c = fgetc(stream))); |
120 } while (!isspace(c = fgetc(stream))); |
| 100 movestr[i] = '\0'; |
121 movestr[i] = '\0'; |
| 101 if (eval_move(gamestate, movestr, &move, curcol) |
122 if (eval_move(gamestate, movestr, &move, curcol) |
| 102 != VALID_MOVE_SYNTAX) { |
123 != VALID_MOVE_SYNTAX) { |
| 103 return 1; |
124 return pgn_error_move_syntax; |
| 104 } |
125 } |
| 105 if (validate_move(gamestate, &move) != VALID_MOVE_SEMANTICS) { |
126 if (validate_move(gamestate, &move) != VALID_MOVE_SEMANTICS) { |
| 106 return 1; |
127 return pgn_error_move_semantics; |
| 107 } |
128 } |
| 108 apply_move(gamestate, &move); |
129 apply_move(gamestate, &move); |
| 109 |
130 |
| 110 // TODO: parse comments |
131 // TODO: parse comments |
| 111 while (isspace(c = fgetc(stream))); |
132 while (isspace(c = fgetc(stream))); |