4 * ----------------------------------------------------------------------
5 * Copyright (c) 1993, 1994, 1995 Matthias Mutz
6 * Copyright (c) 1999 Michael Vanier and the Free Software Foundation
8 * GNU SHOGI is based on GNU CHESS
10 * Copyright (c) 1988, 1989, 1990 John Stanback
11 * Copyright (c) 1992 Free Software Foundation
13 * This file is part of GNU SHOGI.
15 * GNU Shogi is free software; you can redistribute it and/or modify it
16 * under the terms of the GNU General Public License as published by the
17 * Free Software Foundation; either version 3 of the License,
18 * or (at your option) any later version.
20 * GNU Shogi is distributed in the hope that it will be useful, but WITHOUT
21 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 * You should have received a copy of the GNU General Public License along
26 * with GNU Shogi; see the file COPYING. If not, see
27 * <http://www.gnu.org/licenses/>.
28 * ----------------------------------------------------------------------
35 static short DepthBeyond;
36 unsigned short PrVar[MAXDEPTH];
37 extern short recycle, ISZERO;
38 extern void FlagString(unsigned short flags, char *s);
41 short null; /* Null-move already made or not */
42 short PVari; /* Is this the PV */
49 /* ............ MOVE GENERATION & SEARCH ROUTINES .............. */
54 * Check for draw by fourfold repetition
55 * (same side, same captures, same board).
56 * WARNING: this is not save (sp? safe?) yet due to possible hash collisions.
67 if (GameCnt > Game50 + 6)
69 for (i = GameCnt - 1; i >= Game50; i -= 2)
73 if (g->hashkey == hashkey && g->hashbd == hashbd)
84 int plyscore, globalscore;
88 * Find the best move in the tree between indexes p1 and p2. Swap the best
89 * move into the p1 element.
93 pick(short p1, short p2)
95 struct leaf *p, *q, *r, *k;
103 for (r = p + 1; r <= q; r++)
123 int bookflag = false;
133 * Select a move by calling function search() at progressively deeper ply
134 * until time is up or a mate or draw is reached. An alpha-beta window of
135 * -Awindow to +Bwindow points is set around the score returned from the
136 * previous iteration. If Sdepth != 0 then the program has correctly
137 * predicted the opponents move and the search will start at a depth of
138 * Sdepth + 1 rather than a depth of 1.
142 SelectMove(short side, SelectMove_mode iop)
144 static short i, tempb, tempc, tempsf, tempst, xside, rpt;
145 static short alpha, beta, score;
146 static struct GameRec *g;
147 short sqking, in_check, blockable;
150 printf("hashbd = %ld (hashkey >> 16)|side = %d\n",
151 hashbd, (hashkey >> 16)|side);
154 flag.timeout = false;
156 flag.musttimeout = false;
161 recycle = (GameCnt % rehash) - rehash;
164 ExaminePosition(side);
166 /* if background mode set to infinite */
167 if (iop == BACKGROUND_MODE)
170 /* if background mode set response time to infinite */
171 ResponseTime = 9999999;
175 background = false; /* [HGM] with ponder on we did not switch back to foreground mode??? */
177 SetResponseTime(side);
180 #ifdef QUIETBACKGROUND
182 #endif /* QUIETBACKGROUND */
183 dsp->ShowResponseTime();
187 score = ScorePosition(side);
189 #ifdef QUIETBACKGROUND
191 #endif /* QUIETBACKGROUND */
192 dsp->ShowSidetoMove();
194 #ifdef QUIETBACKGROUND
196 #endif /* QUIETBACKGROUND */
197 dsp->SearchStartStuff(side);
200 array_zero(history, sizeof_history);
203 FROMsquare = TOsquare = -1;
206 if (iop == FOREGROUND_MODE)
210 * If the last move was the hint, select the computed answer to the
211 * hint as first move to examine.
217 SwagHt = (GameList[GameCnt].gmove == PrVar[2]) ? PrVar[3] : 0;
224 for (i = 0; i < MAXDEPTH; i++)
225 PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
227 /* set initial window for search */
231 alpha = -(SCORE_LIMIT + 999);
232 beta = SCORE_LIMIT + 999;
236 alpha = score - ((computer == white) ? BAwindow : WAwindow);
237 beta = score + ((computer == white) ? BBwindow : WBwindow);
244 sqking = PieceList[side][0];
245 in_check = (board[sqking] == king)
246 ? SqAttacked(sqking, side^1, &blockable)
249 MoveList(side, 1, in_check, blockable);
251 for (i = TrPnt[1]; i < TrPnt[2]; i++)
253 if (!pick(i, TrPnt[2] - 1))
257 /* Can I get a book move? */
259 if (flag.regularstart && Book)
261 flag.timeout = bookflag = OpeningBook(&hint);
264 ResponseTime += ResponseTime;
267 /* Zero stats for hash table. */
269 reminus = replus = 0;
270 GenCnt = NodeCnt = ETnodes = EvalNodes = HashCnt
271 = FHashAdd = HashAdd = FHashCnt = THashCol = HashCol = 0;
273 globalscore = plyscore = score;
278 /********************* main loop ********************************/
280 Sdepth = (MaxSearchDepth < (MINDEPTH - 1))
284 while (!flag.timeout)
286 /* go down a level at a time */
294 /* terminate search at DepthBeyond ply past goal depth */
296 DepthBeyond = Sdepth;
299 DepthBeyond = Sdepth + ((Sdepth == 1) ? 3 : 5);
301 DepthBeyond = Sdepth + ((Sdepth == 1) ? 7 : 11);
304 # ifdef QUIETBACKGROUND
306 #endif /* QUIETBACKGROUND */
309 /* search at this level returns score of PV */
310 score = search(side, 1, Sdepth, alpha, beta, PrVar, &rpt);
312 /* save PV as killer */
313 for (i = 1; i <= Sdepth; i++)
314 killr0[i] = PrVar[i];
316 /* low search failure re-search with (-inf, score) limits */
320 #ifdef QUIETBACKGROUND
322 #endif /* QUIETBACKGROUND */
325 if (TCflag && TCcount < MAXTCCOUNTR)
328 ExtraTime += (MAXTCCOUNTR - TCcount) * TCleft;
330 ExtraTime += (8 * TCleft);
332 TCcount = MAXTCCOUNTR - 1;
335 score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
336 (SCORE_LIMIT + 999), PrVar, &rpt);
338 /* high search failure re-search with (score, +inf) limits */
339 else if (score > beta && !(root->flags & exact))
342 #ifdef QUIETBACKGROUND
344 #endif /* QUIETBACKGROUND */
347 score = search(side, 1, Sdepth, -(SCORE_LIMIT + 999),
348 (SCORE_LIMIT + 999), PrVar, &rpt);
351 /**************** out of search ***********************************/
352 CheckForTimeout(score, globalscore, Jscore, zwndw);
354 /************************ time control ****************************/
356 /* save PV as killer */
357 for (i = 1; i <= Sdepth + 1; i++)
358 killr0[i] = PrVar[i];
363 /* if (!flag.timeout) */
365 for (i = TrPnt[1] + 1; i < TrPnt[2]; i++)
366 if (!pick (i, TrPnt[2] - 1))
370 /* if done or nothing good to look at quit */
371 if ((root->flags & exact) || (score < -SCORE_LIMIT))
374 /* find the next best move put below root */
378 #if !defined NODYNALPHA
379 Jscore = (plyscore + score) >> 1;
381 zwndw = 20 + abs(Jscore / 12);
384 /* recompute search window */
385 beta = score + ((computer == white) ? BBwindow : WBwindow);
386 #if !defined NODYNALPHA
387 alpha = ((Jscore < score) ? Jscore : score)
388 - ((computer == white) ? BAwindow : WAwindow)
391 alpha = score - ((computer == white) ? BAwindow : WAwindow);
395 #ifdef QUIETBACKGROUND
397 #endif /* QUIETBACKGROUND */
398 dsp->ShowResults(score, PrVar, '.');
401 /********************** end of main loop ***************************/
403 /* background mode */
404 if (iop == BACKGROUND_MODE)
410 DRAW = DRAW_REPETITION;
415 * If there are no moves and we're not in check (stalemate) then
416 * it's mate in shogi (whereas it's a draw in chess).
419 if (GameCnt == MAXMOVES)
422 DRAW = DRAW_MAXMOVES;
426 /* not in book so set hint to guessed move for other side */
428 hint = ((PrVar[1]) ? PrVar[2] : 0);
430 /* if not mate or draw make move and output it */
431 if (((score > -(SCORE_LIMIT + 999))
432 && (rpt <= 3)) || (root->flags & draw))
434 MakeMove(side, &Tree[0], &tempb, &tempc,
435 &tempsf, &tempst, &INCscore);
436 algbr(root->f, root->t, (short) root->flags);
440 algbr(0, 0, 0); /* Zero move string when mate. */
441 root->score = score; /* When mate, ignore distinctions!
445 g = &GameList[GameCnt];
447 if ((g->flags & capture) && (g->piece == king))
448 flag.mate = flag.illegal = true;
450 /* If Time Control get the elapsed time */
452 ElapsedTime(COMPUTE_AND_INIT_MODE);
454 /* update time control info */
457 /* if mate set flag */
458 if ((score == -(SCORE_LIMIT + 999) || score == (SCORE_LIMIT + 998)))
461 /* add move to game list */
464 g->time = (et +50)/100;
465 /* g->time = TCcount; */
468 /* update time control info */
471 TimeControl.clock[side] -= (et + OperatorTime);
472 timecomp[compptr] = (et + OperatorTime);
474 /* finished our required moves - setup the next set */
475 --TimeControl.moves[side];
478 /* check for end conditions */
479 if ((root->flags & draw) /* && flag.bothsides */)
483 else if (GameCnt == MAXMOVES)
487 /* out of move store, you lose */
490 /* switch to other side */
494 /* if mate clear hint */
504 * Perform an alpha-beta search to determine the score for the current
505 * board position. If depth <= 0 only capturing moves and responses to
506 * check are generated and searched, otherwise all moves are processed. The
507 * search depth is modified for check evasions, certain re-captures and
508 * threats. Extensions may continue for up to 11 ply beyond the nominal
518 unsigned short *bstline,
522 short tempb, tempc, tempsf, tempst;
523 short xside, pbst, score, rcnt, in_check, blockable;
524 unsigned short mv, nxtline[MAXDEPTH];
525 struct leaf *node, tmp;
526 short best = -(SCORE_LIMIT + 3000);
537 /* look every ZNODE nodes for a timeout */
542 if (NodeCnt > ETnodes)
544 ElapsedTime(COMPUTE_MODE);
550 flag.musttimeout = false;
552 else if (TCflag || MaxResponseTime)
554 if ((et >= (ResponseTime + ExtraTime))
555 && (Sdepth > MINDEPTH))
557 /* try to extend to finish ply */
558 if (flag.back || (TCflag && TCcount < MAXTCCOUNTX))
561 flag.musttimeout = true;
569 flag.musttimeout = false;
577 flag.musttimeout = false;
580 #ifdef QUIETBACKGROUND
583 dsp->ShowResponseTime();
585 else if (!TCflag && flag.musttimeout && Sdepth > MINDEPTH)
588 flag.musttimeout = false;
595 score = evaluate(side, ply, alpha, beta,
596 INCscore, &in_check, &blockable);
599 * check for possible repitition if so call repitition - rpt is
603 if ((ply <= Sdepth + 3) && rpthash[side][hashkey & 0xFF] > 0)
608 * repeat position >3 don't need to return score it's taken
625 /* score > SCORE_LIMIT its a draw or mate */
626 if (score > SCORE_LIMIT)
632 /* Do we need to add depth because of special conditions */
633 /* if in check or in capture sequence search deeper */
635 /***************** depth extensions *****************/
639 /* Allow opponent a chance to check again */
646 && (score > alpha) && (score < beta)
648 && CptrFlag[ply - 1] && CptrFlag[ply - 2])
667 timeout = flag.timeout;
671 || ((!timeout && (hung[side] > 1))
672 && (ply == Sdepth + 1))))
676 else if ((score <= beta)
677 && (((ply < Sdepth + 4) && (ply > 4))
680 && (ChkFlag[ply - 2] != ChkFlag[ply - 4])))
686 /***************************************************/
687 /* try the local transition table if it's there */
690 if (/* depth > 0 && */ flag.hash && ply > 1)
693 && ProbeTTable(side, depth, ply, &alpha, &beta, &score) == true)
696 bstline[ply + 1] = 0;
698 if (beta == -((SCORE_LIMIT + 1000) * 2))
706 /* ok try the transition file if its there */
708 && (depth > HashDepth)
709 && (GameCnt < HashMoveLimit)
710 && (ProbeFTable(side, depth, ply, &alpha, &beta, &score)
713 PutInTTable(side, score, depth, ply, beta, PV);
715 bstline[ply + 1] = 0;
717 if (beta == -((SCORE_LIMIT + 1000) * 2))
725 #endif /* HASHFILE */
729 if (TrPnt[ply] > (TREE - 300))
735 * If more then DepthBeyond ply past goal depth or at goal depth and
736 * score > beta quit - means we are out of the window.
739 if (mustcut || (ply > DepthBeyond) || ((depth < 1) && (score > beta)))
743 * If below first ply and not at goal depth generate all moves else
744 * only capture moves.
749 if ((depth > 0) || (ply < (SDEPTHLIM))
750 || (background && (ply < Sdepth + 2)))
751 MoveList(side, ply, in_check, blockable);
753 CaptureList(side, ply, in_check, blockable);
756 /* no moves return what we have */
759 * normally a search will continue til past goal and no more capture
763 /* unless it hits DepthBeyond */
764 if (TrPnt[ply] == TrPnt[ply + 1])
767 /* if not at goal set best = -inf else current score */
768 best = (depth > 0) ? -(SCORE_LIMIT + 3000) : score;
774 /* CHECKME: is the & really an && here? */
775 if (!null && /* no previous null-move */
776 !PVari && /* no null-move during the PV */
777 (ply > 2) & /* not at ply 1 */
780 !in_check) /* no check */
781 /* enough material such that zugzwang is unlikely
782 * but who knows which value is suitable? */
785 OK, we make a null move, i.e. this means we have nothing to do
786 but we have to keep the some arrays up to date otherwise gnushogi
787 gets confused. Maybe somebody knows exactly which information is
788 important and which isn't.
790 Another idea is that we try the null-move first and generate the
791 moves later. This may save time but we have to take care that
792 PV and other variables contain the right value so that the move
793 ordering works right.
798 nxtline[ply + 1] = 0;
805 g = &GameList[++GameCnt];
806 g->hashkey = hashkey;
808 FROMsquare = TOsquare = -1;
815 best = -search(xside, ply + 1, depth - 2,
816 -beta - 1, -beta, nxtline, &rcnt);
823 best = -(SCORE_LIMIT + 3000);
825 else if (best > beta)
831 best = -(SCORE_LIMIT + 3000);
836 /* if best so far is better than alpha set alpha to best */
840 /********************** main loop ****************************/
842 /* look at each move until no more or beta cutoff */
843 for (pnt = pbst = TrPnt[ply];
844 (pnt < TrPnt[ply + 1]) && (best <= beta);
847 /* find the most interesting looking of the remaining moves */
849 pick(pnt, TrPnt[ply + 1] - 1);
852 PVari = PVarisave && (pnt == TrPnt[ply]); /* Is this the PV? */
857 /* is this a forbidden move */
858 if (/* ply == 1 && */ node->score <= DONTUSE)
861 nxtline[ply + 1] = 0;
863 /* if at top level */
866 /* at the top update search status */
869 #ifdef QUIETBACKGROUND
871 #endif /* QUIETBACKGROUND */
872 dsp->ShowCurrentMove(pnt, node->f, node->t);
876 if (!(node->flags & exact))
878 /* make the move and go deeper */
880 MakeMove(side, node, &tempb, &tempc, &tempsf,
882 CptrFlag[ply] = ((node->flags & capture) != 0);
883 TesujiFlag[ply] = (node->flags & tesuji)
884 && (node->flags & dropmask);
885 Tscore[ply] = node->score;
888 node->score = -search(xside, ply + 1,
889 (depth > 0) ? (depth - 1) : 0,
895 * node->score = score;
898 node->width = ((ply % 2) == 1)
899 ? (TrPnt[ply + 2] - TrPnt[ply + 1])
902 if ((node->score > SCORE_LIMIT) || (node->score < -SCORE_LIMIT) )
903 node->flags |= exact;
908 || ((node->score == (SCORE_LIMIT + 999) - ply)
911 node->flags |= (draw | exact);
912 DRAW = DRAW_JUSTDRAW;
913 node->score = ((side == computer) ? contempt : -contempt);
916 node->reply = nxtline[ply + 1];
918 /* reset to try next move */
919 UnmakeMove(side, node, &tempb, &tempc, &tempsf, &tempst);
922 /* if best move so far */
923 /* CHECKME: flag.timeout isn't valid if no hard time limit */
925 && ((node->score > best)
926 || ((node->score == best) && (node->width > bestwidth))))
929 * All things being equal pick the denser part of the
932 bestwidth = node->width;
935 * If not at goal depth and better than alpha and not
936 * an exact score increment by depth.
939 if ((depth > 0) && (node->score > alpha)
940 && !(node->flags & exact))
942 node->score += depth;
951 /* update best line */
952 for (j = ply + 1; nxtline[j] > 0; j++)
953 bstline[j] = nxtline[j];
956 bstline[ply] = (node->f << 8) | node->t;
962 * If it's better than the root score make it the root.
964 if ((best > root->score)
965 || ((best == root->score)
966 && (bestwidth > root->width)))
970 for (j = pnt - 1; j >= 0; j--)
971 Tree[j + 1] = Tree[j];
977 #ifdef QUIETBACKGROUND
980 #endif /* QUIETBACKGROUND */
985 dsp->ShowResults(best, bstline, '+');
987 else if (best < alpha)
989 dsp->ShowResults(best, bstline, '-');
993 dsp->ShowResults(best, bstline, '&');
996 #ifdef QUIETBACKGROUND
1003 return Tscore[ply - 1];
1006 /******************************************************/
1009 mv = (node->f << 8) | node->t;
1016 * We have a move so put it in local table - if it's already there
1017 * done else if not there or needs to be updated also put it in
1022 if (flag.hash && ply <= Sdepth && *rpt == 0 && best == alpha)
1024 # ifdef HASHFILE /* MCV: warning: this confuses the formatter. */
1026 && PutInTTable(side, best, depth, ply, beta, mv)
1028 && (depth > HashDepth)
1029 && (GameCnt < HashMoveLimit))
1032 && PutInTTable(side, best, depth, ply, beta, mv))
1035 PutInFTable(side, best, depth, ply,
1036 alpha, beta, node->f, node->t);
1044 unsigned short h, x;
1047 if (history[x = hindex(side, h)] < HISTORYLIM)
1048 history[x] += (unsigned short) 1 << depth;
1051 if (node->t != (short)(GameList[GameCnt].gmove & 0xFF))
1057 else if (mv != killr1[ply])
1059 killr2[ply] = killr1[ply];
1064 killr0[ply] = ((best > SCORE_LIMIT) ? mv : 0);
1073 * Update the PieceList and Pindex arrays when a piece is captured or when a
1074 * capture is unmade.
1078 UpdatePieceList(short side, short sq, UpdatePieceList_mode iop)
1082 if (iop == REMOVE_PIECE)
1086 for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
1088 PieceList[side][i] = PieceList[side][i + 1];
1089 Pindex[PieceList[side][i]] = i;
1092 else if (board[sq] == king)
1094 /* king must have index 0 */
1095 for (i = PieceCnt[side]; i >= 0; i--)
1097 PieceList[side][i + 1] = PieceList[side][i];
1098 Pindex[PieceList[side][i + 1]] = i + 1;
1102 PieceList[side][0] = sq;
1108 PieceList[side][PieceCnt[side]] = sq;
1109 Pindex[sq] = PieceCnt[side];
1115 /* Make or Unmake drop move. */
1118 drop(short side, short piece, short t, short iop)
1126 #if !defined SAVE_SVALUE
1130 n = Captured[side][piece]--;
1132 UpdateDropHashbd(side, piece, n);
1133 UpdateHashbd(side, piece, -1, t);
1134 UpdatePieceList(side, t, ADD_PIECE);
1138 ++PawnCnt[side][column(t)];
1142 HasPiece[side][piece]++;
1147 board[t] = no_piece;
1149 n = ++Captured[side][piece];
1151 UpdateDropHashbd(side, piece, n);
1152 UpdateHashbd(side, piece, -1, t);
1153 UpdatePieceList(side, t, REMOVE_PIECE);
1156 --PawnCnt[side][column(t)];
1159 HasPiece[side][piece]--;
1168 unsigned long chashkey, chashbd;
1170 chashbd = chashkey = 0;
1172 for (sq = 0; sq < NO_SQUARES; sq++)
1174 if (color[sq] != neutral)
1176 chashbd ^= (*hashcode)[color[sq]][board[sq]][sq].bd;
1177 chashkey ^= (*hashcode)[color[sq]][board[sq]][sq].key;
1180 /* hashcodes for initial board are 0 ! */
1181 if (Stcolor[sq] != neutral)
1183 chashbd ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].bd;
1184 chashkey ^= (*hashcode)[Stcolor[sq]][Stboard[sq]][sq].key;
1188 for (side = 0; side <= 1; side++)
1192 for (piece = 0; piece < NO_PIECES; piece++)
1194 short n = Captured[side][piece];
1200 for (i = 1; i <= n; i++)
1202 chashbd ^= (*drop_hashcode)[side][piece][i].bd;
1203 chashkey ^= (*drop_hashcode)[side][piece][i].key;
1209 if (chashbd != hashbd)
1210 printf("chashbd %lu != hashbd %lu\n", chashbd, hashbd);
1212 if (chashkey != hashkey)
1213 printf("chashkey %lu != hashkey %lu\n", chashkey, hashkey);
1215 if (chashbd != hashbd || chashkey != hashkey)
1226 * Update Arrays board[], color[], and Pindex[] to reflect the new board
1227 * position obtained after making the move pointed to by node. Also update
1228 * miscellaneous stuff that changes when a move is made.
1232 MakeMove(short side,
1234 short *tempb, /* piece at to square */
1235 short *tempc, /* color of to square */
1236 short *tempsf, /* static value of piece on from */
1237 short *tempst, /* static value of piece on to */
1238 short *INCscore) /* score increment */
1245 g = &GameList[++GameCnt];
1246 g->hashkey = hashkey;
1248 FROMsquare = f = node->f;
1249 TOsquare = t = (node->t & 0x7f);
1250 *INCscore = (short)node->INCscore;
1252 g->gmove = (f << 8) | node->t;
1253 g->flags = node->flags;
1259 algbr(f, t, node->flags);
1260 printf("error before MakeMove: %s\n", mvstr[0]);
1261 UpdateDisplay(0, 0, 1, 0);
1263 for (i = 1; i <= GameCnt; i++)
1265 movealgbr(GameList[i].gmove, mvstr[0]);
1266 printf("%d: %s\n", i, mvstr[0]);
1273 rpthash[side][hashkey & 0xFF]++, ISZERO++;
1277 g->fpiece = (node->flags & pmask);
1278 g->piece = *tempb = no_piece;
1279 g->color = *tempc = neutral;
1281 #if !defined SAVE_SVALUE
1283 *tempst = svalue[t];
1286 (void)drop(side, g->fpiece, t, 1);
1290 #if !defined SAVE_SVALUE
1291 *tempsf = svalue[f];
1292 *tempst = svalue[t];
1295 g->fpiece = board[f];
1296 g->piece = *tempb = board[t];
1297 g->color = *tempc = color[t];
1301 if (*tempc != neutral)
1303 /* Capture a piece */
1304 UpdatePieceList(*tempc, t, REMOVE_PIECE);
1306 /* if capture decrement pawn count */
1308 --PawnCnt[*tempc][column(t)];
1310 mtl[xside] -= (*value)[stage][*tempb];
1311 HasPiece[xside][*tempb]--;
1314 short n, upiece = unpromoted[*tempb];
1316 /* add "upiece" captured by "side" */
1317 n = ++Captured[side][upiece];
1319 UpdateDropHashbd(side, upiece, n);
1320 mtl[side] += (*value)[stage][upiece];
1323 /* remove "*tempb" of "xside" from board[t] */
1324 UpdateHashbd(xside, *tempb, -1, t);
1326 #if !defined SAVE_SVALUE
1327 *INCscore += *tempst; /* add value of catched piece
1336 #if !defined SAVE_SVALUE
1337 svalue[t] = svalue[f];
1341 Pindex[t] = Pindex[f];
1342 PieceList[side][Pindex[t]] = t;
1344 board[f] = no_piece;
1346 if (node->flags & promote)
1350 board[t] = tob = promoted[fromb];
1352 /* remove unpromoted piece from board[f] */
1353 UpdateHashbd(side, fromb, f, -1);
1355 /* add promoted piece to board[t] */
1356 UpdateHashbd(side, tob, -1, t);
1357 mtl[side] += value[stage][tob] - value[stage][fromb];
1360 --PawnCnt[side][column(f)];
1362 HasPiece[side][fromb]--;
1363 HasPiece[side][tob]++;
1365 #if !defined SAVE_SVALUE
1366 *INCscore -= *tempsf;
1372 /* remove piece from board[f] and add it to board[t] */
1373 UpdateHashbd(side, fromb, f, t);
1380 algbr(f, t, node->flags);
1384 printf("error in MakeMove: %s\n", mvstr[0]);
1398 UnmakeMove(short side,
1410 Game50 = GameList[GameCnt].Game50;
1412 if (node->flags & dropmask)
1414 (void)drop(side, (node->flags & pmask), t, 2);
1416 #if !defined SAVE_SVALUE
1417 svalue[t] = *tempst;
1424 color[f] = color[t];
1425 board[f] = tob = fromb = board[t];
1427 #if !defined SAVE_SVALUE
1428 svalue[f] = *tempsf;
1431 Pindex[f] = Pindex[t];
1432 PieceList[side][Pindex[f]] = f;
1436 #if !defined SAVE_SVALUE
1437 svalue[t] = *tempst;
1441 if (node->flags & promote)
1443 board[f] = fromb = unpromoted[tob];
1444 mtl[side] += value[stage][fromb] - value[stage][tob];
1447 ++PawnCnt[side][column(f)];
1449 HasPiece[side][fromb]++;
1450 HasPiece[side][tob]--;
1452 /* add unpromoted piece to board[f] */
1453 UpdateHashbd(side, fromb, f, -1);
1455 /* remove promoted piece from board[t] */
1456 UpdateHashbd(side, tob, -1, t);
1462 --PawnCnt[side][column(t)];
1463 ++PawnCnt[side][column(f)];
1466 /* remove piece from board[t] and add it to board[f] */
1467 UpdateHashbd(side, fromb, f, t);
1471 if (*tempc != neutral)
1473 short n, upiece = unpromoted[*tempb];
1475 UpdatePieceList(*tempc, t, ADD_PIECE);
1478 ++PawnCnt[*tempc][column(t)];
1480 mtl[xside] += (*value)[stage][*tempb];
1481 HasPiece[xside][*tempb]++;
1482 mtl[side] -= (*value)[stage][upiece];
1484 /* remove "upiece" captured by "side" */
1485 n = Captured[side][upiece]--;
1487 UpdateDropHashbd(side, upiece, n);
1489 /* replace captured piece on board[t] */
1490 UpdateHashbd(xside, *tempb, -1, t);
1498 rpthash[side][hashkey & 0xFF]--, ISZERO--;
1501 algbr(f, t, node->flags);
1505 printf("error in UnmakeMove: %s\n", mvstr[0]);
1514 * Scan thru the board seeing what's on each square. If a piece is found,
1515 * update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
1516 * determine the material for each side and set the hashkey and hashbd
1517 * variables to represent the current board position. Array
1518 * PieceList[side][indx] contains the location of all the pieces of either
1519 * side. Array Pindex[sq] contains the indx into PieceList for a given
1524 InitializeStats(void)
1528 for (i = 0; i < NO_COLS; i++)
1529 PawnCnt[black][i] = PawnCnt[white][i] = 0;
1531 mtl[black] = mtl[white] = 0;
1532 PieceCnt[black] = PieceCnt[white] = 0;
1533 hashbd = hashkey = 0;
1535 for (sq = 0; sq < NO_SQUARES; sq++)
1537 if (color[sq] != neutral)
1539 mtl[color[sq]] += (*value)[stage][board[sq]];
1541 if (board[sq] == pawn)
1542 ++PawnCnt[color[sq]][column(sq)];
1544 Pindex[sq] = ((board[sq] == king) ? 0 : ++PieceCnt[color[sq]]);
1545 PieceList[color[sq]][Pindex[sq]] = sq;
1546 UpdateHashbd(color[sq], board[sq], sq, -1);
1549 /* hashcodes for initial board are 0 ! */
1550 if (Stcolor[sq] != neutral)
1551 UpdateHashbd(Stcolor[sq], Stboard[sq], sq, -1);
1557 for (side = 0; side <= 1; side++)
1561 for (piece = 0; piece < NO_PIECES; piece++)
1563 short n = Captured[side][piece];
1567 Captured[side][piece] = 0;
1569 for (i = 1; i <= n; i++)
1571 ++Captured[side][piece];
1572 UpdateDropHashbd(side, piece, i);
1573 mtl[side] += (*value)[stage][piece];
1583 printf("error in InitializeStats\n");