{                             SEARCH.CH
                              CHESS 4.0
            Copyright (c) 1985, 87 by Borland International, Inc.
 
  This module performs look ahead analysis.
 
}
var
  KillingMove : array[ 0..MaxPly,0..1] of MoveType;
  CheckTab : array[-1..MaxPly] of boolean;       { Table of checks }
  { Square of eventual pawn On 7th Rank }
  PassedPawn : array[-2..MaxPly] of EdgeSquareType;
 
procedure ClearKillMove;
{ Initializes KillingMove, CheckTab and PassedPawn }
const rank7 : array[ColorType] of SquareType = ($60,$10);
var
  Dep : DepthType;
  Col : ColorType;
  Sq  : SquareType;
  i   : byte;
begin
  for Dep := 0 to MaxPly do for i := 0 to 1 do  {     Clear KillingMove }
    KillingMove[Dep,i] := ZeroMove;
  CheckTab[-1] := False;                        { No Check at First Ply }
  PassedPawn[-2] := -1;
  PassedPawn[-1] := -1;
  { Place eventual pawns On 7th Rank in PassedPawn }
  for Col := White to Black do
    for Sq := rank7[Col] to rank7[Col] + 7 do
      with Board[Sq] do
        if (Piece = Pawn) and (Color = Col) then
          if Col = Player then
            PassedPawn[-2] := Sq
          else
            PassedPawn[-1] := Sq;
end; { ClearKillMove }
 
var   SkipSearch : boolean;
procedure CallSmallTalk;
{ Communicates with the user }
var   SearchStateDepth : DepthType;
 
   procedure GetProgramState;
   { Backup the Search and setup Talk surroundings }
   var   OldPlayer : ColorType;
   begin
      SearchStateDepth := Depth;
      while Depth > 0 do
      begin
         Depth := Depth - 1;
         OldPlayer := Opponent;
         Opponent := Player;
         Player   := OldPlayer;
         Perform(MovTab[Depth],true);
      end;
      Depth := Depth - 1;
      if OpAn then TakeBackMove(MovTab[Depth]);
   end; { GetProgramState }
 
   procedure GetSearchState;
   { Restore the Search surroundings }
   var   OldPlayer : ColorType;
   begin
      if OpAn then MakeMove(MovTab[Depth + 1]);
      Depth := Depth + 1;
      while Depth < SearchStateDepth do
      begin
         Perform(MovTab[Depth],False);
         OldPlayer := Player;
         Player   := Opponent;
         Opponent := OldPlayer;
         Depth := Depth + 1;
      end;
   end; { GetSearchState }
 
begin { CallSmallTalk }
   GetProgramState;     { Setup surroundings }
   MainOption;          { makes sure that the current option
                          variable is set for case statements }
   SmallTalk;
   if Length(Command) > 0 then
      if Analysis then
      begin
         if CurOpt = PlayIt then    { Terminate Search or ignore input }
            SkipSearch := true
         else
            Command :='';
      end
      else
      begin     { Continue Search if the Hint Move is entered,
                  otherwise Skip Search }
         SkipSearch := true;
         if OpAn and not MultiMove then
            if Command ='Move' then
               if EqMove(KeyMove,MovTab[Depth + 1]) then
               begin
                  SkipSearch := False;
                  EnterKeyMove;
                  StartAnalysis;
                  PrintBestMove(MainLine,MainEvalu);
               end;
      end;
 
   GetSearchState;             { Restore Search surroundings }
end;
 
type  InfType = record
                   PrincipVar : boolean;  { Principal Variation Search }
                   Value,              { Static incremental Evaluation }
                   Evaluation : MaxType;      { Evaluation of position }
                end;
 
var   StartInf :   InfType;    { Inf at First Ply }
      AlphaWindow : MaxType;   { Alpha window Value }
      RepeatEvalu : MaxType;   { MainEvalu at Ply One }
 
function Search(Alpha, Beta :   MaxType;
                Ply :          integer;
                Inf :          InfType;
       var BestLine :          LineType) : MaxType;
 
{ Performs 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 informations.
 
  On Exit :
     BestLine contains the principal variation.
     Search contains the Evaluation for Player }
 
var   Line :          LineType;   { Best Line at Next Ply }
      CaptureSearch : boolean;    { Indicates capture Search }
      MaxVal:        MaxType;    { Maximal Evaluation
                                   (returned in Search) }
      NextPly :       integer;    { Depth of Search at Next Ply }
      Next :          InfType;    { Information at Next Ply }
      ZeroWindow :    boolean;    { Zero-Width Alpha-Beta-window }
      MovGenType :    (Main,SpecialCap,Kill,Normal);   { Move type }
 
