6dbca38e4acab55be9b8e5d12133792457c9bda1
[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 small_short pattern_data[MAX_PATTERN_DATA];
41
42 /* minimal ShowMessage to avoid dependency on extraneous display code */
43 static void
44 Dummy_ShowMessage(char *s)
45 {
46     printf("%s\n", s);
47 }
48 static struct display dummydsp = {
49   .ShowMessage = Dummy_ShowMessage,
50 };
51 struct display *dsp = &dummydsp;
52
53 #define is_digit(c) (((c) >= '0') && ((c) <= '9'))
54 #define is_alpha(c) ((((c) >= 'a') && ((c) <= 'z')) \
55     || (((c) >= 'A') && ((c) <= 'Z')))
56 #define eos(s)      ((*s == '\0') || (*s == '\n'))
57
58
59 /* skip blanks and comments in brackets */
60
61 static void
62 skipbb(char **s)
63 {
64     while ((**s == ' ') || (**s == '|') || (**s == '['))
65     {
66         if (**s == '[')
67         {
68             while (**s != ']')
69                 (*s)++;
70         }
71
72         (*s)++;
73     }
74 }
75
76
77 /* skip unsigned numbers */
78
79 static void
80 skipi(char **s)
81 {
82     while (is_digit(**s))
83         (*s)++;
84
85     skipbb(s);
86 }
87
88
89 static short
90 ScanPiece(char **s, small_short *side,
91           small_short *piece, small_short *square)
92 {
93     short isp, isw, c, r;
94
95     /* determine promotion status */
96     if (**s == '+')
97         isp = true, (*s)++;  /* FIXME: split into two lines. */
98     else
99         isp = false;
100
101     /* determine side and piece */
102     for (c = 0; c < NO_PIECES; c++)
103     {
104         if ((isw = (**s == pxx[c])) || (**s == qxx[c]))
105         {
106             *piece = isp ? promoted[c] : unpromoted[c];
107             *side  = isw;
108             (*s)++;
109             break;
110         }
111     }
112
113     if (c == NO_PIECES)
114         return 1;
115
116     if (**s == '*')
117     {
118         /* piece is captured */
119         (*s)++;
120         *square = NO_SQUARES + *piece;
121     }
122     else
123     {
124         /* determine column */
125         for (c = 0; c < NO_COLS; c++)
126         {
127             if (**s == cxx[c])
128             {
129                 (*s)++;
130                 break;
131             }
132         }
133
134         if (c >= NO_COLS)
135             return 1;
136
137         /* determine row */
138         for (r = 0; r < NO_ROWS; r++)
139         {
140             if (**s == rxx[r])
141             {
142                 (*s)++;
143                 break;
144             }
145         }
146
147         if (r >= NO_ROWS)
148             return 1;
149
150         /* determine square */
151         *square = r * NO_COLS + c;
152     }
153
154     skipbb(s);
155     return 0;
156 }
157
158
159 static short
160 ScanPattern (char *s, short *pindex)
161 {
162     small_short side, piece, square;
163     skipbb(&s); /* skip blanks and comments */
164
165     while (is_digit(*s))
166     {
167         pattern_data[(*pindex)++] = atoi(s);
168         skipi(&s);
169     }
170
171     pattern_data[(*pindex)++] = END_OF_LINKS;
172     skipbb(&s);
173
174     while (!eos(s))
175     {
176         if (ScanPiece(&s, &side, &piece, &square))
177         {
178             return 1;
179         }
180         else
181         {
182             pattern_data[(*pindex)++] = piece;
183             pattern_data[(*pindex)++] = (side ? -square : square);
184         }
185
186     }
187
188     pattern_data[(*pindex)++] = END_OF_FIELDS;
189     return 0;
190 }
191
192
193 void
194 ReadOpeningSequences (short *pindex, const char* patternfile)
195 {
196     FILE *fd;
197     char s[256];
198     short max_pattern = 0;
199     short max_opening_sequence = 0;
200
201     fd = fopen (patternfile, "r");
202
203     if (fd == NULL) {
204         sprintf(s, "no pattern file '%s'", patternfile);
205         dsp->ShowMessage(s);
206         return;
207     }
208
209     *pindex = 0;
210
211     while (fgets (s, 256, fd) != NULL)
212     {
213         if (*s == '#')
214         {
215             /* comment, skip line */
216         }
217         else if (is_alpha(*s))
218         {
219             if (max_opening_sequence++ > 0)
220             {
221                 pattern_data[(*pindex)++] = END_OF_PATTERNS;
222             }
223
224             pattern_data[(*pindex)++] = ValueOfOpeningName(s);
225         }
226         else
227         {
228             if (ScanPattern(s, pindex))
229             {
230                 dsp->ShowMessage("error in pattern sequence...");
231                 exit(1);
232             }
233             else
234             {
235                 max_pattern++;
236             }
237         }
238     }
239
240     pattern_data[(*pindex)++] = END_OF_PATTERNS;
241     pattern_data[(*pindex)++] = END_OF_SEQUENCES;
242
243     sprintf(s,
244             "Pattern: %d bytes for %d sequences with %d patterns.\n",
245             *pindex, max_opening_sequence, max_pattern);
246     dsp->ShowMessage(s);
247
248     fclose(fd);
249 }
250
251
252 void
253 WriteOpeningSequences (short pindex, const char* patternincfile)
254 {
255     FILE *fd;
256     short n = 0;
257     short max_pattern = 0;
258     short max_opening_sequence = 0;
259
260     fd = fopen (patternincfile, "w");
261     fprintf(fd, "#define MAX_PATTERN_DATA %d\n\n", pindex);
262     fprintf(fd, "small_short pattern_data[MAX_PATTERN_DATA] =\n{\n");
263
264     do
265     {
266         fprintf(fd, "  %d,\n", pattern_data[n++]);
267
268         do
269         {
270             fprintf(fd, "    ");
271
272             /* write links */
273             while (pattern_data[n] != END_OF_LINKS)
274             {
275                 fprintf(fd, "%d, ", pattern_data[n++]);
276             };
277
278             fprintf(fd, "%d, ", pattern_data[n++]);
279
280             /* write pattern */
281             do
282             {
283                 fprintf(fd, "%d,", pattern_data[n++]);
284             }
285             while (pattern_data[n] != END_OF_FIELDS);
286
287             fprintf(fd, "%d,\n", pattern_data[n++]);
288             max_pattern++;
289         }
290         while (pattern_data[n] != END_OF_PATTERNS);
291
292         fprintf(fd, "    %d,\n", pattern_data[n++]);
293         max_opening_sequence++;
294     }
295     while (pattern_data[n] != END_OF_SEQUENCES);
296
297     fprintf(fd, "  %d\n}; \n", pattern_data[n++]);
298     fprintf(fd, "\n#define MAX_OPENING_SEQUENCE %d\n", max_opening_sequence);
299     fprintf(fd, "\n#define MAX_PATTERN %d\n", max_pattern);
300     fclose(fd);
301 }
302
303