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