procedure UpdateKill(BestMove : MoveType);
{ Update KillingMove using BestMove }
begin
   with BestMove do
      if MovPiece <> Empty then
      begin
         { Update KillingMove unless the Move is a capture of
           Last moved Piece }
         if (MovTab[Depth - 1].MovPiece = Empty) or
            (New1 <> MovTab[Depth - 1].New1) then
            if (KillingMove[Depth,0].MovPiece = Empty) or
               EqMove(BestMove,KillingMove[Depth,1]) then
            begin
               KillingMove[Depth,1] := KillingMove[Depth,0];
               KillingMove[Depth,0] := BestMove;
            end
            else
              if not EqMove(BestMove,KillingMove[Depth,0]) then
              begin
                 KillingMove[Depth,1] := BestMove;
              end;
      end; { if }
end; { UpdateKill }
 
 
function LoopBody : boolean;
{ The inner loop of the Search procedure.
  MovTab[Depth] contains the Move }
 
   function GeneratedBefore : boolean;
   { Test if Move has been generated before }
   var i : 0..1;
   begin
      GeneratedBefore := true;
      if MovGenType <> Main then
      begin
         if EqMove(MovTab[Depth],BestLine[Depth]) then Exit;
         if not CaptureSearch then
            if MovGenType <> Kill then
                  for i := 0 to 1 do
                     if EqMove(MovTab[Depth],
                               KillingMove[Depth,i]) then Exit;
      end;
      GeneratedBefore := False;
   end; { GeneratedBefore }
 
function Update : boolean;
{ Performs Move, calculates Evaluation, tests Cut-off etc. }
 
function Cut(CutVal : MaxType) : boolean;
{ Tests Cut-off. CutVal contains the maximal Possible Evaluation }
begin
   Cut := False;
   if CutVal <= Alpha then
   begin
      Cut := true;
      if MaxVal < CutVal then MaxVal := CutVal;
   end;
end; { Cut }
 
var
  Selection : boolean;
 
label AcceptMove,TakeBackMove,CutMove;
begin    { Update }
  with MovTab[Depth] do
  begin
    IncNode(Nodes);
    NextPly := Ply - 1;                { Calculate next ply }
    if Level = MateSearch then           { MateSearch }
    begin
      Perform(MovTab[Depth],False);   { Perform Move On the Board }
      { Check if Move is Legal }
      if Attacks(Opponent,PieceTab[Player,0].ISquare) then
        goto TakeBackMove;
      if Depth = 0 then
        LegalMoves := LegalMoves + 1;
      CheckTab[Depth] := False;
      PassedPawn[Depth] := -1;
      Next.Value := 0;
      Next.Evaluation := 0;
      if NextPly <= 0 then { Calculate Check and Perform evt. Cut-off }
      begin
        if NextPly = 0 then
        CheckTab[Depth] := Attacks(Player,PieceTab[Opponent,0].ISquare);
        if not CheckTab[Depth] then
        begin
          if Cut(Next.Value) then goto TakeBackMove;
        end;
     end;
     goto AcceptMove;
   end;
   { Make special limited CaptureSearch at First iteration }
   if MaxDepth <= 1 then
     if CaptureSearch and (Depth >= 2) then
       if not ((Content < MovPiece) or
              (MovGenType = SpecialCap) or
              (Old = MovTab[Depth - 2].New1)) then
         goto CutMove;
         { Calculate Next static incremental Evaluation }
   Next.Value := -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(MovPiece,Player,New1,
                                   PieceTab[Opponent,0].ISquare);
   if CheckTab[Depth] then NextPly := Ply;
    { Calculate PassedPawn. Moving a Pawn to 7th Rank does not Count as a Ply }
   PassedPawn[Depth] := PassedPawn[Depth - 2];
   if MovPiece = Pawn then
     if (New1 < $18) or (New1 >= $60) then
     begin
       PassedPawn[Depth] := New1;
       NextPly := Ply;
     end;
     { Perform Selection at Last Ply and in capture Search }
     Selection := (NextPly <= 0) and not CheckTab[Depth] and (Depth > 0);
     if Selection then                  { Check Evaluation }
     if Cut(Next.Value + 0) then goto CutMove;
     Perform(MovTab[Depth],False);  { Perform Move On the Board }
     { check if move is legal }
     if Attacks(Opponent,PieceTab[Player,0].ISquare) then goto TakeBackMove;
     if PassedPawn[Depth] >= 0 then            { Check PassedPawn }
       with Board[PassedPawn[Depth]] do
         if (Piece <> Pawn) or (Color <> Player) then
           PassedPawn[Depth] := -1;
     if Depth = 0 then      { Count Number of Legal moves at Ply 0 }
       LegalMoves := LegalMoves + 1;
     if Depth = 0 then                          { Calculate Random }
       Next.Value := Next.Value + Random(4);
     { Calculate the Evaluation for the position }
     Next.Evaluation := Next.Value;
   end { with };
