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
.coords
= flag
.hash
= flag
.easy
501 = flag
.beep
= flag
.rcptr
503 flag
.stars
= flag
.shade
= flag
.back
= flag
.musttimeout
= false;
508 GenCnt
= NodeCnt
= et0
= dither
= XCmore
= 0;
517 MaxSearchDepth
= MAXDEPTH
- 1;
522 CptrFlag
[0] = TesujiFlag
[0] = false;
525 GameType
[0] = GameType
[1] = UNKNOWN
;
526 Pscore
[0] = Tscore
[0] = (SCORE_LIMIT
+ 3000);
527 opponent
= player
= black
;
530 for (l
= 0; l
< TREE
; l
++)
531 Tree
[l
].f
= Tree
[l
].t
= 0;
533 gsrand((unsigned int) 1);
537 for (c
= black
; c
<= white
; c
++)
539 for (p
= pawn
; p
<= king
; p
++)
541 for (l
= 0; l
< NO_SQUARES
; l
++)
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);
565 for (c
= black
; c
<= white
; c
++)
567 for (p
= pawn
; p
<= king
; p
++)
569 for (l
= 0; l
< MAX_CAPTURED
; l
++)
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);
594 for (l
= 0; l
< NO_SQUARES
; l
++)
596 board
[l
] = Stboard
[l
];
597 color
[l
] = Stcolor
[l
];
605 #ifdef HAVE_GETTIMEOFDAY
606 gettimeofday(&tv
, NULL
);
607 time0
= tv
.tv_sec
*100 + tv
.tv_usec
/10000;
609 time0
= time((long *) 0);
612 /* resetting reference time */
613 ElapsedTime(COMPUTE_AND_INIT_MODE
);
614 flag
.regularstart
= true;
624 else if (MaxResponseTime
== 0)
625 dsp
->SelectLevel(sx
);
627 dsp
->UpdateDisplay(0, 0, 1, 0);
629 GetOpeningPatterns(&max_opening_sequence
);
642 hashbd
= hashkey
= 0;
652 gsrand(starttime
= ((unsigned int)time((long *)0))); /* init urand */
659 if (Initialize_data() != 0)
684 #if !defined SAVE_NEXTPOS
702 hashfile
= fopen(HASHFILE
, RWA_ACC
);
706 fseek(hashfile
, 0L, SEEK_END
);
707 filesz
= ftell(hashfile
) / sizeof(struct fileentry
) - 1 - MAXrehash
;
708 hashmask
= filesz
>> 1;
709 hashbase
= hashmask
+ 1;
711 #endif /* HASHFILE */
728 #endif /* HASHFILE */