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 */