Make piece-type testable by bitmask
[gnushogi.git] / gnushogi / init.c
1 /*
2  * FILE: init.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
33 #include "gnushogi.h"
34
35 #if defined HAVE_GETTIMEOFDAY
36 #include <sys/time.h>
37 #endif
38
39 #include <signal.h>
40
41 #include "pattern.h"
42
43 /****************************************
44  *     A variety of global flags.
45  ****************************************/
46
47 /*
48  * If hard_time_limit is nonzero, exceeding the time limit means
49  * losing the game.
50  */
51
52 short hard_time_limit = 1;
53 #ifdef LIST_ON_EXIT
54 short nolist          = 0;  /* List the game after exit. */
55 #else
56 short nolist          = 1;  /* Don't list the game after exit. */
57 #endif
58
59 /*
60  * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
61  * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
62  */
63
64 display_t display_type = DISPLAY_X;
65
66 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
67
68 #ifdef SAVE_NEXTPOS
69 const small_short psweep[NO_PTYPE_PIECES] =
70 {
71     false, true, false, false, false, true, true, true, true, false,
72     false, true, false, false, false
73 };
74 #endif
75
76 const small_short sweep[NO_PIECES] =
77 {
78     false, false,
79 #ifndef MINISHOGI
80     true, false,
81 #endif
82     false, false, true, true,
83     false,
84 #ifndef MINISHOGI
85     false, false,
86 #endif
87     false, true, true, false
88 };
89
90 const int typeMask[NO_PIECES] =
91 {
92     0, T_PAWN,
93 #ifndef MINISHOGI
94     T_LANCE, T_KNIGHT,
95 #endif
96     T_SILVER, T_GOLD, T_BISHOP, T_ROOK,
97     T_PPAWN,
98 #ifndef MINISHOGI
99     T_PLANCE, T_PKNIGHT,
100 #endif
101     T_PSILVER, T_PBISHOP, T_PROOK, T_KING
102 };
103
104
105 #ifdef SAVE_DISTDATA
106 short
107 distance(short a, short b)
108 {
109     return (short)computed_distance(a, b);
110 }
111 #else
112 short
113 distance(short a, short b)
114 {
115     return (use_distdata
116             ? (short)(*distdata)[(int)a][(int)b]
117             : (short)computed_distance(a, b));
118 }
119 #endif
120
121
122 void
123 Initialize_dist(void)
124 {
125     short a, b, d, di, ptyp;
126 #ifndef SAVE_DISTDATA
127     for (a = 0; a < NO_SQUARES; a++)
128     {
129         for (b = 0; b < NO_SQUARES; b++)
130         {
131             d = abs(column(a) - column(b));
132             di = abs(row(a) - row(b));
133             (*distdata)[a][b] = (small_short)((d > di) ? d : di);
134         }
135     }
136 #endif
137 #ifndef SAVE_PTYPE_DISTDATA
138     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
139     {
140         for (a = 0; a < NO_SQUARES; a++)
141             for (b = 0; b < NO_SQUARES; b++)
142                 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
143     }
144 #endif
145 }
146
147
148 /*
149  * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
150  * of positions reachable from from-square in ppos with ptype such that the
151  * sequence
152  *
153  *     ppos = nextpos[ptype][from-square];
154  *     pdir = nextdir[ptype][from-square];
155  *     u = ppos[sq];
156  *
157  *     do
158  *     {
159  *         u = ppos[u];
160  *
161  *         if(color[u] != neutral)
162  *             u = pdir[u];
163  *     }
164  *     while (sq != u);
165  *
166  * will generate the sequence of all squares reachable from sq.
167  *
168  * If the path is blocked u = pdir[sq] will generate the continuation of the
169  * sequence in other directions.
170  */
171
172
173 const small_short is_promoted[NO_PIECES] =
174 {
175     false, false,
176 #ifndef MINISHOGI
177     false, false,
178 #endif
179     false, false, false, false,
180     true,
181 #ifndef MINISHOGI
182     true, true,
183 #endif
184     true, true, true, false
185 };
186
187 /* data used to generate nextpos/nextdir */
188 #ifndef MINISHOGI
189 /* FIXME: use predefined constants ! */
190 #if !defined SAVE_NEXTPOS
191 static
192 #endif
193 const small_short direc[NO_PTYPE_PIECES][8] =
194 {
195     {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  0 ptype_pawn    */
196     {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  1 ptype_lance   */
197     {  21,  23,   0,   0,   0,   0,   0,   0 },   /*  2 ptype_knight  */
198     {  10,  11,  12, -12, -10,   0,   0,   0 },   /*  3 ptype_silver  */
199     {  10,  11,  12,  -1,   1, -11,   0,   0 },   /*  4 ptype_gold    */
200     {  10,  12, -12, -10,   0,   0,   0,   0 },   /*  5 ptype_bishop  */
201     {  11,  -1,   1, -11,   0,   0,   0,   0 },   /*  6 ptype_rook    */
202     {  10,  12, -12, -10,  11,  -1,   1, -11 },   /*  7 ptype_pbishop */
203     {  11,  -1,   1, -11,  10,  12, -12, -10 },   /*  8 ptype_prook   */
204     {  10,  11,  12,  -1,   1, -12, -11, -10 },   /*  9 ptype_king    */
205     { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 10 ptype_wpawn   */
206     { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 11 ptype_wlance  */
207     { -21, -23,   0,   0,   0,   0,   0,   0 },   /* 12 ptype_wknight */
208     { -10, -11, -12,  12,  10,   0,   0,   0 },   /* 13 ptype_wsilver */
209     { -10, -11, -12,   1,  -1,  11,   0,   0 }    /* 14 ptype_wgold */
210 };
211 #else
212 #if !defined SAVE_NEXTPOS
213 static
214 #endif
215 const small_short direc[NO_PTYPE_PIECES][8] =
216 {
217     {   7,   0,   0,   0,   0,   0,   0,   0 },   /*  0 ptype_pawn    */
218     {   6,   7,   8,  -8,  -6,   0,   0,   0 },   /*  3 ptype_silver  */
219     {   6,   7,   8,  -1,   1,  -7,   0,   0 },   /*  4 ptype_gold    */
220     {   6,   8,  -8,  -6,   0,   0,   0,   0 },   /*  5 ptype_bishop  */
221     {   7,  -1,   1,  -7,   0,   0,   0,   0 },   /*  6 ptype_rook    */
222     {   6,   8,  -8,  -6,   7,  -1,   1,  -7 },   /*  7 ptype_pbishop */
223     {   7,  -1,   1,  -7,   6,   8,  -8,  -6 },   /*  8 ptype_prook   */
224     {   6,   7,   8,  -1,   1,  -8,  -7,  -6 },   /*  9 ptype_king    */
225     {  -7,   0,   0,   0,   0,   0,   0,   0 },   /* 10 ptype_wpawn   */
226     {  -6,  -7,  -8,   8,   6,   0,   0,   0 },   /* 13 ptype_wsilver */
227     {  -6,  -7,  -8,   1,  -1,   7,   0,   0 }    /* 14 ptype_wgold */
228 };
229 #endif
230
231
232 small_short diagonal(short d)
233 {
234   return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
235 }
236
237
238 #ifndef MINISHOGI
239 /* FIXME */
240 static const small_short max_steps[NO_PTYPE_PIECES] =
241 {
242     1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
243 };
244 #else
245 static const small_short max_steps[NO_PTYPE_PIECES] =
246 {
247     1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
248 };
249 #endif
250
251 #ifndef MINISHOGI
252 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
253 {
254     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
255     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
256     -1,  0,  1,  2,  3,  4,  5,  6,  7,  8, -1,
257     -1,  9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
258     -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
259     -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
260     -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
261     -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
262     -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
263     -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
264     -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
265     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
266     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
267 };
268
269
270 const small_short inunmap[NO_SQUARES] =
271 {
272      23,  24,  25,  26,  27,  28,  29,  30,  31,
273      34,  35,  36,  37,  38,  39,  40,  41,  42,
274      45,  46,  47,  48,  49,  50,  51,  52,  53,
275      56,  57,  58,  59,  60,  61,  62,  63,  64,
276      67,  68,  69,  70,  71,  72,  73,  74,  75,
277      78,  79,  80,  81,  82,  83,  84,  85,  86,
278      89,  90,  91,  92,  93,  94,  95,  96,  97,
279     100, 101, 102, 103, 104, 105, 106, 107, 108,
280     111, 112, 113, 114, 115, 116, 117, 118, 119
281 };
282 #else
283 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
284 {
285     -1, -1, -1, -1, -1, -1, -1,
286     -1,  0,  1,  2,  3,  4, -1,
287     -1,  5,  6,  7,  8,  9, -1,
288     -1, 10, 11, 12, 13, 14, -1,
289     -1, 15, 16, 17, 18, 19, -1,
290     -1, 20, 21, 22, 23, 24, -1,
291     -1, -1, -1, -1, -1, -1, -1,
292 };
293
294
295 const small_short inunmap[NO_SQUARES] =
296 {
297       8,   9,  10,  11,  12,
298      15,  16,  17,  18,  19,
299      22,  23,  24,  25,  26,
300      29,  30,  31,  32,  33,
301      36,  37,  38,  39,  40,
302 };
303 #endif
304
305 int InitFlag = false;
306
307
308 #if defined SAVE_NEXTPOS
309
310 short
311 next_direction(short ptyp, short *d, short sq)
312 {
313     short delta, to, sfrom = inunmap[sq];
314
315     do
316     {
317         (*d)++;
318         if (*d >= 8)
319             return sq;
320
321         delta = direc[ptyp][*d];
322         if (delta == 0)
323             return sq;
324
325         to = nunmap[sfrom + delta];
326     }
327     while (to < 0);
328
329     return to;
330 }
331
332
333 short
334 next_position(short ptyp, short *d, short sq, short u)
335 {
336     if (*d < 4 && psweep[ptyp])
337     {
338         short to = nunmap[inunmap[u] + direc[ptyp][*d]];
339
340         if (to < 0)
341             return next_direction(ptyp, d, sq);
342         else
343             return to;
344     }
345     else
346     {
347         return next_direction(ptyp, d, sq);
348     }
349 }
350
351
352 short
353 first_direction(short ptyp, short *d, short sq)
354 {
355     *d = -1;
356     return next_direction(ptyp, d, sq);
357 }
358
359 #else
360
361 /*
362  * This procedure pre-calculates all moves for every piece from every
363  * square.  This data is stored in nextpos/nextdir and used later in the
364  * move generation routines.
365  */
366
367 void
368 Initialize_moves(void)
369 {
370     short ptyp, po, p0, d, di, s, delta;
371     unsigned char *ppos, *pdir;
372     short dest[8][9];
373     short sorted[9];
374     short steps[8];
375     short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
376
377     /* pre-fill nextpos and nextdir with source position, probably so
378      * (color[u] == neutral) stops to match once all moves have been seen
379      */
380     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
381     {
382         for (po = 0; po < NO_SQUARES; po++)
383         {
384             for (p0 = 0; p0 < NO_SQUARES; p0++)
385             {
386                 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
387                 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
388             }
389         }
390     }
391
392     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
393     {
394         for (po = fpo; po < tpo; po++)
395         {
396             if (nunmap[po] >= (small_short)0)
397             {
398                 ppos = (*nextpos[ptyp])[nunmap[po]];
399                 pdir = (*nextdir[ptyp])[nunmap[po]];
400
401                 /* dest is a function of direction and steps */
402                 for (d = 0; d < 8; d++)
403                 {
404                     dest[d][0] = nunmap[po];
405                     delta = direc[ptyp][d];
406
407                     if (delta != 0)
408                     {
409                         p0 = po;
410
411                         for (s = 0; s < max_steps[ptyp]; s++)
412                         {
413                             p0 = p0 + delta;
414
415                             /*
416                              * break if (off board) or (promoted rooks
417                              * wishes to move two steps diagonal) or
418                              * (promoted bishops wishes to move two steps
419                              * non-diagonal)
420                              */
421                             if ((nunmap[p0] < (small_short)0)
422                                 || ((ptyp == ptype_prook)
423                                     && (s > 0)
424                                     && diagonal(delta))
425                                 || ((ptyp == ptype_pbishop)
426                                     && (s > 0)
427                                     && !diagonal(delta)))
428                                 break;
429                             else
430                                 dest[d][s] = nunmap[p0];
431                         }
432                     }
433                     else
434                     {
435                         s = 0;
436                     }
437
438                     /*
439                      * Sort dest in number of steps order; currently no sort
440                      * is done due to compatibility with the move generation
441                      * order in old gnuchess.
442                      */
443
444                     steps[d] = s;
445
446                     for (di = d; s > 0 && di > 0; di--)
447                     {
448                         if (steps[sorted[di - 1]] == 0) /* should be: < s */
449                             sorted[di] = sorted[di - 1];
450                         else
451                             break;
452                     }
453
454                     sorted[di] = d;
455                 }
456
457                 /*
458                  * update nextpos/nextdir
459                  */
460
461                 p0 = nunmap[po];
462                 pdir[p0] = (unsigned char)dest[sorted[0]][0];
463
464                 for (d = 0; d < 8; d++)
465                 {
466                     for (s = 0; s < steps[sorted[d]]; s++)
467                     {
468                         ppos[p0] = (unsigned char)dest[sorted[d]][s];
469                         p0 = dest[sorted[d]][s];
470
471                         if (d < 7)
472                             pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
473
474                         /*
475                          * else is already initialized
476                          */
477                     }
478                 }
479             }
480         }
481     }
482 }
483
484 #endif
485
486
487
488 /*
489  * Reset the board and other variables to start a new game.
490  */
491
492 void
493 NewGame(void)
494 {
495     short l, c, p, max_opening_sequence;
496 #ifdef HAVE_GETTIMEOFDAY
497     struct timeval tv;
498 #endif
499     compptr = oppptr = 0;
500     stage = 0;
501     stage2 = -1;    /* the game is not yet started */
502     flag.illegal = flag.mate = flag.quit
503         = flag.reverse = flag.bothsides = flag.onemove = flag.force
504         = false;
505     flag.post &= xboard; /* xboard: do not alter post status on 'new' */
506     flag.material = flag.coords = flag.hash = flag.easy
507         = flag.beep = flag.rcptr
508         = true;
509     flag.stars  = flag.shade = flag.back = flag.musttimeout = false;
510     flag.gamein = false;
511     flag.rv     = true;
512
513     mycnt1 = mycnt2 = 0;
514     GenCnt = NodeCnt = et0 = dither =  XCmore = 0;
515     znodes = ZNODES;
516     WAwindow = WAWNDW;
517     WBwindow = WBWNDW;
518     BAwindow = BAWNDW;
519     BBwindow = BBWNDW;
520     xwndw = BXWNDW;
521
522     if (!MaxSearchDepth)
523         MaxSearchDepth = MAXDEPTH - 1;
524
525     contempt = 0;
526     GameCnt = 0;
527     Game50 = 1;
528     CptrFlag[0] = TesujiFlag[0] = false;
529     hint = OPENING_HINT;
530     ZeroRPT();
531     GameType[0] = GameType[1] = UNKNOWN;
532     Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
533     opponent = player = black;
534     computer = white;
535
536     for (l = 0; l < TREE; l++)
537         Tree[l].f = Tree[l].t = 0;
538
539     gsrand((unsigned int) 1);
540
541     if (!InitFlag)
542     {
543         for (c = black; c <= white; c++)
544         {
545             for (p = pawn; p <= king; p++)
546             {
547                 for (l = 0; l < NO_SQUARES; l++)
548                 {
549                     (*hashcode)[c][p][l].key
550                          = (((unsigned long) urand()));
551                     (*hashcode)[c][p][l].key
552                         += (((unsigned long) urand()) << 16);
553                     (*hashcode)[c][p][l].bd
554                          = (((unsigned long) urand()));
555                     (*hashcode)[c][p][l].bd
556                         += (((unsigned long) urand()) << 16);
557 #if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
558                     (*hashcode)[c][p][l].key
559                         += (((unsigned long) urand()) << 32);
560                     (*hashcode)[c][p][l].key
561                         += (((unsigned long) urand()) << 48);
562                     (*hashcode)[c][p][l].bd
563                         += (((unsigned long) urand()) << 32);
564                     (*hashcode)[c][p][l].bd
565                         += (((unsigned long) urand()) << 48);
566 #endif
567                 }
568             }
569         }
570
571         for (c = black; c <= white; c++)
572         {
573             for (p = pawn; p <= king; p++)
574             {
575                 for (l = 0; l < MAX_CAPTURED; l++)
576                 {
577                     (*drop_hashcode)[c][p][l].key
578                          = (((unsigned long) urand()));
579                     (*drop_hashcode)[c][p][l].key
580                         += (((unsigned long) urand()) << 16);
581                     (*drop_hashcode)[c][p][l].bd
582                          = (((unsigned long) urand()));
583                     (*drop_hashcode)[c][p][l].bd
584                         += (((unsigned long) urand()) << 16);
585 #if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
586                     (*drop_hashcode)[c][p][l].key
587                         += (((unsigned long) urand()) << 32);
588                     (*drop_hashcode)[c][p][l].key
589                         += (((unsigned long) urand()) << 48);
590                     (*drop_hashcode)[c][p][l].bd
591                         += (((unsigned long) urand()) << 32);
592                     (*drop_hashcode)[c][p][l].bd
593                         += (((unsigned long) urand()) << 48);
594 #endif
595                 }
596             }
597         }
598     }
599
600     for (l = 0; l < NO_SQUARES; l++)
601     {
602         board[l] = Stboard[l];
603         color[l] = Stcolor[l];
604         Mvboard[l] = 0;
605     }
606
607     ClearCaptured();
608     dsp->ClearScreen();
609     InitializeStats();
610
611 #ifdef HAVE_GETTIMEOFDAY
612     gettimeofday(&tv, NULL);
613     time0 = tv.tv_sec*100 + tv.tv_usec/10000;
614 #else
615     time0 = time((long *) 0);
616 #endif
617
618     /* resetting reference time */
619     ElapsedTime(COMPUTE_AND_INIT_MODE);
620     flag.regularstart = true;
621     Book = BOOKFAIL;
622
623     if (!InitFlag)
624     {
625         char sx[256];
626         strcpy(sx, "level");
627
628         if (TCflag)
629             SetTimeControl();
630         else if (MaxResponseTime == 0)
631             dsp->SelectLevel(sx);
632
633         dsp->UpdateDisplay(0, 0, 1, 0);
634         GetOpenings();
635         GetOpeningPatterns(&max_opening_sequence);
636
637         InitFlag = true;
638     }
639
640 #if ttblsz
641     if (TTadd)
642     {
643         ZeroTTable();
644         TTadd = 0;
645     }
646 #endif /* ttblsz */
647
648     hashbd = hashkey = 0;
649     return;
650 }
651
652
653
654
655 int
656 InitMain(void)
657 {
658     gsrand(starttime = ((unsigned int)time((long *)0)));    /* init urand */
659
660 #if ttblsz
661     ttblsize = ttblsz;
662     rehash = -1;
663 #endif /* ttblsz */
664
665     if (Initialize_data() != 0)
666         return 1;
667
668     strcpy(ColorStr[0], "Black");
669     strcpy(ColorStr[1], "White");
670
671     XC = 0;
672     MaxResponseTime = 0;
673
674     if (XSHOGI)
675     {
676         TCmoves      = 40;
677         TCminutes    = 5;
678         TCseconds    = 0;
679         TCadd        = 0;
680
681         TCflag       = true;
682         OperatorTime = 0;
683     }
684     else
685     {
686         TCflag       = false;
687         OperatorTime = 0;
688     }
689
690     dsp->Initialize();
691     Initialize_dist();
692     Initialize_eval();
693 #if !defined SAVE_NEXTPOS
694     Initialize_moves();
695 #endif
696
697     NewGame();
698
699     flag.easy = ahead;
700     flag.hash = hash;
701
702     if (xwin)
703         xwndw = atoi(xwin);
704
705 #ifdef HASHFILE
706     hashfile = NULL;
707 #endif
708
709 #if ttblsz
710 #ifdef HASHFILE
711     hashfile = fopen(HASHFILE, RWA_ACC);
712
713     if (hashfile)
714     {
715         fseek(hashfile, 0L, SEEK_END);
716         filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
717         hashmask = filesz >> 1;
718         hashbase = hashmask + 1;
719     }
720 #endif /* HASHFILE */
721 #endif /* ttblsz */
722
723     savefile[0] = '\0';
724     listfile[0] = '\0';
725
726     return 0;
727 }
728
729
730 void
731 ExitMain(void)
732 {
733 #if ttblsz
734 #ifdef HASHFILE
735     if (hashfile)
736         fclose(hashfile);
737 #endif /* HASHFILE */
738 #endif /* ttblsz */
739
740     dsp->ExitShogi();
741 }
742