/*
  Glaurung, a UCI chess playing engine.
  Copyright (C) 2004-2007 Tord Romstad

  Glaurung is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  Glaurung is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


////
//// Includes
////

#include <cassert>

#include "distance.h"
#include "evaluate.h"
#include "material.h"
#include "pawns.h"
#include "scale.h"
#include "thread.h"
#include "ucioption.h"


////
//// Local definitions
////

namespace {

  const int Sign[2] = {1, -1};

  // Evaluation grain size
  const int GrainSize = 4;

  // Use mobility evaluation for various piece types.  Note: The constants
  // for bishops and rooks are not yet used.  FIXME
  const bool EvaluateKnightMobility = true;
  const bool EvaluateBishopMobility = true;
  const bool EvaluateRookMobility = true;
  const bool EvaluateQueenMobility = false;

  // Evaluate king safety?
  const bool EvaluateKingSafety = true;

  // Knight mobility bonus in middle game and endgame, indexed by the number
  // of attacked squares not occupied by friendly piecess.
  const Value MidgameKnightMobilityBonus[] = {
    Value(-30), Value(-20), Value(-10), Value(0), Value(10),
    Value(20), Value(25), Value(30), Value(30)
  };

  const Value EndgameKnightMobilityBonus[] = {
    Value(-30), Value(-20), Value(-10), Value(0), Value(10),
    Value(20), Value(25), Value(30), Value(30)
  };

  // Bishop mobility bonus in middle game and endgame, indexed by the number
  // of attacked squares.  Ideally, we shouldn't count squares attacked by
  // friendly pieces, but we currently count all attacked squares, for
  // efficiency reasons.
  const Value MidgameBishopMobilityBonus[] = {
    Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45),
    Value(58), Value(66), Value(72), Value(76), Value(78), Value(80),
    Value(81), Value(82), Value(83), Value(83)
  };

  const Value EndgameBishopMobilityBonus[] = {
    Value(-30), Value(-15), Value(0), Value(15), Value(30), Value(45),
    Value(58), Value(66), Value(72), Value(76), Value(78), Value(80),
    Value(81), Value(82), Value(83), Value(83)
  };

  // Rook mobility bonus in middle game and endgame, indexed by the number
  // of attacked squares.  Ideally, we shouldn't count squares attacked by
  // friendly pieces, but we currently count all attacked squares, for
  // efficiency reasons.
  const Value MidgameRookMobilityBonus[] = {
    Value(-18), Value(-12), Value(-6), Value(0), Value(6), Value(12),
    Value(16), Value(21), Value(24), Value(27), Value(28), Value(29),
    Value(30), Value(31), Value(32), Value(33)
  };
  
  const Value EndgameRookMobilityBonus[] = {
    Value(-30), Value(-18), Value(-6), Value(6), Value(18), Value(30),
    Value(42), Value(54), Value(66), Value(74), Value(78), Value(80),
    Value(81), Value(82), Value(83), Value(83)
  };

  // Queen mobility bonus in middle game and endgame, indexed by the number
  // of attacked squares.  Ideally, we shouldn't count squares attacked by
  // friendly pieces, but we currently count all attacked squares, for
  // efficiency reasons.
  const Value MidgameQueenMobilityBonus[] = {
    Value(-10), Value(-8), Value(-6), Value(-4), Value(-2), Value(0), Value(2),
    Value(4), Value(6), Value(8), Value(10), Value(12), Value(13), Value(14),
    Value(15), Value(16), Value(16), Value(16), Value(16), Value(16),
    Value(16), Value(16), Value(16), Value(16), Value(16), Value(16),
    Value(16), Value(16), Value(16), Value(16), Value(16), Value(16)
  };

  const Value EndgameQueenMobilityBonus[] = {
    Value(-20), Value(-15), Value(-10), Value(-5), Value(0), Value(5),
    Value(10), Value(15), Value(19), Value(23), Value(27), Value(29),
    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
    Value(30), Value(30), Value(30), Value(30), Value(30), Value(30),
    Value(30), Value(30)
  };


  // Outpost bonuses for knights and bishops, indexed by square (from white's
  // point of view).
  const Value KnightOutpostBonus[64] = {
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(5),Value(10),Value(10),Value(5),Value(0),Value(0),
    Value(0),Value(5),Value(20),Value(30),Value(30),Value(20),Value(5),Value(0),
    Value(0),Value(10),Value(30),Value(40),Value(40),Value(30),Value(10),Value(0),
    Value(0),Value(5),Value(20),Value(20),Value(20),Value(20),Value(5),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0)
  };

  const Value BishopOutpostBonus[64] = {
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(5),Value(5),Value(5),Value(5),Value(0),Value(0),
    Value(0),Value(5),Value(10),Value(10),Value(10),Value(10),Value(5),Value(0),
    Value(0),Value(10),Value(20),Value(20),Value(20),Value(20),Value(10),Value(0),
    Value(0),Value(5),Value(8),Value(8),Value(8),Value(8),Value(5),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),
    Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0),Value(0)
  };

  // Bonus for unstoppable passed pawns:
  const Value UnstoppablePawnValue = Value(0x500);

  // Rooks and queens on the 7th rank:
  const Value MidgameRookOn7thBonus = Value(50);
  const Value EndgameRookOn7thBonus = Value(100);
  const Value MidgameQueenOn7thBonus = Value(25);
  const Value EndgameQueenOn7thBonus = Value(50);

  // Rooks on open files:
  const Value RookOpenFileBonus = Value(40);
  const Value RookHalfOpenFileBonus = Value(20);
  const Value RookAttacksKingBonus = Value(12);

  // Penalty for rooks trapped inside a friendly king which has lost the
  // right to castle:
  const Value TrappedRookPenalty = Value(180);

  // Penalty for a bishop on a7/h7 (a2/h2 for black) which is trapped by
  // enemy pawns:
  const Value TrappedBishopA7H7Penalty = Value(300);

  // Bitboard masks for detecting trapped bishops on a7/h7 (a2/h2 for black):
  const Bitboard MaskA7H7[2] = {
    ((1ULL << SQ_A7) | (1ULL << SQ_H7)),
    ((1ULL << SQ_A2) | (1ULL << SQ_H2))
  };

  // Penalty for a bishop on a1/h1 (a8/h8 for black) which is trapped by
  // a friendly pawn on b2/g2 (b7/g7 for black).  This can obviously only
  // happen in Chess960 games.
  const Value TrappedBishopA1H1Penalty = Value(100);

  // Bitboard masks for detecting trapped bishops on a1/h1 (a8/h8 for black):
  const Bitboard MaskA1H1[2] = {
    ((1ULL << SQ_A1) | (1ULL << SQ_H1)),
    ((1ULL << SQ_A8) | (1ULL << SQ_H8))
  };

  // Pawn and material hash tables, indexed by the current thread id:
  PawnInfoTable* PawnTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  MaterialInfoTable* MaterialTable[8] = {0, 0, 0, 0, 0, 0, 0, 0};

  // Sizes of pawn and material hash tables:
  const int PawnTableSize = 16384;
  const int MaterialTableSize = 1024;

  // Array which gives the number of nonzero bits in an 8-bit integer:
  uint8 BitCount8Bit[256];

  // Function prototypes:
  void evaluate_knight(const Position& p, Square s, Color c, 
                       Value* mgValue, Value* egValue);
  void evaluate_bishop(const Position& p, Square s, Color c, 
                       Value* mgValue, Value* egValue);
  void evaluate_rook(const Position& p, Square s, Color c,
                     PawnInfo* pi, Value* mgValue, Value* egValue);
  void evaluate_queen(const Position& p, Square s, Color c, 
                      Value* mgValue, Value* egValue);
  void evaluate_king(const Position& p, Square s, Color c, 
                     Value* mgValue, Value* egValue);

  Value evaluate_king_safety(const Position& p, Square ksq, Color c,
                             int shelter);

  void evaluate_passed_pawns(const Position& pos, Bitboard passedPawns,
                             Value* mgValue, Value* egValue);

  Bitboard knights_attacking_king(const Position& pos, Color side, Square ksq);
  Bitboard bishops_attacking_king(const Position& pos, Color side, Square ksq);
  Bitboard rooks_attacking_king(const Position& pos, Color side, Square ksq);
  Bitboard queens_attacking_king(const Position& pos, Color side, Square ksq);

  void evaluate_trapped_bishop_a7h7(const Position& pos, Square s, Color c,
                                    Value* mgValue, Value* egValue);
  void evaluate_trapped_bishop_a1h1(const Position& pos, Square s, Color c,
                                    Value* mgValue, Value* egValue);

  Value scale_by_game_phase(Value mv, Value ev, Phase ph, ScaleFactor sf[]);

  int count_1s_8bit(int b);

}


////
//// Functions
////

/// evaluate() is the main evaluation function.  It always computes two
/// values, an endgame score and a middle game score, and interpolates
/// between them based on the remaining material.

Value evaluate(const Position& pos, int threadID) {
  Value mgValue, egValue;
  Color stm;
  Square s;
  ScaleFactor factor[2] = {SCALE_FACTOR_NORMAL, SCALE_FACTOR_NORMAL};
  Phase phase;

  assert(pos.is_ok());
  assert(threadID >= 0 && threadID < THREAD_MAX);

  stm = pos.side_to_move();

  // Initialize by reading the incrementally updated scores included in the
  // position object (material + piece square tables):
  mgValue = pos.mg_value();
  egValue = pos.eg_value();

  // Probe the material hash table:
  MaterialInfo *mi = MaterialTable[threadID]->get_material_info(pos);
  mgValue += mi->mg_value();
  egValue += mi->eg_value();

  factor[WHITE] = mi->scale_factor(pos, WHITE);
  factor[BLACK] = mi->scale_factor(pos, BLACK);

  // If we have a specialized evaluation function for the current material
  // configuration, call it and return:
  if(mi->specialized_eval_exists())
    return mi->evaluate(pos);

  phase = pos.game_phase();

  // Probe the pawn hash table:
  PawnInfo *pi = PawnTable[threadID]->get_pawn_info(pos);
  mgValue += pi->mg_value();
  egValue += pi->eg_value();

  // Evaluate passed pawns:
  if(pi->passed_pawns())
    evaluate_passed_pawns(pos, pi->passed_pawns(), &mgValue, &egValue);

  // Evaluate pieces:
  for(Color c = WHITE; c <= BLACK; c++) {
    Bitboard b;

    // Knights
    for(int i = 0; i < pos.knight_count(c); i++) {
      s = pos.knight_list(c, i);
      evaluate_knight(pos, s, c, &mgValue, &egValue);
    }
    
    // Bishops
    for(int i = 0; i < pos.bishop_count(c); i++) {
      s = pos.bishop_list(c, i);
      evaluate_bishop(pos, s, c, &mgValue, &egValue);
    }

    // Rooks
    for(int i = 0; i < pos.rook_count(c); i++) {
      s = pos.rook_list(c, i);
      evaluate_rook(pos, s, c, pi, &mgValue, &egValue);
    }

    // Queens
    for(int i = 0; i < pos.queen_count(c); i++) {
      s = pos.queen_list(c, i);
      evaluate_queen(pos, s, c, &mgValue, &egValue);
    }

    // Kings
    s = pos.king_square(c);
    evaluate_king(pos, s, c, &mgValue, &egValue);

    // Some special patterns:

    // Trapped bishops on a7/h7/a2/h2
    b = pos.bishops_of_color(c) & MaskA7H7[c];
    while(b) {
      s = pop_1st_bit(&b);
      evaluate_trapped_bishop_a7h7(pos, s, c, &mgValue, &egValue);
    }

    // Trapped bishops on a1/h1/a8/h8 in Chess960:
    if(Chess960) {
      b = pos.bishops_of_color(c) & MaskA1H1[c];
      while(b) {
        s = pop_1st_bit(&b);
        evaluate_trapped_bishop_a1h1(pos, s, c, &mgValue, &egValue);
      }
    }
    
  }


  // Middle-game specific evaluation terms
  if(phase > PHASE_ENDGAME) {

    // Pawn storms in positions with opposite castling.
    if(square_file(pos.king_square(WHITE)) >= FILE_E &&
       square_file(pos.king_square(BLACK)) <= FILE_D)
      mgValue +=
        pi->queenside_storm_value(WHITE) -
        pi->kingside_storm_value(BLACK);
    else if(square_file(pos.king_square(WHITE)) <= FILE_D &&
            square_file(pos.king_square(BLACK)) >= FILE_E)
      mgValue += 
        pi->kingside_storm_value(WHITE) -
        pi->queenside_storm_value(BLACK);
  }

  // If we don't already have an unusual scale factor, check for opposite
  // colored bishop endgames, and use a lower scale for those:
  if(phase < PHASE_MIDGAME && pos.opposite_colored_bishops()
     && ((factor[WHITE] == SCALE_FACTOR_NORMAL && egValue > Value(0)) ||
         (factor[BLACK] == SCALE_FACTOR_NORMAL && egValue < Value(0)))) {
    if(pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK) ==
       2*BishopValueMidgame) {
      // Only the two bishops
      if(pos.pawn_count(WHITE) + pos.pawn_count(BLACK) == 1) {
        // KBP vs KB with only a single pawn; almost certainly a draw.
        if(factor[WHITE] == SCALE_FACTOR_NORMAL)
          factor[WHITE] = ScaleFactor(8);
        if(factor[BLACK] == SCALE_FACTOR_NORMAL)
          factor[BLACK] = ScaleFactor(8);
      }
      else {
        // At least two pawns
        if(factor[WHITE] == SCALE_FACTOR_NORMAL)
          factor[WHITE] = ScaleFactor(32);
        if(factor[BLACK] == SCALE_FACTOR_NORMAL)
          factor[BLACK] = ScaleFactor(32);
      }
    }
    else {
      // Endgame with opposite-colored bishops, but also other pieces.
      // Still a bit drawish, but not as drawish as with only the two
      // bishops.
      if(factor[WHITE] == SCALE_FACTOR_NORMAL)
        factor[WHITE] = ScaleFactor(50);
      if(factor[BLACK] == SCALE_FACTOR_NORMAL)
        factor[BLACK] = ScaleFactor(50);
    }
  }

  // Interpolate between the middle game and the endgame score, and
  // return:
  Value value = scale_by_game_phase(mgValue, egValue, phase, factor);

  return Sign[stm] * value;
}


/// quick_evaluate does a very approximate evaluation of the current position.
/// It currently considers only material and piece square table scores.  Perhaps
/// we should add scores from the pawn and material hash tables?

Value quick_evaluate(const Position& pos) {
  Color stm;
  Value mgValue, egValue;
  ScaleFactor factor[2] = {SCALE_FACTOR_NORMAL, SCALE_FACTOR_NORMAL};
  Phase phase;
  
  assert(pos.is_ok());

  stm = pos.side_to_move();

  mgValue = pos.mg_value();
  egValue = pos.eg_value();
  phase = pos.game_phase();

  Value value = scale_by_game_phase(mgValue, egValue, phase, factor);

  return Sign[stm] * value;
}
  

/// init_eval initializes various tables used by the evaluation function.

void init_eval(int threads) {
  assert(threads <= THREAD_MAX);
  
  for(int i = 0; i < threads; i++) {
    if(PawnTable[i] == NULL)
      PawnTable[i] = new PawnInfoTable(PawnTableSize);
    if(MaterialTable[i] == NULL)
      MaterialTable[i] = new MaterialInfoTable(MaterialTableSize);
  }
  for(int i = threads; i < THREAD_MAX; i++) {
    if(PawnTable[i] != NULL) {
      delete PawnTable[i];
      PawnTable[i] = NULL;
    }
    if(MaterialTable[i] != NULL) {
      delete MaterialTable[i];
      MaterialTable[i] = NULL;
    }
  }

  for(Bitboard b = 0ULL; b < 256ULL; b++)
    BitCount8Bit[b] = count_1s(b);
}


/// quit_eval releases heap-allocated memory at program termination.

void quit_eval() {
  for(int i = 0; i < THREAD_MAX; i++) {
    delete PawnTable[i];
    delete MaterialTable[i];
  }
}


namespace {

  // evaluate_knight() assigns bonuses and penalties to a knight of a given
  // color on a given square.
  
  void evaluate_knight(const Position& p, Square s, Color c, 
                       Value* mgValue, Value* egValue) {
    // Mobility
    if(EvaluateKnightMobility) {
      int mob = count_1s_max_15(p.knight_attacks(s) & ~p.pieces_of_color(c));
      *mgValue += Sign[c] * MidgameKnightMobilityBonus[mob];
      *egValue += Sign[c] * EndgameKnightMobilityBonus[mob];
    }

    // Knight outposts:
    if(p.square_is_weak(s, opposite_color(c))) {
      Value v, bonus;
      
      // Initial bonus based on square:
      v = bonus = KnightOutpostBonus[relative_square(c, s)];

      // Increase bonus if supported by pawn, especially if the opponent has
      // no minor piece which can exchange the outpost piece:
      if(v && p.pawn_attacks(opposite_color(c), s) & p.pawns_of_color(c)) {
        bonus += v/2;
        if(p.knight_count(opposite_color(c)) == 0 &&
           (SquaresByColorBB[square_color(s)] &
            p.bishops_of_color(opposite_color(c))) == EmptyBoardBB) {
          bonus += v;
        }
      }

      *mgValue += Sign[c] * bonus;
      *egValue += Sign[c] * bonus;
    }
  }


  // evaluate_bishop() assigns bonuses and penalties to a bishop of a given
  // color on a given square.
  
  void evaluate_bishop(const Position& p, Square s, Color c, 
                       Value* mgValue, Value* egValue) {
    // Mobility:
    // int mob = bishop_mobility(s, p.occupied_squares());
    int mob =
      (bishop_mobility(s, p.occupied_squares())
       + bishop_mobility(s, p.occupied_squares() & ~p.knights_of_color(c)))
      / 2;
    
    *mgValue += Sign[c] * MidgameBishopMobilityBonus[mob];
    *egValue += Sign[c] * EndgameBishopMobilityBonus[mob];

    // Bishop outposts:
    if(p.square_is_weak(s, opposite_color(c))) {
      Value v, bonus;
      
      // Initial bonus based on square:
      v = bonus = BishopOutpostBonus[relative_square(c, s)];

      // Increase bonus if supported by pawn, especially if the opponent has
      // no minor piece which can exchange the outpost piece:
      if(v && p.pawn_attacks(opposite_color(c), s) & p.pawns_of_color(c)) {
        bonus += v/2;
        if(p.knight_count(opposite_color(c)) == 0 &&
           (SquaresByColorBB[square_color(s)] &
            p.bishops_of_color(opposite_color(c))) == EmptyBoardBB) {
          bonus += v;
        }
      }

      *mgValue += Sign[c] * bonus;
      *egValue += Sign[c] * bonus;
    }    
  }
  

  // evaluate_rook() assigns bonuses and penalties to a rook of a given
  // color on a given square.
  
  void evaluate_rook(const Position& p, Square s, Color c, PawnInfo* pi,
                     Value* mgValue, Value* egValue) {
    // Open and half-open files:
    File f = square_file(s);
    if(pi->file_is_half_open(c, f)) {
      if(pi->file_is_half_open(opposite_color(c), f)) {
        *mgValue += Sign[c] * RookOpenFileBonus;
        *egValue += Sign[c] * RookOpenFileBonus;
      }
      else {
        *mgValue += Sign[c] * RookHalfOpenFileBonus;
        *egValue += Sign[c] * RookHalfOpenFileBonus;
      }
    }

    // Rook on 7th rank:
    if(pawn_rank(c, s) == RANK_7 &&
       pawn_rank(c, p.king_square(opposite_color(c))) == RANK_8) {
      *mgValue += Sign[c] * MidgameRookOn7thBonus;
      *egValue += Sign[c] * EndgameRookOn7thBonus;
    }

    // Mobility
    int mob = rook_mobility(s, p.occupied_squares());
    *mgValue += Sign[c] * MidgameRookMobilityBonus[mob];
    *egValue += Sign[c] * EndgameRookMobilityBonus[mob];

    // Penalize rooks which are trapped inside a king which has lost the
    // right to castle:
    if(mob <= 6 && !pi->file_is_half_open(c, f)) {
      Square ksq = p.king_square(c);
      if(square_file(ksq) >= FILE_E && square_file(s) > square_file(ksq) &&
         (pawn_rank(c, ksq) == RANK_1 || square_rank(ksq) == square_rank(s))) {
        // Is there a half-open file between the king and the edge of the
        // board?
        if(!(pi->has_open_file_to_right(c, square_file(ksq)))) {
          *mgValue -= p.can_castle(c)?
            Sign[c] * ((TrappedRookPenalty - mob * 16) / 2) :
            Sign[c] * (TrappedRookPenalty - mob * 16);
        }
      }
      else if(square_file(ksq) <= FILE_D && square_file(s) < square_file(ksq)
              && (pawn_rank(c, ksq) == RANK_1 ||
                  square_rank(ksq) == square_rank(s))) {
        // Is there a half-open file between the king and the edge of the
        // board?
        if(!(pi->has_open_file_to_left(c, square_file(ksq)))) {
          *mgValue -= p.can_castle(c)?
            Sign[c] * ((TrappedRookPenalty - mob * 16) / 2) :
            Sign[c] * (TrappedRookPenalty - mob * 16);
        }
      }
    }
  }


  // evaluate_queen() assigns bonuses and penalties to a queen of a given
  // color on a given square.
  
  void evaluate_queen(const Position& p, Square s, Color c, 
                      Value* mgValue, Value* egValue) {
    // Queen on 7th rank:
    if(pawn_rank(c, s) == RANK_7 &&
       pawn_rank(c, p.king_square(opposite_color(c))) == RANK_8) {
      *mgValue += Sign[c] * MidgameQueenOn7thBonus;
      *egValue += Sign[c] * EndgameQueenOn7thBonus;
    }

    // Mobility
    if(EvaluateQueenMobility) {
      int mob = queen_mobility(s, p.occupied_squares());
      *mgValue += Sign[c] * MidgameQueenMobilityBonus[mob];
      *egValue += Sign[c] * EndgameQueenMobilityBonus[mob];
    }
  }


  // evaluate_king() assigns bonuses and penalties to a king of a given
  // color on a given square.
  
  void evaluate_king(const Position& p, Square s, Color c,
                     Value* mgValue, Value* egValue) {
    int shelter = 0;
    Rank r = square_rank(s);
    File f = square_file(s);
    Bitboard pawns = p.pawns_of_color(c) & this_and_neighboring_files_bb(f);
    if(c == WHITE) {
      // King shelter.  As an optimization, perhaps we could avoid evaluating
      // the king shelter in the late endgame?
      if(r <= RANK_4) {
        shelter += count_1s_8bit(pawns >> ((r+1)*8)) * 64;
        shelter += count_1s_8bit(pawns >> ((r+2)*8)) * 32;
        shelter += count_1s_8bit(pawns >> ((r+3)*8)) * 16;
      }
      *mgValue += Value(shelter);

      // King safety.
      if(EvaluateKingSafety && p.queen_count(BLACK) >= 1 && 
         p.non_pawn_material(BLACK) >= QueenValueMidgame + RookValueMidgame)
        *mgValue += evaluate_king_safety(p, s, c, shelter);
    }
    else {
      // King shelter.  As an optimization, perhaps we could avoid evaluating
      // the king shelter in the late endgame?
      if(r >= RANK_5) {
        shelter += count_1s_8bit(pawns >> ((r-1)*8)) * 64;
        shelter += count_1s_8bit(pawns >> ((r-2)*8)) * 32;
        shelter += count_1s_8bit(pawns >> ((r-3)*8)) * 16;
      }
      *mgValue -= Value(shelter);

      // King safety.
      if(EvaluateKingSafety && p.queen_count(WHITE) >= 1 && 
         p.non_pawn_material(WHITE) >= QueenValueMidgame + RookValueMidgame)
        *mgValue -= evaluate_king_safety(p, s, c, shelter);
    }
  }


  // Evaluate the king safety for a king of the given color on the given
  // square.  The king safety evaluation is still very rudimentary; we
  // simply count the number of attacking pieces of each type and insert
  // the numbers in a simple formula.  We do not do any detailed analysis
  // of the attackers and defenders of each square around the king:  It is
  // not clear how to do this efficiently with bitboards.
  //
  // This function must be replaced with something more sophisticated later
  // on.  FIXME
  
  Value evaluate_king_safety(const Position& pos, Square ksq, Color c,
                             int shelter) {
    Color attacker = opposite_color(c);
    Bitboard attacking_knights = knights_attacking_king(pos, attacker, ksq);
    Bitboard attacking_bishops = bishops_attacking_king(pos, attacker, ksq);
    Bitboard attacking_rooks = rooks_attacking_king(pos, attacker, ksq);
    Bitboard attacking_queens = queens_attacking_king(pos, attacker, ksq);
    int count = 0, weight = 0, i;
    
    i = count_1s_max_15(attacking_knights);
    count += i; weight += 3*i;
    i = count_1s_max_15(attacking_bishops);
    count += i; weight += 3*i;
    i = count_1s_max_15(attacking_rooks);
    count += i; weight += 5*i;
    i = count_1s_max_15(attacking_queens);
    count += i; weight += 10*i;
    
    return (count >= 2)? 
      -Value(count * weight * (13 - shelter/32)) : Value(0);
  }
      

  // knights_attacking_king() returns a bitboard of all knights of a given
  // color which attacks squares adjacent to a given square.  It is used
  // in the king safety evaluation.
  
  Bitboard knights_attacking_king(const Position& pos, Color side, 
                                  Square ksq) {
    return pos.knights_of_color(side) & KnightAttackKingMask[ksq];
  }


  // bishops_attacking_king() returns a bitboard of all bishops of a given
  // color which attacks squares adjacent to a given square.  It is used
  // in the king safety evaluation.

  Bitboard bishops_attacking_king(const Position& pos, Color side,
                                  Square ksq) {
    Bitboard bishops = pos.bishops_of_color(side);
    Bitboard b1, b2, result;
    Square s;
    
    result = bishops & BishopAttackKingMask1[ksq];
    b1 = bishops & BishopAttackKingMask2[ksq] & ~result;
    b2 = pos.king_attacks(ksq);
    while(b1) {
      s = pop_1st_bit(&b1);
      if(pos.bishop_attacks(s) & b2)
        set_bit(&result, s);
    }
    return result;
  }


  // rooks_attacking_king() returns a bitboard of all rooks of a given
  // color which attacks squares adjacent to a given square.  It is used
  // in the king safety evaluation.

  Bitboard rooks_attacking_king(const Position& pos, Color side,
                                Square ksq) {
    Bitboard rooks = pos.rooks_of_color(side);
    Bitboard b1, b2, result;
    Square s;
    
    result = rooks & RookAttackKingMask1[ksq];
    b1 = rooks & RookAttackKingMask2[ksq] & ~result;
    b2 = pos.king_attacks(ksq);
    while(b1) {
      s = pop_1st_bit(&b1);
      if(pos.rook_attacks(s) & b2)
        set_bit(&result, s);
    }
    return result;
  }
    
    
  // queens_attacking_king() returns a bitboard of all queens of a given
  // color which attacks squares adjacent to a given square.  It is used
  // in the king safety evaluation.

  Bitboard queens_attacking_king(const Position& pos, Color side,
                                Square ksq) {
    Bitboard queens = pos.queens_of_color(side);
    Bitboard b1, b2, result;
    Square s;
    
    result = queens & QueenAttackKingMask1[ksq];
    b1 = queens & BishopAttackKingMask2[ksq] & ~result;
    b2 = pos.king_attacks(ksq);
    while(b1) {
      s = pop_1st_bit(&b1);
      if(pos.bishop_attacks(s) & b2)
        set_bit(&result, s);
    }
    b1 = queens & RookAttackKingMask2[ksq] & ~result;
    while(b1) {
      s = pop_1st_bit(&b1);
      if(pos.rook_attacks(s) & b2)
        set_bit(&result, s);
    }
    return result;
  }


  // evaluate_passed_pawns() evaluates the passed pawns for both sides.

  void evaluate_passed_pawns(const Position& pos, Bitboard passedPawns,
                             Value* mgValue, Value* egValue) {
    bool hasUnstoppable[2] = {false, false};
    int movesToGo[2] = {100, 100};

    for(Color c = WHITE; c <= BLACK; c++) {
      Square ourKingSq = pos.king_square(c);
      Square theirKingSq = pos.king_square(opposite_color(c));
      Bitboard b = passedPawns & pos.pawns_of_color(c);

      while(b) {
        Square s = pop_1st_bit(&b);
        assert(pos.piece_on(s) == pawn_of_color(c));
        assert(pos.pawn_is_passed(c, s));

        int r = int(pawn_rank(c, s) - RANK_2);
        Square blockSq = s + ((c == WHITE)? DELTA_N : DELTA_S);

        // Base bonus based on rank:
        Value mbonus = Value(8 + r * r * 8);
        Value ebonus = Value(16 + r * r * 12);

        // Adjust bonus based on king proximity:
        ebonus -= Value(square_distance(ourKingSq, blockSq) * r * 4);
        ebonus += Value(square_distance(theirKingSq, blockSq) * r * 6);

        // If the pawn is free to advance, increase bonus:
        if(pos.square_is_empty(blockSq) /*&& pos.see(s, blockSq) == 0*/)
          ebonus += Value(r * 12);

        // If the pawn is supported by a friendly pawn, increase bonus.
        Bitboard bb = 
          pos.pawns_of_color(c) & neighboring_files_bb(s);
        if(bb & rank_bb(s))
          ebonus += Value(r * 20);
        else if(pos.pawn_attacks(opposite_color(c), s) & bb)
          ebonus += Value(r * 12);

        // If the other side has only a king, check whether the pawn is
        // unstoppable:
        if(pos.non_pawn_material(opposite_color(c)) == Value(0)) {
          Square qsq;
          int tempo, d;

          tempo = (c == pos.side_to_move())? 0 : 1;
          qsq = relative_square(c, make_square(square_file(s), RANK_8));
          d = square_distance(s, qsq) - square_distance(theirKingSq, qsq)
            + tempo;

          if(d < 0) {
            int mtg = RANK_8 - pawn_rank(c, s);
            int blockerCount =
              count_1s(squares_in_front_of(c, s) & pos.occupied_squares());
            mtg += blockerCount;
            d += blockerCount;
            if(d < 0) {
              hasUnstoppable[c] = true;
              movesToGo[c] = Min(movesToGo[c], mtg);
            }
          }
        }
        *mgValue += Sign[c] * mbonus;
        *egValue += Sign[c] * ebonus;
      }
    }

    // Does either side have an unstoppable passed pawn?
    if(hasUnstoppable[WHITE] && !hasUnstoppable[BLACK])
      *egValue += UnstoppablePawnValue - Value(0x40 * movesToGo[WHITE]);
    else if(hasUnstoppable[BLACK] && !hasUnstoppable[WHITE])
      *egValue -= UnstoppablePawnValue - Value(0x40 * movesToGo[BLACK]);
    else if(hasUnstoppable[BLACK] && hasUnstoppable[WHITE]) {
      // Both sides have unstoppable pawns!  Try to find out who queens
      // first.  We begin by transforming 'movesToGo' to the number of
      // plies until the pawn queens for both sides:
      movesToGo[WHITE] *= 2;
      movesToGo[BLACK] *= 2;
      movesToGo[pos.side_to_move()]--;

      // If one side queens at least three plies before the other, that
      // side wins:
      if(movesToGo[WHITE] <= movesToGo[BLACK] - 3)
        *egValue += UnstoppablePawnValue - Value(0x40 * (movesToGo[WHITE]/2));
      else if(movesToGo[BLACK] <= movesToGo[WHITE] - 3)
        *egValue -= UnstoppablePawnValue - Value(0x40 * (movesToGo[BLACK]/2));

      // We could also add some rules about the situation when one side
      // queens exactly one ply before the other:  Does the first queen
      // check the opponent's king, or attack the opponent's queening square?
      // This is slightly tricky to get right, because it is possible that
      // the opponent's king has moved somewhere before the first pawn queens.
    }
      
  }


  // evaluate_trapped_bishop_a7h7() determines whether a bishop on a7/h7
  // (a2/h2 for black) is trapped by enemy pawns, and assigns a penalty
  // if it is.
  
  void evaluate_trapped_bishop_a7h7(const Position& pos, Square s, Color c,
                                    Value* mgValue, Value* egValue) {
    Piece pawn = pawn_of_color(opposite_color(c));
    Square b6, b8;

    assert(square_is_ok(s));
    assert(pos.piece_on(s) == bishop_of_color(c));

    if(square_file(s) == FILE_A) {
      b6 = relative_square(c, SQ_B6);
      b8 = relative_square(c, SQ_B8);
    }
    else {
      b6 = relative_square(c, SQ_G6);
      b8 = relative_square(c, SQ_G8);
    }

    if(pos.piece_on(b6) == pawn && pos.see(s, b6) < 0 && pos.see(s, b8) < 0) {
      *mgValue -= Sign[c] * TrappedBishopA7H7Penalty;
      *egValue -= Sign[c] * TrappedBishopA7H7Penalty;
    }

  }


  // evaluate_trapped_bishop_a1h1() determines whether a bishop on a1/h1
  // (a8/h8 for black) is trapped by a friendly pawn on b2/g2 (b7/g7 for
  // black), and assigns a penalty if it is.  This pattern can obviously
  // only occur in Chess960 games.
  
  void evaluate_trapped_bishop_a1h1(const Position& pos, Square s, Color c,
                                    Value* mgValue, Value* egValue) {
    Piece pawn = pawn_of_color(c);
    Square b2, b3, c3;

    assert(Chess960);
    assert(square_is_ok(s));
    assert(pos.piece_on(s) == bishop_of_color(c));

    if(square_file(s) == FILE_A) {
      b2 = relative_square(c, SQ_B2);
      b3 = relative_square(c, SQ_B3);
      c3 = relative_square(c, SQ_C3);
    }
    else {
      b2 = relative_square(c, SQ_G2);
      b3 = relative_square(c, SQ_G3);
      c3 = relative_square(c, SQ_F3);
    }

    if(pos.piece_on(b2) == pawn) {
      Value penalty;

      if(!pos.square_is_empty(b3))
        penalty = 2*TrappedBishopA1H1Penalty;
      else if(pos.piece_on(c3) == pawn)
        penalty = TrappedBishopA1H1Penalty;
      else
        penalty = TrappedBishopA1H1Penalty / 2;
      
      *mgValue -= Sign[c] * penalty;
      *egValue -= Sign[c] * penalty;
    }

  }


  // scale_by_game_phase interpolates between a middle game and an endgame
  // score, based on game phase.  It also scales the return value by a
  // ScaleFactor array.
  
  Value scale_by_game_phase(Value mv, Value ev, Phase ph, ScaleFactor sf[]) {
    assert(mv > -VALUE_INFINITE && mv < VALUE_INFINITE);
    assert(ev > -VALUE_INFINITE && ev < VALUE_INFINITE);
    assert(ph >= PHASE_ENDGAME && ph <= PHASE_MIDGAME);

    if(ev > Value(0))
      ev = apply_scale_factor(ev, sf[WHITE]);
    else
      ev = apply_scale_factor(ev, sf[BLACK]);

    Value result = Value(int((mv * ph + ev * (128 - ph)) / 128));
    return Value(int(result) & ~(GrainSize - 1));
  }


  // count_1s_8bit() counts the number of nonzero bits in the 8 least
  // significant bits of an integer.  This function is used by the king
  // shield evaluation.
  
  int count_1s_8bit(int b) {
    return int(BitCount8Bit[b & 0xFF]);
  }

}
