#include <math.h>
#include "win32compat.h"
#include <stdio.h>
#include "data.h"
#include "evaluate.h"

//
// MatingEval is called when neither side has any pawns left on the board
//
//
const int BISHVKN = 2*PieceValues [ WBISHOP ] - PieceValues [ WKNIGHT ];

int MatingEval (const SBoard &Board, const int &nWKingSq, const int &nBKingSq, int eval)
	{
	int nSq;

		// Is there sufficicent Material to Mate?
		if (Board.MatVal <=0 && Board.nBP <= 1 && Board.nBP == Board.nBMinors) return 0;
		if (Board.MatVal >= 0 && Board.nWP <= 1 && Board.nWP == Board.nWMinors) return 0;
			
		// BLACK has no pieces
		if (Board.nBP == 0) 
			{
			if (Board.nWMinors == 2 && Board.nWP == 2)  
				{
				if (Board.WMat == KNIGHTSV ) return 1; // 2 Knights == drawn endgame
				nSq = 25;
				// FixMe: Promoted to Bishop?
				if (Board.WPiece [10]!= CAPTURED) nSq = Board.WPiece[10];
				if (Board.WPiece [11]!= CAPTURED) nSq = Board.WPiece[11];
				if (SQCOLOR [ nSq ] == 2)
					eval += ((WKingValueKBNK[ nBKingSq ]*3) + 50); 
				else eval += WKingValueKBNK[ SQ ( SQFILE[nBKingSq]-1, SQRANK[nBKingSq]-1 )]*3 + 50;
				}
				else eval -= ((WKingValueKRK[nBKingSq]<<1) - 300);

			// Encourage White King to move next to Black King
			eval -= ChessDist ( nWKingSq, nBKingSq) * 8;
			return eval;
			}
		// WHITE has no pieces
		if (Board.nWP == 0) 
			{
			if (Board.nBMinors == 2 && Board.nBP == 2)  
				{
				if (Board.BMat == KNIGHTSV  ) return -1;
				nSq = 25;
				if (Board.BPiece [10]!= CAPTURED) nSq = Board.BPiece[10];
				if (Board.BPiece [11]!= CAPTURED) nSq = Board.BPiece[11];

				if (SQCOLOR [ nSq ] == 2) eval -= ((WKingValueKBNK[nWKingSq]*3) + 50); 
					else eval -= WKingValueKBNK[ SQ ( SQFILE[nWKingSq]-1, SQRANK[nWKingSq]-1 )]*3 + 50;
				}
				else eval += ((WKingValueKRK[nWKingSq]<<1) - 300);

			eval += ChessDist ( nWKingSq, nBKingSq) * 8;
			return eval;
			}
		// Both Sides have pieces of unequal value, do King Centralization and distance between kings
		if (abs (Board.MatVal) > 40 )
			{
			if (Board.MatVal > 40)	eval -= ChessDist ( nWKingSq, nBKingSq) * 16;
			if (Board.MatVal <-40)	eval += ChessDist ( nWKingSq, nBKingSq) * 16;

			eval += (WKingValueEnd [ nWKingSq ] + (WKingValueEnd [ nWKingSq ]>>1));
			eval -= (WKingValueEnd [ nBKingSq ] + (WKingValueEnd [ nBKingSq ]>>1));
			}
		// One Side is up only 1 minor piece, should probably be a draw unless that side has more than 2 pieces.
		// One side is only up the exchange, should draw
		if (eval > 0)
			{
			if (Board.WMat == KNIGHTSV ) return 1; // 2 Knights == drawn endgame
			if (Board.nWP == (Board.nBP+1) && Board.nWMinors == (Board.nBMinors+1) && Board.MatVal < 400 ) 
				{if (Board.nWP > 2)  eval = (eval>>1);
					else 
					{if (Board.WMat == PieceValues[ WROOK ] + PieceValues[ WBISHOP ] || Board.WMat > PieceValues[WQUEEN] || Board.MatVal == BISHVKN) eval = (eval>>2);
						else eval = (eval>>3); 
					}
				}
			if ( Board.WMat == PieceValues [WROOK] && Board.nBP == 1)
				{
				if (Board.BMat == PieceValues[ WKNIGHT] ) // Rook Versus Knight, rewared knight near King
					{
					int nKnightSq = Board.BPiece[8];
					if ( nKnightSq == CAPTURED)  nKnightSq = Board.BPiece[9];
					eval = ((eval + ChessDist ( nBKingSq, nKnightSq ) * 16)>>2);
					}
				else eval = (eval>>3) + (eval>>4);
				}
			}
		else
			{
			if (Board.BMat == KNIGHTSV  ) return -1;
			if (Board.nBP == (Board.nWP+1) && Board.nBMinors == (Board.nWMinors+1) && Board.MatVal > -400 ) 
				{	if (Board.nBP > 2) eval = (eval>>1); 
						else 
						{if (Board.BMat == PieceValues[ WROOK ] + PieceValues[ WBISHOP ] || Board.BMat > PieceValues[WQUEEN] || Board.MatVal == -BISHVKN) eval = (eval>>2);
							else eval = (eval>>3); 
						}
				}
			if (Board.BMat == PieceValues [WROOK] && Board.nWP == 1)
				{
				if (Board.WMat == PieceValues[ WKNIGHT])
					{
					int nKnightSq = Board.WPiece[8];
					if ( nKnightSq == CAPTURED)  nKnightSq = Board.WPiece[9];
					eval = ((eval - ChessDist ( nWKingSq, nKnightSq  ) * 16)>>2);
					}
				else eval = (eval>>3) + (eval>>4);
				}
			}

	return eval;
	}


