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