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