1 /* pgn.cc
2
3 GNU Chess frontend
4
5 Copyright (C) 2001-2020 Free Software Foundation, Inc.
6
7 GNU Chess is based on the two research programs
8 Cobalt by Chua Kong-Sian and Gazebo by Stuart Cracraft.
9
10 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
22
23 Contact Info:
24 bug-gnu-chess@gnu.org
25 cracraft@ai.mit.edu, cracraft@stanfordalumni.org, cracraft@earthlink.net
26 */
27
28 #include <stdio.h>
29 #include <sys/time.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include <time.h>
33 #include <errno.h>
34
35 #include "common.h"
36 #include "version.h"
37 #include "lexpgn.h"
38 #include "gettext.h"
39
40 #define _(str) gettext (str)
41
42 #define NULL2EMPTY(x) ( (x) ? (x) : "")
43
44 extern FILE *yyin;
45
46 extern int yylex (void);
47
PGNSaveToFile(const char * file,const char * resultstr)48 void PGNSaveToFile (const char *file, const char *resultstr)
49 /****************************************************************************
50 *
51 * To save a game into PGN format to a file, if the file does not exist.
52 * If the file exists, it will not be written and the user will be informed.
53 *
54 ****************************************************************************/
55 {
56 FILE *fp;
57 char s[100];
58 int len;
59 char *p;
60 int i;
61 time_t secs;
62 struct tm *timestruct;
63
64 fp = fopen(file, "r");
65 if (fp) {
66 fclose(fp);
67 printf(_("File '%s' already exists. Please delete it first, or choose a different file name.\n"), file);
68 return;
69 }
70
71 fp = fopen (file, "w");
72 if (fp == NULL)
73 {
74 printf(_("Cannot write to file %s\n"), file);
75 return;
76 }
77
78 /* Write the seven tags */
79 fprintf (fp, "[Event \"%s\"]\n", NULL2EMPTY(pgn_event));
80 fprintf (fp, "[Site \"%s\"]\n", NULL2EMPTY(pgn_site));
81 secs=time(0);
82 if (pgn_date)
83 fprintf(fp,"[Date \"%s\"]\n", pgn_date);
84 else {
85 timestruct=localtime((time_t*) &secs);
86 fprintf(fp,"[Date \"%4d.%02d.%02d\"]\n",timestruct->tm_year+1900,
87 timestruct->tm_mon+1,timestruct->tm_mday);
88 }
89 fprintf (fp, "[Round \"%s\"]\n", NULL2EMPTY(pgn_round));
90
91 if (pgn_white)
92 fprintf (fp, "[White \"%s\"]\n", pgn_white);
93 else if (computer == white)
94 fprintf (fp, "[White \"%s %s\"]\n",PROGRAM,VERSION);
95 else
96 fprintf (fp, "[White \"%s\"]\n",name);
97
98 if (pgn_black)
99 fprintf (fp, "[Black \"%s\"]\n", pgn_black);
100 else if (computer == black)
101 fprintf (fp, "[Black \"%s %s\"]\n",PROGRAM,VERSION);
102 else
103 fprintf (fp, "[Black \"%s\"]\n",name);
104
105 if (pgn_whiteELO)
106 fprintf (fp, "[WhiteELO \"%s\"]\n", NULL2EMPTY(pgn_white));
107 else
108 fprintf(fp, "[WhiteELO \"%d\"]\n",computer==white?myrating:opprating);
109 if (pgn_blackELO)
110 fprintf (fp, "[BlackELO \"%s\"]\n", NULL2EMPTY(pgn_black));
111 else
112 fprintf (fp, "[BlackELO \"%d\"]\n",computer==white?opprating:myrating);
113
114 if (pgn_result)
115 fprintf (fp, "[Result \"%s\"]\n", pgn_result);
116 else {
117 /* Revive the little-known standard functions! */
118 len = strcspn(resultstr," {");
119 fprintf (fp, "[Result \"%.*s\"]\n", len, resultstr);
120 }
121
122 if (pgn_othertags) {
123 fprintf (fp, "%s", pgn_othertags);
124 }
125
126 fprintf (fp, "\n");
127
128 if (initial_comments)
129 {
130 fprintf(fp, "\n%s\n", initial_comments);
131 /* If it doesn't end in \n, add it */
132 if (initial_comments[0] &&
133 initial_comments[strlen(initial_comments)-1] != '\n')
134 fprintf(fp, "\n");
135 }
136
137 s[0] = '\0';
138 for (i = 0; i <= GameCnt; i++)
139 {
140 if (! (i % 2)) {
141 char num[6];
142 sprintf(num, "%d. ", i/2 + 1);
143 strcat(s, num);
144 }
145 strcat(s, Game[i].SANmv);
146 strcat(s, " ");
147 if (strlen (s) > 80)
148 {
149 p = s + 79;
150 while (*p-- != ' ');
151 *++p = '\0';
152 fprintf (fp, "%s\n", s);
153 strcpy (s, p+1);
154 }
155 if (Game[i].comments) {
156 fprintf (fp, "%s\n", s);
157 fprintf (fp, "%s", Game[i].comments);
158 if (Game[i].comments[0] &&
159 Game[i].comments[strlen(Game[i].comments)-1] != '\n')
160 fprintf(fp, "\n");
161 s[0] = '\0';
162 }
163 }
164 fprintf (fp, "%s", s);
165 fprintf (fp, "%s", resultstr);
166 fprintf (fp, "\n\n");
167 fclose (fp);
168
169 }
170
171
PGNReadFromFile(const char * file,int showheading)172 void PGNReadFromFile (const char *file, int showheading)
173 /****************************************************************************
174 *
175 * To read a game from a PGN file.
176 *
177 ****************************************************************************/
178 {
179 FILE *fp;
180
181 fp = fopen (file, "r");
182 if (fp == NULL)
183 {
184 printf(_("Cannot open file %s\n"), file);
185 return;
186 }
187 yyin = fp;
188
189 InitVars ();
190
191 data_dest = DEST_GAME;
192 (void) yylex();
193
194 fclose (fp);
195
196 ShowBoard ();
197
198 if ( showheading ) {
199 printf("\n--------------------------------------------------\n");
200 printf("%s (%s) x %s (%s) - %s\nSite: %s\nDate: %s\n",
201 pgn_white != NULL ? pgn_white : "Unknown", pgn_whiteELO != NULL ? pgn_whiteELO : "Unknown",
202 pgn_black != NULL ? pgn_black : "Unknown", pgn_blackELO != NULL ? pgn_blackELO : "Unknown",
203 pgn_result != NULL ? pgn_result : "Unknown", pgn_site != NULL ? pgn_site : "Unknown",
204 pgn_date != NULL ? pgn_date : "Unknown");
205 printf("--------------------------------------------------\n");
206 }
207 }
208
209 /* Only players in the table below are permitted into the opening book
210 from the PGN files. Please expand the table as needed. Generally,
211 I would recommend only acknowledged GM's and IM's and oneself, but
212 because of the self-changing nature of the book, anything inferior
213 will eventually be eliminated through automatic play as long as
214 you feed the games the program plays back to itself with "book add pgnfile"
215 */
216 /* TODO: Fix this so the list isn't hardcoded. */
217
218 static const char *const trusted_players[] = {
219 "Alekhine",
220 "Adams",
221 "Anand",
222 "Anderssen",
223 "Andersson",
224 "Aronin",
225 "Averbakh",
226 "Balashov",
227 "Beliavsky",
228 "Benko",
229 "Bernstein",
230 "Bird",
231 "Bogoljubow",
232 "Bolbochan",
233 "Boleslavsky",
234 "Byrne",
235 "Botvinnik",
236 "Bronstein",
237 "Browne",
238 "Capablanca",
239 "Chigorin",
240 "Christiansen",
241 "De Firmian",
242 "Deep Blue",
243 "Deep Thought",
244 "Donner",
245 "Dreev",
246 "Duras",
247 "Euwe",
248 "Evans",
249 "Filip",
250 "Fine",
251 "Fischer",
252 "Flohr",
253 "Furman",
254 "Gelfand",
255 "Geller",
256 "Gereben",
257 "Glek",
258 "Gligoric",
259 "GNU",
260 "Golombek",
261 "Gruenfeld",
262 "Guimard",
263 "Hodgson",
264 "Ivanchuk",
265 "Ivkov",
266 "Janowsky",
267 "Kamsky",
268 "Kan",
269 "Karpov",
270 "Kasparov",
271 "Keres",
272 "Korchnoi",
273 "Kortschnoj",
274 "Kotov",
275 "Kramnik",
276 "Kupreich",
277 "Lasker",
278 "Lautier",
279 "Letelier",
280 "Lilienthal",
281 "Ljubojevic",
282 "Marshall",
283 "Maroczy",
284 "Mieses",
285 "Miles",
286 "Morphy",
287 "Mueller", /* Every other German has this name... */
288 "Nimzowitsch",
289 "Nunn",
290 "Opocensky",
291 "Pachman",
292 "Petrosian",
293 "Piket",
294 "Pilnik",
295 "Pirc",
296 "Polgar",
297 "Portisch",
298 "Psakhis",
299 "Ragozin",
300 "Reshevsky",
301 "Reti",
302 "Romanish",
303 "Rubinstein",
304 "Saemisch",
305 "Seirawan",
306 "Shirov",
307 "Short",
308 "Silman",
309 "Smyslov",
310 "Sokolsky",
311 "Spassky",
312 "Sveshnikov",
313 "Stahlberg",
314 "Steinitz",
315 "Tal",
316 "Tarjan",
317 "Tartakower",
318 "Timman",
319 "Topalov",
320 "Torre",
321 "Vidmar"
322
323 };
324
IsTrustedPlayer(const char * name)325 int IsTrustedPlayer(const char *name)
326 /* Return 1 if name in trusted_players list, else 0 */
327 {
328 unsigned int i;
329 for (i = 0; i < (sizeof(trusted_players) / sizeof(*trusted_players));
330 i++) {
331 if (strstr(name, trusted_players[i]) != NULL)
332 return 1;
333 }
334 return 0;
335 }
336