e6b495f527aa182fbd58b15832bbefd0aa13d00a
[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  *
8  * GNU SHOGI is based on GNU CHESS
9  *
10  * Copyright (c) 1988, 1989, 1990 John Stanback
11  * Copyright (c) 1992 Free Software Foundation
12  *
13  * This file is part of GNU SHOGI.
14  *
15  * GNU Shogi is free software; you can redistribute it and/or modify it
16  * under the terms of the GNU General Public License as published by the
17  * Free Software Foundation; either version 3 of the License,
18  * or (at your option) any later version.
19  *
20  * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
23  * for more details.
24  *
25  * You should have received a copy of the GNU General Public License along
26  * with GNU Shogi; see the file COPYING. If not, see
27  * <http://www.gnu.org/licenses/>.
28  * ----------------------------------------------------------------------
29  *
30  */
31
32 #include "gnushogi.h"
33
34 #if defined HAVE_GETTIMEOFDAY
35 #include <sys/time.h>
36 #endif
37
38 #include <signal.h>
39
40 #include "pattern.h"
41
42 /****************************************
43  *     A variety of global flags.
44  ****************************************/
45
46 /*
47  * If hard_time_limit is nonzero, exceeding the time limit means
48  * losing the game.
49  */
50
51 short hard_time_limit = 1;
52 short barebones       = 0;  /* Suppress printing of statistics
53                              * (mainly for xshogi). */
54 #ifdef LIST_ON_EXIT
55 short nolist          = 0;  /* List the game after exit. */
56 #else
57 short nolist          = 1;  /* Don't list the game after exit. */
58 #endif
59
60 /*
61  * The default display type can be DISPLAY_RAW, DISPLAY_CURSES,
62  * or DISPLAY_X; the default is DISPLAY_X to make life easier for xshogi.
63  */
64
65 display_t display_type = DISPLAY_X;
66
67 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
68
69 #ifdef SAVE_NEXTPOS
70 const small_short psweep[NO_PTYPE_PIECES] =
71 {
72     false, true, false, false, false, true, true, true, true, false,
73     false, true, false, false, false
74 };
75 #endif
76
77 const small_short sweep[NO_PIECES] =
78 {
79     false, false,
80 #ifndef MINISHOGI
81     true, false,
82 #endif
83     false, false, true, true,
84     false,
85 #ifndef MINISHOGI
86     false, false,
87 #endif
88     false, true, true, false
89 };
90
91
92 #ifdef SAVE_DISTDATA
93 short
94 distance(short a, short b)
95 {
96     return (short)computed_distance(a, b);
97 }
98 #else
99 short
100 distance(short a, short b)
101 {
102     return (use_distdata
103             ? (short)(*distdata)[(int)a][(int)b]
104             : (short)computed_distance(a, b));
105 }
106 #endif
107
108
109 void
110 Initialize_dist(void)
111 {
112     short a, b, d, di, ptyp;
113 #ifndef SAVE_DISTDATA
114     for (a = 0; a < NO_SQUARES; a++)
115     {
116         for (b = 0; b < NO_SQUARES; b++)
117         {
118             d = abs(column(a) - column(b));
119             di = abs(row(a) - row(b));
120             (*distdata)[a][b] = (small_short)((d > di) ? d : di);
121         }
122     }
123 #endif
124 #ifndef SAVE_PTYPE_DISTDATA
125     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
126     {
127         for (a = 0; a < NO_SQUARES; a++)
128             for (b = 0; b < NO_SQUARES; b++)
129                 (*ptype_distdata[ptyp])[a][b] = ptype_distance(ptyp, a, b);
130     }
131 #endif
132 }
133
134
135 /*
136  * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
137  * of positions reachable from from-square in ppos with ptype such that the
138  * sequence
139  *
140  *     ppos = nextpos[ptype][from-square];
141  *     pdir = nextdir[ptype][from-square];
142  *     u = ppos[sq];
143  *
144  *     do
145  *     {
146  *         u = ppos[u];
147  *
148  *         if(color[u] != neutral)
149  *             u = pdir[u];
150  *     }
151  *     while (sq != u);
152  *
153  * will generate the sequence of all squares reachable from sq.
154  *
155  * If the path is blocked u = pdir[sq] will generate the continuation of the
156  * sequence in other directions.
157  */
158
159
160 const small_short is_promoted[NO_PIECES] =
161 {
162     false, false,
163 #ifndef MINISHOGI
164     false, false,
165 #endif
166     false, false, false, false,
167     true,
168 #ifndef MINISHOGI
169     true, true,
170 #endif
171     true, true, true, false
172 };
173
174 /* data used to generate nextpos/nextdir */
175 #ifndef MINISHOGI
176 /* FIXME: use predefined constants ! */
177 #if !defined SAVE_NEXTPOS
178 static
179 #endif
180 const small_short direc[NO_PTYPE_PIECES][8] =
181 {
182     {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  0 ptype_pawn    */
183     {  11,   0,   0,   0,   0,   0,   0,   0 },   /*  1 ptype_lance   */
184     {  21,  23,   0,   0,   0,   0,   0,   0 },   /*  2 ptype_knight  */
185     {  10,  11,  12, -12, -10,   0,   0,   0 },   /*  3 ptype_silver  */
186     {  10,  11,  12,  -1,   1, -11,   0,   0 },   /*  4 ptype_gold    */
187     {  10,  12, -12, -10,   0,   0,   0,   0 },   /*  5 ptype_bishop  */
188     {  11,  -1,   1, -11,   0,   0,   0,   0 },   /*  6 ptype_rook    */
189     {  10,  12, -12, -10,  11,  -1,   1, -11 },   /*  7 ptype_pbishop */
190     {  11,  -1,   1, -11,  10,  12, -12, -10 },   /*  8 ptype_prook   */
191     {  10,  11,  12,  -1,   1, -12, -11, -10 },   /*  9 ptype_king    */
192     { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 10 ptype_wpawn   */
193     { -11,   0,   0,   0,   0,   0,   0,   0 },   /* 11 ptype_wlance  */
194     { -21, -23,   0,   0,   0,   0,   0,   0 },   /* 12 ptype_wknight */
195     { -10, -11, -12,  12,  10,   0,   0,   0 },   /* 13 ptype_wsilver */
196     { -10, -11, -12,   1,  -1,  11,   0,   0 }    /* 14 ptype_wgold */
197 };
198 #else
199 #if !defined SAVE_NEXTPOS
200 static
201 #endif
202 const small_short direc[NO_PTYPE_PIECES][8] =
203 {
204     {   7,   0,   0,   0,   0,   0,   0,   0 },   /*  0 ptype_pawn    */
205     {   6,   7,   8,  -8,  -6,   0,   0,   0 },   /*  3 ptype_silver  */
206     {   6,   7,   8,  -1,   1,  -7,   0,   0 },   /*  4 ptype_gold    */
207     {   6,   8,  -8,  -6,   0,   0,   0,   0 },   /*  5 ptype_bishop  */
208     {   7,  -1,   1,  -7,   0,   0,   0,   0 },   /*  6 ptype_rook    */
209     {   6,   8,  -8,  -6,   7,  -1,   1,  -7 },   /*  7 ptype_pbishop */
210     {   7,  -1,   1,  -7,   6,   8,  -8,  -6 },   /*  8 ptype_prook   */
211     {   6,   7,   8,  -1,   1,  -8,  -7,  -6 },   /*  9 ptype_king    */
212     {  -7,   0,   0,   0,   0,   0,   0,   0 },   /* 10 ptype_wpawn   */
213     {  -6,  -7,  -8,   8,   6,   0,   0,   0 },   /* 13 ptype_wsilver */
214     {  -6,  -7,  -8,   1,  -1,   7,   0,   0 }    /* 14 ptype_wgold */
215 };
216 #endif
217
218
219 small_short diagonal(short d)
220 {
221   return (abs(d) == (NO_COLS+1) || abs(d) == (NO_COLS+3));
222 }
223
224
225 #ifndef MINISHOGI
226 /* FIXME */
227 static const small_short max_steps[NO_PTYPE_PIECES] =
228 {
229     1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
230 };
231 #else
232 static const small_short max_steps[NO_PTYPE_PIECES] =
233 {
234     1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
235 };
236 #endif
237
238 #ifndef MINISHOGI
239 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 4)] =
240 {
241     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
242     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
243     -1,  0,  1,  2,  3,  4,  5,  6,  7,  8, -1,
244     -1,  9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
245     -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
246     -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
247     -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
248     -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
249     -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
250     -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
251     -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
252     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
253     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
254 };
255
256
257 const small_short inunmap[NO_SQUARES] =
258 {
259      23,  24,  25,  26,  27,  28,  29,  30,  31,
260      34,  35,  36,  37,  38,  39,  40,  41,  42,
261      45,  46,  47,  48,  49,  50,  51,  52,  53,
262      56,  57,  58,  59,  60,  61,  62,  63,  64,
263      67,  68,  69,  70,  71,  72,  73,  74,  75,
264      78,  79,  80,  81,  82,  83,  84,  85,  86,
265      89,  90,  91,  92,  93,  94,  95,  96,  97,
266     100, 101, 102, 103, 104, 105, 106, 107, 108,
267     111, 112, 113, 114, 115, 116, 117, 118, 119
268 };
269 #else
270 const small_short nunmap[(NO_COLS + 2)*(NO_ROWS + 2)] =
271 {
272     -1, -1, -1, -1, -1, -1, -1,
273     -1,  0,  1,  2,  3,  4, -1,
274     -1,  5,  6,  7,  8,  9, -1,
275     -1, 10, 11, 12, 13, 14, -1,
276     -1, 15, 16, 17, 18, 19, -1,
277     -1, 20, 21, 22, 23, 24, -1,
278     -1, -1, -1, -1, -1, -1, -1,
279 };
280
281
282 const small_short inunmap[NO_SQUARES] =
283 {
284       8,   9,  10,  11,  12,
285      15,  16,  17,  18,  19,
286      22,  23,  24,  25,  26,
287      29,  30,  31,  32,  33,
288      36,  37,  38,  39,  40,
289 };
290 #endif
291
292 int InitFlag = false;
293
294
295 #if defined SAVE_NEXTPOS
296
297 short
298 next_direction(short ptyp, short *d, short sq)
299 {
300     short delta, to, sfrom = inunmap[sq];
301
302     do
303     {
304         (*d)++;
305         if (*d >= 8)
306             return sq;
307
308         delta = direc[ptyp][*d];
309         if (delta == 0)
310             return sq;
311
312         to = nunmap[sfrom + delta];
313     }
314     while (to < 0);
315
316     return to;
317 }
318
319
320 short
321 next_position(short ptyp, short *d, short sq, short u)
322 {
323     if (*d < 4 && psweep[ptyp])
324     {
325         short to = nunmap[inunmap[u] + direc[ptyp][*d]];
326
327         if (to < 0)
328             return next_direction(ptyp, d, sq);
329         else
330             return to;
331     }
332     else
333     {
334         return next_direction(ptyp, d, sq);
335     }
336 }
337
338
339 short
340 first_direction(short ptyp, short *d, short sq)
341 {
342     *d = -1;
343     return next_direction(ptyp, d, sq);
344 }
345
346 #else
347
348 /*
349  * This procedure pre-calculates all moves for every piece from every
350  * square.  This data is stored in nextpos/nextdir and used later in the
351  * move generation routines.
352  */
353
354 void
355 Initialize_moves(void)
356 {
357     short ptyp, po, p0, d, di, s, delta;
358     unsigned char *ppos, *pdir;
359     short dest[8][9];
360     short sorted[9];
361     short steps[8];
362     short fpo = inunmap[0], tpo = 1 + inunmap[NO_SQUARES-1];
363
364     /* pre-fill nextpos and nextdir with source position, probably so
365      * (color[u] == neutral) stops to match once all moves have been seen
366      */
367     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
368     {
369         for (po = 0; po < NO_SQUARES; po++)
370         {
371             for (p0 = 0; p0 < NO_SQUARES; p0++)
372             {
373                 (*nextpos[ptyp])[po][p0] = (unsigned char)po;
374                 (*nextdir[ptyp])[po][p0] = (unsigned char)po;
375             }
376         }
377     }
378
379     for (ptyp = 0; ptyp < NO_PTYPE_PIECES; ptyp++)
380     {
381         for (po = fpo; po < tpo; po++)
382         {
383             if (nunmap[po] >= (small_short)0)
384             {
385                 ppos = (*nextpos[ptyp])[nunmap[po]];
386                 pdir = (*nextdir[ptyp])[nunmap[po]];
387
388                 /* dest is a function of direction and steps */
389                 for (d = 0; d < 8; d++)
390                 {
391                     dest[d][0] = nunmap[po];
392                     delta = direc[ptyp][d];
393
394                     if (delta != 0)
395                     {
396                         p0 = po;
397
398                         for (s = 0; s < max_steps[ptyp]; s++)
399                         {
400                             p0 = p0 + delta;
401
402                             /*
403                              * break if (off board) or (promoted rooks
404                              * wishes to move two steps diagonal) or
405                              * (promoted bishops wishes to move two steps
406                              * non-diagonal)
407                              */
408                             if ((nunmap[p0] < (small_short)0)
409                                 || ((ptyp == ptype_prook)
410                                     && (s > 0)
411                                     && diagonal(delta))
412                                 || ((ptyp == ptype_pbishop)
413                                     && (s > 0)
414                                     && !diagonal(delta)))
415                                 break;
416                             else
417                                 dest[d][s] = nunmap[p0];
418                         }
419                     }
420                     else
421                     {
422                         s = 0;
423                     }
424
425                     /*
426                      * Sort dest in number of steps order; currently no sort
427                      * is done due to compatibility with the move generation
428                      * order in old gnuchess.
429                      */
430
431                     steps[d] = s;
432
433                     for (di = d; s > 0 && di > 0; di--)
434                     {
435                         if (steps[sorted[di - 1]] == 0) /* should be: < s */
436                             sorted[di] = sorted[di - 1];
437                         else
438                             break;
439                     }
440
441                     sorted[di] = d;
442                 }
443
444                 /*
445                  * update nextpos/nextdir
446                  */
447
448                 p0 = nunmap[po];
449                 pdir[p0] = (unsigned char)dest[sorted[0]][0];
450
451                 for (d = 0; d < 8; d++)
452                 {
453                     for (s = 0; s < steps[sorted[d]]; s++)
454                     {
455                         ppos[p0] = (unsigned char)dest[sorted[d]][s];
456                         p0 = dest[sorted[d]][s];
457
458                         if (d < 7)
459                             pdir[p0] = (unsigned char)dest[sorted[d + 1]][0];
460
461                         /*
462                          * else is already initialized
463                          */
464                     }
465                 }
466             }
467         }
468     }
469 }
470
471 #endif
472
473
474
475 /*
476  * Reset the board and other variables to start a new game.
477  */
478
479 void
480 NewGame(void)
481 {
482     short l, c, p, max_opening_sequence;
483 #ifdef HAVE_GETTIMEOFDAY
484     struct timeval tv;
485 #endif
486     compptr = oppptr = 0;
487     stage = 0;
488     stage2 = -1;    /* the game is not yet started */
489     flag.illegal = flag.mate = flag.post = flag.quit
490         = flag.reverse = flag.bothsides = flag.onemove = flag.force
491         = false;
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     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             SelectLevel(sx);
618
619         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         barebones    = 1;
670     }
671     else
672     {
673         TCflag       = false;
674         OperatorTime = 0;
675         barebones    = 0;
676     }
677
678     Initialize();
679     Initialize_dist();
680     Initialize_eval();
681 #if !defined SAVE_NEXTPOS
682     Initialize_moves();
683 #endif
684
685     NewGame();
686
687     flag.easy = ahead;
688     flag.hash = hash;
689
690     if (xwin)
691         xwndw = atoi(xwin);
692
693 #ifdef HASHFILE
694     hashfile = NULL;
695 #endif
696
697 #if ttblsz
698 #ifdef HASHFILE
699     hashfile = fopen(HASHFILE, RWA_ACC);
700
701     if (hashfile)
702     {
703         fseek(hashfile, 0L, SEEK_END);
704         filesz = ftell(hashfile) / sizeof(struct fileentry) - 1 - MAXrehash;
705         hashmask = filesz >> 1;
706         hashbase = hashmask + 1;
707     }
708 #endif /* HASHFILE */
709 #endif /* ttblsz */
710
711     savefile[0] = '\0';
712     listfile[0] = '\0';
713
714     return 0;
715 }
716
717
718 void
719 ExitMain(void)
720 {
721 #if ttblsz
722 #ifdef HASHFILE
723     if (hashfile)
724         fclose(hashfile);
725 #endif /* HASHFILE */
726 #endif /* ttblsz */
727
728     ExitShogi();
729 }
730