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;
54 short nolist
= 0; /* List the game after exit. */
56 short nolist
= 1; /* Don't list the game after exit. */
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.
64 display_t display_type
= DISPLAY_X
;
66 /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */
69 static const bool psweep
[NO_PTYPE_PIECES
] =
75 false, false, true, true,
76 true, true, false, false,
84 const bool sweep
[NO_PIECES
] =
90 false, false, true, true,
95 false, true, true, false
101 distance(short a
, short b
)
103 return (short)computed_distance(a
, b
);
107 distance(short a
, short b
)
110 ? (short)(*distdata
)[(int)a
][(int)b
]
111 : (short)computed_distance(a
, b
));
117 Initialize_dist(void)
119 short a
, b
, d
, di
, ptyp
;
120 #ifndef SAVE_DISTDATA
121 for (a
= 0; a
< NO_SQUARES
; a
++)
123 for (b
= 0; b
< NO_SQUARES
; b
++)
125 d
= abs(column(a
) - column(b
));
126 di
= abs(row(a
) - row(b
));
127 (*distdata
)[a
][b
] = (small_short
)((d
> di
) ? d
: di
);
131 #ifndef SAVE_PTYPE_DISTDATA
132 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
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
);
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
147 * ppos = nextpos[ptype][from-square];
148 * pdir = nextdir[ptype][from-square];
155 * if(color[u] != neutral)
160 * will generate the sequence of all squares reachable from sq.
162 * If the path is blocked u = pdir[sq] will generate the continuation of the
163 * sequence in other directions.
167 const bool is_promoted
[NO_PIECES
] =
173 false, false, false, false,
178 true, true, true, false
181 /* data used to generate nextpos/nextdir */
183 /* FIXME: use predefined constants ! */
184 #if !defined SAVE_NEXTPOS
187 const small_short direc
[NO_PTYPE_PIECES
][8] =
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 */
206 #if !defined SAVE_NEXTPOS
209 const small_short direc
[NO_PTYPE_PIECES
][8] =
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 */
226 small_short
diagonal(short d
)
228 return (abs(d
) == (NO_COLS
+1) || abs(d
) == (NO_COLS
+3));
234 static const small_short max_steps
[NO_PTYPE_PIECES
] =
236 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
239 static const small_short max_steps
[NO_PTYPE_PIECES
] =
241 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
246 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 4)] =
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
264 const small_short inunmap
[NO_SQUARES
] =
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
277 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 2)] =
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,
289 const small_short inunmap
[NO_SQUARES
] =
299 static bool InitFlag
= false;
302 #if defined SAVE_NEXTPOS
305 next_direction(short ptyp
, short *d
, short sq
)
307 short delta
, to
, sfrom
= inunmap
[sq
];
315 delta
= direc
[ptyp
][*d
];
319 to
= nunmap
[sfrom
+ delta
];
328 next_position(short ptyp
, short *d
, short sq
, short u
)
330 if (*d
< 4 && psweep
[ptyp
])
332 short to
= nunmap
[inunmap
[u
] + direc
[ptyp
][*d
]];
335 return next_direction(ptyp
, d
, sq
);
341 return next_direction(ptyp
, d
, sq
);
347 first_direction(short ptyp
, short *d
, short sq
)
350 return next_direction(ptyp
, d
, sq
);
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.
362 Initialize_moves(void)
364 short ptyp
, po
, p0
, d
, di
, s
, delta
;
365 unsigned char *ppos
, *pdir
;
369 short fpo
= inunmap
[0], tpo
= 1 + inunmap
[NO_SQUARES
-1];
371 /* pre-fill nextpos and nextdir with source position, probably so
372 * (color[u] == neutral) stops to match once all moves have been seen
374 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
376 for (po
= 0; po
< NO_SQUARES
; po
++)
378 for (p0
= 0; p0
< NO_SQUARES
; p0
++)
380 (*nextpos
[ptyp
])[po
][p0
] = (unsigned char)po
;
381 (*nextdir
[ptyp
])[po
][p0
] = (unsigned char)po
;
386 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
388 for (po
= fpo
; po
< tpo
; po
++)
390 if (nunmap
[po
] >= (small_short
)0)
392 ppos
= (*nextpos
[ptyp
])[nunmap
[po
]];
393 pdir
= (*nextdir
[ptyp
])[nunmap
[po
]];
395 /* dest is a function of direction and steps */
396 for (d
= 0; d
< 8; d
++)
398 dest
[d
][0] = nunmap
[po
];
399 delta
= direc
[ptyp
][d
];
405 for (s
= 0; s
< max_steps
[ptyp
]; s
++)
410 * break if (off board) or (promoted rooks
411 * wishes to move two steps diagonal) or
412 * (promoted bishops wishes to move two steps
415 if ((nunmap
[p0
] < (small_short
)0)
416 || ((ptyp
== ptype_prook
)
419 || ((ptyp
== ptype_pbishop
)
421 && !diagonal(delta
)))
424 dest
[d
][s
] = nunmap
[p0
];
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.
440 for (di
= d
; s
> 0 && di
> 0; di
--)
442 if (steps
[sorted
[di
- 1]] == 0) /* should be: < s */
443 sorted
[di
] = sorted
[di
- 1];
452 * update nextpos/nextdir
456 pdir
[p0
] = (unsigned char)dest
[sorted
[0]][0];
458 for (d
= 0; d
< 8; d
++)
460 for (s
= 0; s
< steps
[sorted
[d
]]; s
++)
462 ppos
[p0
] = (unsigned char)dest
[sorted
[d
]][s
];
463 p0
= dest
[sorted
[d
]][s
];
466 pdir
[p0
] = (unsigned char)dest
[sorted
[d
+ 1]][0];
469 * else is already initialized
483 * Reset the board and other variables to start a new game.
489 short l
, c
, p
, max_opening_sequence
;
490 #ifdef HAVE_GETTIMEOFDAY
493 compptr
= oppptr
= 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
499 flag
.post
&= xboard
; /* xboard: do not alter post status on 'new' */
500 flag
.material
= flag
.hash
= flag
.easy
501 = flag
.beep
= flag
.rcptr
503 flag
.back
= flag
.musttimeout
= false;
507 GenCnt
= NodeCnt
= et0
= dither
= XCmore
= 0;
516 MaxSearchDepth
= MAXDEPTH
- 1;
521 CptrFlag
[0] = TesujiFlag
[0] = false;
524 GameType
[0] = GameType
[1] = UNKNOWN
;
525 Pscore
[0] = Tscore
[0] = (SCORE_LIMIT
+ 3000);
526 opponent
= player
= black
;
529 for (l
= 0; l
< TREE
; l
++)
530 Tree
[l
].f
= Tree
[l
].t
= 0;
532 gsrand((unsigned int) 1);
536 for (c
= black
; c
<= white
; c
++)
538 for (p
= pawn
; p
<= king
; p
++)
540 for (l
= 0; l
< NO_SQUARES
; l
++)
542 (*hashcode
)[c
][p
][l
].key
543 = (((unsigned long) urand()));
544 (*hashcode
)[c
][p
][l
].key
545 += (((unsigned long) urand()) << 16);
546 (*hashcode
)[c
][p
][l
].bd
547 = (((unsigned long) urand()));
548 (*hashcode
)[c
][p
][l
].bd
549 += (((unsigned long) urand()) << 16);
550 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
551 (*hashcode
)[c
][p
][l
].key
552 += (((unsigned long) urand()) << 32);
553 (*hashcode
)[c
][p
][l
].key
554 += (((unsigned long) urand()) << 48);
555 (*hashcode
)[c
][p
][l
].bd
556 += (((unsigned long) urand()) << 32);
557 (*hashcode
)[c
][p
][l
].bd
558 += (((unsigned long) urand()) << 48);
564 for (c
= black
; c
<= white
; c
++)
566 for (p
= pawn
; p
<= king
; p
++)
568 for (l
= 0; l
< MAX_CAPTURED
; l
++)
570 (*drop_hashcode
)[c
][p
][l
].key
571 = (((unsigned long) urand()));
572 (*drop_hashcode
)[c
][p
][l
].key
573 += (((unsigned long) urand()) << 16);
574 (*drop_hashcode
)[c
][p
][l
].bd
575 = (((unsigned long) urand()));
576 (*drop_hashcode
)[c
][p
][l
].bd
577 += (((unsigned long) urand()) << 16);
578 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
579 (*drop_hashcode
)[c
][p
][l
].key
580 += (((unsigned long) urand()) << 32);
581 (*drop_hashcode
)[c
][p
][l
].key
582 += (((unsigned long) urand()) << 48);
583 (*drop_hashcode
)[c
][p
][l
].bd
584 += (((unsigned long) urand()) << 32);
585 (*drop_hashcode
)[c
][p
][l
].bd
586 += (((unsigned long) urand()) << 48);
593 for (l
= 0; l
< NO_SQUARES
; l
++)
595 board
[l
] = Stboard
[l
];
596 color
[l
] = Stcolor
[l
];
604 #ifdef HAVE_GETTIMEOFDAY
605 gettimeofday(&tv
, NULL
);
606 time0
= tv
.tv_sec
*100 + tv
.tv_usec
/10000;
608 time0
= time((long *) 0);
611 /* resetting reference time */
612 ElapsedTime(COMPUTE_AND_INIT_MODE
);
613 flag
.regularstart
= true;
623 else if (MaxResponseTime
== 0)
624 dsp
->SelectLevel(sx
);
626 dsp
->UpdateDisplay(0, 0, 1, 0);
628 GetOpeningPatterns(&max_opening_sequence
);
641 hashbd
= hashkey
= 0;
651 gsrand(starttime
= ((unsigned int)time((long *)0))); /* init urand */
658 if (Initialize_data() != 0)
683 #if !defined SAVE_NEXTPOS
701 hashfile
= fopen(HASHFILE
, RWA_ACC
);
705 fseek(hashfile
, 0L, SEEK_END
);
706 filesz
= ftell(hashfile
) / sizeof(struct fileentry
) - 1 - MAXrehash
;
707 hashmask
= filesz
>> 1;
708 hashbase
= hashmask
+ 1;
710 #endif /* HASHFILE */
727 #endif /* HASHFILE */