unit eval;

interface
uses genMov;
Type
 TStBoard = packed array[0..63] of smallInt;
 PStBoard = ^TStBoard;
 I64 = int64;
 TExtScoreRec = array[cWhite..cBlack] of TScore;
Const
   MaxStValue = valueP div 2;

    __endGSt:TStBoard  =
       (  1 ,2 ,3 ,4 ,  4, 3, 2, 1,
          9,10,11,12 , 12,11,10, 9,
         17,18,19,20 , 20,19,18,17,
         25,26,27,28 , 28,27,26,25,

         25,26,27,28 , 28,27,26,25,
         17,18,19,20 , 20,19,18,17,
          9,10,11,12 , 12,19,18,17,
          1, 2, 3, 4 ,  4, 3, 2, 1
        );
    __BlackSt:TStBoard =
        (
          1, 2, 3, 4, 5, 6, 7, 8 ,
          9,10,11,12,13,14,15,16 ,
         17,18,19,20,21,22,23,24 ,
         25,26,27,28,29,30,31,32 ,
         33,34,35,36,37,38,39,40 ,
         41,42,43,44,45,46,47,48 ,
         49,50,51,52,53,54,55,56 ,
         57,58,59,60,61,62,63,64
        );
    __WhiteSt:TStBoard =
        (
         64,63,62,61,60,59,58,57 ,
         56,55,54,53,52,51,50,49 ,
         48,47,46,45,44,43,42,41 ,
         40,39,38,37,36,35,34,33 ,
         32,31,30,29,28,27,26,25 ,
         24,23,22,21,20,19,18,17 ,
         16,15,14,13,12,11,10, 9 ,
          8, 7, 6, 5, 4, 3, 2, 1
        );

 __KingOpening:TStBoard =
   (  0,  0, -4,-10,-10, -4,  0,  0,
     -4, -4, -8,-12,-12, -8, -4, -4,
    -12,-16,-20,-20,-20,-20,-16,-12,
    -16,-20,-24,-24,-24,-24,-20,-16,
    -16,-20,-24,-24,-24,-24,-20,-16,
    -12,-16,-20,-20,-20,-20,-16,-12,
     -4, -4, -8,-12,-12, -8, -4, -4,
      0,  0, -4,-10,-10, -4,  0,  0);
  __KingEnding:TStBoard =
   ( 0, 4, 8,12,12, 8, 4, 0,
     4,16,20,24,24,20,16, 4,
     8,20,28,32,32,28,20, 8,
    12,24,32,36,36,32,24,12,
    12,24,32,36,36,32,24,12,
     8,20,28,32,32,28,20, 8,
     4,16,20,24,24,20,16, 4,
     0, 4, 8,12,12, 8, 4, 0);

  __knight:TStBoard =
   ( 0, 4, 8,10,10, 8, 4, 0,
     4, 8,16,20,20,16, 8, 4,
     8,16,24,28,28,24,16, 8,
    10,20,28,32,32,28,20,10,
    10,20,28,32,32,28,20,10,
     8,16,24,28,28,24,16, 8,
     4, 8,16,20,20,16, 8, 4,
     0, 4, 8,10,10, 8, 4, 0);
  __bishop:TStBoard =
   (14,14,14,14,14,14,14,14,
    14,22,18,18,18,18,22,14,
    14,18,22,22,22,22,18,14,
    14,18,22,22,22,22,18,14,
    14,18,22,22,22,22,18,14,
    14,18,22,22,22,22,18,14,
    14,22,18,18,18,18,22,14,
    14,14,14,14,14,14,14,14);
  __BlackPawnAdvance:TStBoard =
   ( 0, 0, 0, 0, 0, 0, 0, 0,
     4, 4, 4, 0, 0, 4, 4, 4,
     6, 8, 2,10,10, 2, 8, 6,
     6, 8,12,16,16,12, 8, 6,
     8,12,16,24,24,16,12, 8,
    12,16,24,32,32,24,16,12,
    12,16,24,32,32,24,16,12,
     0, 0, 0, 0, 0, 0, 0, 0);
  __WhitePawnAdvance:TStBoard =
   ( 0, 0, 0, 0, 0, 0, 0, 0,
    12,16,24,32,32,24,16,12,
    12,16,24,32,32,24,16,12,
     8,12,16,24,24,16,12, 8,
     6, 8,12,16,16,12, 8, 6,
     6, 8, 2,10,10, 2, 8, 6,
     4, 4, 4, 0, 0, 4, 4, 4,
     0, 0, 0, 0, 0, 0, 0, 0);

  __Empty:TStBoard =
  (
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0
  );

  r1 = 1; r2 = 2; r3 = 3; r4 = 4; r5 = 5; r6 = 6;
  __BlackPassedPawn1:TStBoard =
  (
    0   ,  0,  0,  0,  0,  0,  0,  0,
   30-r1, 30, 30, 30, 30, 30, 30, 30-r1,
   40-r2, 40, 40, 40, 40, 40, 40, 40-r2,
   60-r3, 60, 60, 60, 60, 60, 60, 60-r3,
  100-r4,100,100,100,100,100,100,100-r4,
  180-r5,180,180,180,180,180,180,190-r5,
  300-r6,300,300,300,300,300,300,300-r6,
    0   ,  0,  0,  0,  0,  0,  0,  0
  );
  __WhitePassedPawn1:TStBoard =
  (
    0  ,  0,  0,  0,  0,  0,  0,  0,
  300-r6,300,300,300,300,300,300,300-r6,
  180-r5,180,180,180,180,180,180,180-r5,
  100-r4,100,100,100,100,100,100,100-r4,
   60-r3, 60, 60, 60, 60, 60, 60, 65-r3,
   40-r2, 40, 40, 40, 40, 40, 40, 40-r2,
   30-r1, 30, 30, 30, 30, 30, 30, 30-r1,
    0  ,  0,  0,  0,  0,  0,  0,  0
  );

  __BlackPassedPawn2:TStBoard =
  (
    0 ,  0,  0,  0,  0,  0,  0,  0,
   40-r1, 60, 60, 60, 60, 60, 60, 40-r1,
   60-r2, 80, 80, 80, 80, 80, 80, 60-r2,
   80-r3,120,120,120,120,120,120, 80-r3,
  120-r4,200,200,200,200,200,200,120-r4,
  200-r5,360,360,360,360,360,360,200-r5,
  360-r6,600,600,600,600,600,600,360-r6,
    0,  0,  0,  0,  0,  0,  0,  0
  );
  __WhitePassedPawn2:TStBoard =
  (
    0,  0,  0,  0,  0,  0,  0,  0,
  360-r6,600,600,600,600,600,600,360-r6,
  200-r5,360,360,360,360,360,360,200-r5,
  120-r4,200,200,200,200,200,200,120-r4,
   80-r3,120,120,120,120,120,120, 80-r3,
   60-r2, 80, 80, 80, 80, 80, 80, 60-r2,
   40-r1, 60, 60, 60, 60, 60, 60, 40-r1,
       0,  0,  0,  0,  0,  0,  0,  0
  );