AcceptMove :
   if Analysis then
     DisplayMove(SingleStep,MaxDepth,Next.Evaluation,False);
   Update := False;
   Exit;
TakeBackMove :
   Perform(MovTab[Depth],true);
CutMove :
   if Analysis then
   begin
     DisplayMove(SingleStep,MaxDepth,Next.Evaluation,true);
   end;
   Update := true;
end { Update };
 
   function DrawGame : boolean;
   { Calculate Draw bonus/penalty, and set Draw if the game is a Draw }
   var   DrawCount : 0..4;
         SearchRepeat : RepeatType;
         SearchFifty : FiftyType;
   begin
      DrawGame := False;
      if Depth = 1 then
      begin
         SearchFifty := FiftyMoveCnt;
         SearchRepeat := Repetition(False);
         if SearchRepeat >= 3 then              { 3rd Repetition is Draw }
         begin
            DrawGame := true;
            Next.Evaluation := 0;
            Exit;
         end;
         DrawCount := 0;
         if SearchFifty >= 96 then        { 48 moves without Pawn }
            DrawCount := 3                  {  moves or captures }
         else
           if SearchRepeat >= 2 then         { 2nd Repetition }
              DrawCount := 2
           else
             if SearchFifty >= 20 then        { 10 moves without Pawn }
                DrawCount := 1;                 {  moves or captures }
         Next.Value :=
            Next.Value + (RepeatEvalu div 4) * DrawCount;
         Next.Evaluation :=
            Next.Evaluation + (RepeatEvalu div 4) * DrawCount;
      end; { if }
      if Depth >= 3 then
      begin
         SearchRepeat := Repetition(true);
         if SearchRepeat >= 2 then
         begin                          { Immediate Repetition }
            DrawGame := true;                 {  counts as a Draw }
            Next.Evaluation := 0;
            Exit;
         end;
      end; { if }
   end; { DrawGame }
 
   procedure UpdateBestLine;
   { Update BestLine and MainEvalu using Line and MaxVal }
   begin
      BestLine := Line;
      BestLine[Depth] := MovTab[Depth];
      if Depth = 0 then
      begin
         MainEvalu := MaxVal;
         if Level = MateSearch then
            MaxVal := AlphaWindow;
         if Analysis then PrintBestMove(MainLine,MainEvalu);
      end;
   end { UpdateBestLine };
 
var   OldPlayer :    ColorType;
      LastAnalysis : boolean;
 
label RepeatSearch,NotSearch;
begin
   LoopBody := False;
   if GeneratedBefore then Exit;
   if Depth < MaxPly then                   { Initialize Line }
   begin
      Line[Depth + 1] := ZeroMove;
      if MovGenType = Main then
         Line := BestLine;
   end;
   { PrincipVar indicates Principal Variation Search.
     ZeroWindow indicates zero - Width Alpha - Beta window }
   Next.PrincipVar := False;
   ZeroWindow := False;
   if Inf.PrincipVar then
      if MovGenType = Main then
         Next.PrincipVar := BestLine[Depth + 1].MovPiece <> Empty
      else
         ZeroWindow := MaxVal >= Alpha;
RepeatSearch :
   if Update then Exit;         { Update and test Cut-off }
   if Level = MateSearch then     { Stop evt. Search }
      if (NextPly <= 0) and not CheckTab[Depth] then goto NotSearch;
   if DrawGame then goto NotSearch;
   if Depth >= MaxPly then
      goto NotSearch;
   { Analyse NextPly using a recursive call to Search }
   OldPlayer := Player;   Player := Opponent;
   Opponent := OldPlayer;
   Depth := Depth + 1;
   if ZeroWindow then
      Next.Evaluation := -Search(-Alpha - 1,- Alpha,NextPly,Next,Line)
   else
      Next.Evaluation := -Search(-Beta  ,- Alpha,NextPly,Next,Line);
   Depth := Depth - 1;
   OldPlayer := Opponent;   Opponent := Player;   Player := OldPlayer;
