Implement XBoard memory command
[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 int
140 AllocateTT(int size)
141 {
142     int n = sizeof(struct hashentry)*(size + rehash);
143     static int oldSize;
144     int doit = true;
145
146     if(oldSize == size) return use_ttable;
147     oldSize = ttblsize = size;
148
149     if(ttable[0]) free(ttable[0]);
150     if(ttable[1]) free(ttable[1]);
151
152     while (doit && ttblsize > MINTTABLE)
153     {
154         ttable[0] = malloc(n);  /* FIXME: cast to the correct type. */
155         ttable[1] = ttable[0] ? malloc(n) : NULL;
156
157         if (!ttable[0] || !ttable[1])
158         {
159             if (!ttable[0])
160                 free(ttable[0]);
161
162             if (!ttable[1])
163                 free(ttable[1]);
164
165             ttblsize = ttblsize >> 1;
166             n = sizeof(struct hashentry) * (ttblsize + rehash);
167         }
168         else
169         {
170             doit = false;
171         }
172     }
173
174     if (ttblsize <= MINTTABLE)
175     {
176         use_ttable = false;
177     }
178
179     if (use_ttable)
180     {
181         /* CHECKME: is the precedence here correct? */
182         /* ttbllimit = ttblsize << 1 - ttblsize >> 2; */
183         ttbllimit = (ttblsize << 1) - (ttblsize >> 2);
184     }
185     else
186     {
187         ttable[0] = ttable[1] = NULL;
188     }
189
190     return use_ttable;
191 }
192
193 int
194 Initialize_data(void)
195 {
196     size_t n;
197     int i;
198     char buffer[60];
199
200     {
201         small_short x = -1;
202
203         if (x >= 0)
204         {
205             dsp->ShowMessage("datatype 'small_short' is unsigned; "
206                         "check gnushogi.h\n");
207             return 1;
208         }
209     }
210
211     n = sizeof(struct leaf) * (size_t)TREE;
212     Tree = malloc(n);
213
214     if (!Tree)
215     {
216         sprintf(buffer, "Cannot allocate %ld bytes for search tree",
217                 (long)n);
218         dsp->ShowMessage(buffer);
219         return 1;
220     }
221
222     n = sizeof(hashcode_array);
223     hashcode = malloc(n);
224
225     if (!hashcode)
226     {
227         sprintf(buffer, "Cannot allocate %ld bytes for hashcode", (long)n);
228         dsp->ShowMessage(buffer);
229         return 1;
230     }
231
232     n = sizeof(drop_hashcode_array);
233     drop_hashcode = malloc(n);
234
235     if (!drop_hashcode)
236     {
237         sprintf(buffer,
238                 "Cannot allocate %ld bytes for drop_hashcode",
239                 (long)n);
240         dsp->ShowMessage(buffer);
241         return 1;
242     }
243
244     n = sizeof(struct GameRec) * (size_t)(MAXMOVES + MAXDEPTH);
245     GameList = malloc(n);
246
247     if (!GameList)
248     {
249         sprintf(buffer,
250                 "Cannot allocate %ld bytes for game record",
251                 (long)n);
252         dsp->ShowMessage(buffer);
253         return 1;
254     }
255
256 #if !defined SAVE_NEXTPOS
257     n = sizeof(next_array);
258
259     for (i = 0; i < NO_PTYPE_PIECES; i++)
260     {
261         nextdir[i] = use_nextpos ? malloc(n) : NULL;
262
263         if (!nextdir[i])
264         {
265             if (use_nextpos)
266             {
267                 sprintf(buffer, "cannot allocate %ld space for nextdir %d",
268                         (long)(n), i);
269                 dsp->ShowMessage(buffer);
270             }
271
272             nextdir[i] = NULL;
273             use_nextpos = false;
274         }
275
276         nextpos[i] = use_nextpos ? malloc(n) : NULL;
277
278         if (!nextpos[i])
279         {
280             if (use_nextpos)
281             {
282                 sprintf(buffer, "cannot allocate %ld space for nextpos %d",
283                         (long)(n), i);
284                 dsp->ShowMessage(buffer);
285             }
286
287             use_nextpos = false;
288         }
289     }
290
291     if (!use_nextpos)
292     {
293         return 1;
294     }
295 #endif
296
297     n = sizeof(value_array);
298     value = malloc(n);
299
300     if (!value)
301     {
302         dsp->ShowMessage("cannot allocate value space");
303         return 1;
304     }
305
306     n = sizeof(fscore_array);
307     fscore = malloc(n);
308
309     if (!fscore)
310     {
311         dsp->ShowMessage("cannot allocate fscore space");
312         return 1;
313     }
314
315 #if defined HISTORY
316     n = sizeof_history;
317     history = malloc(n);
318
319     if (!history)
320     {
321         sprintf(buffer, "Cannot allocate %ld bytes for history table",
322                 (long)sizeof_history);
323         dsp->ShowMessage(buffer);
324         use_history = false;
325     }
326 #endif
327
328 #if defined CACHE
329     n = sizeof(struct etable) * (size_t)ETABLE;
330
331     for (i = 0; i < 2; i++)
332     {
333         etab[i] = use_etable ? malloc(n) : 0;
334
335         if (!etab[i])
336         {
337             sprintf(buffer, "Cannot allocate %ld bytes for cache table %ld",
338                     (long)n, (long)i);
339             dsp->ShowMessage(buffer);
340             use_etable = false;
341         }
342     }
343 #endif
344
345 #if ttblsz
346
347     if (rehash < 0)
348         rehash = MAXrehash;
349
350     if (!AllocateTT(ttblsize))
351     {
352         sprintf(buffer, "Cannot allocate %ld bytes for transposition table",
353                 (long)(2 * n));
354         dsp->ShowMessage(buffer);
355     }
356 #endif /* ttblsz */
357
358 #if !defined SAVE_DISTDATA
359     n = sizeof(distdata_array);
360     distdata = malloc(n);
361
362     if (!distdata)
363     {
364         dsp->ShowMessage("cannot allocate distdata space...");
365         use_distdata = false;
366     }
367 #endif
368
369 #if !defined SAVE_PTYPE_DISTDATA
370     n = sizeof(distdata_array);
371
372     for (i = 0; i < NO_PTYPE_PIECES; i++)
373     {
374         ptype_distdata[i] = use_ptype_distdata ? malloc(n) : 0;
375
376         if (!ptype_distdata[i])
377         {
378             sprintf(buffer,
379                     "cannot allocate %ld bytes for ptype_distdata %d...",
380                     (long)n, i);
381             use_ptype_distdata = false;
382         }
383     }
384 #endif
385
386     return 0;
387 }
388
389
390 #ifdef SAVE_PTYPE_DISTDATA
391 short
392 piece_distance(short side, short piece, short f, short t)
393 {
394     return ((f > NO_SQUARES)
395             ? (short)1
396             : (short)ptype_distance(ptype[side][piece], f, t));
397 }
398 #else
399 short
400 piece_distance(short side, short piece, short f, short t)
401 {
402     return ((f > NO_SQUARES)
403             ? (short)1
404             : (use_ptype_distdata
405                ? (short)(*ptype_distdata[ptype[side][piece]])[f][t]
406                : (short)ptype_distance(ptype[side][piece], f, t)));
407 }
408 #endif
409
410
411 /*
412  * Determine the minimum number of moves for a piece from
413  * square "f" to square "t". If the piece cannot reach "t",
414  * the count is set to CANNOT_REACH.
415  */
416
417 #define csquare(sq) ((side == black) ? sq : (NO_SQUARES - 1 - sq))
418 #define crow(sq) row(csquare(sq))
419 #define ccol(sq) column(csquare(sq))
420
421 short
422 ptype_distance(short ptyp, short f, short t)
423 {
424     short side, piece;
425     short colf, colt, rowf, rowt, dcol, drow;
426
427     if (f == t)
428         return 0;
429
430     piece = piece_of_ptype[ptyp];
431     side  = side_of_ptype[ptyp];
432
433     dcol = (colt = ccol(t)) - (colf = ccol(f));
434     drow = (rowt = crow(t)) - (rowf = crow(f));
435
436     switch (piece)
437     {
438     case pawn:
439         if ((dcol != 0) || (drow < 1))
440             return CANNOT_REACH;
441         else
442             return drow;
443
444 #ifndef MINISHOGI
445     case lance:
446         if ((dcol != 0) || (drow < 1))
447             return CANNOT_REACH;
448         else
449             return 1;
450
451     case knight:
452         if (odd(drow) || (odd(drow / 2) != odd(dcol)))
453             return CANNOT_REACH;
454         else if ((drow == 0) || ((drow / 2) < abs(dcol)))
455             return CANNOT_REACH;
456         else
457             return (drow / 2);
458 #endif
459
460     case silver:
461         if (drow > 0)
462         {
463             if (odd(drow) == odd(dcol))
464             {
465                 return max(abs(drow), abs(dcol));
466             }
467             else
468             {
469                 if (abs(dcol) <= drow)
470                     return drow;
471                 else
472                     return (max(abs(drow), abs(dcol)) + 1);
473             }
474         }
475         else
476         {
477             if (odd(drow) == odd(dcol))
478                 return (max(abs(drow), abs(dcol)));
479             else
480                 return (max(abs(drow) + 1, abs(dcol)) + 1);
481         };
482
483     case gold:
484     case ppawn:
485 #ifndef MINISHOGI
486     case pknight:
487     case plance:
488 #endif
489     case psilver:
490         if (abs(dcol) == 0)
491             return (abs(drow));
492         else if (drow >= 0)
493             return max(drow, abs(dcol));
494         else
495             return (abs(dcol) - drow);
496
497     case bishop:
498         if (odd(dcol) != odd(drow))
499             return CANNOT_REACH;
500         else
501             return ((abs(dcol) == abs(drow)) ? 1 : 2);
502
503     case pbishop:
504         if (odd(dcol) != odd(drow))
505         {
506             if ((abs(dcol) <= 1) && (abs(drow) <= 1))
507                 return 1;
508             else if (abs(abs(dcol) - abs(drow)) == 1)
509                 return 2;
510             else
511                 return 3;
512         }
513         else
514         {
515             return ((abs(dcol) == abs(drow)) ? 1 : 2);
516         }
517
518     case rook:
519         if ((dcol == 0) || (drow == 0))
520             return 1;
521         else
522             return 2;
523
524     case prook:
525         if ((dcol == 0) || (drow == 0))
526             return 1;
527         else if ((abs(dcol) == 1) && (abs(drow) == 1))
528             return 1;
529         else
530             return 2;
531
532     case king:
533         return max(abs(drow), abs(dcol));
534
535     default:
536         /* should never occur */
537         return (CANNOT_REACH);
538     }
539 }