StMain:array[cWhite..cBlack] of PStBoard = (@__WhiteSt,@__BlackSt);

StAdvance:array[cWhite..cBlack,pKing..pPawn] of PStBoard =
(
 (
  @__KingOpening,@__Empty,@__Empty,@__Bishop,@__knight,@__WhitePawnAdvance
 ),
 (
  @__KingOpening,@__Empty,@__Empty,@__Bishop,@__knight,@__BlackPawnAdvance
 )
);

 passedPawn:array[cWhite..cBlack] of PStBoard =
  (@__WhitePassedPawn1,@__BlackPassedPawn1);

 chkCnt:array[cWhite..cBlack] of integer = (0,0);


Type
 TTaxiArray = array[0..7,0..7] of shortInt;


procedure StInit;
function ExtEvaluatePos(side:TColor):TScore;
procedure GetExtQRBScore(var rec:TExtScoreRec);

implementation



var
 square:array[0..63] of I64; {маска в пределах 2 квадрата от фигуры}
 byteBitCount:array[0..255] of byte;{количество битов в байте}


  procedure InitSquare;
  const
     addXKing:array[0..7]   of integer = (1,-1,1,-1,1,-1,0,0);
     addYKing:array[0..7]   of integer = (1,-1,-1,1,0,0,1,-1);
     addXKnight:array[0..7] of integer = (1,1,-1,-1,2,-2,2,-2);
     addYKnight:array[0..7] of integer = (2,-2,2,-2,1,1,-1,-1);
  var
     X,Y,J,N,K:integer;
  begin
    for N := 0 to 63 do begin
     square[N] := 0;
     for J := 1 to 2 do
      for K := 0 to 7 do
      begin
         Y := (N shr 3) + addYKing[K]*J;
         X := (N and 7) + addXKing[K]*J;
         if word(X or Y) < 8 then
            square[N] := square[N] or (I64(1) shl (Y*8 + X));
      end;{for K}
     for K := 0 to 7 do
     begin
         Y := (N shr 3) + addYKnight[K];
         X := (N and 7) + addXKnight[K];
         if word(X or Y) < 8 then
            square[N] := square[N] or (I64(1) shl (Y*8 + X));
     end;{for K}
    end;{for N}
  end;{function}