#define PAWNUP_KPKP 25
#define OUTSIDE_PAWN 110
#define KING_AWOL 100
#define KING_AWOL_1P 40
#define PAWNRACE 495
//
// 
// Test to see if any PASSED PAWNS ARE UNSTOPPABLE (can definitely promote) 
//
//
int PawnRacesEval (const SBoard &Board, int &eval, const int &nWKingSq, const int &nBKingSq, const PawnHashEntry &SPawns)
{
int nSq, BQdist = 10, WQdist = 10, nDist = 0, stm, lFile = 0, rFile = 0, nMaxDist = 0;
if (Board.nBP == 0)  // White passed Pawns
	{
	stm = Board.SideToMove == BLACK ? 1:0;
	for (int i = 0; i < 4; i++)
		{
		nSq=SPawns.WPassSqs[i];
		if (nSq==0) break;
		nDist = 8-SQRANK [nSq];
		if (nDist > 5) nDist = 5;
		if (i == 0) {lFile = SQFILE[nSq]; nMaxDist = nDist;} else rFile = SQFILE[nSq];
		int KingDst = ChessDist ( WQUEENSQ[nSq] , nBKingSq);
		int fKingDst = ChessDist  ( WQUEENSQ[nSq] , nWKingSq);
		if (SQFILE [nWKingSq] == SQFILE [nSq] && nWKingSq < nSq) nDist++; // King in front of pawn
		if ((KingDst > (nDist+stm) )  // Runaway pawn
			|| ( ((fKingDst == 1 && nDist< 4) || (nDist < 3 && fKingDst <= 2 && (KingDst>1 || (KingDst == 1 && nDist == 1 && stm == 0))) )   // Pawn guided by king
				&& ((SQFILE[nWKingSq]&7)>1 || (nDist-1) != (8-SQRANK [nSq])) )) // Make sure the king isn't trapped in front of the pawn
				{if (nDist < WQdist) WQdist = nDist;
				}
		}
	if (nDist != nMaxDist)  
		{if (nDist > nMaxDist) nMaxDist = nDist; // Split passers where at least 1 will outrun the king
		 if (nMaxDist > 0) rFile += 1-stm; // stm bonus, can be split 1 less
		}
	if ((rFile-lFile) > nMaxDist) if (nMaxDist < WQdist) WQdist = nMaxDist;
	}
if (Board.nWP == 0) // Black passed Pawns
	{
	rFile = 0; nMaxDist = 0;
	stm = Board.SideToMove == WHITE ? 1:0;
	for (int i = 0; i < 4; i++)
		{
		nSq=SPawns.BPassSqs[i];
		if (nSq==0) break;
		nDist = SQRANK [nSq]-1;
		if (nDist > 5) nDist = 5;
		if (i == 0) {lFile = SQFILE[nSq]; nMaxDist = nDist;} else rFile = SQFILE[nSq];
		int KingDst = ChessDist ( BQUEENSQ[nSq], nWKingSq);
		int fKingDst = ChessDist  ( BQUEENSQ[nSq] , nBKingSq);
		if (SQFILE [nBKingSq] == SQFILE [nSq] && nBKingSq > nSq) nDist++;
		if ( (KingDst > (nDist+stm))
			|| ( ((fKingDst == 1 && nDist < 4) || ( nDist < 3 && fKingDst <= 2 && (KingDst>1 || (KingDst == 1 && nDist == 1 && stm == 0))))
				&& ((SQFILE[nBKingSq]&7)>1 || (nDist-1) != (SQRANK [nSq]-1) ) ))
				{if (nDist < BQdist) BQdist = nDist;}
		}
	if (nDist != nMaxDist)  
		{if (nDist > nMaxDist) nMaxDist = nDist;
		 if (nMaxDist > 0) rFile += 1-stm; // stm bonus, can be split 1 less
		}
	if ((rFile-lFile) > nMaxDist) if (nMaxDist < BQdist) BQdist = nMaxDist;
	}
WQdist = (WQdist<<1);
BQdist = (BQdist<<1); 
if (Board.SideToMove == BLACK) WQdist++; else BQdist++;
if (WQdist < (BQdist-1) ) {eval+=PAWNRACE; return WHITE;}
if (BQdist < (WQdist-1) ) {eval-=PAWNRACE; return BLACK;}
return 0;
}

