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
] =
77 false, false, true, true,
78 true, true, false, false,
86 const small_short sweep
[NO_PIECES
] =
92 false, false, true, true,
97 false, true, true, false
103 distance(short a
, short b
)
105 return (short)computed_distance(a
, b
);
109 distance(short a
, short b
)
112 ? (short)(*distdata
)[(int)a
][(int)b
]
113 : (short)computed_distance(a
, b
));
119 Initialize_dist(void)
121 short a
, b
, d
, di
, ptyp
;
122 #ifndef SAVE_DISTDATA
123 for (a
= 0; a
< NO_SQUARES
; a
++)
125 for (b
= 0; b
< NO_SQUARES
; b
++)
127 d
= abs(column(a
) - column(b
));
128 di
= abs(row(a
) - row(b
));
129 (*distdata
)[a
][b
] = (small_short
)((d
> di
) ? d
: di
);
133 #ifndef SAVE_PTYPE_DISTDATA
134 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
136 for (a
= 0; a
< NO_SQUARES
; a
++)
137 for (b
= 0; b
< NO_SQUARES
; b
++)
138 (*ptype_distdata
[ptyp
])[a
][b
] = ptype_distance(ptyp
, a
, b
);
145 * nextpos[ptype][from-square], nextdir[ptype][from-square] gives vector
146 * of positions reachable from from-square in ppos with ptype such that the
149 * ppos = nextpos[ptype][from-square];
150 * pdir = nextdir[ptype][from-square];
157 * if(color[u] != neutral)
162 * will generate the sequence of all squares reachable from sq.
164 * If the path is blocked u = pdir[sq] will generate the continuation of the
165 * sequence in other directions.
169 const small_short is_promoted
[NO_PIECES
] =
175 false, false, false, false,
180 true, true, true, false
183 /* data used to generate nextpos/nextdir */
185 /* FIXME: use predefined constants ! */
186 #if !defined SAVE_NEXTPOS
189 const small_short direc
[NO_PTYPE_PIECES
][8] =
191 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
192 { 11, 0, 0, 0, 0, 0, 0, 0 }, /* 1 ptype_lance */
193 { 21, 23, 0, 0, 0, 0, 0, 0 }, /* 2 ptype_knight */
194 { 10, 11, 12, -12, -10, 0, 0, 0 }, /* 3 ptype_silver */
195 { 10, 11, 12, -1, 1, -11, 0, 0 }, /* 4 ptype_gold */
196 { 10, 12, -12, -10, 0, 0, 0, 0 }, /* 5 ptype_bishop */
197 { 11, -1, 1, -11, 0, 0, 0, 0 }, /* 6 ptype_rook */
198 { 10, 12, -12, -10, 11, -1, 1, -11 }, /* 7 ptype_pbishop */
199 { 11, -1, 1, -11, 10, 12, -12, -10 }, /* 8 ptype_prook */
200 { 10, 11, 12, -1, 1, -12, -11, -10 }, /* 9 ptype_king */
201 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
202 { -11, 0, 0, 0, 0, 0, 0, 0 }, /* 11 ptype_wlance */
203 { -21, -23, 0, 0, 0, 0, 0, 0 }, /* 12 ptype_wknight */
204 { -10, -11, -12, 12, 10, 0, 0, 0 }, /* 13 ptype_wsilver */
205 { -10, -11, -12, 1, -1, 11, 0, 0 } /* 14 ptype_wgold */
208 #if !defined SAVE_NEXTPOS
211 const small_short direc
[NO_PTYPE_PIECES
][8] =
213 { 7, 0, 0, 0, 0, 0, 0, 0 }, /* 0 ptype_pawn */
214 { 6, 7, 8, -8, -6, 0, 0, 0 }, /* 3 ptype_silver */
215 { 6, 7, 8, -1, 1, -7, 0, 0 }, /* 4 ptype_gold */
216 { 6, 8, -8, -6, 0, 0, 0, 0 }, /* 5 ptype_bishop */
217 { 7, -1, 1, -7, 0, 0, 0, 0 }, /* 6 ptype_rook */
218 { 6, 8, -8, -6, 7, -1, 1, -7 }, /* 7 ptype_pbishop */
219 { 7, -1, 1, -7, 6, 8, -8, -6 }, /* 8 ptype_prook */
220 { 6, 7, 8, -1, 1, -8, -7, -6 }, /* 9 ptype_king */
221 { -7, 0, 0, 0, 0, 0, 0, 0 }, /* 10 ptype_wpawn */
222 { -6, -7, -8, 8, 6, 0, 0, 0 }, /* 13 ptype_wsilver */
223 { -6, -7, -8, 1, -1, 7, 0, 0 } /* 14 ptype_wgold */
228 small_short
diagonal(short d
)
230 return (abs(d
) == (NO_COLS
+1) || abs(d
) == (NO_COLS
+3));
236 static const small_short max_steps
[NO_PTYPE_PIECES
] =
238 1, 8, 1, 1, 1, 8, 8, 8, 8, 1, 1, 8, 1, 1, 1
241 static const small_short max_steps
[NO_PTYPE_PIECES
] =
243 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1
248 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 4)] =
250 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
251 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
252 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1,
253 -1, 9, 10, 11, 12, 13, 14, 15, 16, 17, -1,
254 -1, 18, 19, 20, 21, 22, 23, 24, 25, 26, -1,
255 -1, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1,
256 -1, 36, 37, 38, 39, 40, 41, 42, 43, 44, -1,
257 -1, 45, 46, 47, 48, 49, 50, 51, 52, 53, -1,
258 -1, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1,
259 -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, -1,
260 -1, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1,
261 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
262 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
266 const small_short inunmap
[NO_SQUARES
] =
268 23, 24, 25, 26, 27, 28, 29, 30, 31,
269 34, 35, 36, 37, 38, 39, 40, 41, 42,
270 45, 46, 47, 48, 49, 50, 51, 52, 53,
271 56, 57, 58, 59, 60, 61, 62, 63, 64,
272 67, 68, 69, 70, 71, 72, 73, 74, 75,
273 78, 79, 80, 81, 82, 83, 84, 85, 86,
274 89, 90, 91, 92, 93, 94, 95, 96, 97,
275 100, 101, 102, 103, 104, 105, 106, 107, 108,
276 111, 112, 113, 114, 115, 116, 117, 118, 119
279 const small_short nunmap
[(NO_COLS
+ 2)*(NO_ROWS
+ 2)] =
281 -1, -1, -1, -1, -1, -1, -1,
282 -1, 0, 1, 2, 3, 4, -1,
283 -1, 5, 6, 7, 8, 9, -1,
284 -1, 10, 11, 12, 13, 14, -1,
285 -1, 15, 16, 17, 18, 19, -1,
286 -1, 20, 21, 22, 23, 24, -1,
287 -1, -1, -1, -1, -1, -1, -1,
291 const small_short inunmap
[NO_SQUARES
] =
301 int InitFlag
= false;
304 #if defined SAVE_NEXTPOS
307 next_direction(short ptyp
, short *d
, short sq
)
309 short delta
, to
, sfrom
= inunmap
[sq
];
317 delta
= direc
[ptyp
][*d
];
321 to
= nunmap
[sfrom
+ delta
];
330 next_position(short ptyp
, short *d
, short sq
, short u
)
332 if (*d
< 4 && psweep
[ptyp
])
334 short to
= nunmap
[inunmap
[u
] + direc
[ptyp
][*d
]];
337 return next_direction(ptyp
, d
, sq
);
343 return next_direction(ptyp
, d
, sq
);
349 first_direction(short ptyp
, short *d
, short sq
)
352 return next_direction(ptyp
, d
, sq
);
358 * This procedure pre-calculates all moves for every piece from every
359 * square. This data is stored in nextpos/nextdir and used later in the
360 * move generation routines.
364 Initialize_moves(void)
366 short ptyp
, po
, p0
, d
, di
, s
, delta
;
367 unsigned char *ppos
, *pdir
;
371 short fpo
= inunmap
[0], tpo
= 1 + inunmap
[NO_SQUARES
-1];
373 /* pre-fill nextpos and nextdir with source position, probably so
374 * (color[u] == neutral) stops to match once all moves have been seen
376 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
378 for (po
= 0; po
< NO_SQUARES
; po
++)
380 for (p0
= 0; p0
< NO_SQUARES
; p0
++)
382 (*nextpos
[ptyp
])[po
][p0
] = (unsigned char)po
;
383 (*nextdir
[ptyp
])[po
][p0
] = (unsigned char)po
;
388 for (ptyp
= 0; ptyp
< NO_PTYPE_PIECES
; ptyp
++)
390 for (po
= fpo
; po
< tpo
; po
++)
392 if (nunmap
[po
] >= (small_short
)0)
394 ppos
= (*nextpos
[ptyp
])[nunmap
[po
]];
395 pdir
= (*nextdir
[ptyp
])[nunmap
[po
]];
397 /* dest is a function of direction and steps */
398 for (d
= 0; d
< 8; d
++)
400 dest
[d
][0] = nunmap
[po
];
401 delta
= direc
[ptyp
][d
];
407 for (s
= 0; s
< max_steps
[ptyp
]; s
++)
412 * break if (off board) or (promoted rooks
413 * wishes to move two steps diagonal) or
414 * (promoted bishops wishes to move two steps
417 if ((nunmap
[p0
] < (small_short
)0)
418 || ((ptyp
== ptype_prook
)
421 || ((ptyp
== ptype_pbishop
)
423 && !diagonal(delta
)))
426 dest
[d
][s
] = nunmap
[p0
];
435 * Sort dest in number of steps order; currently no sort
436 * is done due to compatibility with the move generation
437 * order in old gnuchess.
442 for (di
= d
; s
> 0 && di
> 0; di
--)
444 if (steps
[sorted
[di
- 1]] == 0) /* should be: < s */
445 sorted
[di
] = sorted
[di
- 1];
454 * update nextpos/nextdir
458 pdir
[p0
] = (unsigned char)dest
[sorted
[0]][0];
460 for (d
= 0; d
< 8; d
++)
462 for (s
= 0; s
< steps
[sorted
[d
]]; s
++)
464 ppos
[p0
] = (unsigned char)dest
[sorted
[d
]][s
];
465 p0
= dest
[sorted
[d
]][s
];
468 pdir
[p0
] = (unsigned char)dest
[sorted
[d
+ 1]][0];
471 * else is already initialized
485 * Reset the board and other variables to start a new game.
491 short l
, c
, p
, max_opening_sequence
;
492 #ifdef HAVE_GETTIMEOFDAY
495 compptr
= oppptr
= 0;
497 stage2
= -1; /* the game is not yet started */
498 flag
.illegal
= flag
.mate
= flag
.post
= flag
.quit
499 = flag
.reverse
= flag
.bothsides
= flag
.onemove
= flag
.force
501 flag
.material
= flag
.coords
= flag
.hash
= flag
.easy
502 = flag
.beep
= flag
.rcptr
504 flag
.stars
= flag
.shade
= flag
.back
= flag
.musttimeout
= false;
509 GenCnt
= NodeCnt
= et0
= dither
= XCmore
= 0;
518 MaxSearchDepth
= MAXDEPTH
- 1;
523 CptrFlag
[0] = TesujiFlag
[0] = false;
526 GameType
[0] = GameType
[1] = UNKNOWN
;
527 Pscore
[0] = Tscore
[0] = (SCORE_LIMIT
+ 3000);
528 opponent
= player
= black
;
531 for (l
= 0; l
< TREE
; l
++)
532 Tree
[l
].f
= Tree
[l
].t
= 0;
534 gsrand((unsigned int) 1);
538 for (c
= black
; c
<= white
; c
++)
540 for (p
= pawn
; p
<= king
; p
++)
542 for (l
= 0; l
< NO_SQUARES
; l
++)
544 (*hashcode
)[c
][p
][l
].key
545 = (((unsigned long) urand()));
546 (*hashcode
)[c
][p
][l
].key
547 += (((unsigned long) urand()) << 16);
548 (*hashcode
)[c
][p
][l
].bd
549 = (((unsigned long) urand()));
550 (*hashcode
)[c
][p
][l
].bd
551 += (((unsigned long) urand()) << 16);
552 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
553 (*hashcode
)[c
][p
][l
].key
554 += (((unsigned long) urand()) << 32);
555 (*hashcode
)[c
][p
][l
].key
556 += (((unsigned long) urand()) << 48);
557 (*hashcode
)[c
][p
][l
].bd
558 += (((unsigned long) urand()) << 32);
559 (*hashcode
)[c
][p
][l
].bd
560 += (((unsigned long) urand()) << 48);
566 for (c
= black
; c
<= white
; c
++)
568 for (p
= pawn
; p
<= king
; p
++)
570 for (l
= 0; l
< MAX_CAPTURED
; l
++)
572 (*drop_hashcode
)[c
][p
][l
].key
573 = (((unsigned long) urand()));
574 (*drop_hashcode
)[c
][p
][l
].key
575 += (((unsigned long) urand()) << 16);
576 (*drop_hashcode
)[c
][p
][l
].bd
577 = (((unsigned long) urand()));
578 (*drop_hashcode
)[c
][p
][l
].bd
579 += (((unsigned long) urand()) << 16);
580 #if SIZEOF_LONG == 8 /* 64-bit long i.e. 8 bytes */
581 (*drop_hashcode
)[c
][p
][l
].key
582 += (((unsigned long) urand()) << 32);
583 (*drop_hashcode
)[c
][p
][l
].key
584 += (((unsigned long) urand()) << 48);
585 (*drop_hashcode
)[c
][p
][l
].bd
586 += (((unsigned long) urand()) << 32);
587 (*drop_hashcode
)[c
][p
][l
].bd
588 += (((unsigned long) urand()) << 48);
595 for (l
= 0; l
< NO_SQUARES
; l
++)
597 board
[l
] = Stboard
[l
];
598 color
[l
] = Stcolor
[l
];
606 #ifdef HAVE_GETTIMEOFDAY
607 gettimeofday(&tv
, NULL
);
608 time0
= tv
.tv_sec
*100 + tv
.tv_usec
/10000;
610 time0
= time((long *) 0);
613 /* resetting reference time */
614 ElapsedTime(COMPUTE_AND_INIT_MODE
);
615 flag
.regularstart
= true;
625 else if (MaxResponseTime
== 0)
628 UpdateDisplay(0, 0, 1, 0);
630 GetOpeningPatterns(&max_opening_sequence
);
643 hashbd
= hashkey
= 0;
653 gsrand(starttime
= ((unsigned int)time((long *)0))); /* init urand */
660 if (Initialize_data() != 0)
663 strcpy(ColorStr
[0], "Black");
664 strcpy(ColorStr
[1], "White");
690 #if !defined SAVE_NEXTPOS
708 hashfile
= fopen(HASHFILE
, RWA_ACC
);
712 fseek(hashfile
, 0L, SEEK_END
);
713 filesz
= ftell(hashfile
) / sizeof(struct fileentry
) - 1 - MAXrehash
;
714 hashmask
= filesz
>> 1;
715 hashbase
= hashmask
+ 1;
717 #endif /* HASHFILE */
734 #endif /* HASHFILE */