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 * ----------------------------------------------------------------------
36 static short DepthBeyond;
37 unsigned short PrVar[MAXDEPTH];
38 extern short recycle, ISZERO;
39 extern void FlagString(unsigned short flags, char *s);
42 short null; /* Null-move already made or not */
43 short PVari; /* Is this the PV */
50 /* ............ MOVE GENERATION & SEARCH ROUTINES .............. */
55 * Check for draw by fourfold repetition
56 * (same side, same captures, same board).
57 * WARNING: this is not save (sp? safe?) yet due to possible hash collisions.
68 if (GameCnt > Game50 + 6)
70 for (i = GameCnt - 1; i >= Game50; i -= 2)
74 if (g->hashkey == hashkey && g->hashbd == hashbd)
85 int plyscore, globalscore;
89 * Find the best move in the tree between indexes p1 and p2. Swap the best
90 * move into the p1 element.
94 pick(short p1, short p2)
96 struct leaf *p, *q, *r, *k;
104 for (r = p + 1; r <= q; r++)
124 int bookflag = false;
134 * Select a move by calling function search() at progressively deeper ply
135 * until time is up or a mate or draw is reached. An alpha-beta window of
136 * -Awindow to +Bwindow points is set around the score returned from the
137 * previous iteration. If Sdepth != 0 then the program has correctly
138 * predicted the opponents move and the search will start at a depth of
139 * Sdepth + 1 rather than a depth of 1.
143 SelectMove(short side, SelectMove_mode iop)
145 static short i, tempb, tempc, tempsf, tempst, xside, rpt;
146 static short alpha, beta, score;
147 static struct GameRec *g;
148 short sqking, in_check, blockable;
151 printf("hashbd = %ld (hashkey >> 16)|side = %d\n",
152 hashbd, (hashkey >> 16)|side);
155 flag.timeout = false;
157 flag.musttimeout = false;
162 recycle = (GameCnt % rehash) - rehash;
165 ExaminePosition(side);
167 /* if background mode set to infinite */
168 if (iop == BACKGROUND_MODE)
171 /* if background mode set response time to infinite */
172 ResponseTime = 9999999;
176 background = false; /* [HGM] with ponder on we did not switch back to foreground mode??? */
178 SetResponseTime(side);
181 #ifdef QUIETBACKGROUND
183 #endif /* QUIETBACKGROUND */
188 score = ScorePosition(side);
190 #ifdef QUIETBACKGROUND
192 #endif /* QUIETBACKGROUND */
195 #ifdef QUIETBACKGROUND
197 #endif /* QUIETBACKGROUND */
198 SearchStartStuff(side);
201 array_zero(history, sizeof_history);
204 FROMsquare = TOsquare = -1;
207 if (iop == FOREGROUND_MODE)
211 * If the last move was the hint, select the computed answer to the
212 * hint as first move to examine.
218 SwagHt = (GameList[GameCnt].gmove == PrVar[2]) ? PrVar[3] : 0;
225 for (i = 0; i < MAXDEPTH; i++)
226 PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
228 /* set initial window for search */
232 alpha = -(SCORE_LIMIT + 999);
233 beta = SCORE_LIMIT + 999;
237 alpha = score - ((computer == white) ? BAwindow : WAwindow);
238 beta = score + ((computer == white) ? BBwindow : WBwindow);
245 sqking = PieceList[side][0];
246 in_check = (board[sqking] == king)
247 ? SqAttacked(sqking, side^1, &blockable)
250 MoveList(side, 1, in_check, blockable);
252 for (i = TrPnt[1]; i < TrPnt[2]; i++)
254 if (!pick(i, TrPnt[2] - 1))
258 /* Can I get a book move? */
260 if (flag.regularstart && Book)
262 flag.timeout = bookflag = OpeningBook(&hint, side);
265 ResponseTime += ResponseTime;
268 /* Zero stats for hash table. */
270 reminus = replus = 0;
271 GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt
272 = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
274 globalscore = plyscore = score;
279 /********************* main loop ********************************/
281 Sdepth = (MaxSearchDepth < (MINDEPTH - 1))
285 while (!flag.timeout)
287 /* go down a level at a time */
295 /* terminate search at DepthBeyond ply past goal depth */
297 DepthBeyond = Sdepth;
300 DepthBeyond = Sdepth + ((Sdepth == 1) ? 3 : 5);
302 DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
305 # ifdef QUIETBACKGROUND
307 #endif /* QUIETBACKGROUND */
310 /* search at this level returns score of PV */
311 score = search(side, 1, Sdepth, alpha, beta, PrVar, &rpt);
313 /* save PV as killer */
314 for (i = 1; i <= Sdepth; i++)
315 killr0[i] = PrVar[i];
317 /* low search failure re-search with (-inf, score) limits */
321 #ifdef QUIETBACKGROUND
323 #endif /* QUIETBACKGROUND */
326 if (TCflag && TCcount < MAXTCCOUNTR)
329 ExtraTime += (MAXTCCOUNTR - TCcount) * TCleft;
331 ExtraTime += (8 * TCleft);
333 TCcount = MAXTCCOUNTR - 1;
336 score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
337 (SCORE_LIMIT + 999), PrVar, &rpt);
339 /* high search failure re-search with (score, +inf) limits */
340 else if (score > beta && !(root->flags & exact))
343 #ifdef QUIETBACKGROUND
345 #endif /* QUIETBACKGROUND */
348 score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
349 (SCORE_LIMIT + 999), PrVar, &rpt);
352 /**************** out of search ***********************************/
353 CheckForTimeout(score, globalscore, Jscore, zwndw);
355 /************************ time control ****************************/
357 /* save PV as killer */
358 for (i = 1; i <= Sdepth + 1; i++)
359 killr0[i] = PrVar[i];
364 /* if (!flag.timeout) */
366 for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
367 if (!pick (i, TrPnt[2] - 1))
371 /* if done or nothing good to look at quit */
372 if ((root->flags & exact) || (score < -SCORE_LIMIT))
375 /* find the next best move put below root */
379 #if !defined NODYNALPHA
380 Jscore = (plyscore + score) >> 1;
382 zwndw = 20 + abs(Jscore / 12);
385 /* recompute search window */
386 beta = score + ((computer == white) ? BBwindow : WBwindow);
387 #if !defined NODYNALPHA
388 alpha = ((Jscore < score) ? Jscore : score)
389 - ((computer == white) ? BAwindow : WAwindow)
392 alpha = score - ((computer == white) ? BAwindow : WAwindow);
396 #ifdef QUIETBACKGROUND
398 #endif /* QUIETBACKGROUND */
399 ShowResults(score, PrVar, '.');
402 /********************** end of main loop ***************************/
404 /* background mode */
405 if (iop == BACKGROUND_MODE)
411 DRAW = DRAW_REPETITION;
416 * If there are no moves and we're not in check (stalemate) then
417 * it's mate in shogi (whereas it's a draw in chess).
420 if (GameCnt == MAXMOVES)
423 DRAW = DRAW_MAXMOVES;
427 /* not in book so set hint to guessed move for other side */
429 hint = ((PrVar[1]) ? PrVar[2] : 0);
431 /* if not mate or draw make move and output it */
432 if (((score > -(SCORE_LIMIT + 999))
433 && (rpt <= 3)) || (root->flags & draw))
435 MakeMove(side, &Tree[0], &tempb, &tempc,
436 &tempsf, &tempst, &INCscore);
437 algbr(root->f, root->t, (short) root->flags);
441 algbr(0, 0, 0); /* Zero move string when mate. */
442 root->score = score; /* When mate, ignore distinctions!
446 g = &GameList[GameCnt];
448 if ((g->flags & capture) && (g->piece == king))
449 flag.mate = flag.illegal = true;
451 /* If Time Control get the elapsed time */
453 ElapsedTime(COMPUTE_AND_INIT_MODE);
455 /* update time control info */
458 /* if mate set flag */
459 if ((score == -(SCORE_LIMIT + 999) || score == (SCORE_LIMIT + 998)))
462 /* add move to game list */
465 g->time = (et +50)/100;
466 /* g->time = TCcount; */
469 /* update time control info */
472 TimeControl.clock[side] -= (et + OperatorTime);
473 timecomp[compptr] = (et + OperatorTime);
475 /* finished our required moves - setup the next set */
476 --TimeControl.moves[side];
479 /* check for end conditions */
480 if ((root->flags & draw) /* && flag.bothsides */)
484 else if (GameCnt == MAXMOVES)
488 /* out of move store, you lose */
491 /* switch to other side */
495 /* if mate clear hint */
505 * Perform an alpha-beta search to determine the score for the current
506 * board position. If depth <= 0 only capturing moves and responses to
507 * check are generated and searched, otherwise all moves are processed. The
508 * search depth is modified for check evasions, certain re-captures and
509 * threats. Extensions may continue for up to 11 ply beyond the nominal
519 unsigned short *bstline,
523 short tempb, tempc, tempsf, tempst;
524 short xside, pbst, score, rcnt, in_check, blockable;
525 unsigned short mv, nxtline[MAXDEPTH];
526 struct leaf *node, tmp;
527 short best = -(SCORE_LIMIT + 3000);
538 /* look every ZNODE nodes for a timeout */
543 if (NodeCnt > ETnodes)
545 ElapsedTime(COMPUTE_MODE);
551 flag.musttimeout = false;
553 else if (TCflag || MaxResponseTime)
555 if ((et >= (ResponseTime + ExtraTime))
556 && (Sdepth > MINDEPTH))
558 /* try to extend to finish ply */
559 if (flag.back || (TCflag && TCcount < MAXTCCOUNTX))
562 flag.musttimeout = true;
570 flag.musttimeout = false;
578 flag.musttimeout = false;
581 #ifdef QUIETBACKGROUND
586 else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
589 flag.musttimeout = false;
596 score = evaluate(side, ply, alpha, beta,
597 INCscore, &in_check, &blockable);
600 * check for possible repitition if so call repitition - rpt is
604 if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
609 * repeat position >3 don't need to return score it's taken
626 /* score > SCORE_LIMIT its a draw or mate */
627 if (score > SCORE_LIMIT)
633 /* Do we need to add depth because of special conditions */
634 /* if in check or in capture sequence search deeper */
636 /***************** depth extensions *****************/
640 /* Allow opponent a chance to check again */
647 && (score > alpha) && (score < beta)
649 && CptrFlag[ply - 1] && CptrFlag[ply - 2])
668 timeout = flag.timeout;
672 || ((!timeout && (hung[side] > 1))
673 && (ply == Sdepth + 1))))
677 else if ((score <= beta)
678 && (((ply < Sdepth + 4) && (ply > 4))
681 && (ChkFlag[ply - 2] != ChkFlag[ply - 4])))
687 /***************************************************/
688 /* try the local transition table if it's there */
691 if (/* depth > 0 && */ flag.hash && ply > 1)
694 && ProbeTTable(side, depth, ply, &alpha, &beta, &score) == true)
697 bstline[ply + 1] = 0;
699 if (beta == -((SCORE_LIMIT + 1000) * 2))
707 /* ok try the transition file if its there */
709 && (depth > HashDepth)
710 && (GameCnt < HashMoveLimit)
711 && (ProbeFTable(side, depth, ply, &alpha, &beta, &score)
714 PutInTTable(side, score, depth, ply, alpha, beta, PV);
716 bstline[ply + 1] = 0;
718 if (beta == -((SCORE_LIMIT + 1000) * 2))
726 #endif /* HASHFILE */
730 if (TrPnt[ply] > (TREE - 300))
736 * If more then DepthBeyond ply past goal depth or at goal depth and
737 * score > beta quit - means we are out of the window.
740 if (mustcut || (ply > DepthBeyond) || ((depth < 1) && (score > beta)))
744 * If below first ply and not at goal depth generate all moves else
745 * only capture moves.
750 if ((depth > 0) || (ply < (SDEPTHLIM))
751 || (background && (ply < Sdepth + 2)))
752 MoveList(side, ply, in_check, blockable);
754 CaptureList(side, ply, in_check, blockable);
757 /* no moves return what we have */
760 * normally a search will continue til past goal and no more capture
764 /* unless it hits DepthBeyond */
765 if (TrPnt[ply] == TrPnt[ply + 1])
768 /* if not at goal set best = -inf else current score */
769 best = (depth > 0) ? -(SCORE_LIMIT + 3000) : score;
775 /* CHECKME: is the & really an && here? */
776 if (!null && /* no previous null-move */
777 !PVari && /* no null-move during the PV */
778 (ply > 2) & /* not at ply 1 */
781 !in_check) /* no check */
782 /* enough material such that zugzwang is unlikely
783 * but who knows which value is suitable? */
786 OK, we make a null move, i.e. this means we have nothing to do
787 but we have to keep the some arrays up to date otherwise gnushogi
788 gets confused. Maybe somebody knows exactly which information is
789 important and which isn't.
791 Another idea is that we try the null-move first and generate the
792 moves later. This may save time but we have to take care that
793 PV and other variables contain the right value so that the move
794 ordering works right.
799 nxtline[ply + 1] = 0;
806 g = &GameList[++GameCnt];
807 g->hashkey = hashkey;
809 FROMsquare = TOsquare = -1;
816 best = -search(xside, ply + 1, depth - 2,
817 -beta - 1, -beta, nxtline, &rcnt);
824 best = -(SCORE_LIMIT + 3000);
826 else if (best > beta)
832 best = -(SCORE_LIMIT + 3000);
837 /* if best so far is better than alpha set alpha to best */
841 /********************** main loop ****************************/
843 /* look at each move until no more or beta cutoff */
844 for (pnt = pbst = TrPnt[ply];
845 (pnt < TrPnt[ply + 1]) && (best <= beta);
848 /* find the most interesting looking of the remaining moves */
850 pick(pnt, TrPnt[ply + 1] - 1);
853 PVari = PVarisave && (pnt == TrPnt[ply]); /* Is this the PV? */
858 /* is this a forbidden move */
859 if (/* ply == 1 && */ node->score <= DONTUSE)
862 nxtline[ply + 1] = 0;
864 /* if at top level */
868 /* at the top update search status */
871 #ifdef QUIETBACKGROUND
873 #endif /* QUIETBACKGROUND */
874 ShowCurrentMove(pnt, node->f, node->t);
879 if (!(node->flags & exact))
881 /* make the move and go deeper */
883 MakeMove(side, node, &tempb, &tempc, &tempsf,
885 CptrFlag[ply] = ((node->flags & capture) != 0);
886 TesujiFlag[ply] = (node->flags & tesuji)
887 && (node->flags & dropmask);
888 Tscore[ply] = node->score;
891 node->score = -search(xside, ply + 1,
892 (depth > 0) ? (depth - 1) : 0,
898 * node->score = score;
901 node->width = ((ply % 2) == 1)
902 ? (TrPnt[ply + 2] - TrPnt[ply + 1])
905 if ((node->score > SCORE_LIMIT) || (node->score < -SCORE_LIMIT) )
906 node->flags |= exact;
911 || ((node->score == (SCORE_LIMIT + 999) - ply)
914 node->flags |= (draw | exact);
915 DRAW = DRAW_JUSTDRAW;
916 node->score = ((side == computer) ? contempt : -contempt);
919 node->reply = nxtline[ply + 1];
921 /* reset to try next move */
922 UnmakeMove(side, node, &tempb, &tempc, &tempsf, &tempst);
925 /* if best move so far */
926 /* CHECKME: flag.timeout isn't valid if no hard time limit */
928 && ((node->score > best)
929 || ((node->score == best) && (node->width > bestwidth))))
932 * All things being equal pick the denser part of the
935 bestwidth = node->width;
938 * If not at goal depth and better than alpha and not
939 * an exact score increment by depth.
942 if ((depth > 0) && (node->score > alpha)
943 && !(node->flags & exact))
945 node->score += depth;
954 /* update best line */
955 for (j = ply + 1; nxtline[j] > 0; j++)
956 bstline[j] = nxtline[j];
959 bstline[ply] = (node->f << 8) | node->t;
965 * If it's better than the root score make it the root.
967 if ((best > root->score)
968 || ((best == root->score)
969 && (bestwidth > root->width)))
973 for (j = pnt - 1; j >= 0; j--)
974 Tree[j + 1] = Tree[j];
980 #ifdef QUIETBACKGROUND
983 #endif /* QUIETBACKGROUND */
988 ShowResults(best, bstline, '+');
990 else if (best < alpha)
992 ShowResults(best, bstline, '-');
996 ShowResults (best, bstline, '&');
999 #ifdef QUIETBACKGROUND
1006 return Tscore[ply - 1];
1009 /******************************************************/
1012 mv = (node->f << 8) | node->t;
1019 * We have a move so put it in local table - if it's already there
1020 * done else if not there or needs to be updated also put it in
1025 if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
1027 # ifdef HASHFILE /* MCV: warning: this confuses the formatter. */
1029 && PutInTTable(side, best, depth, ply, alpha, beta, mv)
1031 && (depth > HashDepth)
1032 && (GameCnt < HashMoveLimit))
1035 && PutInTTable(side, best, depth, ply, alpha, beta, mv))
1038 PutInFTable(side, best, depth, ply,
1039 alpha, beta, node->f, node->t);
1047 unsigned short h, x;
1050 if (history[x = hindex(side, h)] < HISTORYLIM)
1051 history[x] += (unsigned short) 1 << depth;
1054 if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
1060 else if (mv != killr1[ply])
1062 killr2[ply] = killr1[ply];
1067 killr0[ply] = ((best > SCORE_LIMIT) ? mv : 0);
1076 * Update the PieceList and Pindex arrays when a piece is captured or when a
1077 * capture is unmade.
1081 UpdatePieceList(short side, short sq, UpdatePieceList_mode iop)
1085 if (iop == REMOVE_PIECE)
1089 for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
1091 PieceList[side][i] = PieceList[side][i + 1];
1092 Pindex[PieceList[side][i]] = i;
1095 else if (board[sq] == king)
1097 /* king must have index 0 */
1098 for (i = PieceCnt[side]; i >= 0; i--)
1100 PieceList[side][i + 1] = PieceList[side][i];
1101 Pindex[PieceList[side][i + 1]] = i + 1;
1105 PieceList[side][0] = sq;
1111 PieceList[side][PieceCnt[side]] = sq;
1112 Pindex[sq] = PieceCnt[side];
1118 /* Make or Unmake drop move. */
1121 drop(short side, short piece, short f, short t, short iop)
1129 #if !defined SAVE_SVALUE
1133 n = Captured[side][piece]--;
1135 UpdateDropHashbd(side, piece, n);
1136 UpdateHashbd(side, piece, -1, t);
1137 UpdatePieceList(side, t, ADD_PIECE);
1141 ++PawnCnt[side][column(t)];
1145 HasPiece[side][piece]++;
1150 board[t] = no_piece;
1152 n = ++Captured[side][piece];
1154 UpdateDropHashbd(side, piece, n);
1155 UpdateHashbd(side, piece, -1, t);
1156 UpdatePieceList(side, t, REMOVE_PIECE);
1159 --PawnCnt[side][column(t)];
1162 HasPiece[side][piece]--;
1171 unsigned long chashkey, chashbd;
1173 chashbd = chashkey = 0;
1175 for (sq = 0; sq < NO_SQUARES; sq++)
1177 if (color[sq] != neutral)
1179 chashbd ^= (*hashcode)[color[sq]][board[sq]][sq].bd;
1180 chashkey ^= (*hashcode)[color[sq]][board[sq]][sq].key;
1183 /* hashcodes for initial board are 0 ! */
1184 if (Stcolor[sq] != neutral)
1186 chashbd ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].bd;
1187 chashkey ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].key;
1191 for (side = 0; side <= 1; side++)
1195 for (piece = 0; piece < NO_PIECES; piece++)
1197 short n = Captured[side][piece];
1203 for (i = 1; i <= n; i++)
1205 chashbd ^= (*drop_hashcode)[side][piece][i].bd;
1206 chashkey ^= (*drop_hashcode)[side][piece][i].key;
1212 if (chashbd != hashbd)
1213 printf("chashbd %lu != hashbd %lu\n", chashbd, hashbd);
1215 if (chashkey != hashkey)
1216 printf("chashkey %lu != hashkey %lu\n", chashkey, hashkey);
1218 if (chashbd != hashbd || chashkey != hashkey)
1229 * Update Arrays board[], color[], and Pindex[] to reflect the new board
1230 * position obtained after making the move pointed to by node. Also update
1231 * miscellaneous stuff that changes when a move is made.
1235 MakeMove(short side,
1237 short *tempb, /* piece at to square */
1238 short *tempc, /* color of to square */
1239 short *tempsf, /* static value of piece on from */
1240 short *tempst, /* static value of piece on to */
1241 short *INCscore) /* score increment */
1248 g = &GameList[++GameCnt];
1249 g->hashkey = hashkey;
1251 FROMsquare = f = node->f;
1252 TOsquare = t = (node->t & 0x7f);
1253 *INCscore = (short)node->INCscore;
1255 g->gmove = (f << 8) | node->t;
1256 g->flags = node->flags;
1262 algbr(f, t, node->flags);
1263 printf("error before MakeMove: %s\n", mvstr[0]);
1264 UpdateDisplay(0, 0, 1, 0);
1266 for (i = 1; i <= GameCnt; i++)
1268 movealgbr(GameList[i].gmove, mvstr[0]);
1269 printf("%d: %s\n", i, mvstr[0]);
1276 rpthash[side][hashkey & 0xFF]++, ISZERO++;
1280 g->fpiece = (node->flags & pmask);
1281 g->piece = *tempb = no_piece;
1282 g->color = *tempc = neutral;
1284 #if !defined SAVE_SVALUE
1286 *tempst = svalue[t];
1289 (void)drop(side, g->fpiece, f, t, 1);
1293 #if !defined SAVE_SVALUE
1294 *tempsf = svalue[f];
1295 *tempst = svalue[t];
1298 g->fpiece = board[f];
1299 g->piece = *tempb = board[t];
1300 g->color = *tempc = color[t];
1304 if (*tempc != neutral)
1306 /* Capture a piece */
1307 UpdatePieceList(*tempc, t, REMOVE_PIECE);
1309 /* if capture decrement pawn count */
1311 --PawnCnt[*tempc][column(t)];
1313 mtl[xside] -= (*value)[stage][*tempb];
1314 HasPiece[xside][*tempb]--;
1317 short n, upiece = unpromoted[*tempb];
1319 /* add "upiece" captured by "side" */
1320 n = ++Captured[side][upiece];
1322 UpdateDropHashbd(side, upiece, n);
1323 mtl[side] += (*value)[stage][upiece];
1326 /* remove "*tempb" of "xside" from board[t] */
1327 UpdateHashbd(xside, *tempb, -1, t);
1329 #if !defined SAVE_SVALUE
1330 *INCscore += *tempst; /* add value of catched piece
1339 #if !defined SAVE_SVALUE
1340 svalue[t] = svalue[f];
1344 Pindex[t] = Pindex[f];
1345 PieceList[side][Pindex[t]] = t;
1347 board[f] = no_piece;
1349 if (node->flags & promote)
1353 board[t] = tob = promoted[fromb];
1355 /* remove unpromoted piece from board[f] */
1356 UpdateHashbd(side, fromb, f, -1);
1358 /* add promoted piece to board[t] */
1359 UpdateHashbd(side, tob, -1, t);
1360 mtl[side] += value[stage][tob] - value[stage][fromb];
1363 --PawnCnt[side][column(f)];
1365 HasPiece[side][fromb]--;
1366 HasPiece[side][tob]++;
1368 #if !defined SAVE_SVALUE
1369 *INCscore -= *tempsf;
1375 /* remove piece from board[f] and add it to board[t] */
1376 UpdateHashbd(side, fromb, f, t);
1383 algbr(f, t, node->flags);
1387 printf("error in MakeMove: %s\n", mvstr[0]);
1401 UnmakeMove(short side,
1413 Game50 = GameList[GameCnt].Game50;
1415 if (node->flags & dropmask)
1417 (void)drop(side, (node->flags & pmask), f, t, 2);
1419 #if !defined SAVE_SVALUE
1420 svalue[t] = *tempst;
1427 color[f] = color[t];
1428 board[f] = tob = fromb = board[t];
1430 #if !defined SAVE_SVALUE
1431 svalue[f] = *tempsf;
1434 Pindex[f] = Pindex[t];
1435 PieceList[side][Pindex[f]] = f;
1439 #if !defined SAVE_SVALUE
1440 svalue[t] = *tempst;
1444 if (node->flags & promote)
1446 board[f] = fromb = unpromoted[tob];
1447 mtl[side] += value[stage][fromb] - value[stage][tob];
1450 ++PawnCnt[side][column(f)];
1452 HasPiece[side][fromb]++;
1453 HasPiece[side][tob]--;
1455 /* add unpromoted piece to board[f] */
1456 UpdateHashbd(side, fromb, f, -1);
1458 /* remove promoted piece from board[t] */
1459 UpdateHashbd(side, tob, -1, t);
1465 --PawnCnt[side][column(t)];
1466 ++PawnCnt[side][column(f)];
1469 /* remove piece from board[t] and add it to board[f] */
1470 UpdateHashbd(side, fromb, f, t);
1474 if (*tempc != neutral)
1476 short n, upiece = unpromoted[*tempb];
1478 UpdatePieceList(*tempc, t, ADD_PIECE);
1481 ++PawnCnt[*tempc][column(t)];
1483 mtl[xside] += (*value)[stage][*tempb];
1484 HasPiece[xside][*tempb]++;
1485 mtl[side] -= (*value)[stage][upiece];
1487 /* remove "upiece" captured by "side" */
1488 n = Captured[side][upiece]--;
1490 UpdateDropHashbd(side, upiece, n);
1492 /* replace captured piece on board[t] */
1493 UpdateHashbd(xside, *tempb, -1, t);
1501 rpthash[side][hashkey & 0xFF]--, ISZERO--;
1504 algbr(f, t, node->flags);
1508 printf("error in UnmakeMove: %s\n", mvstr[0]);
1517 * Scan thru the board seeing what's on each square. If a piece is found,
1518 * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
1519 * determine the material for each side and set the hashkey and hashbd
1520 * variables to represent the current board position. Array
1521 * PieceList[side][indx] contains the location of all the pieces of either
1522 * side. Array Pindex[sq] contains the indx into PieceList for a given
1527 InitializeStats(void)
1531 for (i = 0; i < NO_COLS; i++)
1532 PawnCnt[black][i] = PawnCnt[white][i] = 0;
1534 mtl[black] = mtl[white] = 0;
1535 PieceCnt[black] = PieceCnt[white] = 0;
1536 hashbd = hashkey = 0;
1538 for (sq = 0; sq < NO_SQUARES; sq++)
1540 if (color[sq] != neutral)
1542 mtl[color[sq]] += (*value)[stage][board[sq]];
1544 if (board[sq] == pawn)
1545 ++PawnCnt[color[sq]][column(sq)];
1547 Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
1548 PieceList[color[sq]][Pindex[sq]] = sq;
1549 UpdateHashbd(color[sq], board[sq], sq, -1);
1552 /* hashcodes for initial board are 0 ! */
1553 if (Stcolor[sq] != neutral)
1554 UpdateHashbd(Stcolor[sq], Stboard[sq], sq, -1);
1560 for (side = 0; side <= 1; side++)
1564 for (piece = 0; piece < NO_PIECES; piece++)
1566 short n = Captured[side][piece];
1570 Captured[side][piece] = 0;
1572 for (i = 1; i <= n; i++)
1574 ++Captured[side][piece];
1575 UpdateDropHashbd(side, piece, i);
1576 mtl[side] += (*value)[stage][piece];
1586 printf("error in InitializeStats\n");