#include "eval.h"
#include "bitcount.h"
#include "engine.h" // in order to use debugMode indicator
int queenWeight;
int rookWeight;
int bishopWeight;
int knightWeight;
int pawnWeight;
int kingMobilityFactor;
int queenMobilityFactor;
int rookMobilityFactor;
int bishopMobilityFactor;
int knightMobilityFactor;
int pawnMobilityFactor;
int pawnStructureFactor;
// TODO: improve the evaluation method with D,S,I
//
// SHANNON'S EVAL FUNCTION
//f(p) = 200(K-K')
// + 9(Q-Q')
// + 5(R-R')
// + 3(B-B' + N-N')
// + 1(P-P')
// - 0.5(D-D' + S-S' + I-I')
// + 0.1(M-M') + ...
//KQRBNP = number of kings, queens, rooks, bishops, knights and pawns
//D,S,I = doubled, blocked and isolated pawns
//M = Mobility (the number of legal moves)
Value EvaluateBoard(Position& p)
{
Value staticEval = EvaluateStaticScore(p);
/*
// DEBUG - STRANGE SCORE DETECTED
if(debugMode)
{
if(abs(staticEval) > 1500 && abs(staticEval)<(VALUE_MATE/2) )
{
std::cout << "STRANGE SCORE DETECTED = " << staticEval << std::endl;
for(int i=0;i<PIECEBB_SIZE;i++)
{
if(board.piecesBB[i])
{
std::cout << "Bitboard for " << " PNBRQK pnbrqk "[(int)i] << std::endl;
print(board.piecesBB[i]);
}
}
}
}
*/
if( staticEval < -VALUE_KNOWN_WIN || staticEval > +VALUE_KNOWN_WIN) return staticEval;
int mobilityEval = EvaluateMobilityScore(p);
int pawnStructsEval = EvaluatePawnHandicapScore(p);
return staticEval + mobilityEval + pawnStructsEval;
return staticEval;
}
Value EvaluateBoard(Position& p, Color turn)
{
if(turn == WHITE)
return EvaluateBoard(p);
else
return -EvaluateBoard(p);
}
Value EvaluateBoard(Position& p, Color turn, int depth)
{
if( (turn+depth) % 2 )
return -EvaluateBoard(p);
else
return EvaluateBoard(p);
}
Value EvaluateMobilityScore(Position& p)
{
/*
attack_t whites, blacks;
// TODO: launch this part only once - should be factorized with the 'isCheck' validation (movegen)
get_attacks(p, WHITE, whites);
get_attacks(p, BLACK, blacks);
// be carefull : make a copy before popcounts
Bitboard wka = whites.kingAttacks;
Bitboard wqa = whites.queenAttacks;
Bitboard wra = whites.rookAttacks;
Bitboard wba = whites.bishopAttacks;
Bitboard wna = whites.knightAttacks;
Bitboard wpa = whites.pawnAttacks;
Bitboard bka = blacks.kingAttacks;
Bitboard bqa = blacks.queenAttacks;
Bitboard bra = blacks.rookAttacks;
Bitboard bba = blacks.bishopAttacks;
Bitboard bna = blacks.knightAttacks;
Bitboard bpa = blacks.pawnAttacks;
int mobility = 0;
mobility += kingMobilityFactor * (popcount<Max15>(wka) - popcount<Max15>(bka));
mobility += queenMobilityFactor * (popcount<Full>(wqa) - popcount<Full>(bqa));
mobility += rookMobilityFactor * (popcount<Max15>(wra) - popcount<Max15>(bra));
mobility += bishopMobilityFactor * (popcount<Max15>(wba) - popcount<Max15>(bba));
mobility += knightMobilityFactor * (popcount<Max15>(wna) - popcount<Max15>(bna));
mobility += pawnMobilityFactor * (popcount<Full>(wpa) - popcount<Full>(bpa));
int attack = 0;
const int attackFactor = 100;
Bitboard waf = b.colorBB[BLACK] & whites.allAttacks;
Bitboard baf = b.colorBB[BLACK] & whites.allAttacks;
attack += attackFactor * (popcount<Full>(waf) - popcount<Full>(baf));
return Value((mobility/600) + (attack/100));
*/
return Value(0);
}
// new static eval using bitboards and fast bitcount ops
Value EvaluateStaticScore(Position& p)
{
// be carefull : make a copy before popcounts
Bitboard wk = p.pieces(WHITE, KING);
Bitboard wq = p.pieces(WHITE, QUEEN);
Bitboard wr = p.pieces(WHITE, ROOK);
Bitboard wb = p.pieces(WHITE, BISHOP);
Bitboard wn = p.pieces(WHITE, KNIGHT);
Bitboard wp = p.pieces(WHITE, PAWN);
Bitboard bk = p.pieces(BLACK, KING);
Bitboard bq = p.pieces(BLACK, QUEEN);
Bitboard br = p.pieces(BLACK, ROOK);
Bitboard bb = p.pieces(BLACK, BISHOP);
Bitboard bn = p.pieces(BLACK, KNIGHT);
Bitboard bp = p.pieces(BLACK, PAWN);
int result;
// king value is always 30000
result = 30000 * (popcount<Full>(wk) - popcount<Full>(bk));
result += queenWeight * (popcount<Full>(wq) - popcount<Full>(bq));
result += rookWeight * (popcount<Full>(wr) - popcount<Full>(br));
result += bishopWeight * (popcount<Full>(wb) - popcount<Full>(bb));
result += knightWeight * (popcount<Full>(wn) - popcount<Full>(bn));
result += pawnWeight * (popcount<Full>(wp) - popcount<Full>(bp));
return Value(result);
}
//D,S,I = doubled, blocked and isolated pawns
//score = - 0.5(D-D' + S-S' + I-I')
Value EvaluatePawnHandicapScore(Position& p)
{
/*
// calculation of the doubled pawns
int doubled = 0;
for(File f=FILE_A; f<=FILE_H; f+=(File)1)
{
Bitboard w_doubled = board.piecesBB[W_PAWN] & FileBB[f];
Bitboard b_doubled = board.piecesBB[B_PAWN] & FileBB[f];
//pop_1st_bit(&w_doubled);
//pop_1st_bit(&b_doubled);
doubled += popcount<Max15>(b_doubled) - popcount<Max15>(w_doubled);
}
// calculation of the blocked pawns
Bitboard w_blocked = (p.piecesBB[W_PAWN] << DELTA_N) & board.colorBB[BLACK];
Bitboard b_blocked = (p.piecesBB[B_PAWN] >> DELTA_N) & board.colorBB[WHITE];
int blocked = popcount<Max15>(b_blocked) - popcount<Max15>(w_blocked);
// calculation of isolated pawns
int isolated = 0;
// A file
if((FileBBB & board.piecesBB[W_PAWN]) == 0)
isolated -= popcount<Max15>(FileABB & board.piecesBB[W_PAWN]) ;
if((FileBBB & board.piecesBB[B_PAWN]) == 0)
isolated += popcount<Max15>(FileABB & board.piecesBB[B_PAWN]) ;
// H file
if((FileGBB & board.piecesBB[W_PAWN]) == 0)
isolated -= popcount<Max15>(FileHBB & board.piecesBB[W_PAWN]) ;
if((FileGBB & board.piecesBB[B_PAWN]) == 0)
isolated += popcount<Max15>(FileHBB & board.piecesBB[B_PAWN]) ;
// central files
for(File f=FILE_B; f<=FILE_G; f+=(File)1)
{
if(((FileBB[f-1] | FileBB[f+1]) & board.piecesBB[W_PAWN]) == 0)
isolated -= popcount<Max15>(FileBB[f] & board.piecesBB[W_PAWN]) ;
if(((FileBB[f-1] | FileBB[f+1]) & board.piecesBB[B_PAWN]) == 0)
isolated += popcount<Max15>(FileBB[f] & board.piecesBB[B_PAWN]) ;
}
return Value(pawnStructureFactor * (doubled + blocked + isolated));
*/
return Value(0);
}