// Header for Evaluation Functions
// SlowChess 2003

const int F_MARGIN = 100; // Main Search
const int FUTILE_MARGIN = 130; // QSearch
const int LAZY_MARGIN  = 475;
const int LAZY_MARGIN2 = 180;

struct PawnHashEntry
    {
	 unsigned int checksum;
	 short eval, flags;
	 short Mat[4];
	 short MatEnd;
	 unsigned char PawnFileL, PawnFileR;
	 unsigned char OpenFileW, OpenFileB;
	 unsigned char WeakFileB, WeakFileW;
	 unsigned char WPassSqs[4], BPassSqs[4];
	 short PassedCon, extra;
    };

int Liquidate ( SBoard &Board );
short EvaluateBoard (const SBoard &Board, int alpha, int beta);
void Clear_PawnHash ( void );
unsigned int Pawn_HashBoard (const SBoard &Board);

void EvalPawns ( const SBoard &Board, PawnHashEntry &TEntry);
void PawnRookEval ( SBoard &Board, int &PawnEval, int &WRookEval, int &BRookEval );

const int KINGBYPAWN[9]      = { 0, 0,  0,  0,  0, 45, 75, 100,  0 };
const int KINGPAWNDIST[16]   = { 0, 0,  2, 12, 20, 28, 36, 40,  44, 44 };
const int BLOCKEDPASSPAWN[9] = { 0, 0,  0,  0,  8, 15, 20, 35 ,  0 };
const int WBLOCKER[16] = {  0, 0, 0, 1, 1, 1, 0, 1,  0, 0, 0, 0, 0, 0, 0, 0  };   
const int BBLOCKER[16] = {  0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 1, 1, 1, 0, 1  };   
#define ROOK_BEHIND_PP 21 // behind a passed pawn
const int ROOK_PP[30] = { 0, 0, ROOK_BEHIND_PP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -ROOK_BEHIND_PP, 0, 0, 0, 0, 0, 0, 0};
const int ROOK_PP1W[30] = { 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -6, 0, 0, 0, 0, 0, 0, 0};
const int ROOK_PP1B[30] = { 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -14, 0, 0, 0, 0, 0, 0, 0};

// If one side is up in material, it gets a bonus, using the number of total pieces on the board as the index into this array.
const int LIQUIDATION[36] = {  36,  36,  36, 36, 34, 32, 24, 16, 12,  8,  4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0, 0, 0, 0, 0};
#define MORE_PIECES 70

int inline MatEval ( const SBoard &Board, int nWP, int nBP, const int &MatVal)
{
	int eval = 0;

	if (Board.WPiece[14] != CAPTURED) nWP++; // Queen counts as 2 for this code
	if (Board.BPiece[14] != CAPTURED) nBP++;
	// More Pieces/ Number of pieces left
	if (nWP > nBP) eval+= MORE_PIECES; 
	if (nBP > nWP) eval-= MORE_PIECES;

	if (MatVal >  178 && Board.nWPawns > Board.nBPawns) eval+= LIQUIDATION [ nBP + nWP ];
	if (MatVal < -178 && Board.nBPawns > Board.nWPawns) eval-= LIQUIDATION [ nBP + nWP ];

	return eval;
}

//
// Number of moves for a king to walk form nSq1 to nSq2
//
int inline ChessDist (const int &nSq1, const int &nSq2)
	{
	int Dist1 = abs (SQRANK[nSq1] - SQRANK[nSq2]);
	int Dist2 = abs (SQFILE[nSq1] - SQFILE[nSq2]);
	return (Dist1 > Dist2) ? Dist1 : Dist2;
	}

int inline ChessDistW (const int &nSq1, const int &nSq2)
	{
	int Dist1 = SQRANK[nSq2] - SQRANK[nSq1];
	int Dist2 = abs (SQFILE[nSq1] - SQFILE[nSq2]);
	return (Dist1 > Dist2) ? Dist1 : Dist2;
	}

int inline ChessDistB (const int &nSq1, const int &nSq2)
	{
	int Dist1 = SQRANK[nSq1] - SQRANK[nSq2];
	int Dist2 = abs (SQFILE[nSq1] - SQFILE[nSq2]);
	return (Dist1 > Dist2) ? Dist1 : Dist2;
	}

// Endgame Evaluation
int OnePieceEndgame ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq, const PawnHashEntry &SPawns, const int WMat, const int BMat);
int KingAndPawns ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq, const PawnHashEntry &SPawns );
int MatingEval (const SBoard &Board, const int &nWKingSq, const int &nBKingSq, int eval);

void InitEndgameTables ( );
int ProbePawnBitbases ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq);
int ProbeBitbases ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq);
