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

eval_pawn_structure.inc.h



//
//  eval_pawn_structure.h
//  fornax3
//
//  Created by Anders on 26/04/2020.
//

#ifndef eval_pawn_structure_h
#define eval_pawn_structure_h

#include "../bits.h"
#include "eval_defs.h"
#include "eval_debug_print.hpp"
#include "../parsing.hpp"
#include "../libs/ints.h"

template<direction dir>
static inline bits64 pawn_span(bits64 pawns) {
  return bits_fill<dir>(bits_shift<dir>(pawns));
}

static inline bits64 pawn_file_fill(bits64 pawns) {
  return bits_fill<S>(pawns) | bits_fill<N>(pawns);
}

template<color col>
static inline bits64 backward_pawns(bits64 pawns, bits64 opposingpawns) {
  constexpr direction spandir = col ? S : N;
  constexpr direction shiftE = col ? NE : SE;
  constexpr direction shiftW = col ? NW : SW;
  constexpr direction shift = col ? N : S;
  
  bits64 stops = bits_shift<spandir>(pawns);
  bits64 attack_spans = pawn_span<spandir>(bits_shift_guarded<W>(stops)) | pawn_span<spandir>(bits_shift_guarded<E>(stops));
  bits64 opposing_attacks = bits_shift_guarded<shiftE>(opposingpawns) | bits_shift_guarded<shiftW>(opposingpawns);

  return bits_shift<shift>(stops & opposing_attacks & ~attack_spans);
}

template<color col>
static inline bits64 passed_pawns(bits64 pawns, bits64 opposingpawns) {
  constexpr direction spandir = col ? N : S;
  
  bits64 opposing = pawn_span<spandir>(opposingpawns);
  opposing |= bits_shift_guarded<E>(opposing) | bits_shift_guarded<W>(opposing);
  return pawns & ~opposing;
}

static inline bits64 doubled_pawns(bits64 pawns) {
  return (pawn_span<N>(pawns) | pawn_span<S>(pawns)) & pawns;
}

static inline bits64 isolated_pawns(bits64 pawns) {
  bits64 filefill  = pawn_file_fill(pawns);
  return (pawns & ~bits_shift_guarded<E>(filefill)) & (pawns & ~bits_shift_guarded<W>(filefill));
}


static inline bits64 adjacent_pawns(bits64 pawns) {
  return (bits_shift_guarded<W>(pawns) | bits_shift_guarded<E>(pawns)) & pawns;
}

template<color col>
static inline eval count_passer(bits64 passers) {
  constexpr int8_t const (*passer_pt)[64] = col ? &BLACK_PASSEDPAWN_PIECETABLE : &WHITE_PASSEDPAWN_PIECETABLE;
  
  eval tot = 0;
  while (passers) {
    square sq = bits_pop_trailing(&passers);
    tot += (*passer_pt)[sq];
  }
  return tot;
}

template<bool debug>
static constexpr void eval_pawn_structure(eval* mg, eval* eg, const Board* board) {
  
  bits64 white = board->side[WHITE].pieces[PAWN];
  bits64 black = board->side[BLACK].pieces[PAWN];

  bits64 white_pawn_attacks = board_get_pawns_attackmask(&board->side[WHITE]);
  bits64 black_pawn_attacks = board_get_pawns_attackmask(&board->side[BLACK]);
  bits64 white_piece_stoppers = bits_fill<S>(board->side[BLACK].piecemask);
  bits64 black_piece_stoppers = bits_fill<N>(board->side[WHITE].piecemask);
  bits64 white_attack_stoppers = bits_fill<S>(board->side[BLACK].attackmask);
  bits64 black_attack_stoppers = bits_fill<N>(board->side[WHITE].attackmask);
  bits64 white_protected= board->side[WHITE].pieces[PAWN] & white_pawn_attacks;
  bits64 black_protected = board->side[BLACK].pieces[PAWN] & black_pawn_attacks;

  bits64 white_passers = passed_pawns<WHITE>(white, black);
  bits64 black_passers = passed_pawns<BLACK>(black, white);
  bits64 white_isolated = isolated_pawns(white);
  bits64 black_isolated = isolated_pawns(black);

  bits64 white_doubles = doubled_pawns(white);
  bits64 black_doubles = doubled_pawns(black);
  
  eval mg_tot = 0;
  eval eg_tot = 0;

  eval w_rolling_passers = BITS_COUNT(white_passers & ~(white_piece_stoppers | white_attack_stoppers)) * 50;
  eval b_rolling_passers = BITS_COUNT(black_passers & ~(black_piece_stoppers | black_attack_stoppers)) * 50;
  eval w_bad_passers = count_passer<WHITE>(white_passers & white_piece_stoppers & white_isolated);
  eval b_bad_passers = count_passer<BLACK>(black_passers & black_piece_stoppers & black_isolated);
  eval w_all_passers = count_passer<WHITE>(white_passers);
  eval b_all_passers = count_passer<BLACK>(black_passers);
  eval w_prot_passers = count_passer<WHITE>(white_passers & white_protected);
  eval b_prot_passers = count_passer<BLACK>(black_passers & black_protected);

  eval mg_w_passers = ED_ADD_WHITE_MG("passers", ((w_all_passers - w_bad_passers) + w_prot_passers) / 2);
  eval mg_b_passers = ED_ADD_BLACK_MG("passers", ((b_all_passers - b_bad_passers) + b_prot_passers) / 2);
  eval eg_w_passers = ED_ADD_WHITE_EG("passers", (w_all_passers - w_bad_passers / 2) + w_prot_passers + w_rolling_passers);
  eval eg_b_passers = ED_ADD_BLACK_EG("passers", (b_all_passers - b_bad_passers / 2) + b_prot_passers + b_rolling_passers);
  
  mg_tot += mg_w_passers - mg_b_passers;
  eg_tot += eg_w_passers - eg_b_passers;

  eval protected_diff = ED_ADD_WHITE("protected", BITS_COUNT(white_protected)) - ED_ADD_BLACK("protected", BITS_COUNT(black_protected));
  mg_tot += ED_ADD_DIFF_MG("protected", protected_diff * 4);
  eg_tot += ED_ADD_DIFF_EG("protected", protected_diff * 6);

  eval isolateddiff = ED_ADD_BLACK("isolated",  BITS_COUNT(black_isolated)) - ED_ADD_WHITE("isolated", BITS_COUNT(white_isolated));
  mg_tot += ED_ADD_DIFF_MG("isolated", isolateddiff * 10);
  eg_tot += ED_ADD_DIFF_EG("isolated", isolateddiff * 20);

  eval doublediff = ED_ADD_BLACK("doubled", BITS_COUNT(black_doubles)) - ED_ADD_WHITE("doubled", BITS_COUNT(white_doubles));
  mg_tot += ED_ADD_DIFF_MG("doubled", doublediff * 8);
  eg_tot += ED_ADD_DIFF_EG("doubled", doublediff * 12);
  
  *mg += mg_tot;
  *eg += eg_tot;

}
#endif /* eval_pawn_structure_h */