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