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