NotSearch :
   Perform(MovTab[Depth],true);                 { Take Back Move }
   if SkipSearch then
   begin
      LoopBody := true;
      Exit;
   end;
   LastAnalysis := Analysis;   { Scan keyboard and test SkipSearch }
   ScanKeys;
   if Length(Command) > 0 then
      CallSmallTalk;
   if not SkipSearch then
      if Analysis and not SingleStep and
         ((Depth = 0) or not LastAnalysis) then
      begin
         StopTime(Clock);
         if MainEvalu > AlphaWindow then
            SkipSearch := Clock.TotalTime >= WantedTime * 1.5;
      end;
   if Analysis and (MaxDepth <= 1) then
      SkipSearch := False;
   MaxVal := Max(MaxVal,Next.Evaluation);            { Update MaxVal }
   if EqMove(BestLine[Depth],MovTab[Depth]) then   { Update evt. BestLine }
      UpdateBestLine;
   if Alpha < MaxVal then                   { Update Alpha and test Cut-off }
   begin
      UpdateBestLine;
      if MaxVal >= Beta then
      begin
         LoopBody := true;                  { Cut-off }
         Exit;
      end;
      { Adjust MaxVal (Tolerance Search) }
      if (Ply >= 2) and Inf.PrincipVar and not ZeroWindow then
         MaxVal := Min(MaxVal + Tolerance,Beta - 1);
      Alpha := MaxVal;
      if ZeroWindow and not SkipSearch then
      begin
         { repeat Search with full window }
         ZeroWindow := False;
         goto RepeatSearch;
      end;
   end;
   LoopBody := SkipSearch;
end { LoopBody };
 
