XBoard: teach about xboard move notation.
[gnushogi.git] / gnushogi / makepattern.c
1 /*
2  * FILE: makepattern.c
3  *
4  * ----------------------------------------------------------------------
5  * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6  * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
7  * Copyright (c) 2008, 2013, 2014 Yann Dirson and the Free Software Foundation
8  *
9  * GNU SHOGI is based on GNU CHESS
10  *
11  * Copyright (c) 1988, 1989, 1990 John Stanback
12  * Copyright (c) 1992 Free Software Foundation
13  *
14  * This file is part of GNU SHOGI.
15  *
16  * GNU Shogi is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by the
18  * Free Software Foundation; either version 3 of the License,
19  * or (at your option) any later version.
20  *
21  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
22  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with GNU Shogi; see the file COPYING. If not, see
28  * <http://www.gnu.org/licenses/>.
29  * ----------------------------------------------------------------------
30  *
31  */
32
33 #include "gnushogi.h"
34 #include "pattern.h"
35
36 #define MAX_PATTERN_DATA     5000
37 #define MAX_OPENING_SEQUENCE 20
38 #define MAX_PATTERN          200
39
40 short xboard = false;
41
42 small_short pattern_data[MAX_PATTERN_DATA];
43
44 /* minimal ShowMessage to avoid dependency on extraneous display code */
45 static void
46 Dummy_ShowMessage(char *s)
47 {
48     printf("%s\n", s);
49 }
50 static struct display dummydsp = {
51   .ShowMessage = Dummy_ShowMessage,
52 };
53 struct display *dsp = &dummydsp;
54
55 #define is_digit(c) (((c) >= '0') && ((c) <= '9'))
56 #define is_alpha(c) ((((c) >= 'a') && ((c) <= 'z')) \
57     || (((c) >= 'A') && ((c) <= 'Z')))
58 #define eos(s)      ((*s == '\0') || (*s == '\n'))
59
60
61 /* skip blanks and comments in brackets */
62
63 static void
64 skipbb(char **s)
65 {
66     while ((**s == ' ') || (**s == '|') || (**s == '['))
67     {
68         if (**s == '[')
69         {
70             while (**s != ']')
71                 (*s)++;
72         }
73
74         (*s)++;
75     }
76 }
77
78
79 /* skip unsigned numbers */
80
81 static void
82 skipi(char **s)
83 {
84     while (is_digit(**s))
85         (*s)++;
86
87     skipbb(s);
88 }
89
90
91 static short
92 ScanPiece(char **s, small_short *side,
93           small_short *piece, small_short *square)
94 {
95     short isp, isw, c, r;
96
97     /* determine promotion status */
98     if (**s == '+')
99         isp = true, (*s)++;  /* FIXME: split into two lines. */
100     else
101         isp = false;
102
103     /* determine side and piece */
104     for (c = 0; c < NO_PIECES; c++)
105     {
106         if ((isw = (**s == pxx[c])) || (**s == qxx[c]))
107         {
108             *piece = isp ? promoted[c] : unpromoted[c];
109             *side  = isw;
110             (*s)++;
111             break;
112         }
113     }
114
115     if (c == NO_PIECES)
116         return 1;
117
118     if (**s == '*')
119     {
120         /* piece is captured */
121         (*s)++;
122         *square = NO_SQUARES + *piece;
123     }
124     else
125     {
126         /* determine column */
127         for (c = 0; c < NO_COLS; c++)
128         {
129             if (**s == COL_NAME(c))
130             {
131                 (*s)++;
132                 break;
133             }
134         }
135
136         if (c >= NO_COLS)
137             return 1;
138
139         /* determine row */
140         for (r = 0; r < NO_ROWS; r++)
141         {
142             if (**s == ROW_NAME(r))
143             {
144                 (*s)++;
145                 break;
146             }
147         }
148
149         if (r >= NO_ROWS)
150             return 1;
151
152         /* determine square */
153         *square = r * NO_COLS + c;
154     }
155
156     skipbb(s);
157     return 0;
158 }
159
160
161 static short
162 ScanPattern (char *s, short *pindex)
163 {
164     small_short side, piece, square;
165     skipbb(&s); /* skip blanks and comments */
166
167     while (is_digit(*s))
168     {
169         pattern_data[(*pindex)++] = atoi(s);
170         skipi(&s);
171     }
172
173     pattern_data[(*pindex)++] = END_OF_LINKS;
174     skipbb(&s);
175
176     while (!eos(s))
177     {
178         if (ScanPiece(&s, &side, &piece, &square))
179         {
180             return 1;
181         }
182         else
183         {
184             pattern_data[(*pindex)++] = piece;
185             pattern_data[(*pindex)++] = (side ? -square : square);
186         }
187
188     }
189
190     pattern_data[(*pindex)++] = END_OF_FIELDS;
191     return 0;
192 }
193
194
195 void
196 ReadOpeningSequences (short *pindex, const char* patternfile)
197 {
198     FILE *fd;
199     char s[256];
200     short max_pattern = 0;
201     short max_opening_sequence = 0;
202
203     fd = fopen (patternfile, "r");
204
205     if (fd == NULL) {
206         sprintf(s, "no pattern file '%s'", patternfile);
207         dsp->ShowMessage(s);
208         return;
209     }
210
211     *pindex = 0;
212
213     while (fgets (s, 256, fd) != NULL)
214     {
215         if (*s == '#')
216         {
217             /* comment, skip line */
218         }
219         else if (is_alpha(*s))
220         {
221             if (max_opening_sequence++ > 0)
222             {
223                 pattern_data[(*pindex)++] = END_OF_PATTERNS;
224             }
225
226             pattern_data[(*pindex)++] = ValueOfOpeningName(s);
227         }
228         else
229         {
230             if (ScanPattern(s, pindex))
231             {
232                 dsp->ShowMessage("error in pattern sequence...");
233                 exit(1);
234             }
235             else
236             {
237                 max_pattern++;
238             }
239         }
240     }
241
242     pattern_data[(*pindex)++] = END_OF_PATTERNS;
243     pattern_data[(*pindex)++] = END_OF_SEQUENCES;
244
245     sprintf(s,
246             "Pattern: %d bytes for %d sequences with %d patterns.\n",
247             *pindex, max_opening_sequence, max_pattern);
248     dsp->ShowMessage(s);
249
250     fclose(fd);
251 }
252
253
254 void
255 WriteOpeningSequences (short pindex, const char* patternincfile)
256 {
257     FILE *fd;
258     short n = 0;
259     short max_pattern = 0;
260     short max_opening_sequence = 0;
261
262     fd = fopen (patternincfile, "w");
263     fprintf(fd, "#define MAX_PATTERN_DATA %d\n\n", pindex);
264     fprintf(fd, "small_short pattern_data[MAX_PATTERN_DATA] =\n{\n");
265
266     do
267     {
268         fprintf(fd, "  %d,\n", pattern_data[n++]);
269
270         do
271         {
272             fprintf(fd, "    ");
273
274             /* write links */
275             while (pattern_data[n] != END_OF_LINKS)
276             {
277                 fprintf(fd, "%d, ", pattern_data[n++]);
278             };
279
280             fprintf(fd, "%d, ", pattern_data[n++]);
281
282             /* write pattern */
283             do
284             {
285                 fprintf(fd, "%d,", pattern_data[n++]);
286             }
287             while (pattern_data[n] != END_OF_FIELDS);
288
289             fprintf(fd, "%d,\n", pattern_data[n++]);
290             max_pattern++;
291         }
292         while (pattern_data[n] != END_OF_PATTERNS);
293
294         fprintf(fd, "    %d,\n", pattern_data[n++]);
295         max_opening_sequence++;
296     }
297     while (pattern_data[n] != END_OF_SEQUENCES);
298
299     fprintf(fd, "  %d\n}; \n", pattern_data[n++]);
300     fprintf(fd, "\n#define MAX_OPENING_SEQUENCE %d\n", max_opening_sequence);
301     fprintf(fd, "\n#define MAX_PATTERN %d\n", max_pattern);
302     fclose(fd);
303 }
304
305