procedure InitbyteBitCount;
 function BCount(b:byte):integer;
 var
  cnt:integer;
 begin
  cnt := 0;
  while b <> 0 do begin
    cnt := cnt + 1;
    b := b and (b-1);
  end;
  BCount := cnt;
 end;
 var
  b:word;
begin
  for b := 0 to 255 do
    byteBitCount[b] := BCount(b);
end;{function}

{
 позиция должна быть в pos 
}
procedure StInit;
var
 findQueen:array[cWhite..cBlack] of boolean;
 findPawn:array[cWhite..cBlack] of boolean;
 N:integer;

begin
 {check game status}
 findQueen[cWhite] := false; findQueen[cBlack] := false;
 findPawn[cWhite] := false; findPawn[cBlack] := false;

 for N := 0 to 63 do
   with pos.pos64[N] do
     case Piece of
       pPawn:  findPawn[Color] := true;
       pQueen: findQueen[Color] := true;
     end;

 if findPawn[cWhite] or findPawn[cBlack] then begin
   StMain[cWhite] := @__WhiteSt;
   StMain[cBlack] := @__BlackSt;
   StAdvance[cWhite,pKing] := @__KingOpening;
   StAdvance[cBlack,pKing] := @__KingOpening;
 end else begin
   StMain[cWhite] := @__endGSt;
   StMain[cBlack] := @__endGSt;
   StAdvance[cWhite,pKing] := @__KingEnding;
   StAdvance[cBlack,pKing] := @__KingEnding;
 end;

 if (game.gCurr > 60) or (not (findQueen[cWhite] or findQueen[cBlack])) then
 begin
   passedPawn[cWhite] := @__WhitePassedPawn2;
   passedPawn[cBlack] := @__BlackPassedPawn2;
 end else begin
   passedPawn[cWhite] := @__WhitePassedPawn1;
   passedPawn[cBlack] := @__BlackPassedPawn1;
 end;

 InitSquare;
 InitbyteBitCount;
 chkCnt[cWhite] := 0; chkCnt[cBlack] := 0;
end;

Const
 RMask = not $0101010101010101;
 LMask = not $8080808080808080;
 FMask0 =   $0101010101010101;
 FMask1 =   $0202020202020202;
 FMask2 =   $0404040404040404;
 FMask3 =   $0808080808080808;
 FMask4 =   $1010101010101010;
 FMask5 =   $2020202020202020;
 FMask6 =   $4040404040404040;
 FMask7 =   $8080808080808080;
 FMask:array[0..7] of int64 =
 (
   FMask0,FMask1,FMask2,FMask3,FMask4,FMask5,FMask6,FMask7
 );

  {3 столбца для проходных пешек}
  Column:array[0..7] of I64 =
  (
    FMask0 or FMask1,
    FMask0 or FMask1 or FMask2,
    FMask1 or FMask2 or FMask3,
    FMask2 or FMask3 or FMask4,
    FMask3 or FMask4 or FMask5,
    FMask4 or FMask5 or FMask6,
    FMask5 or FMask6 or FMask7,
              FMask6 or FMask7
  );

  {пространство перед фигурой}
  spaceFront:array[cWhite..cBlack,0..7] of I64 =
  (
    (
     $0000000000000000,
     $00000000000000FF,
     $000000000000FFFF,
     $0000000000FFFFFF,
     $00000000FFFFFFFF,
     $000000FFFFFFFFFF,
     $0000FFFFFFFFFFFF,
     $00FFFFFFFFFFFFFF
     ),
     (
     $FFFFFFFFFFFFFF00,
     $FFFFFFFFFFFF0000,
     $FFFFFFFFFF000000,
     $FFFFFFFF00000000,
     $FFFFFF0000000000,
     $FFFF000000000000,
     $FF00000000000000,
     $0000000000000000
     )
  );