#define NO_CHANCES 100
//
// Endgame with No Pieces
//
int KingAndPawns ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq, const PawnHashEntry &SPawns )
{
	// Normal Pawn Evaluation
	eval += (SPawns.eval>>1) + (SPawns.eval>>2) + SPawns.MatEnd + (SPawns.PassedCon>>2);

	// Check the win/loss/draw bitbases
	if (ProbePawnBitbases (Board, eval, nWKingSq, nBKingSq)) 
		{
		if (eval > 0) eval += SQRANK [ nWKingSq ]*4;
		if (eval < 0) eval -= (9-SQRANK [ nBKingSq ])*4;
		return eval;
		}

	eval += ((WKingValueEnd [ nWKingSq ] - WKingValueEnd [ nBKingSq ])>>2);
	//
	if (Board.nBPawns == 0) eval+= NO_CHANCES;
	if (Board.nWPawns == 0) eval-= NO_CHANCES;

	// PawnRaces
	int nTemp = PawnRacesEval (Board, eval, nWKingSq, nBKingSq, SPawns);
	if (nTemp == 0)
		{
		// Kings & pawns only evaluation (done if there are no won pawn races)

		// Outside passed pawns, etc.
		if ( (SPawns.flags&16) && (SPawns.flags&32) == 0 ) eval+= OUTSIDE_PAWN;
		else if ( (SPawns.flags&32) && (SPawns.flags&16) == 0 ) eval-= OUTSIDE_PAWN;
		else {
			// One king is outside of all pawns
			int KingAwol = 0;
			int nFileW = SQFILE[nWKingSq], nFileB = SQFILE [nBKingSq], wtm = (Board.SideToMove == WHITE) ? 1:0;
	
			if ( (nFileW+1) < SPawns.PawnFileL && (abs(nFileB - SPawns.PawnFileL)+wtm) < abs(nFileW - SPawns.PawnFileL) ) KingAwol ++;
			else if ( (nFileW-1) > SPawns.PawnFileR && (abs(nFileB - SPawns.PawnFileR)+wtm) < abs(nFileW - SPawns.PawnFileR) ) KingAwol ++;
			if ( (nFileB+1) < SPawns.PawnFileL && (abs(nFileW - SPawns.PawnFileL)-wtm+1) < abs(nFileB - SPawns.PawnFileL) ) KingAwol --;
			else if ( (nFileB-1) > SPawns.PawnFileR && (abs(nFileW - SPawns.PawnFileR)-wtm+1) < abs(nFileB - SPawns.PawnFileR) ) KingAwol --;

			if ( KingAwol == 1 ) eval-=KING_AWOL;
			else if ( KingAwol == -1) eval+=KING_AWOL;
			else if (Board.nWPawns > Board.nBPawns) eval+= PAWNUP_KPKP;
			else if (Board.nBPawns > Board.nWPawns) eval-= PAWNUP_KPKP;
			}

		// RookPawn Draw
		if (eval>0)
			{
			if ( (SPawns.flags&4) ) 
				{
				if (KingCorner[ nBKingSq ] == 1 ) return 0;
				if (ChessDist (nBKingSq, 22) <= (ChessDist (nWKingSq, 22)+1) ) eval = (eval>>1);
				}
			if ( (SPawns.flags&8) ) 
				{
				if (KingCorner[ nBKingSq ] == 2 ) return 0;
				if (ChessDist (nBKingSq, 29) <= (ChessDist (nWKingSq, 29)+1) ) eval = (eval>>1);
				}
			}
		else
			{
			if (  (SPawns.flags&1) ) 
				{
				if (KingCorner[ nWKingSq ] == 3) return 0;
				if (ChessDist (nWKingSq, 92) <= (ChessDist (nBKingSq, 92)+1) ) eval = (eval>>1);
				}
			if ( (SPawns.flags&2) ) 
				{
				if (KingCorner[ nWKingSq ] == 4) return 0;
				if (ChessDist (nWKingSq, 99) <= (ChessDist (nBKingSq, 99)+1) ) eval = (eval>>1);
				}
			}
		}

	return eval;
}

