home /
fornax /
fornax-v4-0 /
src /
moving /
movepick.hpp
movepick.hpp
//
// movepick.hpp
// fornax3
//
// Created by Anders on 30/12/2020.
//
#ifndef movepick_h
#define movepick_h
#include "../board.h"
#include "../move.h"
#include "../eval/eval.hpp"
#include "../eval_defs.h"
#include "../eval/eval_piecetables.h"
#include "../parsing.hpp"
static inline eval movepick_debug_print(const char* topic, eval value) {
printf("|%-20s | %5d |\n", topic, value);
return value;
}
#define RECORD_MVAL(topic, value) (debug ? movepick_debug_print(topic, value) : value)
static move movepick_killer1[UINT8_MAX + 1] = { 0 };
static move movepick_killer2[UINT8_MAX + 1] = { 0 };
static inline void movepick_set_killer(uint8_t ply, evalmove m) {
if (MOVE_VALUE(m) > EVAL_MOVEPICK_KILLER_VALUE) return;
if (movepick_killer1[ply] != m) {
movepick_killer2[ply] = movepick_killer1[ply];
movepick_killer1[ply] = (move) m;
}
}
template <color active, bool debug = false>
static constexpr eval movepick_eval(const Board* board, move m) {
if (debug) printf("|topic | value |\n");
if (debug) printf("|---------------------+-------|\n");
constexpr color opp = COLOR_OPPOSITE(active);
constexpr const piecetable *a_mg_psqt = active ? &BLACK_MG_PIECETABLE : &WHITE_MG_PIECETABLE;
constexpr const piecetable *a_eg_psqt = active ? &BLACK_EG_PIECETABLE : &WHITE_EG_PIECETABLE;
const bits64 *attack_levels = board->side[opp].attackmask_levels;
const square origin = MOVE_GET_ORIGIN(m);
const square dest = MOVE_GET_DEST(m);
const piecetype piece = board->piecemap[origin];
const piecetype capture = board->piecemap[dest];
const piecetype promotion = MOVE_GET_PROMOTION(m);
bool is_bad_destination = BITS_TEST(attack_levels[piece], dest);
assert(!(is_bad_destination && piece == KING));
const eval piecevalue = EVAL_PIECE[piece];
const eval origin_mg_psqt_score = (*a_mg_psqt)[piece][origin];
const eval dest_mg_psqt_score = (*a_mg_psqt)[piece][dest];
const eval origin_eg_psqt_score = (*a_eg_psqt)[piece][origin];
const eval dest_eg_psqt_score = (*a_eg_psqt)[piece][dest];
const eval mg_psqt = dest_mg_psqt_score - origin_mg_psqt_score;
const eval eg_psqt = dest_eg_psqt_score - origin_eg_psqt_score;
const eval psqt_tapered = eval_taper(board_get_phase(board), mg_psqt, eg_psqt);
eval value = 0;
value += RECORD_MVAL("PSQT", psqt_tapered);
value += RECORD_MVAL("destination bad", -is_bad_destination * (piecevalue) / 2);
if (promotion != KING) {
value += RECORD_MVAL("promotion bonus", EVAL_PIECE[promotion]);
}
if (capture != NONE) {
value += RECORD_MVAL("capture bonus", EVAL_PIECE[capture] - piecevalue / 8 + EVAL_MOVEPICK_CAPTURE_BONUS);
}
else if (piece == PAWN && SQUARE_X(origin) != SQUARE_X(dest)) {
value += RECORD_MVAL("en passant bonus", EVAL_MOVEPICK_ENPASSANT_VALUE); // ep boost
}
if (debug) printf("|---------------------+-------|\n");
return RECORD_MVAL("total", value);
}
template <color active>
static constexpr void movepick_annotate_list(const Board* board, evalmove moves[128], uint8_t size, move ttmove) {
for (uint8_t n = 0; n < size; n++) {
evalmove m = moves[n];
eval value = movepick_eval<active, false>(board, (move) m);
if ((move) m == ttmove) {
value += EVAL_MOVEPICK_TT_VALUE;
}
else if ((move) m == movepick_killer1[board->ply]) {
value += EVAL_MOVEPICK_KILLER_VALUE;
}
else if ((move) m == movepick_killer2[board->ply]) {
value += EVAL_MOVEPICK_KILLER_VALUE;
}
moves[n] |= (unsigned int) (value << 16);
}
}
static constexpr void movepick_annotate_ttmove(evalmove moves[128],
uint8_t size,
move ttmove) {
if (!ttmove) return;
for (uint8_t n = 0; n < size; n++) {
move m = (move) moves[n];
if (m != ttmove) continue;
moves[n] += EVAL_PIECE_KINGS << 16;
}
}
static constexpr evalmove movepick_find_best(evalmove moves[128], uint8_t size, uint8_t n) {
eval best = INT16_MIN;
uint8_t bi = 0;
for (uint8_t i = n; i < size; i++) {
evalmove m = moves[i];
eval e = MOVE_VALUE(m);
if (e > best) {
best = e;
bi = i;
}
}
evalmove bm = moves[bi];
moves[bi] = moves[n];
return bm;
}
#endif /* movepick_h */