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
9 * GNU SHOGI is based on GNU CHESS
11 * Copyright (c) 1988, 1989, 1990 John Stanback
12 * Copyright (c) 1992 Free Software Foundation
14 * This file is part of GNU SHOGI.
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.
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
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 * ----------------------------------------------------------------------
35 #if defined HAVE_GETTIMEOFDAY
43 /****************************************
44 * A variety of global flags.
45 ****************************************/
48 * If hard_time_limit is nonzero, exceeding the time limit means
52 short hard_time_limit
= 1;
53 short barebones
= 0; /* Suppress printing of statistics
54 * (mainly for xshogi). */
56 short nolist
= 0; /* List the game after exit. */
58 short nolist
= 1; /* Don't list the game after exit. */
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.
66 display_t display_type
= DISPLAY_X
;
68 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
71 const small_short psweep
[NO_PTYPE_PIECES
] =
73 false, true, false, false, false, true, true, true, true, false,
74 false, true, false, false, false
78 const small_short sweep
[NO_PIECES
] =
84 false, false, true, true,
89 false, true, true, false
95 distance(short a
, short b
)
97 return (short)computed_distance(a
, b
);
101 distance(short a
, short b
)
104 ? (short)(*distdata
)[(int)a
][(int)b
]
105 : (short)computed_distance(a
, b
));
111 Initialize_dist(void)
113 short a
, b
, d
, di
, ptyp
;
114 #ifndef SAVE_DISTDATA
115 for (a
= 0; a
< NO_SQUARES
; a
++)
117 for (b
= 0; b
< NO_SQUARES
; b
++)
119 d
= abs(column(a
) - column(b
));
120 di
= abs(row(a
) - row(b
));
121 (*distdata
)[a
][b
] = (small_short
)((d
> di
) ? d
: di
);
125 #ifndef SAVE_PTYPE_DISTDATA
126 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
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
);
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
141 * ppos = nextpos[ptype][from-square];
142 * pdir = nextdir[ptype][from-square];
149 * if(color[u] != neutral)
154 * will generate the sequence of all squares reachable from sq.
156 * If the path is blocked u = pdir[sq] will generate the continuation of the
157 * sequence in other directions.
161 const small_short is_promoted
[NO_PIECES
] =
167 false, false, false, false,
172 true, true, true, false
175 /* data used to generate nextpos/nextdir */
177 /* FIXME: use predefined constants ! */
178 #if !defined SAVE_NEXTPOS
181 const small_short direc
[NO_PTYPE_PIECES
][8] =
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 */
200 #if !defined SAVE_NEXTPOS
203 const small_short direc
[NO_PTYPE_PIECES
][8] =
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 */
220 small_short
diagonal(short d
)
222 return (abs(d
) == (NO_COLS
+1) || abs(d
) == (NO_COLS
+3));
228 static const small_short max_steps
[NO_PTYPE_PIECES
] =
230 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
233 static const small_short max_steps
[NO_PTYPE_PIECES
] =
235 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
240 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 4)] =
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
258 const small_short inunmap
[NO_SQUARES
] =
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
271 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 2)] =
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,
283 const small_short inunmap
[NO_SQUARES
] =
293 int InitFlag
= false;
296 #if defined SAVE_NEXTPOS
299 next_direction(short ptyp
, short *d
, short sq
)
301 short delta
, to
, sfrom
= inunmap
[sq
];
309 delta
= direc
[ptyp
][*d
];
313 to
= nunmap
[sfrom
+ delta
];
322 next_position(short ptyp
, short *d
, short sq
, short u
)
324 if (*d
< 4 && psweep
[ptyp
])
326 short to
= nunmap
[inunmap
[u
] + direc
[ptyp
][*d
]];
329 return next_direction(ptyp
, d
, sq
);
335 return next_direction(ptyp
, d
, sq
);
341 first_direction(short ptyp
, short *d
, short sq
)
344 return next_direction(ptyp
, d
, sq
);
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.
356 Initialize_moves(void)
358 short ptyp
, po
, p0
, d
, di
, s
, delta
;
359 unsigned char *ppos
, *pdir
;
363 short fpo
= inunmap
[0], tpo
= 1 + inunmap
[NO_SQUARES
-1];
365 /* pre-fill nextpos and nextdir with source position, probably so
366 * (color[u] == neutral) stops to match once all moves have been seen
368 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
370 for (po
= 0; po
< NO_SQUARES
; po
++)
372 for (p0
= 0; p0
< NO_SQUARES
; p0
++)
374 (*nextpos
[ptyp
])[po
][p0
] = (unsigned char)po
;
375 (*nextdir
[ptyp
])[po
][p0
] = (unsigned char)po
;
380 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
382 for (po
= fpo
; po
< tpo
; po
++)
384 if (nunmap
[po
] >= (small_short
)0)
386 ppos
= (*nextpos
[ptyp
])[nunmap
[po
]];
387 pdir
= (*nextdir
[ptyp
])[nunmap
[po
]];
389 /* dest is a function of direction and steps */
390 for (d
= 0; d
< 8; d
++)
392 dest
[d
][0] = nunmap
[po
];
393 delta
= direc
[ptyp
][d
];
399 for (s
= 0; s
< max_steps
[ptyp
]; s
++)
404 * break if (off board) or (promoted rooks
405 * wishes to move two steps diagonal) or
406 * (promoted bishops wishes to move two steps
409 if ((nunmap
[p0
] < (small_short
)0)
410 || ((ptyp
== ptype_prook
)
413 || ((ptyp
== ptype_pbishop
)
415 && !diagonal(delta
)))
418 dest
[d
][s
] = nunmap
[p0
];
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.
434 for (di
= d
; s
> 0 && di
> 0; di
--)
436 if (steps
[sorted
[di
- 1]] == 0) /* should be: < s */
437 sorted
[di
] = sorted
[di
- 1];
446 * update nextpos/nextdir
450 pdir
[p0
] = (unsigned char)dest
[sorted
[0]][0];
452 for (d
= 0; d
< 8; d
++)
454 for (s
= 0; s
< steps
[sorted
[d
]]; s
++)
456 ppos
[p0
] = (unsigned char)dest
[sorted
[d
]][s
];
457 p0
= dest
[sorted
[d
]][s
];
460 pdir
[p0
] = (unsigned char)dest
[sorted
[d
+ 1]][0];
463 * else is already initialized
477 * Reset the board and other variables to start a new game.
483 short l
, c
, p
, max_opening_sequence
;
484 #ifdef HAVE_GETTIMEOFDAY
487 compptr
= oppptr
= 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
493 flag
.material
= flag
.coords
= flag
.hash
= flag
.easy
494 = flag
.beep
= flag
.rcptr
496 flag
.stars
= flag
.shade
= flag
.back
= flag
.musttimeout
= false;
501 GenCnt
= NodeCnt
= et0
= dither
= XCmore
= 0;
510 MaxSearchDepth
= MAXDEPTH
- 1;
515 CptrFlag
[0] = TesujiFlag
[0] = false;
518 GameType
[0] = GameType
[1] = UNKNOWN
;
519 Pscore
[0] = Tscore
[0] = (SCORE_LIMIT
+ 3000);
520 opponent
= player
= black
;
523 for (l
= 0; l
< TREE
; l
++)
524 Tree
[l
].f
= Tree
[l
].t
= 0;
526 gsrand((unsigned int) 1);
530 for (c
= black
; c
<= white
; c
++)
532 for (p
= pawn
; p
<= king
; p
++)
534 for (l
= 0; l
< NO_SQUARES
; l
++)
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);
558 for (c
= black
; c
<= white
; c
++)
560 for (p
= pawn
; p
<= king
; p
++)
562 for (l
= 0; l
< MAX_CAPTURED
; l
++)
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);
587 for (l
= 0; l
< NO_SQUARES
; l
++)
589 board
[l
] = Stboard
[l
];
590 color
[l
] = Stcolor
[l
];
598 #ifdef HAVE_GETTIMEOFDAY
599 gettimeofday(&tv
, NULL
);
600 time0
= tv
.tv_sec
*100 + tv
.tv_usec
/10000;
602 time0
= time((long *) 0);
605 /* resetting reference time */
606 ElapsedTime(COMPUTE_AND_INIT_MODE
);
607 flag
.regularstart
= true;
617 else if (MaxResponseTime
== 0)
620 UpdateDisplay(0, 0, 1, 0);
622 GetOpeningPatterns(&max_opening_sequence
);
635 hashbd
= hashkey
= 0;
645 gsrand(starttime
= ((unsigned int)time((long *)0))); /* init urand */
652 if (Initialize_data() != 0)
655 strcpy(ColorStr
[0], "Black");
656 strcpy(ColorStr
[1], "White");
682 #if !defined SAVE_NEXTPOS
700 hashfile
= fopen(HASHFILE
, RWA_ACC
);
704 fseek(hashfile
, 0L, SEEK_END
);
705 filesz
= ftell(hashfile
) / sizeof(struct fileentry
) - 1 - MAXrehash
;
706 hashmask
= filesz
>> 1;
707 hashbase
= hashmask
+ 1;
709 #endif /* HASHFILE */
726 #endif /* HASHFILE */