home *** CD-ROM | disk | FTP | other *** search
- // ObjectWindows - (C) Copyright 1992 by Borland International
-
- #include <windows.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <stdio.h>
- #include <static.h>
- #include <filedial.h>
- #include <inputdia.h>
- #include "wcdefs.h"
- #include "wchess.h"
- #include "externs.h"
-
- #undef max
- #undef min
- #define max(a, b) (((a) > (b)) ? (a) : (b))
- #define min(a, b) (((a) < (b)) ? (a) : (b))
-
- BOOL ComputerThinking = FALSE;
- BOOL GotValidMove = FALSE;
- COLORTYPE Player, Opponent;
- DEPTHTYPE Depth;
- LINETYPE MainLine;
- MAXTYPE MainEvalu;
- int MaxDepth;
- int LegalMoves;
- PIECETAB PieceTab[2][16];
- extern double WantedTime;
- WORD MessageToPost;
- BOOL NoComputerMove = FALSE;
-
- static MOVETYPE movetemp[MAXPLY - BACK + 2];
-
- MOVETYPE *MovTab = &movetemp[-BACK];
-
- #define TOLERANCE 8
- #define IF_EQMOVE(a, b) if ((a.movpiece == b.movpiece) && (a.new1 \
- == b.new1) && (a.old == b.old) && (a.content == b.content) \
- && (a.spe == b.spe))
-
- typedef struct
- {
- short principvar; /* Principal variation search */
- MAXTYPE value, /* Static incremental evaluation */
- evaluation; /* Evaluation of position */
- } INFTYPE;
- typedef enum {mane, specialcap, kill, norml} MOVGENTYPE; /* move type */
- typedef struct
- {
- LINETYPE line; /* best line at next ply */
- short capturesearch; /* indicates capture search */
- MAXTYPE maxval; /* maximal evaluation returned in search */
- int nextply; /* Depth of search at next ply */
- INFTYPE next; /* information at Next ply */
- short zerowindow; /* Zero-width alpha-beta-window */
- MOVGENTYPE movgentype;
- } SEARCHTYPE;
-
- typedef struct
- {
- MAXTYPE alpha, beta;
- int ply;
- INFTYPE *inf;
- MOVETYPE *bestline;
- SEARCHTYPE *S;
- } PARAMTYPE;
-
- /*
- * Global Variables for this module
- */
-
- MOVETYPE killingmove[MAXPLY+1][2];
- short chcktb[MAXPLY+3];
- short *checktab = &chcktb[1];
- /* Square of eventual pawn on 7th rank */
- EDGESQUARETYPE passdpawn[MAXPLY+4];
- EDGESQUARETYPE *passedpawn = &passdpawn[2];
- BOOL SkipSearch;
-
-
-
- inline void DisplayMove()
- {
- if (!Depth)
- {
- sprintf(buf, "%-7d%7s", MaxDepth, MoveStr(&MovTab[0]));
- TInfo->SetDepthText(buf);
- }
- }
-
- /*
- * Initialize killingmove, checktab and passedpawn
- */
-
- static void clearkillmove(void)
- {
- const SQUARETYPE rank7[2] = {0x60, 0x10};
- DEPTHTYPE dep;
- COLORTYPE col;
- SQUARETYPE sq;
- unsigned char i;
-
- for (dep = 0; dep <= MAXPLY; dep++)
- for (i = 0; i < 2; i++)
- killingmove[dep][i] = ZeroMove;
- checktab[-1] = 0;
- passedpawn[-2] = -1; /* No check at first ply */
- passedpawn[-1] = -1;
- /* Place eventual pawns on 7th rank in passedpawn */
- for (col = white; col <= black; ((int)col)++)
- for (sq = rank7[col]; sq <= rank7[col] + 7; sq++)
- if ((Board[sq].piece == pawn) && (Board[sq].color == col))
- if (col == Player)
- passedpawn[-2] = sq;
- else
- passedpawn[-1] = sq;
- }
-
-
- static DEPTHTYPE searchstatedepth;
-
- /*
- * Backup the search and setup talk surroundings
- */
-
- static void getprogramstate(void)
- {
- COLORTYPE oldplayer;
-
- searchstatedepth = Depth;
- while (Depth > 0)
- {
- Depth--;
- oldplayer = Opponent;
- Opponent = Player;
- Player = oldplayer;
- Perform(&MovTab[Depth], 1);
- }
- Depth--;
- if (Opan) TakeBackMove(&MovTab[Depth]);
- }
-
-
- /*
- * Restore the search surroundings
- */
-
- static void getsearchstate(void)
- {
- COLORTYPE oldplayer;
-
- if (Opan) MakeMove(&MovTab[Depth+1]);
- Depth++;
- while (Depth < searchstatedepth)
- {
- Perform(&MovTab[Depth], 0);
- oldplayer = Player;
- Player = Opponent;
- Opponent = oldplayer;
- Depth++;
- }
- }
-
- inline BOOL UsableMessage(MSG msg)
- {
- if (msg.hwnd != hWndMain || msg.message != WM_COMMAND)
- return FALSE;
- return TRUE;
- }
-
- static void MessageScan()
- {
- MSG msg;
- extern HCURSOR hWaitCursor;
- extern HMENU ThinkMenu;
- extern HANDLE hAccel;
-
- if (!PeekMessage(&msg, hWndMain, 0, 0, PM_REMOVE))
- return;
- if (TranslateAccelerator(hWndMain, HACCEL(hAccel), &msg))
- {
- PostMessage(hWndMain, WM_COMMAND, MessageToPost, 0L);
- MessageToPost = 0;
- SkipSearch = FALSE;
- return;
- }
-
- if (Analysis)
- {
- switch (msg.message)
- {
- case WM_SETCURSOR :
- DispatchMessage(&msg);
- break;
- case WM_COMMAND :
- switch (msg.wParam)
- {
- case CM_STOP :
- SkipSearch = TRUE;
- AutoPlay = FALSE;
- break;
- }
- break;
- default:
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- break;
- }
- }
- else
- {
- switch (msg.message)
- {
- case WM_LBUTTONDOWN :
- getprogramstate();
- NoComputerMove = TRUE;
- GotValidMove = FALSE;
- DispatchMessage(&msg);
- NoComputerMove = FALSE;
- if (Opan && !MultiMove && GotValidMove)
- {
- IF_EQMOVE(KeyMove, MovTab[Depth + 1])
- {
- SkipSearch = FALSE;
- GotValidMove = FALSE;
- EnterKeyMove();
- StartAnalysis();
- PrintBestMove(&MainLine[0], MainEvalu);
- SetMenu(hWndMain, ThinkMenu);
- SetClassWord(hWndMain, GCW_HCURSOR, WORD(hWaitCursor));
- SetCursor(hWaitCursor);
- }
- else
- SkipSearch = TRUE;
- }
- getsearchstate();
- break;
- default:
- if (UsableMessage(msg))
- {
- SkipSearch = TRUE;
- if (msg.message != WM_PAINT)
- PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
- }
- else
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- break;
- }
- }
- }
-
-
- static INFTYPE startinf; /* Inf at first ply */
- static MAXTYPE alphawindow; /* alpha window value */
- static MAXTYPE repeatevalu; /* MainEvalu at ply one */
-
- static MAXTYPE search(MAXTYPE alpha, MAXTYPE beta, int ply, INFTYPE *inf,
- MOVETYPE *bestline);
-
- /*
- * Update killingmove using bestmove
- */
-
- inline void updatekill(MOVETYPE *bestmove)
- {
- if (bestmove->movpiece != empty)
- {
- /* Update killingmove unless the move is a capture of last
- piece moved */
- if ((MovTab[Depth - 1].movpiece == empty) ||
- (bestmove->new1 != MovTab[Depth-1].new1))
- if ((killingmove[Depth][0].movpiece == empty) ||
- (EqMove(bestmove, &killingmove[Depth][1])))
- {
- killingmove[Depth][1] = killingmove[Depth][0];
- killingmove[Depth][0] = *bestmove;
- }
- else if (!EqMove(bestmove, &killingmove[Depth][0]))
- killingmove[Depth][1] = *bestmove;
- }
- } /* Updatekill */
-
-
-
- /*
- * Test if move has been generated before
- */
-
- short generatedbefore(PARAMTYPE *P)
- {
- char i;
-
- if (P->S->movgentype != mane)
- {
- IF_EQMOVE(MovTab[Depth], P->bestline[Depth]) return 1;
-
-
- if (!P->S->capturesearch)
- if (P->S->movgentype != kill)
- for (i = 0; i < 2; i++)
- IF_EQMOVE(MovTab[Depth], killingmove[Depth][i])
- return 1;
- }
- return 0;
- }
-
-
- /*
- * Test cut-off. Cutval cantains the maximal possible evaluation
- */
-
- inline short cut(MAXTYPE cutval, PARAMTYPE *P)
- {
- short ct = 0;
-
- if (cutval <= P->alpha)
- {
- ct = 1;
- if (P->S->maxval < cutval) P->S->maxval = cutval;
- }
- return ct;
- }
-
-
- /*
- * Perform move, calculate evaluation, test cut-off, etc
- */
-
- static short update(PARAMTYPE *P)
- {
- short selection;
-
- IncNode(&Nodes);
- P->S->nextply = P->ply - 1; /* Calculate next ply */
- if (Level == matesearch) /* Matesearch */
- {
- Perform(&MovTab[Depth], 0); /* Perform Move on the board */
- /* Check if Move is legal */
- if (Attacks(Opponent, PieceTab[Player][0].isquare))
- goto TAKEBACKMOVE;
- if (!Depth) LegalMoves++;
- checktab[Depth] = 0;
- passedpawn[Depth] = -1;
- P->S->next.value = P->S->next.evaluation = 0;
- if (P->S->nextply <= 0) /* Calculate chech and perform evt. cut-off */
- {
- if (!P->S->nextply)
- checktab[Depth] = Attacks(Player,
- PieceTab[Opponent][0].isquare);
- if (!checktab[Depth])
- if (cut(P->S->next.value, P)) goto TAKEBACKMOVE;
- }
- goto ACCEPTMOVE;
- }
- /* Make special limited capturesearch at first iteration */
- if (MaxDepth <= 1)
- if (P->S->capturesearch && Depth >= 2)
- if (!((MovTab[Depth].content < MovTab[Depth].movpiece)
- || (P->S->movgentype == specialcap) || (MovTab[Depth].old
- == MovTab[Depth-2].new1)))
- goto CUTMOVE;
- /* Calculate nxt static incremental evaluation */
- P->S->next.value = -P->inf->value + StatEvalu(&MovTab[Depth]);
- /* Calculate checktab (only checks with moved piece are calculated)
- Giving Check does not count as a ply */
- checktab[Depth] = PieceAttacks(MovTab[Depth].movpiece, Player,
- MovTab[Depth].new1, PieceTab[Opponent][0].isquare);
- if (checktab[Depth]) P->S->nextply = P->ply;
- /* Calculate passedpawn. Moving a pawn to 7th rank does not
- count as a ply */
- passedpawn[Depth] = passedpawn[Depth - 2];
- if (MovTab[Depth].movpiece == pawn)
- if ((MovTab[Depth].new1 < 0x18) || (MovTab[Depth].new1 >= 0x60))
- {
- passedpawn[Depth] = MovTab[Depth].new1;
- P->S->nextply = P->ply;
- }
- /* Perform selection at last ply and in capture search */
- selection = ((P->S->nextply <= 0) && !checktab[Depth] && (Depth > 0));
- if (selection) /* check evaluation */
- if (cut(P->S->next.value + 0, P)) goto CUTMOVE;
- Perform(&MovTab[Depth], 0); /* perform move on the board */
- /* check if move is legal */
- if (Attacks(Opponent, PieceTab[Player][0].isquare))
- goto TAKEBACKMOVE;
- if (passedpawn[Depth] >= 0) /* check passedpawn */
- if (Board[passedpawn[Depth]].piece != pawn ||
- Board[passedpawn[Depth]].color != Player)
- passedpawn[Depth] = -1;
- if (!Depth)
- {
- LegalMoves++;
- P->S->next.value += random(4);
- }
- P->S->next.evaluation = P->S->next.value;
- ACCEPTMOVE:
- if (Analysis)
- DisplayMove();
- return 0;
- TAKEBACKMOVE:
- Perform(&MovTab[Depth], 1);
- CUTMOVE:
- if (Analysis)
- DisplayMove();
- return 1;
- }
-
-
- /*
- * Calculate draw bonus/penalty, and set draw if the game is a draw
- */
-
- static short drawgame(SEARCHTYPE *S)
- {
- int drawcount;
- REPEATTYPE searchrepeat;
- FIFTYTYPE searchfifty;
-
- if (Depth == 1)
- {
- searchfifty = FiftyMoveCnt();
- searchrepeat = Repetition(0);
- if (searchrepeat >= 3)
- {
- S->next.evaluation = 0;
- return 1;
- }
- drawcount = 0;
- if (searchfifty >= 96) /* 48 moves without pawn moves or captures */
- drawcount = 3;
- else
- {
- if (searchrepeat >= 2) /* 2nd repetition */
- drawcount = 2;
- else if (searchfifty >= 20) /* 10 moves without pawn moves or */
- drawcount = 1; /* captures */
- }
- S->next.value += (repeatevalu / 4) * drawcount;
- S->next.evaluation += (repeatevalu / 4 ) * drawcount;
- }
- if (Depth >= 3)
- {
- searchrepeat = Repetition(1);
- if (searchrepeat >= 2) /* Immediate repetition counts as */
- { /* a draw */
- S->next.evaluation = 0;
- return 1;
- }
- }
- return 0;
- }
-
-
- /*
- * Update bestline and MainEvalu using line and maxval
- */
-
- inline void updatebestline(PARAMTYPE *P)
- {
- memcpy(P->bestline, &P->S->line[0], sizeof(LINETYPE));
- /* *bestline = P->S->line; */
- P->bestline[Depth] = MovTab[Depth];
- if (!Depth)
- {
- MainEvalu = P->S->maxval;
- if (Level == matesearch)
- P->S->maxval = alphawindow;
- if (Analysis) PrintBestMove(&MainLine[0], MainEvalu);
- }
- }
-
-
- /*
- * The inner loop of the search procedure. MovTab[Depth] contains the move.
- */
-
- static short loopbody(PARAMTYPE *P)
- {
- COLORTYPE oldplayer;
- short lastanalysis;
-
- if (generatedbefore(P)) return 0;
- if (Depth < MAXPLY)
- {
- P->S->line[Depth + 1] = ZeroMove;
- if (P->S->movgentype == mane)
- memmove(&P->S->line[0], P->bestline, sizeof(LINETYPE));
- /* P->S->line = *bestline; */
- }
- /* Principvar indicates principal variation search */
- /* Zerowindow indicates zero - width alpha - beta window */
- P->S->next.principvar = 0;
- P->S->zerowindow = 0;
- if (P->inf->principvar)
- if (P->S->movgentype == mane)
- P->S->next.principvar = (P->bestline[Depth+1].movpiece != empty);
- else
- P->S->zerowindow = (P->S->maxval >= P->alpha);
- REPEATSEARCH:
- if (update(P)) return 0;
- if (Level == matesearch) /* stop evt. search */
- if ((P->S->nextply <= 0) && !checktab[Depth]) goto NOTSEARCH;
- if (drawgame(P->S)) goto NOTSEARCH;
- if (Depth >= MAXPLY)
- goto NOTSEARCH;
- /* Analyse nextply using a recursive call to search */
- oldplayer = Player;
- Player = Opponent;
- Opponent = oldplayer;
- Depth++;
- if (P->S->zerowindow)
- P->S->next.evaluation = -search(-P->alpha - 1, -P->alpha, P->S->nextply,
- &P->S->next, &P->S->line[0]);
- else
- P->S->next.evaluation = -search(-P->beta, -P->alpha, P->S->nextply,
- &P->S->next, &P->S->line[0]);
- Depth--;
- oldplayer = Opponent;
- Opponent = Player;
- Player = oldplayer;
- NOTSEARCH:
- Perform(&MovTab[Depth], 1); /* take back move */
- if (SkipSearch)
- return 1;
- lastanalysis = Analysis; /* scan messages and test SkipSearch */
- MessageScan();
- if (!SkipSearch)
- if (Analysis && !SingleStep && ((!Depth) || !lastanalysis))
- {
- StopTime(&ChessClock);
- if (MainEvalu > alphawindow)
- SkipSearch = ChessClock.totaltime >= (WantedTime * 1.5);
- }
- if (Analysis && (MaxDepth <= 1))
- SkipSearch = 0;
- P->S->maxval = max(P->S->maxval, P->S->next.evaluation); /* Update Maxval */
- IF_EQMOVE(P->bestline[Depth], MovTab[Depth]) /* Update evt. bestline */
- updatebestline(P);
- if (P->alpha < P->S->maxval) /* update alpha and test cutoff */
- {
- updatebestline(P);
- if (P->S->maxval >= P->beta)
- return 1;
- /* Adjust maxval (tolerance search) */
- if (P->ply >= 2 && P->inf->principvar && !P->S->zerowindow)
- P->S->maxval = min(P->S->maxval + TOLERANCE, P->beta - 1);
- P->alpha = P->S->maxval;
- if (P->S->zerowindow && ! SkipSearch)
- {
- /* repeat search with full window */
- P->S->zerowindow = 0;
- goto REPEATSEARCH;
- }
- }
- return SkipSearch;
- }
-
-
- /*
- * generate pawn promotions
- */
-
- static short pawnpromotiongen(PARAMTYPE *P)
- {
- PIECETYPE promote;
-
- MovTab[Depth].spe = 1;
- for (promote = queen; promote <= knight; ((int)promote)++)
- {
- MovTab[Depth].movpiece = promote;
- if (loopbody(P)) return 1;
- }
- MovTab[Depth].spe = 0;
- return 0;
- }
-
-
- /*
- * Generate captures of the piece on Newsq
- */
-
- static short capmovgen(SQUARETYPE newsq, PARAMTYPE *P)
- {
- EDGESQUARETYPE nxtsq, sq;
- INDEXTYPE i;
-
- MovTab[Depth].content = Board[newsq].piece;
- MovTab[Depth].spe = 0;
- MovTab[Depth].new1 = newsq;
- MovTab[Depth].movpiece = pawn; /* pawn captures */
- nxtsq = MovTab[Depth].new1 - PawnDir[Player];
- for (sq = nxtsq - 1; sq <= nxtsq + 1; sq++)
- if (sq != nxtsq)
- if (!(sq & 0x88))
- if (Board[sq].piece == pawn && Board[sq].color == Player)
- {
- MovTab[Depth].old = sq;
- if (MovTab[Depth].new1 < 8 || MovTab[Depth].new1
- >= 0x70)
- {
- if (pawnpromotiongen(P))
- return 1;
- }
- else if (loopbody(P))
- return 1;
- }
- for (i = OfficerNo[Player]; i >= 0; i--) /* other captures */
- if (PieceTab[Player][i].ipiece != empty &&
- PieceTab[Player][i].ipiece != pawn)
- if (PieceAttacks(PieceTab[Player][i].ipiece, Player,
- PieceTab[Player][i].isquare, newsq))
- {
- MovTab[Depth].old = PieceTab[Player][i].isquare;
- MovTab[Depth].movpiece = PieceTab[Player][i].ipiece;
- if (loopbody(P)) return 1;
- }
- return 0;
- }
-
-
- /*
- * Generates non captures for the piece on oldsq
- */
-
- static short noncapmovgen(SQUARETYPE oldsq, PARAMTYPE *P)
- {
- DIRTYPE first, last, dir;
- int direction;
- EDGESQUARETYPE newsq;
-
- MovTab[Depth].spe = 0;
- MovTab[Depth].old = oldsq;
- MovTab[Depth].movpiece = Board[oldsq].piece;
- MovTab[Depth].content = empty;
- switch (MovTab[Depth].movpiece)
- {
- case king :
- for (dir = 7; dir >= 0; dir--)
- {
- newsq = MovTab[Depth].old + DirTab[dir];
- if (!(newsq & 0x88))
- if (Board[newsq].piece == empty)
- {
- MovTab[Depth].new1 = newsq;
- if (loopbody(P))
- return 1;
- }
- }
- break;
- case knight :
- for (dir = 7; dir >= 0; dir--)
- {
- newsq = MovTab[Depth].old + KnightDir[dir];
- if (!(newsq & 0x88))
- if (Board[newsq].piece == empty)
- {
- MovTab[Depth].new1 = newsq;
- if (loopbody(P))
- return 1;
- }
- }
- break;
- case queen :
- case rook :
- case bishop :
- first = 7;
- last = 0;
- if (MovTab[Depth].movpiece == rook) first = 3;
- else if (MovTab[Depth].movpiece == bishop) last = 4;
- for (dir = first; dir >= last; dir--)
- {
- direction = DirTab[dir];
- newsq = MovTab[Depth].old + direction;
- while (!(newsq & 0x88))
- {
- if (Board[newsq].piece != empty) goto TEN;
- MovTab[Depth].new1 = newsq;
- if (loopbody(P))
- return 1;
- newsq = MovTab[Depth].new1 + direction;
- }
- TEN:
- continue;
- }
- break;
- case pawn :
- /* One square forward */
- MovTab[Depth].new1 = MovTab[Depth].old + PawnDir[Player];
- if (Board[MovTab[Depth].new1].piece == empty)
- if (MovTab[Depth].new1 < 8 || MovTab[Depth].new1 >= 0x70)
- {
- if (pawnpromotiongen(P)) return 1;
- }
- else
- {
- if (loopbody(P))
- return 1;
- if (MovTab[Depth].old < 0x18 || MovTab[Depth].old
- >= 0x60)
- {
- /* two squares forward */
- MovTab[Depth].new1 += (MovTab[Depth].new1
- - MovTab[Depth].old);
- if (Board[MovTab[Depth].new1].piece == empty)
- if (loopbody(P))
- return 1;
- }
- }
- } /* switch */
- return 0;
- }
-
-
- /*
- * castling moves
- */
-
- static short castlingmovgen(PARAMTYPE *P)
- {
- CASTDIRTYPE castdir;
-
- MovTab[Depth].spe = 1;
- MovTab[Depth].movpiece = king;
- MovTab[Depth].content = empty;
- for (castdir = (CASTDIRTYPE)(lng-1); castdir <= shrt-1; ((int)castdir)++)
- {
- MovTab[Depth].new1 = CastMove[Player][castdir].castnew;
- MovTab[Depth].old = CastMove[Player][castdir].castold;
- if (KillMovGen(&MovTab[Depth]))
- if (loopbody(P))
- return 1;
- }
- return 0;
- }
-
-
- /*
- * e.p. captures
- */
-
- static short epcapmovgen(PARAMTYPE *P)
- {
- EDGESQUARETYPE sq;
-
- if (MovTab[Depth - 1].movpiece == pawn)
- if (abs(MovTab[Depth - 1].new1 - MovTab[Depth - 1].old) >= 0x20)
- {
- MovTab[Depth].spe = 1;
- MovTab[Depth].movpiece = pawn;
- MovTab[Depth].content = empty;
- MovTab[Depth].new1 = (MovTab[Depth - 1].new1 +
- MovTab[Depth - 1].old) / 2;
- for (sq = MovTab[Depth - 1].new1 - 1; sq <=
- MovTab[Depth - 1].new1 + 1; sq++)
- if (sq != MovTab[Depth - 1].new1)
- if (!(sq & 0x88))
- {
- MovTab[Depth].old = sq;
- if (KillMovGen(&MovTab[Depth]))
- if (loopbody(P))
- return 1;
- }
- }
- return 0;
- }
-
-
- /*
- * Generate the next move to be analysed.
- * Controls the order of the movegeneration.
- * The moves are generated in the order:
- * Main variation
- * Captures of last moved piece
- * Killing moves
- * Other captures
- * Pawnpromovtions
- * Castling
- * Normal moves
- * E.p. captures
- */
-
- static void searchmovgen(PARAMTYPE *P)
- {
- INDEXTYPE index;
- char killno;
-
- /* generate move from main variation */
- if (P->bestline[Depth].movpiece != empty)
- {
- MovTab[Depth] = P->bestline[Depth];
- P->S->movgentype = mane;
- if (loopbody(P)) return;
- }
- if (MovTab[Depth - 1].movpiece != empty)
- if (MovTab[Depth - 1].movpiece != king)
- {
- P->S->movgentype = specialcap;
- if (capmovgen(MovTab[Depth - 1].new1, P)) return;
- }
- P->S->movgentype = kill;
- if (!P->S->capturesearch)
- for (killno = 0; killno <= 1; killno++)
- {
- MovTab[Depth] = killingmove[Depth][killno];
- if (MovTab[Depth - 1].movpiece != empty)
- if (KillMovGen(&MovTab[Depth]))
- if (loopbody(P)) return;
- }
- P->S->movgentype = norml;
- for (index = 1; index <= PawnNo[Opponent]; index++)
- if (PieceTab[Opponent][index].ipiece != empty)
- if (MovTab[Depth-1].movpiece == empty ||
- PieceTab[Opponent][index].isquare !=
- MovTab[Depth-1].new1)
- if (capmovgen(PieceTab[Opponent][index].isquare, P))
- return;
- if (P->S->capturesearch)
- {
- if (passedpawn[Depth-2] >= 0)
- if (Board[passedpawn[Depth-2]].piece == pawn &&
- Board[passedpawn[Depth-2]].color == Player)
- if (noncapmovgen(passedpawn[Depth-2], P)) return;
- }
- if (!P->S->capturesearch) /* non-captures */
- {
- if (castlingmovgen(P))
- return; /* castling */
- for (index = PawnNo[Player]; index >= 0; index--)
- if (PieceTab[Player][index].ipiece != empty)
- if (noncapmovgen(PieceTab[Player][index].isquare, P)) return;
- }
- if (epcapmovgen(P))
- return; /* e.p. captures */
- }
-
-
- /*
- * Perform the search
- * On entry :
- * Player is next to move
- * MovTab[Depth-1] contains last move
- * alpha, beta contains the alpha - beta window
- * ply contains the Depth of the search
- * inf contains various information
- *
- * On exit :
- * Bestline contains the principal variation
- * search contains the evaluation for Player
- */
-
- static MAXTYPE search(MAXTYPE alpha, MAXTYPE beta, int ply, INFTYPE *inf,
- MOVETYPE *bestline)
- {
- SEARCHTYPE S;
- PARAMTYPE P;
- /* Perform capturesearch if ply <= 0 and !check */
- S.capturesearch = ((ply <= 0) && !checktab[Depth-1]);
- if (S.capturesearch) /* initialize maxval */
- {
- S.maxval = -inf->evaluation;
- if (alpha < S.maxval)
- {
- alpha = S.maxval;
- if (S.maxval >= beta) goto STOP;
- }
- }
- else
- S.maxval = -(LOSEVALUE - Depth*DEPTHFACTOR);
- P.alpha = alpha;
- P.beta = beta;
- P.ply = ply;
- P.inf = inf;
- P.bestline = bestline;
- P.S = &S;
- searchmovgen(&P); /* The search loop */
- if (SkipSearch) goto STOP;
- if (S.maxval == -(LOSEVALUE - Depth * DEPTHFACTOR)) /* Test stalemate */
- if (!Attacks(Opponent, PieceTab[Player][0].isquare))
- {
- S.maxval = 0;
- goto STOP;
- }
- updatekill(&bestline[Depth]);
- STOP:
- return S.maxval;
- }
-
-
- /*
- * Begin the search
- */
-
- static MAXTYPE callsearch(MAXTYPE alpha, MAXTYPE beta)
- {
- MAXTYPE maxval;
-
- startinf.principvar = (MainLine[0].movpiece != empty);
- LegalMoves = 0;
- maxval = search(alpha, beta, MaxDepth, &startinf, &MainLine[0]);
- if (!LegalMoves)
- MainEvalu = maxval;
- return maxval;
- }
-
-
- /*
- * Checks whether the search time is used
- */
-
- inline short timeused(void)
- {
- short tu = 0;
-
- if (Analysis && !SingleStep)
- {
- StopTime(&ChessClock);
- tu = (ChessClock.totaltime >= WantedTime);
- }
- return tu;
- }
-
-
- /*
- * setup search
- */
-
- void FindMove(int maxlevel)
- {
- MAXTYPE maxval;
- double calcpvtime;
- InitTime(&ChessClock);
- StartTime(&ChessClock);
- InitNode(&Nodes);
- SkipSearch = 0;
- clearkillmove();
- CalcPVTable();
- StopTime(&ChessClock);
- calcpvtime = ChessClock.totaltime;
- startinf.value = startinf.evaluation = -RootValue;
- MaxDepth = 0;
- MainLine[0] = ZeroMove;
- MainEvalu = RootValue;
- alphawindow = MAXINT;
- ComputerThinking = TRUE;
- do
- {
- /* update various variables */
- if (MaxDepth <= 1) repeatevalu = MainEvalu;
- alphawindow = min(alphawindow, MainEvalu - 0x80);
- if (Level == matesearch)
- {
- alphawindow = 0x6000;
- if (MaxDepth > 0) MaxDepth++;
- }
- MaxDepth++;
- maxval = callsearch(alphawindow, 0x7f00); /* perform the search */
- if (maxval <= alphawindow && !SkipSearch && Level != matesearch &&
- LegalMoves > 0)
- {
- /* Repeat the search if the value falls below the
- alpha-window */
- MainEvalu = alphawindow;
- maxval = callsearch(-0x7F00, alphawindow - TOLERANCE * 2);
- LegalMoves = 2;
- }
- } while (!SkipSearch && !timeused() && (MaxDepth < maxlevel) &&
- (LegalMoves > 1) &&
- (abs(MainEvalu) < MATEVALUE - 24 * DEPTHFACTOR));
- ComputerThinking = FALSE;
- StopTime(&ChessClock);
-
- if (Analysis)
- PrintNodes(&Nodes, (ChessClock.totaltime - calcpvtime));
- }
-
-