home / fornax / fornax-v4-0 / src / eval / eval.cpp

eval.cpp



//
//  eval.cpp
//  fornax3
//
//  Created by Anders on 28/12/2020.
//
#include <stdio.h>
#include "eval.hpp"
#include "../libs/require.h"
#include "eval_pawn_structure.inc.h"
#include "eval_endgame_material.inc.h"
#include "eval_king_safety.inc.h"
#include "eval_activity.inc.h"

static eval configured_contempt = EVAL_CONTEMPT_DEFAULT;

static inline eval get_contempt_from_phase(const Board* board) {
  eval s = board_get_phase(board) * configured_contempt / PHASE_START;
  return s;
}

eval eval_calculate_contempt(const Board* board) {
  return get_contempt_from_phase(board) * (board->active == board->active_initial ? -1 : 1);
}

void eval_set_contempt_factor(long contempt) {
  require(contempt <= EVAL_CONTEMPT_MAX, "contempt was too big %d vs max %d\n", contempt, EVAL_CONTEMPT_MAX);
  require(contempt >= EVAL_CONTEMPT_MIN, "contempt was too small %d vs min %d\n", contempt, EVAL_CONTEMPT_MIN);
  configured_contempt = (eval) contempt;
#ifdef DEBUGLOG
  printf("ok contempt = %d\n", configured_contempt);
#endif
}

eval eval_count_psqt(const Side *side, const piecetable *psqt) {
  eval count = 0;
  for (int i = 0; i < 6; ++i) {
    bits64 bits = side->pieces[i];
    while (bits) count += (*psqt)[i][bits_pop_trailing(&bits)];
  }
  return count;
}

eval eval_count_material(const Side* side) {
  eval count = 0;
  count += BITS_COUNT(side->pieces[QUEEN]) * EVAL_PIECE_QUEENS;
  count += BITS_COUNT(side->pieces[ROOK]) * EVAL_PIECE_ROOKS;
  count += BITS_COUNT(side->pieces[BISHOP]) * EVAL_PIECE_BISHOPS;
  count += BITS_COUNT(side->pieces[KNIGHT]) * EVAL_PIECE_KNIGHTS;
  count += BITS_COUNT(side->pieces[PAWN]) * EVAL_PIECE_PAWNS;
  return count;
}

template<bool debug>
static constexpr eval eval_material(const Side* white, const Side* black) {
  
  eval w_mat = ED_ADD_WHITE("material", white->eval_material);
  eval b_mat = ED_ADD_BLACK("material", black->eval_material);
  
  eval diff = w_mat - b_mat;
  diff = adjust_for_drawish_endgames(w_mat, b_mat, diff);
  
  return diff;
}

template<bool debug>
static constexpr void eval_psqt(eval* mg, eval* eg, const Side* white, const Side* black) {
  eval w_mg_psqt = ED_ADD_WHITE_MG("psqt", white->eval_mg_psqt);
  eval w_eg_psqt = ED_ADD_WHITE_EG("psqt", white->eval_eg_psqt);
  
  eval b_mg_psqt = ED_ADD_BLACK_MG("psqt", black->eval_mg_psqt);
  eval b_eg_psqt = ED_ADD_BLACK_EG("psqt", black->eval_eg_psqt);
  
  *mg += w_mg_psqt - b_mg_psqt;
  *eg += w_eg_psqt - b_eg_psqt;
}

template<bool debug>
static constexpr void eval_bishop_pair(eval* mg, eval* eg, const Side* white, const Side* black) {
  bool w_pair = bits_is_multi_bit(white->pieces[BISHOP]);
  eval w_mg_bp = ED_ADD_WHITE_MG("bishop pair", w_pair * 20);
  eval w_eg_bp = ED_ADD_WHITE_EG("bishop pair", w_pair * 40);
  
  bool b_pair = bits_is_multi_bit(black->pieces[BISHOP]);
  eval b_mg_bp = ED_ADD_BLACK_MG("bishop pair", b_pair * 20);
  eval b_eg_bp = ED_ADD_BLACK_EG("bishop pair", b_pair * 40);
  
  *mg += w_mg_bp - b_mg_bp;
  *eg += w_eg_bp - b_eg_bp;
}

template<bool debug>
static constexpr void eval_rook_pair(eval* eg, const Side* white, const Side* black) {
  bool w_pair = bits_is_multi_bit(white->pieces[ROOK]);
  eval w_eg_rp = ED_ADD_WHITE_EG("rook pair", w_pair * -20);
  
  bool b_pair = bits_is_multi_bit(black->pieces[ROOK]);
  eval b_eg_rp = ED_ADD_BLACK_EG("rook pair", b_pair * -20);
  
  *eg += w_eg_rp - b_eg_rp;
}

template <bool debug = false>
static constexpr eval eval_evaluate_templ(const Board* board) {
  ED_START(board->active == WHITE);
  
  const Side* white = &board->side[WHITE];
  const Side* black = &board->side[BLACK];
  
  eval material = eval_material<debug>(white, black);
  eval mg_total = material;
  eval eg_total = material;
  
  eval_psqt<debug>(&mg_total, &eg_total, white, black);
  eval_activity<debug>(&mg_total, &eg_total, white, black);
  eval_king_safety<debug>(&mg_total, white, black);
  eval_pawn_structure<debug>(&mg_total, &eg_total, board);
  eval_bishop_pair<debug>(&mg_total, &eg_total, white, black);
  eval_rook_pair<debug>(&eg_total, white, black);
  
  uint16_t phase = board_get_phase(board);
  eval total = eval_taper(phase, mg_total, eg_total);
  ED_END(board, total);
  return board->active ? -total : total;
}

eval eval_evaluate(const Board* board) {
  return eval_evaluate_templ<false>(board);
}
eval eval_evaluate_debug(const Board* board) {
  return eval_evaluate_templ<true>(board);
}