procedure SearchMovGen;
{ Generates 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
}
 
   function PawnPromotionGen : boolean;
   { Generate Pawn promotions }
   var   Promote : PieceType;
   begin
      PawnPromotionGen := true;
      with MovTab[Depth] do
      begin
         Spe := true;
         for Promote := Queen to Knight do
         begin
            MovPiece := Promote;
            if LoopBody then Exit;
         end;
         Spe := False;
      end;
      PawnPromotionGen := False;
   end; { PawnPromotionGen }
 
   function CapMovGen(NewSq : SquareType) : boolean;
   { Generates captures of the Piece On NewSq }
   var   NextSq,Sq : EdgeSquareType;
         i :  IndexType;
   begin
      CapMovGen := true;
      with MovTab[Depth] do
      begin
         Content := Board[NewSq].Piece;
         Spe := False;
         New1 := NewSq;
         MovPiece := Pawn;                       { Pawn captures }
         NextSq := New1 - PawnDir[Player];
         for Sq := NextSq - 1 to NextSq + 1 do
           if Sq <> NextSq then
             if (Sq and $88) = 0 then
               with Board[Sq] do
                  if (Piece = Pawn) and (Color = Player) then
                  begin
                     Old := Sq;
                     if (New1 < 8) or (New1 >= $70) then
                     begin
                        if PawnPromotionGen then Exit;
                     end
                     else
                       if LoopBody then Exit;
                  end;
         for i := OfficerNo[Player] downto 0 do      { Other captures }
            with PieceTab[Player,i] do
               if (IPiece <> Empty) and (IPiece <> Pawn) then
                  if PieceAttacks(IPiece,Player,ISquare,NewSq) then
                  begin
                     Old := ISquare;
                     MovPiece := IPiece;
                     if LoopBody then Exit;
                  end;
      end;
      CapMovGen := False;
   end { CapMovGen };
 
   function NonCapMovGen(OldSq : SquareType) : boolean;
   { Generates non captures for the Piece On OldSq }
   var   First,Last,Dir : DirType;
         Direction :      integer;
         NewSq :          EdgeSquareType;
 
   label 10;
   begin
      NonCapMovGen := true;
      with MovTab[Depth] do
      begin
         Spe := False;
         Old := OldSq;
         MovPiece := Board[OldSq].Piece;
         Content := Empty;
         case MovPiece of
           King : for Dir := 7 downto 0 do
                  begin
                    NewSq := Old + DirTab[Dir];
                    if (NewSq and $88) = 0 then
                       if Board[NewSq].Piece = Empty then
                       begin
                          New1 := NewSq;
                          if LoopBody then Exit;
                       end;
                 end;
           Knight : for Dir := 7 downto 0 do
                   begin
                     NewSq := Old + KnightDir[Dir];
                     if (NewSq and $88) = 0 then
                       if Board[NewSq].Piece = Empty then
                       begin
                          New1 := NewSq;
                          if LoopBody then Exit;
                       end;
                 end;
           Queen,
           Rook,
           Bishop : begin
                    First := 7;
                    Last := 0;
                    if MovPiece = Rook then First := 3;
                    if MovPiece = Bishop then Last := 4;
                    for Dir := First downto Last do
                    begin
                       Direction := DirTab[Dir];
                       NewSq := Old + Direction;
                       while (NewSq and $88) = 0 do
                       begin
                          if Board[NewSq].Piece <> Empty then goto 10;
                          New1 := NewSq;
                          if LoopBody then Exit;
                          NewSq := New1 + Direction;
                       end;
                 10 : end;
                 end;
         Pawn :   begin
                    { One Square forward }
                    New1 := Old + PawnDir[Player];
                    if Board[New1].Piece = Empty then
                       if (New1 < 8) or (New1 >= $70) then
                       begin
                          if PawnPromotionGen then Exit;
                       end
                       else
                       begin
                          if LoopBody then Exit;
                          if (Old < $18) or (Old >= $60) then
                          begin
                             { Two squares forward }
                             New1 := New1 + (New1 - Old);
                             if Board[New1].Piece = Empty then
                                if LoopBody then Exit;
                          end;
                       end;
                 end;
         end { case };
      end { with };
      NonCapMovGen := False;
   end { NonCapMovGen };
 
   function CastlingMovGen : boolean;
   { Castling moves }
   var CastDir : CastDirType;
   begin
      CastlingMovGen := true;
      with MovTab[Depth] do
      begin
         Spe := true;
         MovPiece := King;
         Content := Empty;
         for CastDir := Short downto Long do
            with CastMove[Player,CastDir] do
            begin
               New1 := CastNew;
               Old := CastOld;
               if KillMovGen(MovTab[Depth]) then
                  if LoopBody then Exit;
            end;
      end;
      CastlingMovGen := False;
   end { CastlingMovGen };
 
   function EpCapMovGen : boolean;
   { E.p. captures }
   var   Sq : EdgeSquareType;
   begin
      EpCapMovGen := true;
      with MovTab[Depth - 1] do
         if MovPiece = Pawn then
            if abs(New1 - Old) >= $20 then
            begin
               MovTab[Depth].Spe := true;
               MovTab[Depth].MovPiece := Pawn;
               MovTab[Depth].Content := Empty;
               MovTab[Depth].New1 := (New1 + Old) div 2;
               for Sq := New1 - 1 to New1 + 1 do if Sq <> New1 then
                  if (Sq and $88) = 0 then
                  begin
                     MovTab[Depth].Old := Sq;
                     if KillMovGen(MovTab[Depth]) then
                        if LoopBody then Exit;
                  end;
            end;
      EpCapMovGen := False;
   end { EpCapMovGen };
 
var   Index : IndexType;
      KillNo : 0..1;
begin
   with MovTab[Depth] do
   begin
      { Generate Move from Main variation }
      if BestLine[Depth].MovPiece <> Empty then
      begin
         MovTab[Depth] := BestLine[Depth];
         MovGenType := Main;
         if LoopBody then Exit;
      end;
      with MovTab[Depth - 1] do        { Captures of Last moved Piece }
         if MovPiece <> Empty then if MovPiece <> King then
         begin
            MovGenType := SpecialCap;
            if CapMovGen(New1) then Exit;
         end;
      MovGenType := Kill;                             { Killing moves }
      if not CaptureSearch then
         for KillNo := 0 to 1 do
         begin
            MovTab[Depth] := KillingMove[Depth,KillNo];
            if MovPiece <> Empty then
               if KillMovGen(MovTab[Depth]) then
                  if LoopBody then Exit;
         end;
      MovGenType := Normal;                            { Captures }
      for Index := 1 to PawnNo[Opponent] do
         with PieceTab[Opponent,Index] do
            if IPiece <> Empty then
               with MovTab[Depth - 1] do
                  if (MovPiece = Empty) or (ISquare <> New1) then
                     if CapMovGen(ISquare) then Exit;
      if CaptureSearch then                    { Pawnpromotions }
         if PassedPawn[Depth - 2] >= 0 then
            with Board[PassedPawn[Depth - 2]] do
               if (Piece = Pawn) and (Color = Player) then
                  if NonCapMovGen(PassedPawn[Depth - 2]) then Exit;
      if not CaptureSearch then                  { Non-captures }
      begin
         if CastlingMovGen then Exit;            { Castling }
         for Index := PawnNo[Player] downto 0 do   { other moves }
            with PieceTab[Player,Index] do
               if IPiece <> Empty then
                  if NonCapMovGen(ISquare) then Exit;
      end;
      if EpCapMovGen then Exit;       { E.p. captures }
   end;
