Use AM_MAINTAINER_MODE.
[gnushogi.git] / gnushogi / init-common.c
1 /*
2  * FILE: init-common.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 #include "gnushogi.h"
33 #include "pattern.h"
34
35 unsigned int ttbllimit;
36
37 /*
38  * ptype is used to separate black and white pawns, like this; ptyp =
39  * ptype[side][piece] piece can be used directly in nextpos/nextdir when
40  * generating moves for pieces that are not white pawns.
41  */
42
43 const small_short ptype[2][NO_PIECES] =
44 {
45     {
46         ptype_no_piece, ptype_pawn,
47 #ifndef MINISHOGI
48         ptype_lance,  ptype_knight,
49 #endif
50         ptype_silver,   ptype_gold,  ptype_bishop, ptype_rook,
51         ptype_gold,
52 #ifndef MINISHOGI
53         ptype_gold,  ptype_gold,
54 #endif
55         ptype_gold,
56         ptype_pbishop,  ptype_prook, ptype_king
57     },
58     {
59         ptype_no_piece, ptype_wpawn,
60 #ifndef MINISHOGI
61         ptype_wlance, ptype_wknight,
62 #endif
63         ptype_wsilver,  ptype_wgold, ptype_bishop, ptype_rook,
64         ptype_wgold,
65 #ifndef MINISHOGI
66         ptype_wgold, ptype_wgold,
67 #endif
68         ptype_wgold,
69         ptype_pbishop,  ptype_prook, ptype_king
70     },
71 };
72
73 const small_short promoted[NO_PIECES] =
74 {
75     no_piece, ppawn,
76 #ifndef MINISHOGI
77     plance, pknight,
78 #endif
79     psilver, gold, pbishop, prook,
80     ppawn,
81 #ifndef MINISHOGI
82     plance, pknight,
83 #endif
84     psilver, pbishop, prook, king
85 };
86
87 const small_short unpromoted[NO_PIECES] =
88 {
89     no_piece, pawn,
90 #ifndef MINISHOGI
91     lance, knight,
92 #endif
93     silver, gold, bishop, rook,
94     pawn,
95 #ifndef MINISHOGI
96     lance, knight,
97 #endif
98     silver, bishop, rook, king
99 };
100
101
102 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
103
104 #ifndef WIN32
105 #define max(a, b) (((a) < (b))?(b):(a))
106 #endif
107 #define odd(a) ((a) & 1)
108
109 const small_short piece_of_ptype[NO_PTYPE_PIECES] =
110 {
111     pawn,
112 #ifndef MINISHOGI
113     lance, knight,
114 #endif
115     silver, gold, bishop, rook, pbishop, prook, king,
116     pawn,
117 #ifndef MINISHOGI
118     lance, knight,
119 #endif
120     silver, gold
121 };
122
123
124 /* FIXME: all bishops and rooks are black ? */
125 const small_short side_of_ptype[NO_PTYPE_PIECES] =
126 {
127     black,
128 #ifndef MINISHOGI
129     black, black,
130 #endif
131     black, black, black, black, black, black, black,
132     white,
133 #ifndef MINISHOGI
134     white, white,
135 #endif
136     white, white
137 };
138
139
140 int
141 Initialize_data(void)
142 {
143     size_t n;
144     int i;
145     char buffer[60];
146     int doit = true;
147
148     {
149         small_short x = -1;
150
151         if (x >= 0)
152         {
153             dsp->ShowMessage("datatype 'small_short' is unsigned; "
154                         "check gnushogi.h\n");
155             return 1;
156         }
157     }
158
159     n = sizeof(struct leaf) * (size_t)TREE;
160     Tree = malloc(n);
161
162     if (!Tree)
163     {
164         sprintf(buffer, "Cannot allocate %ld bytes for search tree",
165                 (long)n);
166         dsp->ShowMessage(buffer);
167         return 1;
168     }
169
170     n = sizeof(hashcode_array);
171     hashcode = malloc(n);
172
173     if (!hashcode)
174     {
175         sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
176         dsp->ShowMessage(buffer);
177         return 1;
178     }
179
180     n = sizeof(drop_hashcode_array);
181     drop_hashcode = malloc(n);
182
183     if (!drop_hashcode)
184     {
185         sprintf(buffer,
186                 "Cannot allocate %ld bytes for drop_hashcode",
187                 (long)n);
188         dsp->ShowMessage(buffer);
189         return 1;
190     }
191
192     n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
193     GameList = malloc(n);
194
195     if (!GameList)
196     {
197         sprintf(buffer,
198                 "Cannot allocate %ld bytes for game record",
199                 (long)n);
200         dsp->ShowMessage(buffer);
201         return 1;
202     }
203
204 #if !defined SAVE_NEXTPOS
205     n = sizeof(next_array);
206
207     for (i = 0; i < NO_PTYPE_PIECES; i++)
208     {
209         nextdir[i] = use_nextpos ? malloc(n) : NULL;
210
211         if (!nextdir[i])
212         {
213             if (use_nextpos)
214             {
215                 sprintf(buffer, "cannot allocate %ld space for nextdir %d",
216                         (long)(n), i);
217                 dsp->ShowMessage(buffer);
218             }
219
220             nextdir[i] = NULL;
221             use_nextpos = false;
222         }
223
224         nextpos[i] = use_nextpos ? malloc(n) : NULL;
225
226         if (!nextpos[i])
227         {
228             if (use_nextpos)
229             {
230                 sprintf(buffer, "cannot allocate %ld space for nextpos %d",
231                         (long)(n), i);
232                 dsp->ShowMessage(buffer);
233             }
234
235             use_nextpos = false;
236         }
237     }
238
239     if (!use_nextpos)
240     {
241         return 1;
242     }
243 #endif
244
245     n = sizeof(value_array);
246     value = malloc(n);
247
248     if (!value)
249     {
250         dsp->ShowMessage("cannot allocate value space");
251         return 1;
252     }
253
254     n = sizeof(fscore_array);
255     fscore = malloc(n);
256
257     if (!fscore)
258     {
259         dsp->ShowMessage("cannot allocate fscore space");
260         return 1;
261     }
262
263 #if defined HISTORY
264     n = sizeof_history;
265     history = malloc(n);
266
267     if (!history)
268     {
269         sprintf(buffer, "Cannot allocate %ld bytes for history table",
270                 (long)sizeof_history);
271         dsp->ShowMessage(buffer);
272         use_history = false;
273     }
274 #endif
275
276 #if defined CACHE
277     n = sizeof(struct etable) * (size_t)ETABLE;
278
279     for (i = 0; i < 2; i++)
280     {
281         etab[i] = use_etable ? malloc(n) : 0;
282
283         if (!etab[i])
284         {
285             sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
286                     (long)n, (long)i);
287             dsp->ShowMessage(buffer);
288             use_etable = false;
289         }
290     }
291 #endif
292
293 #if ttblsz
294
295     if (rehash < 0)
296         rehash = MAXrehash;
297
298     n = sizeof(struct hashentry)*(ttblsize + rehash);
299
300     while (doit && ttblsize > MINTTABLE)
301     {
302         ttable[0] = malloc(n);  /* FIXME: cast to the correct type. */
303         ttable[1] = ttable[0] ? malloc(n) : NULL;
304
305         if (!ttable[0] || !ttable[1])
306         {
307             if (!ttable[0])
308                 free(ttable[0]);
309
310             if (!ttable[1])
311                 free(ttable[1]);
312
313             ttblsize = ttblsize >> 1;
314             n = sizeof(struct hashentry) * (ttblsize + rehash);
315         }
316         else
317         {
318             doit = false;
319         }
320     }
321
322     if (ttblsize <= MINTTABLE)
323     {
324         use_ttable = false;
325     }
326
327     if (use_ttable)
328     {
329         /* CHECKME: is the precedence here correct? */
330         /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
331         ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
332     }
333     else
334     {
335         sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
336                 (long)(2 * n));
337         dsp->ShowMessage(buffer);
338         ttable[0] = ttable[1] = NULL;
339     }
340 #endif /* ttblsz */
341
342 #if !defined SAVE_DISTDATA
343     n = sizeof(distdata_array);
344     distdata = malloc(n);
345
346     if (!distdata)
347     {
348         dsp->ShowMessage("cannot allocate distdata space...");
349         use_distdata = false;
350     }
351 #endif
352
353 #if !defined SAVE_PTYPE_DISTDATA
354     n = sizeof(distdata_array);
355
356     for (i = 0; i < NO_PTYPE_PIECES; i++)
357     {
358         ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
359
360         if (!ptype_distdata[i])
361         {
362             sprintf(buffer,
363                     "cannot allocate %ld bytes for ptype_distdata %d...",
364                     (long)n, i);
365             use_ptype_distdata = false;
366         }
367     }
368 #endif
369
370     return 0;
371 }
372
373
374 #ifdef SAVE_PTYPE_DISTDATA
375 short
376 piece_distance(short side, short piece, short f, short t)
377 {
378     return ((f > NO_SQUARES)
379             ? (short)1
380             : (short)ptype_distance(ptype[side][piece], f, t));
381 }
382 #else
383 short
384 piece_distance(short side, short piece, short f, short t)
385 {
386     return ((f > NO_SQUARES)
387             ? (short)1
388             : (use_ptype_distdata
389                ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
390                : (short)ptype_distance(ptype[side][piece], f, t)));
391 }
392 #endif
393
394
395 /*
396  * Determine the minimum number of moves for a piece from
397  * square "f" to square "t". If the piece cannot reach "t",
398  * the count is set to CANNOT_REACH.
399  */
400
401 #define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
402 #define crow(sq) row(csquare(sq))
403 #define ccol(sq) column(csquare(sq))
404
405 short
406 ptype_distance(short ptyp, short f, short t)
407 {
408     short side, piece;
409     short colf, colt, rowf, rowt, dcol, drow;
410
411     if (f == t)
412         return 0;
413
414     piece = piece_of_ptype[ptyp];
415     side  = side_of_ptype[ptyp];
416
417     dcol = (colt = ccol(t)) - (colf = ccol(f));
418     drow = (rowt = crow(t)) - (rowf = crow(f));
419
420     switch (piece)
421     {
422     case pawn:
423         if ((dcol != 0) || (drow < 1))
424             return CANNOT_REACH;
425         else
426             return drow;
427
428 #ifndef MINISHOGI
429     case lance:
430         if ((dcol != 0) || (drow < 1))
431             return CANNOT_REACH;
432         else
433             return 1;
434
435     case knight:
436         if (odd(drow) || (odd(drow / 2) != odd(dcol)))
437             return CANNOT_REACH;
438         else if ((drow == 0) || ((drow / 2) < abs(dcol)))
439             return CANNOT_REACH;
440         else
441             return (drow / 2);
442 #endif
443
444     case silver:
445         if (drow > 0)
446         {
447             if (odd(drow) == odd(dcol))
448             {
449                 return max(abs(drow), abs(dcol));
450             }
451             else
452             {
453                 if (abs(dcol) <= drow)
454                     return drow;
455                 else
456                     return (max(abs(drow), abs(dcol)) + 1);
457             }
458         }
459         else
460         {
461             if (odd(drow) == odd(dcol))
462                 return (max(abs(drow), abs(dcol)));
463             else
464                 return (max(abs(drow) + 1, abs(dcol)) + 1);
465         };
466
467     case gold:
468     case ppawn:
469 #ifndef MINISHOGI
470     case pknight:
471     case plance:
472 #endif
473     case psilver:
474         if (abs(dcol) == 0)
475             return (abs(drow));
476         else if (drow >= 0)
477             return max(drow, abs(dcol));
478         else
479             return (abs(dcol) - drow);
480
481     case bishop:
482         if (odd(dcol) != odd(drow))
483             return CANNOT_REACH;
484         else
485             return ((abs(dcol) == abs(drow)) ? 1 : 2);
486
487     case pbishop:
488         if (odd(dcol) != odd(drow))
489         {
490             if ((abs(dcol) <= 1) && (abs(drow) <= 1))
491                 return 1;
492             else if (abs(abs(dcol) - abs(drow)) == 1)
493                 return 2;
494             else
495                 return 3;
496         }
497         else
498         {
499             return ((abs(dcol) == abs(drow)) ? 1 : 2);
500         }
501
502     case rook:
503         if ((dcol == 0) || (drow == 0))
504             return 1;
505         else
506             return 2;
507
508     case prook:
509         if ((dcol == 0) || (drow == 0))
510             return 1;
511         else if ((abs(dcol) == 1) && (abs(drow) == 1))
512             return 1;
513         else
514             return 2;
515
516     case king:
517         return max(abs(drow), abs(dcol));
518
519     default:
520         /* should never occur */
521         return (CANNOT_REACH);
522     }
523 }