XBoard: deal with semantic differences in "post" between xboard and xshogi protocols
[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.quit
489         = flag.reverse = flag.bothsides = flag.onemove = flag.force
490         = false;
491     flag.post &= xboard; /* xboard: do not alter post status on 'new' */
492     flag.material = flag.coords = flag.hash = flag.easy
493         = flag.beep = flag.rcptr
494         = true;
495     flag.stars  = flag.shade = flag.back = flag.musttimeout = false;
496     flag.gamein = false;
497     flag.rv     = true;
498
499     mycnt1 = mycnt2 = 0;
500     GenCnt = NodeCnt = et0 = dither =  XCmore = 0;
501     znodes = ZNODES;
502     WAwindow = WAWNDW;
503     WBwindow = WBWNDW;
504     BAwindow = BAWNDW;
505     BBwindow = BBWNDW;
506     xwndw = BXWNDW;
507
508     if (!MaxSearchDepth)
509         MaxSearchDepth = MAXDEPTH - 1;
510
511     contempt = 0;
512     GameCnt = 0;
513     Game50 = 1;
514     CptrFlag[0] = TesujiFlag[0] = false;
515     hint = OPENING_HINT;
516     ZeroRPT();
517     GameType[0] = GameType[1] = UNKNOWN;
518     Pscore[0] = Tscore[0] = (SCORE_LIMIT + 3000);
519     opponent = player = black;
520     computer = white;
521
522     for (l = 0; l < TREE; l++)
523         Tree[l].f = Tree[l].t = 0;
524
525     gsrand((unsigned int) 1);
526
527     if (!InitFlag)
528     {
529         for (c = black; c <= white; c++)
530         {
531             for (p = pawn; p <= king; p++)
532             {
533                 for (l = 0; l < NO_SQUARES; l++)
534                 {
535                     (*hashcode)[c][p][l].key
536                          = (((unsigned long) urand()));
537                     (*hashcode)[c][p][l].key
538                         += (((unsigned long) urand()) << 16);
539                     (*hashcode)[c][p][l].bd
540                          = (((unsigned long) urand()));
541                     (*hashcode)[c][p][l].bd
542                         += (((unsigned long) urand()) << 16);
543 #if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
544                     (*hashcode)[c][p][l].key
545                         += (((unsigned long) urand()) << 32);
546                     (*hashcode)[c][p][l].key
547                         += (((unsigned long) urand()) << 48);
548                     (*hashcode)[c][p][l].bd
549                         += (((unsigned long) urand()) << 32);
550                     (*hashcode)[c][p][l].bd
551                         += (((unsigned long) urand()) << 48);
552 #endif
553                 }
554             }
555         }
556
557         for (c = black; c <= white; c++)
558         {
559             for (p = pawn; p <= king; p++)
560             {
561                 for (l = 0; l < MAX_CAPTURED; l++)
562                 {
563                     (*drop_hashcode)[c][p][l].key
564                          = (((unsigned long) urand()));
565                     (*drop_hashcode)[c][p][l].key
566                         += (((unsigned long) urand()) << 16);
567                     (*drop_hashcode)[c][p][l].bd
568                          = (((unsigned long) urand()));
569                     (*drop_hashcode)[c][p][l].bd
570                         += (((unsigned long) urand()) << 16);
571 #if SIZEOF_LONG == 8  /* 64-bit long i.e. 8 bytes */
572                     (*drop_hashcode)[c][p][l].key
573                         += (((unsigned long) urand()) << 32);
574                     (*drop_hashcode)[c][p][l].key
575                         += (((unsigned long) urand()) << 48);
576                     (*drop_hashcode)[c][p][l].bd
577                         += (((unsigned long) urand()) << 32);
578                     (*drop_hashcode)[c][p][l].bd
579                         += (((unsigned long) urand()) << 48);
580 #endif
581                 }
582             }
583         }
584     }
585
586     for (l = 0; l < NO_SQUARES; l++)
587     {
588         board[l] = Stboard[l];
589         color[l] = Stcolor[l];
590         Mvboard[l] = 0;
591     }
592
593     ClearCaptured();
594     dsp->ClearScreen();
595     InitializeStats();
596
597 #ifdef HAVE_GETTIMEOFDAY
598     gettimeofday(&tv, NULL);
599     time0 = tv.tv_sec*100 + tv.tv_usec/10000;
600 #else
601     time0 = time((long *) 0);
602 #endif
603
604     /* resetting reference time */
605     ElapsedTime(COMPUTE_AND_INIT_MODE);
606     flag.regularstart = true;
607     Book = BOOKFAIL;
608
609     if (!InitFlag)
610     {
611         char sx[256];
612         strcpy(sx, "level");
613
614         if (TCflag)
615             SetTimeControl();
616         else if (MaxResponseTime == 0)
617             dsp->SelectLevel(sx);
618
619         dsp->UpdateDisplay(0, 0, 1, 0);
620         GetOpenings();
621         GetOpeningPatterns(&max_opening_sequence);
622
623         InitFlag = true;
624     }
625
626 #if ttblsz
627     if (TTadd)
628     {
629         ZeroTTable();
630         TTadd = 0;
631     }
632 #endif /* ttblsz */
633
634     hashbd = hashkey = 0;
635     return;
636 }
637
638
639
640
641 int
642 InitMain(void)
643 {
644     gsrand(starttime = ((unsigned int)time((long *)0)));    /* init urand */
645
646 #if ttblsz
647     ttblsize = ttblsz;
648     rehash = -1;
649 #endif /* ttblsz */
650
651     if (Initialize_data() != 0)
652         return 1;
653
654     strcpy(ColorStr[0], "Black");
655     strcpy(ColorStr[1], "White");
656
657     XC = 0;
658     MaxResponseTime = 0;
659
660     if (XSHOGI)
661     {
662         TCmoves      = 40;
663         TCminutes    = 5;
664         TCseconds    = 0;
665         TCadd        = 0;
666
667         TCflag       = true;
668         OperatorTime = 0;
669     }
670     else
671     {
672         TCflag       = false;
673         OperatorTime = 0;
674     }
675
676     dsp->Initialize();
677     Initialize_dist();
678     Initialize_eval();
679 #if !defined SAVE_NEXTPOS
680     Initialize_moves();
681 #endif
682
683     NewGame();
684
685     flag.easy = ahead;
686     flag.hash = hash;
687
688     if (xwin)
689         xwndw = atoi(xwin);
690
691 #ifdef HASHFILE
692     hashfile = NULL;
693 #endif
694
695 #if ttblsz
696 #ifdef HASHFILE
697     hashfile = fopen(HASHFILE, RWA_ACC);
698
699     if (hashfile)
700     {
701         fseek(hashfile, 0L, SEEK_END);
702         filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
703         hashmask = filesz >> 1;
704         hashbase = hashmask + 1;
705     }
706 #endif /* HASHFILE */
707 #endif /* ttblsz */
708
709     savefile[0] = '\0';
710     listfile[0] = '\0';
711
712     return 0;
713 }
714
715
716 void
717 ExitMain(void)
718 {
719 #if ttblsz
720 #ifdef HASHFILE
721     if (hashfile)
722         fclose(hashfile);
723 #endif /* HASHFILE */
724 #endif /* ttblsz */
725
726     dsp->ExitShogi();
727 }
728