//
// Called when Pieces <= 1 for each side (but if there are no pawns mating eval is called instead)
// RookPawn Endgame Draws
// and opposite bishop endgames
//
const int KINGBYPAWN2[9]      = { 0, 0,  0,  0,  0, 45, 95, 120,  0 };
#define OUTSIDE_PAWN_KNIGHT 40
#define OUTSIDE_PAWN_GEN 38
#define OUTSIDE_PAWN_BISH 24
#define ROOK_V_KNIGHT 42
#define ROOK_V_BISHOP 30
#define CONNECTED_PASSERS_VS_ROOK 460

int OnePieceEndgame ( const SBoard &Board, int &eval, const int nWKingSq, const int nBKingSq, const PawnHashEntry &SPawns, const int WMat, const int BMat)
{
// Pawn Location and King Centralization
eval += SPawns.PassedCon;
eval += SPawns.MatEnd;
if ((Board.nBPawns + Board.nWPawns) < 7) eval += ((WKingValueEnd [ nWKingSq ] - WKingValueEnd [ nBKingSq ])>>1);
	else eval += (WKingValueEnd [ nWKingSq ] - WKingValueEnd [ nBKingSq ]);

// Check if the win/loss/draw bitbases can be used
if (ProbeBitbases (Board, eval, nWKingSq, nBKingSq) ) return eval;

// Get Bishop Sqs
int nwBishSq = Board.WPiece[10];
if (nwBishSq == CAPTURED) nwBishSq = Board.WPiece[11];
int nbBishSq = Board.BPiece[10];
if (nbBishSq == CAPTURED) nbBishSq = Board.BPiece[11];

// Pawns on A or H file draws
if (eval>0)
	{
	if ( (Board.nWP == 0 || SQCOLOR [nwBishSq] == 1 ) && (SPawns.flags&4) ) 
		{
		if (KingCorner[ nBKingSq ] == 1) return 0;
		if (ChessDist (nBKingSq, 22) <= ChessDist (nWKingSq, 22) ) eval = (eval>>1);
		}
	if ( (Board.nWP == 0 || SQCOLOR [nwBishSq] == 2 ) && (SPawns.flags&8) ) 
		{
		if (KingCorner[ nBKingSq ] == 2) return 0;
		if (ChessDist (nBKingSq, 29) <= ChessDist (nWKingSq, 29) ) eval = (eval>>1);
		}
	}
if (eval<0)
	{
	if ( (Board.nBP == 0 || SQCOLOR [nbBishSq] == 2 ) && (SPawns.flags&1) ) 
		{
		if (KingCorner[ nWKingSq ] == 3 ) return 0;
		if (ChessDist (nWKingSq, 92) <= ChessDist (nBKingSq, 92) ) eval = (eval>>1);
		}
	if ( (Board.nBP == 0 || SQCOLOR [nbBishSq] == 1 ) && (SPawns.flags&2) ) 
		{
		if (KingCorner[ nWKingSq ] == 4 ) return 0;
		if (ChessDist (nWKingSq, 99) <= ChessDist (nBKingSq, 99) ) eval = (eval>>1);
		}
	}

// A King near pawns is good
if ( (Board.Sq [ nWKingSq + 20 ]) == WPAWN) eval+=8;
if ( (Board.Sq [ nWKingSq + 11 ]) == WPAWN || (Board.Sq [ nWKingSq + 1 ]&7) == WPAWN) eval+=8;
if ( (Board.Sq [ nWKingSq + 9 ])  == WPAWN || (Board.Sq [ nWKingSq - 1 ]&7) == WPAWN) eval+=8;

if ( (Board.Sq [ nBKingSq - 20 ]) == BPAWN) eval-=8;
if ( (Board.Sq [ nBKingSq - 11 ]) == BPAWN || (Board.Sq [ nBKingSq - 1 ]&7) == WPAWN) eval-=8;
if ( (Board.Sq [ nBKingSq - 9 ])  == BPAWN || (Board.Sq [ nBKingSq + 1 ]&7) == WPAWN) eval-=8;

// Rook Versus Pawns. Passed Pawn Support
int nSq, nSupport, nDist;

if (Board.nWP == 1 && Board.nBPawns>0 )
	{
	int nbRookSq = Board.BPiece[12];
	if (nbRookSq == CAPTURED) nbRookSq = Board.BPiece[13];
	 for (int i = 0; i < 4; i++) // BLACK PAWNS
		{
		nSq=SPawns.BPassSqs[i];
		if (nSq==0) break;
		if (WBLOCKER[ Board.Sq [nSq + 10] ] ) eval+=BLOCKEDPASSPAWN [ 9-SQRANK[nSq] ];

		if (SQRANK[nSq] < 4 && (WMat == PieceValues[WROOK] || WMat == PieceValues[WKNIGHT])) // Rook versus connected passers
			{// (Another sup-par kludge-work of code.)
			int qSq = BQUEENSQ[nSq];			
			if (Board.Sq [qSq-9] == BPAWN || (Board.Sq[qSq-9] == EMPTY && Board.Sq[qSq-19] == BPAWN))
				{if (SQFILE[nWKingSq]>SQFILE[qSq])  qSq+=1;
				 if (SQRANK[nSq] == 2 && Board.Sq [nSq+1] == BPAWN) nDist = 0;
				 else if (Board.Sq[qSq-10] == BPAWN) nDist = 1; else nDist = 2;
				 if (ChessDist (qSq  , nWKingSq) > (nDist +(Board.SideToMove&1))) eval-= CONNECTED_PASSERS_VS_ROOK; // Pawn can Promote
				}
			}

		if (SQRANK[nSq] <=4 && SQRANK[nBKingSq] <= (SQRANK[nSq]+1) && abs (SQFILE[nSq] - SQFILE[nBKingSq]) <=1)
			{
  		    if (WMat == PieceValues [ WROOK ]) nSupport = (KINGBYPAWN2 [ 9-SQRANK[nSq] ]<<1); else nSupport = KINGBYPAWN2 [ 9-SQRANK[nSq] ];
			nDist = ChessDistB (nWKingSq, nSq);
			if (nDist >= 3) eval -= nSupport; else if (nDist >=2) eval -= (nSupport>>1);
			}
			else eval-= KINGPAWNDIST[ ChessDistB (nWKingSq, nSq) ];
			eval+= ROOK_PP1B[ acDirec[ nbRookSq + (nSq<<7) ] + 12 ];
		}
	}

if (Board.nBP == 1  && Board.nWPawns>0)
	{
	int nwRookSq = Board.WPiece[12];
	if (nwRookSq == CAPTURED) nwRookSq = Board.WPiece[13];

	 for (int i = 0; i < 4; i++) // WHITE PAWNS
		{
		nSq=SPawns.WPassSqs[i];
		if (nSq==0) break;
		if (BBLOCKER[Board.Sq [ nSq - 10 ] ]) eval-=BLOCKEDPASSPAWN [ SQRANK[nSq] ];

		if (SQRANK[nSq] > 5 && (BMat == PieceValues[WROOK] || BMat == PieceValues[WKNIGHT])) // Rook versus connected passers
			{
			int qSq = WQUEENSQ[nSq];
			if (Board.Sq [qSq+11] == WPAWN || (Board.Sq[qSq+11] == EMPTY && Board.Sq[qSq+21] == WPAWN))
				{
				if (SQFILE[nBKingSq]>SQFILE[qSq]) qSq+=1;
				if (SQRANK[nSq] == 7 && Board.Sq [nSq+1] == WPAWN) nDist = 0;
				else if (Board.Sq[qSq+10] == WPAWN) nDist = 1; else nDist = 2;
				if (ChessDist (qSq  , nBKingSq) > (nDist +(Board.SideToMove>>1))) eval+= CONNECTED_PASSERS_VS_ROOK; // Pawn can Promote
				}			
			}

		if (SQRANK[nSq] >=5 && SQRANK[nWKingSq] >= (SQRANK[nSq]-1) && abs (SQFILE[nSq] - SQFILE[nWKingSq]) <= 1)
			{
			if (BMat == PieceValues [ WROOK ])   nSupport = (KINGBYPAWN2 [ SQRANK[nSq] ]<<1); else nSupport = KINGBYPAWN2 [ SQRANK[nSq] ];
			nDist = ChessDistW (nBKingSq, nSq);
			if (nDist >= 3) eval += nSupport; else if (nDist >=2) eval += (nSupport>>1);
			}
		else eval+= KINGPAWNDIST[ ChessDistW (nBKingSq, nSq) ];
		eval+= ROOK_PP1W[ acDirec[ nwRookSq + (nSq<<7) ] + 12 ];
		}
	}

// One king is outside of all pawns
int KingAwol = 0;
int nFileW = SQFILE[nWKingSq], nFileB = SQFILE [nBKingSq], wtm = (Board.SideToMove == WHITE) ? 1:0;

if ( (nFileW+1) < SPawns.PawnFileL && (abs(nFileB - SPawns.PawnFileL)+wtm) < abs(nFileW - SPawns.PawnFileL) ) KingAwol ++;
else if ( (nFileW-1) > SPawns.PawnFileR && (abs(nFileB - SPawns.PawnFileR)+wtm) < abs(nFileW - SPawns.PawnFileR) ) KingAwol ++;
if ( (nFileB+1) < SPawns.PawnFileL && (abs(nFileW - SPawns.PawnFileL)-wtm+1) < abs(nFileB - SPawns.PawnFileL) ) KingAwol --;
else if ( (nFileB-1) > SPawns.PawnFileR && (abs(nFileW - SPawns.PawnFileR)-wtm+1) < abs(nFileB - SPawns.PawnFileR) ) KingAwol --;

if ( KingAwol == 1 ) eval-=KING_AWOL_1P;
else if ( KingAwol == -1) eval+=KING_AWOL_1P;

// Outside passed pawns + some knight specific stuff
if (BMat == PieceValues [ WKNIGHT ]) // Black has only a knight
	{
	if (WMat == PieceValues [ WROOK ]) eval+=ROOK_V_KNIGHT;// Rook over knight
	if ( (SPawns.flags&16) && (SPawns.flags&32) == 0 && Board.nWPawns > 1) eval+= OUTSIDE_PAWN_KNIGHT; // outside passer versus knight
	}
else if (BMat == PieceValues [ WBISHOP ])
	{
	if (WMat == PieceValues [ WROOK ]) eval+=ROOK_V_BISHOP;
	if ( (SPawns.flags&64) && (SPawns.flags&32) == 0 && Board.nWPawns > 1) eval+= OUTSIDE_PAWN_BISH;
	}
else if ( (SPawns.flags&64) && (SPawns.flags&32) == 0 && Board.nWPawns > 1) eval+= OUTSIDE_PAWN_GEN;

if (WMat == PieceValues [ WKNIGHT ] )
	{
	if (BMat == PieceValues [ WROOK ]) eval-=ROOK_V_KNIGHT;
	if ( (SPawns.flags&32) && (SPawns.flags&16) == 0 && Board.nBPawns > 1)  eval-= OUTSIDE_PAWN_KNIGHT;
	}
else if (WMat == PieceValues [ WBISHOP ])
	{
	if (BMat == PieceValues [ WROOK ]) eval-=ROOK_V_BISHOP;
	if ( (SPawns.flags&128) && (SPawns.flags&16) == 0 && Board.nBPawns > 1 ) eval-= OUTSIDE_PAWN_BISH;
	}
else if ( (SPawns.flags&128) && (SPawns.flags&16) == 0 && Board.nBPawns > 1 ) eval-= OUTSIDE_PAWN_GEN;

// Opposite Colored Bishops
if (nbBishSq != CAPTURED && nwBishSq != CAPTURED && SQCOLOR [nwBishSq] != SQCOLOR [nbBishSq] )
	{
	if (Board.nWPawns == 2 && Board.nBPawns < 2)
		{
		if (Board.nBPawns==0 && ((SQCOLOR [nwBishSq] == 1 && SPawns.PawnFileL == 1 && KingCorner[ nBKingSq ] == 1) || (SPawns.PawnFileR == 8 && KingCorner[ nBKingSq ] == 2 && SQCOLOR [nwBishSq] == 2 )) ) 
			{eval = (eval >> 4);}
		else if ( (SPawns.PawnFileR-SPawns.PawnFileL) < 3 && SQFILE [ nBKingSq]<=SPawns.PawnFileR && SQFILE [nBKingSq]>=SPawns.PawnFileL && SQRANK[nBKingSq]>5 ) 
			eval = (eval >> 4);
		}
	else if (Board.nBPawns == 2 && Board.nWPawns < 2) 
		{
		if (Board.nWPawns==0 && ((SPawns.PawnFileL == 1 && KingCorner[ nWKingSq ] == 3 && SQCOLOR [nbBishSq] == 2) || (SPawns.PawnFileR == 8 && KingCorner[ nWKingSq ] == 4 && SQCOLOR [nbBishSq] == 1)) ) {eval = (eval >> 4);}
		else if ((SPawns.PawnFileR-SPawns.PawnFileL) < 3 && SQFILE [ nWKingSq]<=SPawns.PawnFileR && SQFILE [nWKingSq]>=SPawns.PawnFileL && SQRANK[nWKingSq]<4 ) 
			eval = (eval >> 4);
		}

	if ( (Board.nWPawns + Board.nBPawns) == 1) eval = (eval>>4); // 1/16th
	else if ( abs (Board.nWPawns- Board.nBPawns) <= 1)	eval = (eval>>2) + (eval>>3) + (eval>>4); // 7/16 
	else if ((Board.nWPawns + Board.nBPawns) > 2)	eval = (eval>>1) + (eval>>2); // 3/8th
	}

if ( abs(WMat - BMat) < 50 ) // Equal Value Pieces 
	{
	if (WMat == PieceValues [ WQUEEN ]) // 2 Queens? Perpetual check danger
		{
		if ((Board.nWPawns + Board.nBPawns) < 4) eval = (eval>>1) + (eval>>3); 
		else if ((Board.nWPawns + Board.nBPawns) < 8) eval = (eval>>1) + (eval>>2);
			else eval = (eval>>1) + (eval>>2) + (eval>>3);
		}
	// 1 Pawn with enemy king in front. Also Rook + 1 Pawn versus Rook endgames 
		if (Board.nBPawns == 0 && Board.nWPawns == 1)
			{
			nSq = SPawns.WPassSqs[0];
			if (SQFILE [ nSq ] == SQFILE [ nBKingSq] && nBKingSq < nSq) {eval = 1;}
				else if (WMat==PieceValues [ WROOK ] && (SQFILE[ nSq ] == 1 || SQFILE[ nSq ] == 8) && SQRANK[nBKingSq] >= (SQRANK[nSq]-1) && abs(SQFILE[nBKingSq] - SQFILE[nSq]) < 4 ) eval = (eval>>1);
			}
		if (Board.nWPawns == 0 && Board.nBPawns == 1)
			{
			nSq = SPawns.BPassSqs[0];
			if (SQFILE [ nSq ] == SQFILE [ nWKingSq] && nWKingSq > nSq)  {eval = -1;}
			else if (BMat==PieceValues [ WROOK ] && (SQFILE[ nSq ] == 1 || SQFILE[ nSq ] == 8) && SQRANK[nWKingSq] <= (SQRANK[nSq]+1) && abs(SQFILE[nWKingSq] - SQFILE[nSq]) < 4 ) eval = (eval>>1);
			}
	}

if (Board.BMat == 0) eval += NO_CHANCES;
if (Board.WMat == 0) eval -= NO_CHANCES;

// Pawn Races
if (Board.nWP == 0 || Board.nBP == 0) 
	{
	PawnRacesEval (Board, eval, nWKingSq, nBKingSq, SPawns);
	}

// One side can't win
if (eval > 0 && Board.nWPawns == 0 )
	{
	if (WMat < PieceValues [WROOK]) eval = -Board.nBPawns;
	if (WMat == PieceValues [WROOK] && Board.nBMinors == 1) // Only up an exchange
		{eval = (eval>>2); }
	}
if (eval < 0 && Board.nBPawns == 0)
	{
	if (BMat < PieceValues [WROOK]) eval = +Board.nWPawns;
	if (BMat == PieceValues [WROOK] && Board.nWMinors == 1)
		{eval = (eval>>2);}
	}

return eval;
}
