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