home / fornax / fornax-v4-0 / src / eval / eval_king_safety.inc.h

eval_king_safety.inc.h



//
// Created by Anders on 11/08/2022.
//

#ifndef FORNAX3_EVAL_KING_SAFETY_INC_H
#define FORNAX3_EVAL_KING_SAFETY_INC_H

#include "eval_defs.h"
#include "eval_debug_print.hpp"
#include "../moving/oracle.hpp"

static inline eval king_threats_or_defence(bits64 attacks, bits64 kingNeighborSquares) {
  return BITS_COUNT(attacks & kingNeighborSquares);
}

template<color c>
static constexpr eval get_king_open_file_score(const Side* friendly,
                                               const Side* hostile) {
  constexpr direction dir = c == WHITE ? N : S;

  square king = bits_get_leading(friendly->pieces[KING]);
  bits64 slide = oracle_get_slide<dir>(king);

  eval count = BITS_COUNT(slide & (friendly->pieces[PAWN] | hostile->pieces[PAWN]));

  switch (count) {
    case 0: return -30;
    case 1: return -15;
    default: return 0;
  }
}

static inline eval king_shield_score(eval pawnShield) {
  switch (pawnShield) {
    case 0: return -60;
    case 1: return -30;
    case 2: return 0;
    case 3: return 10;
    default: return 15;
  }
}

template<color c>
static constexpr eval shield_count(const Side* side) {
  const bits64 king = side->pieces[KING];

  bits64 pawn_shield_area = oracle_get_king_pawn_shield_area(bits_get_leading(king));
  bits64 piece_shield_area = board_get_king_attackmask(side);

  eval pawn_shield = BITS_COUNT(pawn_shield_area & side->pieces[PAWN]);
  eval piece_shield = BITS_COUNT(piece_shield_area & (side->pieces[KNIGHT] | side->pieces[BISHOP]));

  eval total_shield = pawn_shield + piece_shield + ((king & BB_CORNERS) > 0);

  return total_shield;
}

static constexpr eval king_threat_score(eval recorded_nearby_hostile_attacks,
                                     eval recorded_nearby_friendly_attacks,
                                     eval shield_count) {
  shield_count--;
  eval def = shield_count * shield_count + recorded_nearby_friendly_attacks - 12;
  eval attacks = recorded_nearby_hostile_attacks * 2;
  eval diff = attacks - def;
  eval threat = diff > 0 ? (diff * diff) : diff / 2;
  return -threat;
}

template<bool debug>
static constexpr void eval_king_safety(eval* mg,
                                    const Side* white,
                                    const Side* black) {
  if (white->eval_phase < 4 || black->eval_phase < 4) return;

  const bits64 w_king_neighbors = board_get_king_attackmask(white) | white->pieces[KING];
  const bits64 b_king_neighbors = board_get_king_attackmask(black) | black->pieces[KING];
  eval w_king_nearby_friendly_attacks = 0;
  eval w_king_nearby_hostile_attacks = 0;
  eval b_king_nearby_friendly_attacks = 0;
  eval b_king_nearby_hostile_attacks = 0;

  for (uint8_t i = 0; i < white->attackmapsize; ++i) {
    Attackmap set = white->attackkmaps[i];
    bits64 attacks = set.bits;
    w_king_nearby_friendly_attacks += king_threats_or_defence(attacks, w_king_neighbors);
    b_king_nearby_hostile_attacks += king_threats_or_defence(attacks, b_king_neighbors);
  }
  for (uint8_t i = 0; i < black->attackmapsize; ++i) {
    Attackmap set = black->attackkmaps[i];
    bits64 attacks = set.bits;
    b_king_nearby_friendly_attacks += king_threats_or_defence(attacks, b_king_neighbors);
    w_king_nearby_hostile_attacks += king_threats_or_defence(attacks, w_king_neighbors);
  }

  eval w_shield_count = shield_count<WHITE>(white);
  eval b_shield_count = shield_count<BLACK>(black);

  eval w_shield_score = ED_ADD_WHITE_MG("king shield", king_shield_score(w_shield_count));
  eval b_shield_score = ED_ADD_BLACK_MG("king shield", king_shield_score(b_shield_count));
  eval shield_score = w_shield_score - b_shield_score;
  *mg += shield_score;

  eval w_threat_score = ED_ADD_WHITE_MG(
      "king threats",
      king_threat_score(w_king_nearby_hostile_attacks, w_king_nearby_friendly_attacks, w_shield_count)
  );
  eval b_threat_score = ED_ADD_BLACK_MG(
      "king threats",
      king_threat_score(b_king_nearby_hostile_attacks, b_king_nearby_friendly_attacks, b_shield_count)
  );
  eval threat_score = w_threat_score - b_threat_score;
  *mg += threat_score;

  eval w_open_file_score = ED_ADD_WHITE_MG("king open", get_king_open_file_score<WHITE>(white, black));
  eval b_open_file_score = ED_ADD_BLACK_MG("king open", get_king_open_file_score<BLACK>(black, white));
  eval open_score = w_open_file_score - b_open_file_score;
  *mg += open_score;
}

#endif //FORNAX3_EVAL_KING_SAFETY_INC_H