
uses
  SysUtils, Classes, Chess, Move, Moves, Castling, Board, StrUtils;

function IsLegal(const APos: TPosition; const AMove: TMove): boolean;
var
  LPos: TPosition;
var
  LList: array[0..0] of integer;
  LCount: integer;
begin
  Initialize(LList);
  LPos := APos;
  result := FALSE;
  if DoMove(LPos, AMove) then
    with LPos do
      result := (
        //GenerateMoves(LPos)
        GenerateMoves(LPos, LList, LCount, TRUE, TRUE)
        and Pieces[not Side]
        and Kings
      ) = 0;
end;

function Test(const AIniPos, AMove: string; const ADepth, AExpectedResult: integer): integer;
var
  LRes: array of integer;

  procedure GetMovesCount(const APos: TPosition; const ARecurse: integer);
  var
    LList, LList2: array[0..199] of TMove;
    LCount, LLegalCount, i: integer;
    LPos: TPosition;
    LFen: string;
  begin
    result := 0;
    Initialize(LList);
    Initialize(LList2);
    GenerateMoves(APos, LList, LCount);
    GenerateCastling(APos, LList, LCount);
    LLegalCount := 0;
    for i := 0 to Pred(LCount) do
    begin
      if IsLegal(APos, LList[i]) then
      begin
        LList2[LLegalCount] := LList[i];
        Inc(LLegalCount);
      end else
      begin
      end;
    end;
    Inc(LRes[Pred(ADepth - ARecurse)], LLegalCount);
    
    if ARecurse > 0 then
      for i := 0 to Pred(LLegalCount) do
      begin
        LPos := APos;
        if DoMove(LPos, LList2[i]) then
          GetMovesCount(LPos, Pred(ARecurse))
        else
        begin
          WriteLn('Unexpected error');
          Exit;
        end;
      end;
  end;

var
  i: integer;
  t: cardinal;
  
var
  LPos: TPosition;
  
begin
  LPos := CNewPos;
  LPos := EncodePosition(AIniPos);
  
  DoMove(LPos, AMove);
  
  Initialize(LRes);
  SetLength(LRes, ADepth);
  for i := 0 to Pred(ADepth) do
    LRes[i] := 0;
  
  t := GetTickCount64;
  GetMovesCount(LPos, Pred(ADepth));
  t := GetTickCount64 - t;
  
  result := LRes[Pred(ADepth)];
  
  WriteLn(StringOfChar('=', 120));
  
  WriteLn('Position    : ', AIniPos);
  WriteLn('Move        : ', AMove);
  WriteLn('Depth       : ', ADepth);
{
  WriteLn('Time elapsed: ', FormatDateTime('hh:nn:ss:zzz', t / (1000 * SECSPERDAY)));
}
  
  WriteLn(Format('Result      : %d [%s]', [
    result,
    IfThen(result = AExpectedResult, 'SUCCESS', Format('ERROR, %d expected', [AExpectedResult]))
  ]));
  
  SetLength(LRes, 0);
end;

begin
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1g1', 2, 64);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1g1', 2, 42);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1f1', 2, 52);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h2', 2, 95);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h3', 2, 95);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h4', 2, 95);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h5', 2, 95);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h6', 2, 95);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h7', 2, 38);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'h1h8', 2, 57);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1f1', 2, 65);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1f2', 2, 110);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1e2', 2, 110);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1d2', 2, 110);
  Test('5k2/8/8/8/8/8/8/4K2R w K - 0 1', 'e1d1', 2, 75);

  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2d1', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2d2', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2d3', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2e3', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2f3', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'e2f2', 1, 13); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'a7a8n', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'a7a8b', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'a7a8r', 1, 15); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'a7a8q', 1, 15); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'b7b8n', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'b7b8b', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'b7b8r', 1, 15); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'b7b8q', 1, 15); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'c7c8n', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'c7c8b', 1, 17); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'c7c8r', 1, 15); // Cinnamon #3
  //Test('8/PPP4k/8/8/8/8/4Kppp/8 w - - 0 1', 'c7c8q', 1, 15); // Cinnamon #3
end.