procedure GetExtPawnsScore(var rec:TExtScoreRec);
const
 BackFine:array[cWhite..cBLack,0..7] of TScore =
 (
   (-28,-28,-28,-28,-21,-15,-10,-6),
   (-6,-10,-15,-21,-28,-28,-28,-28)
 );
 DoubleFine = -16;//-12;
 IsolFine:array[0..7] of TScore =
 (-12,-16,-20,-24,-24,-20,-16,-12);


var
 MyPawns,OpPawns,List,pawn:I64;
 N,X,Y:integer;
 side,xside:TColor;
begin

 rec[cWhite] := 0; rec[cBlack] := 0;

 {white pawns}
 for side := cWhite to cBlack do
 begin
  xside := OpSide[side];
  MyPawns := Pieces[pPawn].bc64  and  All[side].bc64;
  if MyPawns = 0 then continue;
  OpPawns := Pieces[pPawn].bc64  and  All[xside].bc64;

  List := MyPawns;
  while List <> 0 do begin
   pawn := List and -List;
   N := BitNumber(TBitBoard(pawn));
   X := N and 7; Y := N shr 3;

   {сдвоенные}
   if ( (FMask[X] and MyPawns) and not pawn )  <> 0 then
     rec[side] := rec[side] + DoubleFine;

   {отсталые пешки}
   if (MyPawns and Column[X] and
       not SpaceFront[side,Y] and not FMask[X]) = 0 then
     rec[side] := rec[side] + BackFine[side,Y];
   {изолированные}
   if ((Column[X] and not FMask[X]) and MyPawns) = 0 then
     rec[side] := rec[side] + IsolFine[X];

   {проходные}
   if (spaceFront[side,Y] and  Column[X] and OpPawns) = 0 then
       rec[side] := rec[side] + passedPawn[side]^[N];

   List := List and not pawn;
  end;{while}
 end;{for side}
end;{function}