end { SearchMovGen };
 
label Stop;
begin { Search }
   { Perform CaptureSearch if Ply<=0 and not Check }
   CaptureSearch := (Ply <= 0) and not CheckTab[Depth - 1];
   if CaptureSearch then                     { Initialize MaxVal }
   begin
      MaxVal := -Inf.Evaluation;
      if Alpha < MaxVal then
      begin
         Alpha := MaxVal;
         if MaxVal >= Beta then goto Stop;
      end;
   end
   else
      MaxVal := -(LoseValue - Depth * DepthFactor);
   SearchMovGen;   { The Search loop }
   if SkipSearch then goto Stop;
   if MaxVal = -(LoseValue - Depth * DepthFactor) then   { test stalemate }
      if not Attacks(Opponent,PieceTab[Player,0].ISquare) then
      begin
         MaxVal := 0;
         goto Stop;
      end;
   UpdateKill(BestLine[Depth]);
Stop :
   Search := MaxVal;
end { Search };
 
function CallSearch(Alpha,Beta : MaxType) : MaxType;
{ Perform the Search }
var   MaxVal : MaxType;
begin
   StartInf.PrincipVar := MainLine[0].MovPiece <> Empty;
   LegalMoves := 0;
   MaxVal := Search(Alpha,Beta,MaxDepth,StartInf,MainLine);
   if LegalMoves = 0 then MainEvalu := MaxVal;
   CallSearch := MaxVal;
end; { CallSearch }
 
function TimeUsed : boolean;
{ Checks whether the Search Time is used }
begin
   TimeUsed := False;
   if Analysis and not SingleStep then
   begin
      StopTime(Clock);
      TimeUsed := Clock.TotalTime >= WantedTime;
   end;
end; { TimeUsed }
 
var
  MaxVal     : MaxType;
  CalcPVTime : real;
begin { FindMove }
  InitTime(Clock);                   { Initialize variables }
  StartTime(Clock);
  InitNode(Nodes);
  SkipSearch := False;
  ClearKillMove;
  CalcPVTable;                    { Calculate the P-V table }
  StopTime(Clock);
  CalcPVTime := Clock.TotalTime;
  StartInf.Value := -RootValue;        { Initiate the search }
  StartInf.Evaluation := -RootValue;
  MaxDepth := 0;
  MainLine[0] := ZeroMove;
  MainEvalu := RootValue;
  AlphaWindow := MaxInt;
  if SingleStep then SingleStepMenu;
  repeat                             { The iterative search loop }
      { Update various variables }
    if MaxDepth <= 1 then RepeatEvalu := MainEvalu;
    AlphaWindow := Min(AlphaWindow,MainEvalu - $80);
    if Level = MateSearch then
    begin
      AlphaWindow := $6000;
      if MaxDepth > 0 then MaxDepth := MaxDepth + 1;
    end;
    MaxDepth := MaxDepth + 1;
    MaxVal := CallSearch(AlphaWindow,$7F00);     { Perform the search }
    if (MaxVal <= AlphaWindow) and not SkipSearch and
       (Level <> MateSearch) and (LegalMoves > 0) then
    begin
         { repeat the search if the value falls below
           the Alpha - window }
      MainEvalu := AlphaWindow;
      MaxVal := CallSearch(-$7F00,AlphaWindow - Tolerance * 2);
      LegalMoves := 2;
    end;
  until SkipSearch or TimeUsed or (MaxDepth >= MaxLevel) or
         (LegalMoves <= 1) or
         (abs(MainEvalu) >= MateValue - 24 * DepthFactor);
  while not Analysis and not SkipSearch do
  begin
    ScanKeys;
    if Length(Command) > 0 then
      CallSmallTalk;
  end;
  StopTime(Clock);
  if SingleStep then
  begin
    GotoPos(CommandPos,0,4);
    Write('Move has been selected');
    Delay(1500);
    PrintMenu;
    SingleStep := false;
  end;
  if Analysis then
     PrintNodes(Nodes, (Clock.TotalTime - CalcPVTime));
end; { FindMove }
