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