{безопасность короля}
procedure GetExtKingScore(var rec:TExtScoreRec);
const
 OpenFyleFine       = -24; {вертикаль без пешек рядом с королем}
 PawnKingFine       = -16; {нет ни одной пешки в квадрате короля}
 ThreatOpQueenFine  = -24; {ферзь противника в квадрате короля}
 ThreatMyQueenFine  = -8;  {наш ферзь далеко от своего короля}
 KingFirstMoveFine  = -24; {ход короля до рокировки}
 {штраф от количества шахов королю в строке}
 chkMaxFine = -40;
 chkFine:array[0..3] of integer = (0,-10,-25,chkMaxFine);
 chkMaxNoPawnFine = -10;{ {добавка к штрафу если нет смежной пещки}

 {пешечный экран после рокировки - чем дальше пешка от короля - тем больше штраф}
 scrFine:array[0..7] of integer =
    (0,16,0,-16,OpenFyleFine,OpenFyleFine,OpenFyleFine,OpenFyleFine);
var
 king,opQueen,MyPawns,screen,scrPawn:I64;
 side,xside:TColor;
 kingN,kingX,kingY,temp,scrN:integer;
 castling:boolean;


begin
 rec[cWhite] := 0; rec[cBlack] := 0;
 for side := cWhite to cBlack do
 begin
  xside := OpSide[side];
  king := Pieces[pKing].bc64 and All[side].bc64;
  kingN := BitNumber(TBitBoard(king));
  kingX := kingN and 7; kingY := kingN shr 3;
  castling := pos.pos64[kingN].IsCastling;
  opQueen :=  Pieces[pQueen].bc64 and All[xside].bc64;
  MyPawns := Pieces[pPawn].bc64  and  All[side].bc64;

  {если король или ладья ходили до рокировки}
  if not castling and (game.gCurr < 20)  then begin
     if pos.pos64[kingN].IsMove then begin
       rec[side] := rec[side] + KingFirstMoveFine;
     end else begin
      {ладьи не перемещались и не ходили}
       with pos.pos64[kingN+3] do
        if (Piece <> pRook) or IsMove or (color <> side) then
          rec[side] := rec[side] + KingFirstMoveFine div 2;
       with pos.pos64[kingN-4] do
        if (Piece <> pRook) or IsMove or (color <> side) then
          rec[side] := rec[side] + KingFirstMoveFine div 2;
     end;
  end;



  {если ферзь противника на доске}
  if opQueen <> 0 then begin


    {открытые пешечные вертикали рядом с королем}
    if (KingX-1 >= 0) and ((Fmask[KingX-1] and MyPawns) = 0) then
      rec[side] := rec[side] + OpenFyleFine;
    if (Fmask[KingX] and MyPawns) = 0 then
      rec[side] := rec[side] + OpenFyleFine;
    if (KingX+1 < 8) and ((Fmask[KingX+1] and MyPawns) = 0) then
      rec[side] := rec[side] + OpenFyleFine;

    {пешечный экран после рокировки}
    if castling {or (game.gCurr > 20)} then begin
      screen := MyPawns and Column[kingX] and spaceFront[side,kingY];
      while screen <> 0 do begin
         scrPawn := screen and -screen;
         scrN := BitNumber(TBitBoard(scrPawn));
         rec[side] := rec[side] + scrFine[abs((scrN shr 3)-kingY)];
         screen := screen and (screen-1);
      end;

    end else if (game.gCurr > 20) and (chkCnt[side] = 0) then begin
       {около короля должна быть хотя бы одна пешка}
       if (square[kingN] and MyPawns) = 0 then
         rec[side] := rec[side] + PawnKingFine;
    end;


    {ферзь противника в опасной близости к нашему королю}
    if (square[kingN] and opQueen) <> 0 then
      rec[side] := rec[side] + ThreatOpQueenFine;
    {свой ферзь далеко от своего короля}
    if (square[kingN] and Pieces[pQueen].bc64 and All[side].bc64) = 0 then
      rec[side] := rec[side] + ThreatMyQueenFine;

    {если были шахи и нет пешек немедленно смежных}
    if Pieces[pPawn].bc64 <> 0 then begin
      if chkCnt[side] >= 4 then
         temp := chkMaxFine
      else
         temp := chkFine[chkCnt[side]];
      if (maskKing[kingN].bc64 and MyPawns) = 0 then
         temp := temp + chkMaxNoPawnFine;
      rec[side] := rec[side] + temp;
    end;

  end;{if opQueen <> 0}
 end;{for side}
end;{function}


{
расширенная оценка для дальнобойных фигур
включает мобильность, Xray-атаку, и т.д.
}
procedure GetExtQRBScore(var rec:TExtScoreRec);
Const
 XRayBonus = 8;     {премия для Xray атаки}
 HungBonus = 16;//10;    {атака на большую или незащищенную фигуру}
 AttackBonus = 2;   {просто атака}
 AllNoSafFine = -2; {незащищенная фигура}
 {bishops constants}
 twoBishopBonus = 8; {преимущество 2 слонов}
 BMobilBonus:array[0..17] of integer =  {мобильность слона}
 (-4,0,2,4,6,8,10,12,14,16,16,16,16,16,16,16,16,16 );
// (-8,-6,-2,0,2,4,6,8,10,12,14,16,16,16,16,16,16,16 );
 BishopSquareKingBonus = 8; {атака в квадрат короля}
 {rooks bonus}
 twoRookOnLine = 4; {2 ладьи на одной линии}
 RMobilBonus:array[0..17] of integer =  {мобильность ладьи}
 (0,2,4,6,8,10,11,12,13,14,14,14,14,14,14,14,14,14);
 twoRookOnFirstRow = 8; {2 ладьи на первой горизонтали}
 firstRookMask:array[cWhite..cBlack] of I64 =
 (
   $FF00000000000000,
   $00000000000000FF
 );
 RookOpenFyleBonus = 10; {открытая вертикаль без своих пешек}
 {knight}
 KnightAttackBonus = 4; {2 квадрата до фигуры противника}
 {queen}
 QueenBonus = 2;//1; {коэф. для TAXI}
 {pawns}
 PawnKingSquareBonus = 8;


 pieceCode:array[pEmpty..pPawn] of integer =
 (0,1,2,4,8,16,32);

Type
 PBitRec = ^TBitRec;
 TRecArray = array[0..4] of PBitRec;
const
 arBishop:TRecArray = (@A1H8,@A8H1,NIL,NIL,NIL);
 arRook:TRecArray = (@Normal,@Flipped,NIL,NIL,NIL);
 arQueen:TRecArray = (@A1H8,@A8H1,@Normal,@Flipped,NIL);
var
 side,xside:TColor;
 fSource,fMobilCnt,fXray:integer;
 fAttack:I64;

 {
  мобильность и атака
  pre-init: fSource,side,xside
  output: add to fMobilCnt, fAttack
 }
 procedure GetMA(var recAr:TRecArray);
 var
 P:PBitRec;
 X,Y,index,J,N1,N2:integer;
 line,my,leftBits,rightBits,leftMask,rightMask,moves:byte;
 side1,side2:TColor;
 begin
  fMobilCnt := 0; fAttack := 0; fXRay := 0;
  J := 0; P := recAr[J];
  while P <> NIL do
  begin
   with P^ do begin
      index := toIndex[fSource];
      X := index and 7; Y := index shr 3;
      my := byte(1) shl X;
      line := board.bc8[Y] and  not my  and  maskY[index];
      rightBits := line and (my xor (my-1));
      leftBits := line and not rightBits;
      rightBits := ByteRotate[rightBits];
      leftMask := (leftBits xor (leftBits-1)) and not(leftBits and -leftBits);
      rightMask := (rightBits xor (rightBits-1)) and not(rightBits and -rightBits);
      moves := leftMask and ByteRotate[rightMask] and not my and maskY[index];
      {счетчик возможных перемещений}
      fMobilCnt := fMobilCnt + byteBitCount[moves];
      {атака}
      if leftBits <> 0 then begin
        N1 := fromIndex[ ByteFirstBitNumber[ leftBits and -leftBits] + (Y shl 3)];
        with TBitBoard(fAttack) do
         bc8[N1 shr 3] := bc8[N1 shr 3] or (byte(1) shl (N1 and 7));
        with All[xside] do
         if ( bc8[N1 shr 3] and (byte(1) shl (N1 and 7)) ) <> 0 then
           inc(fMobilCnt);
      end;
      if rightBits <> 0 then begin
        N2 := fromIndex[ (7-ByteFirstBitNumber[ rightBits and -rightBits]) + (Y shl 3)];
        with TBitBoard(fAttack) do
         bc8[N2 shr 3] := bc8[N2 shr 3] or (byte(1) shl (N2 and 7));
        with All[xside] do
         if ( bc8[N2 shr 3] and (byte(1) shl (N2 and 7)) ) <> 0 then
           inc(fMobilCnt);

        if leftBits <> 0 then begin
          side1 := pos.pos64[N1].Color;
          side2 := pos.pos64[N2].Color;
          if (side1 = side) and (side2 = xside) then
            fXRay := fXRay or pieceCode[pos.pos64[N1].Piece]
          else if (side2 = side) and (side1 = xside) then
            fXRay := fXRay or pieceCode[pos.pos64[N2].Piece];
        end;
      end;
   end;{with}
   J := J + 1; P := recAr[J];
  end;{while}
 end;{function}

var
 list,item,tmp,pawns:I64;
 cnt:integer;
 AllAttack:array[cWhite..cBlack] of I64;
 opKing:I64;
 opKingN,opKingX,opKingY,X,Y:integer;
 hasMyQueen:boolean;
 saveHung:I64;
begin {main}
  rec[cWhite] := 0; rec[cBlack] := 0;
  allAttack[cWhite] := 0; allAttack[cBlack] := 0;
  for side := cWhite to cBlack do
  begin
    xside   := OpSide[side];
    opKing  := Pieces[pKing].bc64 and All[xside].bc64;
    opKingN := BitNumber(TBitBoard(opKing));
    opKingX := opKingN and 7; opKingY := opKingN shr 3;

    hasMyQueen := (Pieces[pQueen].bc64 and All[side].bc64) <> 0;
    saveHung := 0;
    {bishops}
    list := Pieces[pBishop].bc64  and All[side].bc64;
    if list <> 0 then begin
      cnt := 0;
      while list <> 0 do begin
        item := list and -list;
        cnt := cnt + 1;
        fSource := BitNumber(TBitBoard(item));
        GetMA(arBishop);
        AllAttack[side] := AllAttack[side] or fAttack;
        {Xray attack}
      //  if (fAttack and Pieces[pQueen].bc64 and All[side].bc64) <> 0 then
      //   rec[side] := rec[side] + XRayBonus;
        if (fXRay and pieceCode[pQueen]) = pieceCode[pQUeen] then
          rec[side] := rec[side] + XRayBonus;
        {мобильность}
        rec[side] := rec[side] + BMobilBonus[fMobilCnt];
        {просто атака}
        if (fAttack and All[xside].bc64) <> 0 then
            rec[side] := rec[side] + AttackBonus;
        {атака в квадрат короля}
        if hasMyQueen and ((MaskKing[opKingN].bc64 and fAttack) <> 0) then
          rec[side] := rec[side] + BishopSquareKingBonus;
        {атака на большую фигуру}
        tmp := fAttack and
              (Pieces[pRook].bc64 or Pieces[pQueen].bc64 or Pieces[pKing].bc64) and
              All[xside].bc64;
        saveHung := saveHung or tmp;
        while tmp <> 0 do begin
          rec[side] := rec[side] + HungBonus;
          tmp := tmp and (tmp-1);
        end;
        list := list and not item;
      end;{while list}
      if cnt > 1 then
        rec[side] := rec[side] + twoBishopBonus;
    end;{if bishops}

    {rooks}
    list := Pieces[pRook].bc64  and All[side].bc64;
    if list <> 0 then begin
     {2 ладьи на первой горизонтали}
      if (Pieces[pPawn].bc64 and All[side].bc64) <> 0 then begin
        tmp := list and firstRookMask[side];
        if (tmp and (tmp-1)) <> 0 then
            rec[side] := rec[side] + twoRookOnFirstRow;
      end;
      while list <> 0 do begin
        item := list and -list;
        fSource := BitNumber(TBitBoard(item));
        X := fSOurce and 7; Y := fSource shr 3;
        GetMA(arRook);
        AllAttack[side] := AllAttack[side] or fAttack;
        {2 ладьи на одной линии}
        if (fAttack and
            (Pieces[pQueen].bc64 or Pieces[pRook].bc64) and
            All[side].bc64) <> 0 then
         rec[side] := rec[side] + twoRookOnLine;
        {просто атака}
        if (fAttack and All[xside].bc64) <> 0 then
            rec[side] := rec[side] + AttackBonus;
        {XRay}
        if (fXRay and (pieceCode[pQueen] or pieceCode[pRook])) <> 0 then
          rec[side] := rec[side] + XRayBonus;
       {мобильность}
       rec[side] := rec[side] + RMobilBonus[fMobilCnt];
       {расстояние до короля}
       if game.gCurr > 20 then
          rec[side] := rec[side] -
             ((abs(X-opKingX) + abs(Y-opKingY)) shr 1);

        {атака на большую фигуру}
        tmp := fAttack and
              (Pieces[pQueen].bc64 or Pieces[pKing].bc64) and
              All[xside].bc64;
        saveHung := saveHung or tmp;
        while tmp <> 0 do begin
          rec[side] := rec[side] + HungBonus;
          tmp := tmp and (tmp-1);
        end;

        {занятие открытой вертикали}
        if (FMask[X] and Pieces[pPawn].bc64 and All[side].bc64) = 0 then
          rec[side] := rec[side] + RookOpenFyleBonus;

        list := list and not item;
      end;{while list}
    end;{if rooks}

   {knights}
    list := Pieces[pKnight].bc64  and All[side].bc64;
    while list <> 0 do begin
        item := list and -list;
        fSource := BitNumber(TBitBoard(item));
        X := fSOurce and 7; Y := fSource shr 3;
        {расстояние до короля}
        if game.gCurr > 10 then
          rec[side] := rec[side] -
             ((abs(X-opKingX) + abs(Y-opKingY)) shr 1);
        fAttack := MaskKnight[fSource].bc64 and (All[xside].bc64 or All[side].bc64);
        AllAttack[side] := AllAttack[side] or fAttack;
        if (fAttack and All[xside].bc64) <> 0 then
          rec[side] := rec[side] + AttackBonus;
        {атака на большую фигуру}
        tmp := fAttack and
              (Pieces[pQueen].bc64 or Pieces[pRook].bc64 or Pieces[pKing].bc64) and
              All[xside].bc64;
        saveHung := saveHung or tmp;
        while tmp <> 0 do begin
          rec[side] := rec[side] + HungBonus;
          tmp := tmp and (tmp-1);
        end;
        list := list and not item;
    end;{while}

    {queen}
    list := Pieces[pQueen].bc64  and All[side].bc64;
     while list <> 0 do begin
        item := list and -list;
        fSource := BitNumber(TBitBoard(item));
        X := fSOurce and 7; Y := fSource shr 3;
        GetMA(arQueen);
        AllAttack[side] := AllAttack[side] or fAttack;
       {расстояние до короля}
       if game.gCurr > 12{6} then
          rec[side] := rec[side] -
             ((abs(X-opKingX) + abs(Y-opKingY)) * QueenBonus);
        {атака на большую фигуру}
        tmp := fAttack and
               Pieces[pKing].bc64 and
              All[xside].bc64;
        saveHung := saveHung or tmp;
        while tmp <> 0 do begin
          rec[side] := rec[side] + HungBonus;
          tmp := tmp and (tmp-1);
        end;
        list := list and not item;
     end;{while list}


     {король}
     item := Pieces[pKing].bc64 and All[side].bc64;
     fSOurce := BitNumber(TBitBoard(item));
     fAttack := maskKing[fSource].bc64 and (All[side].bc64 or All[xside].bc64);
     AllAttack[side] := AllAttack[side] or fAttack;

     {атака пешек}
     pawns := Pieces[pPawn].bc64 and All[side].bc64;
     if pawns <> 0 then
     begin
       if side = cWhite then begin
         fAttack := ((pawns shr 9) and LMask) or
                    ((pawns shr 7) and RMask);
       end else begin
         fAttack := ((pawns shl 9) and RMask) or
                    ((pawns shl 7) and LMask);
       end;
       if hasMyQueen and
          ((fAttack and maskKing[opKingN].bc64) <> 0) then
            rec[side] := rec[side] + PawnKingSquareBonus;
       fAttack := fAttack and (All[side].bc64 or All[xside].bc64);
       AllAttack[side] := AllAttack[side] or fAttack;
       {атака на большую фигуру}
       tmp := fAttack and All[xside].bc64 and not Pieces[pPawn].bc64;
       saveHung := saveHung or tmp;
       while tmp <> 0 do begin
          rec[side] := rec[side] + HungBonus;
          tmp := tmp and (tmp-1);
       end;
     end;{pawns}
  end;{for side}


  {зависающие фигуры}
  for side := cWhite to cBlack do
  begin      
    xside := OpSide[side];

    {незащищенная фигура}
    tmp := not AllAttack[side] and All[side].bc64;
    with TBitBoard(tmp) do
     rec[side] := rec[side] -
     (
       byteBitCount[bc8[0]]+ byteBitCount[bc8[1]]+ byteBitCount[bc8[2]]
       + byteBitCount[bc8[3]]+ byteBitCount[bc8[4]]+ byteBitCount[bc8[5]]
       + byteBitCount[bc8[6]]+ byteBitCount[bc8[7]]
     ) * -AllNoSafFine;
     {незащищенные и атакованные фигуры}
     tmp := tmp and AllAttack[xside] and not saveHung;
    while tmp <> 0 do begin
      rec[side] := rec[side] - HungBonus;
      tmp := tmp and (tmp-1);
    end;
  end;{for}

end;{function}


{
 полная дополнительная оценка позиции
}
function ExtEvaluatePos(side:TColor):TScore;
var
 scorePawns,scoreKing,scoreAll:TExtScoreRec;
 xside:TColor;
begin
  xside := OpSide[side];
  if Pieces[pPawn].bc64 <> 0 then
    GetExtPawnsScore(scorePawns)
  else begin
    scorePawns[cWhite] := 0; scorePawns[cBlack] := 0;
  end;
  GetExtKingScore(scoreKing);
  GetExtQRBScore(scoreAll);

  ExtEvaluatePos := (
                     scorePawns[side] + scoreKing[side] +
                     scoreAll[side]

                     ) -
                    (
                     scorePawns[xside] + scoreKing[xside] +
                     scoreAll[xSide]
                     );
end;{function}







end.
