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