
/**
 *  class Evaluation
 *
 *  This is class conataining static evaluation methods
 *  We have this in an own class to easily switch evaluation if needed
 *  
 *  @author Jonatan Pettersson (mediocrechess@gmail.com)
 */
public class Evaluation implements Definitions
{
	// Evaluation constants
	public static final int PASSED_PAWN = 20;
	public static final int DOUBLED_PAWN = -10; 
	public static final int ISOLATED_PAWN = -5;
	public static final int ROOK_ON_SEVENTH = 10; 
	public static final int ROOK_ON_OPEN = 15;
	public static final int ROOK_ON_SEMI = 10;
	public static final int PASSED_MULTI = 2; // Multiplies the number of ranks it has progressed for a bigger value
	public static final int PASSED_MULTI_ENDING = 3;
	public static final int CONNECTED_PASSERS = 30;
	
	public static final int[] KING_ATTACK_WEIGHT = {0,0,20,30,35,37,39,40}; 
	
	public static int gamePhase;

	public static int evaluate(Board board)
	{
		
		gamePhase = PHASE_OPENING; // Initialize the game phase to opening, will be updated in the material search

		int finalEval = 0;

		finalEval += material(board); // Start with the evaluations

		return finalEval*board.toMove; // Flip the eval if black to move
		
	}
	
	public static int material(Board board)
	{
		int evaluation = 0;
		
		int materialBalance = 0;
		int piecePositioning = 0;
		int rookEval = 0;
		int pawnEval = 0;
		int trappedPiece = 0;
		int pawnShieldWhite = 0;
		int pawnShieldBlack = 0;
		
		
		
		
		// LOOP 1
		// Check material balance, set the gamePhase, check for possible drawn by material
		// and setup the pawns
		int gamePhaseCheck = 0;
		boolean canBeDrawnByMaterial = true;
		boolean queensOnBoard = false;
		int [][] pawnPositions = new int[2][10];
		for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
		{
			int index = board.pieces[piecesIndex];
			if(index != -1)
			{			
				materialBalance += PIECE_VALUE_ARRAY[board.pieceTypeOnIndex(index) + 7];
				switch(board.pieceTypeOnIndex(index))
				{
				case W_PAWN:
					canBeDrawnByMaterial = false;
					if(pawnPositions[0][(index%16)+1] == 0 || pawnPositions[0][(index%16)+1] > (index-(index%16))/16)
					{
						pawnPositions[0][(index%16)+1] = (index-(index%16))/16; 
					}
					break;
				case B_PAWN:
					canBeDrawnByMaterial = false;
					if(pawnPositions[1][(index%16)+1] == 0 || pawnPositions[1][(index%16)+1] < (index-(index%16))/16)
					{
						pawnPositions[1][(index%16)+1] = (index-(index%16))/16; 
					}
					break;
				case W_KNIGHT:
					gamePhaseCheck += 1;
					break;
				case B_KNIGHT:
					gamePhaseCheck += 1;
					break;
				case W_BISHOP:
					gamePhaseCheck += 1;
					break;
				case B_BISHOP:
					gamePhaseCheck += 1;
					break;
				case W_ROOK:
					gamePhaseCheck += 2;
					canBeDrawnByMaterial = false;
					break;
				case B_ROOK:
					gamePhaseCheck += 2;
					canBeDrawnByMaterial = false;
					break;
				case W_QUEEN:
					gamePhaseCheck += 4;
					queensOnBoard = true;
					canBeDrawnByMaterial = false;						
					break;
				case B_QUEEN:
					gamePhaseCheck += 4;
					queensOnBoard = true;
					canBeDrawnByMaterial = false;
					break;
				}
			}
		}
		
		// There are no pawns, queens or rooks on the board
		// check if it really is drawn, if it is return 0
		if(canBeDrawnByMaterial)
		{
			if(isDrawnByMaterial(board)) return 0;
		}
		
		if(gamePhaseCheck == 0) gamePhase = PHASE_PAWN_ENDING;
		else if(gamePhaseCheck <= 8) gamePhase = PHASE_ENDING;
		else if(gamePhaseCheck >20) gamePhase = PHASE_OPENING;
		else gamePhase = PHASE_MIDDLE;
		
		int whiteKingAttackMulti = 0;
		int whiteKingAttackNumber = 0;
		int blackKingAttackMulti = 0;
		int blackKingAttackNumber = 0;
		
		// LOOP 2
		// Piece positioning, king attack, pawn evaluation, and trapped bishop/rook
		
		// LOOP 2a
		// Middle game or opening with queens
		// Use normal piece tables, check for king attacks
		// and evaluate pawn shield
		if(queensOnBoard && gamePhase <= PHASE_MIDDLE)
		{
			for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
			{
				//boolean lastWhitePawnWasPasser = false;
				//boolean lastBlackPawnWasPasser = false;
					int i = board.pieces[piecesIndex];
					if(i != -1)
					{
						switch(board.pieceTypeOnIndex(i))
						{
							case W_KING: piecePositioning += W_KING_POS[i];	break;
							case B_KING: piecePositioning -= B_KING_POS[i]; break;
							case W_KNIGHT: piecePositioning += W_KNIGHT_POS[i];	break;
							case B_KNIGHT: piecePositioning -= B_KNIGHT_POS[i];	break;
							case W_QUEEN:
								if(attacksBlackKing(W_QUEEN, i, board))
								{
									whiteKingAttackMulti += 4;
									whiteKingAttackNumber += 1;							
								}
								piecePositioning += W_QUEEN_POS[i];
								break;
							case B_QUEEN:
							{
								if(attacksWhiteKing(B_QUEEN, i, board))
								{
									blackKingAttackMulti += 4;
									blackKingAttackNumber += 1;							
								}
								piecePositioning -= B_QUEEN_POS[i];
								break;								
							}
							case W_ROOK:
							{
								if(attacksBlackKing(W_ROOK, i, board))
								{
									whiteKingAttackMulti += 2;
									whiteKingAttackNumber += 1;							
								}
								piecePositioning += W_ROOK_POS[i];	
								
								// Rook on row with only enemy pawns
								if(pawnPositions[0][(i%16)+1] == 0 && pawnPositions[1][(i%16)+1] != 0)
								{
									rookEval += ROOK_ON_SEMI;
								}
								// Rook on open row
								else if(pawnPositions[0][(i%16)+1] == 0)
								{
									rookEval += ROOK_ON_OPEN;
								}
		
								// Rook on seventh rank
								if((i-(i%16))/16 == 6)
								{
									rookEval += ROOK_ON_SEVENTH;
								}
								
								// Blocked rook, if rook is on say h1 or g1 and the white king is on f1 or g1 the rook is blocked
								if((i == 0 || i == 1) && (board.pieces[31] == 1 || board.pieces[31] == 2)) trappedPiece -= 50;
								else if((i == 6 || i == 7) && (board.pieces[31] == 5 || board.pieces[31] == 6)) trappedPiece -= 50;
								break;
								
							}
							case B_ROOK:
							{
								piecePositioning -= B_ROOK_POS[i];							

								// Rook on row with only enemy pawns
								if(pawnPositions[1][(i%16)+1] == 0 && pawnPositions[0][(i%16)+1] != 0)
								{
									rookEval -= ROOK_ON_SEMI;
								}
								// Rook on open row
								else if(pawnPositions[1][(i%16)+1] == 0)
								{
									rookEval -= ROOK_ON_OPEN;
								}	
								// Rook on second rank
								if((i-(i%16))/16 == 1)
								{
									rookEval -= ROOK_ON_SEVENTH;
								}
								
								if((i == 112 || i == 113) && (board.pieces[15] == 113 || board.pieces[15] == 114)) trappedPiece += 50;
								else if((i == 118 || i == 119) && (board.pieces[15] == 117 || board.pieces[15] == 118)) trappedPiece += 50;
								
								break;
								
							}
							case W_BISHOP:
							{
								piecePositioning += W_BISHOP_POS[i];
								
								// Checks for trapped bishop
								// e.g. bishop on a7 and black pawn on b6 traps the bishop
								if(i == 96 && board.pieceTypeOnIndex(81) == B_PAWN) trappedPiece -= 100; // a7, b6
								else if(i == 113 && board.pieceTypeOnIndex(98) == B_PAWN) trappedPiece -= 100; // b8, c7
								else if(i == 103 && board.pieceTypeOnIndex(86) == B_PAWN) trappedPiece -= 100; // h7, g6
								else if(i == 118 && board.pieceTypeOnIndex(101) == B_PAWN) trappedPiece -= 100; // g8, f7
								else if(i == 80 && board.pieceTypeOnIndex(65) == B_PAWN) trappedPiece -= 100; // a6, b5
								else if(i == 87 && board.pieceTypeOnIndex(70) == B_PAWN) trappedPiece -= 100; // h6, g5
								
								// Blocked in piece
								// If bishop on c1 or f1 and d2/e2 has white pawn and d3/e3 has white piece the bishop is blocked
								else if(i == 2 && board.pieceTypeOnIndex(19) == W_PAWN && board.pieceTypeOnIndex(35) > 0) trappedPiece -= 50;
								else if(i == 5 && board.pieceTypeOnIndex(20) == W_PAWN && board.pieceTypeOnIndex(36) > 0) trappedPiece -= 50;
								
								break;
							}
							case B_BISHOP:
							{
								piecePositioning -= B_BISHOP_POS[i];
								
								if(i == 16 && board.pieceTypeOnIndex(33) == W_PAWN) trappedPiece += 100;
								else if(i == 32 && board.pieceTypeOnIndex(49) == W_PAWN) trappedPiece += 100;
								else if(i == 1 && board.pieceTypeOnIndex(18) == W_PAWN) trappedPiece += 100;
								else if(i == 6 && board.pieceTypeOnIndex(21) == W_PAWN) trappedPiece += 100;
								else if(i == 23 && board.pieceTypeOnIndex(38) == W_PAWN) trappedPiece += 100;
								else if(i == 39 && board.pieceTypeOnIndex(54) == W_PAWN) trappedPiece += 100;
								
								else if(i == 114 && board.pieceTypeOnIndex(99) == B_PAWN && board.pieceTypeOnIndex(83) < 0) trappedPiece += 50;
								else if(i == 117 && board.pieceTypeOnIndex(100) == B_PAWN && board.pieceTypeOnIndex(84) < 0) trappedPiece += 50;
								break;
							}
							case W_PAWN:
							{
								piecePositioning += W_PAWN_POS[i];
		
								// Check for doubled pawn
								// If the rank recorded is not the same as this pawn which is
								// on the same row, there is another pawn on the same row
								// so the pawns are doubled
								if(pawnPositions[0][(i%16)+1] != (i-(i%16))/16)
								{
									pawnEval += DOUBLED_PAWN;						
								}
		
								// Check for isolated pawn
								// If the row to the right and left of this row does not contain
								// any friendly pawns, the pawn is isolated
								if(pawnPositions[0][(i%16)+1+1] == 0 &&
										pawnPositions[0][(i%16)+1-1] == 0)
								{
									pawnEval += ISOLATED_PAWN;						
								}
		
								// Check for passed pawn
								// If the row does not contain an enemy pawn or the enemypawn is behind it
								// and the rows to the right and left does not contain enemy pawns or they are behind
								// the pawn is passed
								if((pawnPositions[1][(i%16)+1]   == 0 || pawnPositions[1][(i%16)+1] < (i-(i%16))/16) &&
										(pawnPositions[1][(i%16)+1+1] == 0 || pawnPositions[1][(i%16)+1+1] <= (i-(i%16))/16) &&
										(pawnPositions[1][(i%16)+1-1] == 0 || pawnPositions[1][(i%16)+1-1] <= (i-(i%16))/16))
								{

									/*if(lastWhitePawnWasPasser)
									{
										pawnEval += CONNECTED_PASSERS;
									}
									lastWhitePawnWasPasser = true;
									*/
									// Add the passed pawn bonus, + an extra bonus for every rank it has moved
									pawnEval += PASSED_PAWN + Math.pow((((i-(i%16))/16)), PASSED_MULTI);
								}
								/*else
								{
									lastWhitePawnWasPasser = false;
								}*/
								break;
							}
							case B_PAWN:
							{
								piecePositioning -= B_PAWN_POS[i];
		
								// Check for doubled pawn
								// If the rank recorded is not the same as this pawn which is
								// on the same row, there is another pawn on the same row
								// so the pawns are doubled
								if(pawnPositions[1][(i%16)+1] != (i-(i%16))/16)
								{
									pawnEval -= DOUBLED_PAWN;						
								}
		
								// Check for isolated pawn
								// If the row to the right and left of this row does not contain
								// any friendly pawns, the pawn is isolated
								if(pawnPositions[1][(i%16)+1+1] == 0 &&
										pawnPositions[1][(i%16)+1-1] == 0)
								{
									pawnEval -= ISOLATED_PAWN;						
								}

								// Check for passed pawn
								// If the row does not contain an enemy pawn or the enemypawn is behind it
								// and the rows to the right and left does not contain enemy pawns or they are behind
								// the pawn is passed
								if((pawnPositions[0][(i%16)+1]   == 0 || pawnPositions[0][(i%16)+1] > (i-(i%16))/16) &&
										(pawnPositions[0][(i%16)+1+1] == 0 || pawnPositions[0][(i%16)+1+1] >= (i-(i%16))/16) &&
										(pawnPositions[0][(i%16)+1-1] == 0 || pawnPositions[0][(i%16)+1-1] >= (i-(i%16))/16))
								{
									/*if(lastBlackPawnWasPasser)
									{
										pawnEval += CONNECTED_PASSERS;
									}
									lastBlackPawnWasPasser = true;*/
									// Add the passed pawn bonus, + an extra bonus for every rank it has moved
									pawnEval -= PASSED_PAWN + Math.pow((7-((i-(i%16))/16)), PASSED_MULTI);
								}
								/*else
								{
									lastBlackPawnWasPasser = false;
								}*/
								break;
							}
						}

					}
			}


			int pawnRank;

			// White pawn shield

			// Find the rank the pawn in front of the king is on
			pawnRank = pawnPositions[0][board.pieces[31]%16+1];
			// If there is no pawn in front of the king, penalize with 36
			if(pawnRank == 0)
			{
				pawnShieldWhite -= 36;
			}
			// If there is a pawn in front of the king penalize with the number
			// of ranks it has advanced
			// e.g. advanced 2 ranks (on rank 4 (=3 on the board))
			// 36 - (7-3)*(7-3) = 20 penalty 
			else
			{
				pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
			}
			// Look for the pawn to the right in front of the king, make sure
			// we are not off the board and do the same thing as above
			if((board.pieces[31]%16+1+1) != 9)
			{
				pawnRank = pawnPositions[0][board.pieces[31]%16+1+1];
				if(pawnRank == 0)
				{
					pawnShieldWhite -= 36;
				}
				else
				{
					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
				}
			}
			if((board.pieces[31]%16) != 0)
			{
				pawnRank = pawnPositions[0][board.pieces[31]%16];
				if(pawnRank == 0)
				{
					pawnShieldWhite -= 36;
				}
				else
				{
					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
				}
			}

			// Black pawn shield

			// Same as above but the formula is without '7-'
			// e.g. pawn in front of king advanced 2 ranks (on rank 4 in the board array)
			// 36 - 4*4 = 20 penalty
			pawnRank = pawnPositions[1][board.pieces[15]%16+1];
			if(pawnRank == 0)
			{
				pawnShieldBlack += 36;
			}
			else
			{
				pawnShieldWhite += 36 - ((pawnRank)*(pawnRank));
			}
			if((board.pieces[15]%16+1+1) != 9)
			{
				pawnRank = pawnPositions[1][board.pieces[15]%16+1+1];
				if(pawnRank == 0)
				{
					pawnShieldBlack += 36;
				}
				else
				{
					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
				}
			}
			if((board.pieces[15]%16) != 0)
			{
				pawnRank = pawnPositions[1][board.pieces[15]%16];
				if(pawnRank == 0)
				{
					pawnShieldBlack += 36;
				}
				else
				{
					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
				}
			}

			// Account for back rank trouble
			// if none of the pawns in front of the king advanced
			// we add a small penalty for back rank threats
			if(pawnShieldWhite == 0) pawnShieldWhite = -11;
			if(pawnShieldBlack == 0) pawnShieldBlack = 11;
						
		}
		// LOOP 2b
		// Middle game or opening without queens
		// Use normal piece tables and do not check for king attacks
		// and evaluate pawn shield
		else if(gamePhase <= PHASE_MIDDLE)
		{
			for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
			{
				//boolean lastWhitePawnWasPasser = false;
				//boolean lastBlackPawnWasPasser = false;
				int i = board.pieces[piecesIndex];
				if(i != -1)
				{
					switch(board.pieceTypeOnIndex(i))
					{
					case W_KING: piecePositioning += W_KING_POS[i];	break;
					case B_KING: piecePositioning -= B_KING_POS[i]; break;
					case W_KNIGHT: piecePositioning += W_KNIGHT_POS[i];	break;
					case B_KNIGHT: piecePositioning -= B_KNIGHT_POS[i];	break;
					case W_QUEEN: piecePositioning += W_QUEEN_POS[i]; break;
					case B_QUEEN: piecePositioning -= B_QUEEN_POS[i]; break;								
					case W_ROOK:
					{
						piecePositioning += W_ROOK_POS[i];	

						// Rook on row with only enemy pawns
						if(pawnPositions[0][(i%16)+1] == 0 && pawnPositions[1][(i%16)+1] != 0)
						{
							rookEval += ROOK_ON_SEMI;
						}
						// Rook on open row
						else if(pawnPositions[0][(i%16)+1] == 0)
						{
							rookEval += ROOK_ON_OPEN;
						}

						// Rook on seventh rank
						if((i-(i%16))/16 == 6)
						{
							rookEval += ROOK_ON_SEVENTH;
						}

						// Blocked rook, if rook is on say h1 or g1 and the white king is on f1 or g1 the rook is blocked
						if((i == 0 || i == 1) && (board.pieces[31] == 1 || board.pieces[31] == 2)) trappedPiece -= 50;
						else if((i == 6 || i == 7) && (board.pieces[31] == 5 || board.pieces[31] == 6)) trappedPiece -= 50;
						break;

					}
					case B_ROOK:
					{
						piecePositioning -= B_ROOK_POS[i];							

						// Rook on row with only enemy pawns
						if(pawnPositions[1][(i%16)+1] == 0 && pawnPositions[0][(i%16)+1] != 0)
						{
							rookEval -= ROOK_ON_SEMI;
						}
						// Rook on open row
						else if(pawnPositions[1][(i%16)+1] == 0)
						{
							rookEval -= ROOK_ON_OPEN;
						}	
						// Rook on second rank
						if((i-(i%16))/16 == 1)
						{
							rookEval -= ROOK_ON_SEVENTH;
						}

						if((i == 112 || i == 113) && (board.pieces[15] == 113 || board.pieces[15] == 114)) trappedPiece += 50;
						else if((i == 118 || i == 119) && (board.pieces[15] == 117 || board.pieces[15] == 118)) trappedPiece += 50;

						break;

					}
					case W_BISHOP:
					{
						piecePositioning += W_BISHOP_POS[i];

						// Checks for trapped bishop
						// e.g. bishop on a7 and black pawn on b6 traps the bishop
						if(i == 96 && board.pieceTypeOnIndex(81) == B_PAWN) trappedPiece -= 100; // a7, b6
						else if(i == 113 && board.pieceTypeOnIndex(98) == B_PAWN) trappedPiece -= 100; // b8, c7
						else if(i == 103 && board.pieceTypeOnIndex(86) == B_PAWN) trappedPiece -= 100; // h7, g6
						else if(i == 118 && board.pieceTypeOnIndex(101) == B_PAWN) trappedPiece -= 100; // g8, f7
						else if(i == 80 && board.pieceTypeOnIndex(65) == B_PAWN) trappedPiece -= 100; // a6, b5
						else if(i == 87 && board.pieceTypeOnIndex(70) == B_PAWN) trappedPiece -= 100; // h6, g5

						// Blocked in piece
						// If bishop on c1 or f1 and d2/e2 has white pawn and d3/e3 has white piece the bishop is blocked
						else if(i == 2 && board.pieceTypeOnIndex(19) == W_PAWN && board.pieceTypeOnIndex(35) > 0) trappedPiece -= 50;
						else if(i == 5 && board.pieceTypeOnIndex(20) == W_PAWN && board.pieceTypeOnIndex(36) > 0) trappedPiece -= 50;

						break;
					}
					case B_BISHOP:
					{
						piecePositioning -= B_BISHOP_POS[i];

						if(i == 16 && board.pieceTypeOnIndex(33) == W_PAWN) trappedPiece += 100;
						else if(i == 32 && board.pieceTypeOnIndex(49) == W_PAWN) trappedPiece += 100;
						else if(i == 1 && board.pieceTypeOnIndex(18) == W_PAWN) trappedPiece += 100;
						else if(i == 6 && board.pieceTypeOnIndex(21) == W_PAWN) trappedPiece += 100;
						else if(i == 23 && board.pieceTypeOnIndex(38) == W_PAWN) trappedPiece += 100;
						else if(i == 39 && board.pieceTypeOnIndex(54) == W_PAWN) trappedPiece += 100;

						else if(i == 114 && board.pieceTypeOnIndex(99) == B_PAWN && board.pieceTypeOnIndex(83) < 0) trappedPiece += 50;
						else if(i == 117 && board.pieceTypeOnIndex(100) == B_PAWN && board.pieceTypeOnIndex(84) < 0) trappedPiece += 50;
						break;
					}
					case W_PAWN:
					{
						piecePositioning += W_PAWN_POS[i];
				
						// Check for doubled pawn
						// If the rank recorded is not the same as this pawn which is
						// on the same row, there is another pawn on the same row
						// so the pawns are doubled
						if(pawnPositions[0][(i%16)+1] != (i-(i%16))/16)
						{
							pawnEval += DOUBLED_PAWN;						
						}

						// Check for isolated pawn
						// If the row to the right and left of this row does not contain
						// any friendly pawns, the pawn is isolated
						if(pawnPositions[0][(i%16)+1+1] == 0 &&
								pawnPositions[0][(i%16)+1-1] == 0)
						{
							pawnEval += ISOLATED_PAWN;						
						}

						// Check for passed pawn
						// If the row does not contain an enemy pawn or the enemypawn is behind it
						// and the rows to the right and left does not contain enemy pawns or they are behind
						// the pawn is passed
						if((pawnPositions[1][(i%16)+1]   == 0 || pawnPositions[1][(i%16)+1] < (i-(i%16))/16) &&
								(pawnPositions[1][(i%16)+1+1] == 0 || pawnPositions[1][(i%16)+1+1] <= (i-(i%16))/16) &&
								(pawnPositions[1][(i%16)+1-1] == 0 || pawnPositions[1][(i%16)+1-1] <= (i-(i%16))/16))
						{

							/*if(lastWhitePawnWasPasser)
							{
								pawnEval += CONNECTED_PASSERS;
							}
							lastWhitePawnWasPasser = true;
							*/
							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
							pawnEval += PASSED_PAWN + Math.pow((((i-(i%16))/16)), PASSED_MULTI);
						}
						break;
					}
					case B_PAWN:
					{
						piecePositioning -= B_PAWN_POS[i];

						// Check for doubled pawn
						// If the rank recorded is not the same as this pawn which is
						// on the same row, there is another pawn on the same row
						// so the pawns are doubled
						if(pawnPositions[1][(i%16)+1] != (i-(i%16))/16)
						{
							pawnEval -= DOUBLED_PAWN;						
						}

						// Check for isolated pawn
						// If the row to the right and left of this row does not contain
						// any friendly pawns, the pawn is isolated
						if(pawnPositions[1][(i%16)+1+1] == 0 &&
								pawnPositions[1][(i%16)+1-1] == 0)
						{
							pawnEval -= ISOLATED_PAWN;						
						}

						// Check for passed pawn
						// If the row does not contain an enemy pawn or the enemypawn is behind it
						// and the rows to the right and left does not contain enemy pawns or they are behind
						// the pawn is passed
						if((pawnPositions[0][(i%16)+1]   == 0 || pawnPositions[0][(i%16)+1] > (i-(i%16))/16) &&
								(pawnPositions[0][(i%16)+1+1] == 0 || pawnPositions[0][(i%16)+1+1] >= (i-(i%16))/16) &&
								(pawnPositions[0][(i%16)+1-1] == 0 || pawnPositions[0][(i%16)+1-1] >= (i-(i%16))/16))
						{
							/*if(lastBlackPawnWasPasser)
							{
								pawnEval += CONNECTED_PASSERS;
							}
							lastBlackPawnWasPasser = true;
							*/
							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
							pawnEval -= PASSED_PAWN + Math.pow((7-((i-(i%16))/16)), PASSED_MULTI);
						}
						break;
					}
					}

				}
			}


			int pawnRank;

			// White pawn shield

			// Find the rank the pawn in front of the king is on
			pawnRank = pawnPositions[0][board.pieces[31]%16+1];
			// If there is no pawn in front of the king, penalize with 36
			if(pawnRank == 0)
			{
				pawnShieldWhite -= 36;
			}
			// If there is a pawn in front of the king penalize with the number
			// of ranks it has advanced
			// e.g. advanced 2 ranks (on rank 4 (=3 on the board))
			// 36 - (7-3)*(7-3) = 20 penalty 
			else
			{
				pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
			}
			// Look for the pawn to the right in front of the king, make sure
			// we are not off the board and do the same thing as above
			if((board.pieces[31]%16+1+1) != 9)
			{
				pawnRank = pawnPositions[0][board.pieces[31]%16+1+1];
				if(pawnRank == 0)
				{
					pawnShieldWhite -= 36;
				}
				else
				{
					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
				}
			}
			if((board.pieces[31]%16) != 0)
			{
				pawnRank = pawnPositions[0][board.pieces[31]%16];
				if(pawnRank == 0)
				{
					pawnShieldWhite -= 36;
				}
				else
				{
					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
				}
			}

			// Black pawn shield

			// Same as above but the formula is without '7-'
			// e.g. pawn in front of king advanced 2 ranks (on rank 4 in the board array)
			// 36 - 4*4 = 20 penalty
			pawnRank = pawnPositions[1][board.pieces[15]%16+1];
			if(pawnRank == 0)
			{
				pawnShieldBlack += 36;
			}
			else
			{
				pawnShieldWhite += 36 - ((pawnRank)*(pawnRank));
			}
			if((board.pieces[15]%16+1+1) != 9)
			{
				pawnRank = pawnPositions[1][board.pieces[15]%16+1+1];
				if(pawnRank == 0)
				{
					pawnShieldBlack += 36;
				}
				else
				{
					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
				}
			}
			if((board.pieces[15]%16) != 0)
			{
				pawnRank = pawnPositions[1][board.pieces[15]%16];
				if(pawnRank == 0)
				{
					pawnShieldBlack += 36;
				}
				else
				{
					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
				}
			}

			// Account for back rank trouble
			// if none of the pawns in front of the king advanced
			// we add a small penalty for back rank threats
			if(pawnShieldWhite == 0) pawnShieldWhite = -11;
			if(pawnShieldBlack == 0) pawnShieldBlack = 11;

		}
		// LOOP 2c
		// End game or pawn end game
		// End game piece tables and do not check for king attacks
		// and do not evaluate pawn shield
		else
		{
			for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
			{
				//boolean lastWhitePawnWasPasser = false;
				//boolean lastBlackPawnWasPasser = false;
				int i = board.pieces[piecesIndex];
				if(i != -1)
				{
					switch(board.pieceTypeOnIndex(i))
					{
					case W_KING: piecePositioning += KING_POS_ENDING[i];	break;
					case B_KING: piecePositioning -= KING_POS_ENDING[i]; break;
					case W_KNIGHT: piecePositioning += KNIGHT_POS_ENDING[i];	break;
					case B_KNIGHT: piecePositioning -= KNIGHT_POS_ENDING[i];	break;
					case W_QUEEN: piecePositioning += QUEEN_POS_ENDING[i]; break;
					case B_QUEEN: piecePositioning -= QUEEN_POS_ENDING[i]; break;								
					case W_ROOK:
					{
						piecePositioning += ROOK_POS_ENDING[i];	

						// Rook on row with only enemy pawns
						if(pawnPositions[0][(i%16)+1] == 0 && pawnPositions[1][(i%16)+1] != 0)
						{
							rookEval += ROOK_ON_SEMI;
						}
						// Rook on open row
						else if(pawnPositions[0][(i%16)+1] == 0)
						{
							rookEval += ROOK_ON_OPEN;
						}

						// Rook on seventh rank
						if((i-(i%16))/16 == 6)
						{
							rookEval += ROOK_ON_SEVENTH;
						}

						// Blocked rook, if rook is on say h1 or g1 and the white king is on f1 or g1 the rook is blocked
						if((i == 0 || i == 1) && (board.pieces[31] == 1 || board.pieces[31] == 2)) trappedPiece -= 50;
						else if((i == 6 || i == 7) && (board.pieces[31] == 5 || board.pieces[31] == 6)) trappedPiece -= 50;
						break;

					}
					case B_ROOK:
					{
						piecePositioning -= ROOK_POS_ENDING[i];							

						// Rook on row with only enemy pawns
						if(pawnPositions[1][(i%16)+1] == 0 && pawnPositions[0][(i%16)+1] != 0)
						{
							rookEval -= ROOK_ON_SEMI;
						}
						// Rook on open row
						else if(pawnPositions[1][(i%16)+1] == 0)
						{
							rookEval -= ROOK_ON_OPEN;
						}	
						// Rook on second rank
						if((i-(i%16))/16 == 1)
						{
							rookEval -= ROOK_ON_SEVENTH;
						}

						if((i == 112 || i == 113) && (board.pieces[15] == 113 || board.pieces[15] == 114)) trappedPiece += 50;
						else if((i == 118 || i == 119) && (board.pieces[15] == 117 || board.pieces[15] == 118)) trappedPiece += 50;

						break;

					}
					case W_BISHOP:
					{
						piecePositioning += BISHOP_POS_ENDING[i];

						// Checks for trapped bishop
						// e.g. bishop on a7 and black pawn on b6 traps the bishop
						if(i == 96 && board.pieceTypeOnIndex(81) == B_PAWN) trappedPiece -= 100; // a7, b6
						else if(i == 113 && board.pieceTypeOnIndex(98) == B_PAWN) trappedPiece -= 100; // b8, c7
						else if(i == 103 && board.pieceTypeOnIndex(86) == B_PAWN) trappedPiece -= 100; // h7, g6
						else if(i == 118 && board.pieceTypeOnIndex(101) == B_PAWN) trappedPiece -= 100; // g8, f7
						else if(i == 80 && board.pieceTypeOnIndex(65) == B_PAWN) trappedPiece -= 100; // a6, b5
						else if(i == 87 && board.pieceTypeOnIndex(70) == B_PAWN) trappedPiece -= 100; // h6, g5

						// Blocked in piece
						// If bishop on c1 or f1 and d2/e2 has white pawn and d3/e3 has white piece the bishop is blocked
						else if(i == 2 && board.pieceTypeOnIndex(19) == W_PAWN && board.pieceTypeOnIndex(35) > 0) trappedPiece -= 50;
						else if(i == 5 && board.pieceTypeOnIndex(20) == W_PAWN && board.pieceTypeOnIndex(36) > 0) trappedPiece -= 50;

						break;
					}
					case B_BISHOP:
					{
						piecePositioning -= BISHOP_POS_ENDING[i];

						if(i == 16 && board.pieceTypeOnIndex(33) == W_PAWN) trappedPiece += 100;
						else if(i == 32 && board.pieceTypeOnIndex(49) == W_PAWN) trappedPiece += 100;
						else if(i == 1 && board.pieceTypeOnIndex(18) == W_PAWN) trappedPiece += 100;
						else if(i == 6 && board.pieceTypeOnIndex(21) == W_PAWN) trappedPiece += 100;
						else if(i == 23 && board.pieceTypeOnIndex(38) == W_PAWN) trappedPiece += 100;
						else if(i == 39 && board.pieceTypeOnIndex(54) == W_PAWN) trappedPiece += 100;

						else if(i == 114 && board.pieceTypeOnIndex(99) == B_PAWN && board.pieceTypeOnIndex(83) < 0) trappedPiece += 50;
						else if(i == 117 && board.pieceTypeOnIndex(100) == B_PAWN && board.pieceTypeOnIndex(84) < 0) trappedPiece += 50;
						break;
					}
					case W_PAWN:
					{
						piecePositioning += W_PAWN_POS_ENDING[i];

						// Check for doubled pawn
						// If the rank recorded is not the same as this pawn which is
						// on the same row, there is another pawn on the same row
						// so the pawns are doubled
						if(pawnPositions[0][(i%16)+1] != (i-(i%16))/16)
						{
							pawnEval += DOUBLED_PAWN;						
						}

						// Check for isolated pawn
						// If the row to the right and left of this row does not contain
						// any friendly pawns, the pawn is isolated
						if(pawnPositions[0][(i%16)+1+1] == 0 &&
								pawnPositions[0][(i%16)+1-1] == 0)
						{
							pawnEval += ISOLATED_PAWN;						
						}

						// Check for passed pawn
						// If the row does not contain an enemy pawn or the enemypawn is behind it
						// and the rows to the right and left does not contain enemy pawns or they are behind
						// the pawn is passed
						if((pawnPositions[1][(i%16)+1]   == 0 || pawnPositions[1][(i%16)+1] < (i-(i%16))/16) &&
								(pawnPositions[1][(i%16)+1+1] == 0 || pawnPositions[1][(i%16)+1+1] <= (i-(i%16))/16) &&
								(pawnPositions[1][(i%16)+1-1] == 0 || pawnPositions[1][(i%16)+1-1] <= (i-(i%16))/16))
						{

							/*if(lastWhitePawnWasPasser)
							{
								pawnEval += CONNECTED_PASSERS;
							}
							lastWhitePawnWasPasser = true;
							*/
							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
							pawnEval += PASSED_PAWN + Math.pow((((i-(i%16))/16)), PASSED_MULTI_ENDING);
						}
						break;
					}
					case B_PAWN:
					{
						piecePositioning -= B_PAWN_POS_ENDING[i];
						

						// Check for doubled pawn
						// If the rank recorded is not the same as this pawn which is
						// on the same row, there is another pawn on the same row
						// so the pawns are doubled
						if(pawnPositions[1][(i%16)+1] != (i-(i%16))/16)
						{
							pawnEval -= DOUBLED_PAWN;						
						}

						// Check for isolated pawn
						// If the row to the right and left of this row does not contain
						// any friendly pawns, the pawn is isolated
						if(pawnPositions[1][(i%16)+1+1] == 0 &&
								pawnPositions[1][(i%16)+1-1] == 0)
						{
							pawnEval -= ISOLATED_PAWN;						
						}

						// Check for passed pawn
						// If the row does not contain an enemy pawn or the enemypawn is behind it
						// and the rows to the right and left does not contain enemy pawns or they are behind
						// the pawn is passed
						if((pawnPositions[0][(i%16)+1]   == 0 || pawnPositions[0][(i%16)+1] > (i-(i%16))/16) &&
								(pawnPositions[0][(i%16)+1+1] == 0 || pawnPositions[0][(i%16)+1+1] >= (i-(i%16))/16) &&
								(pawnPositions[0][(i%16)+1-1] == 0 || pawnPositions[0][(i%16)+1-1] >= (i-(i%16))/16))
						{
							/*if(lastBlackPawnWasPasser)
							{
								pawnEval += CONNECTED_PASSERS;
							}
							lastBlackPawnWasPasser = true;
							*/
							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
							pawnEval -= PASSED_PAWN + Math.pow((7-((i-(i%16))/16)), PASSED_MULTI_ENDING);
						}
						break;
					}
					}

				}
			}
			
		}
		
		/*System.out.println("Gamephase: " + gamePhase);
		System.out.println("whiteKingAttack: " + whiteKingAttackMulti*KING_ATTACK_WEIGHT[whiteKingAttackNumber]);
		System.out.println("blackKingAttack (-): " + blackKingAttackMulti*KING_ATTACK_WEIGHT[blackKingAttackNumber]);
		System.out.println("piecePositioning: " + piecePositioning);
		System.out.println("rookEval: " + rookEval);
		System.out.println("trappedPiece: " + trappedPiece);
		System.out.println("pawnShieldWhite: " + pawnShieldWhite);
		System.out.println("pawnShieldBlack: " + pawnShieldBlack);
		System.out.println("pawnEval: " + pawnEval);
		System.out.println("materialBalance: " + materialBalance);
		*/
		evaluation += whiteKingAttackMulti*KING_ATTACK_WEIGHT[whiteKingAttackNumber];
		evaluation -= blackKingAttackMulti*KING_ATTACK_WEIGHT[blackKingAttackNumber];
		evaluation += piecePositioning;
		evaluation += rookEval;
		evaluation += trappedPiece;
		evaluation += pawnShieldWhite;
		evaluation += pawnShieldBlack;
		evaluation += pawnEval;
		evaluation += materialBalance;
		
		return evaluation;
		
	}
	// END material()
	
	public static boolean isDrawnByMaterial(Board board)
	{
		boolean whiteHasBishop = false; // Used by draw by material detection
		boolean whiteHasKnight = false; // we need to keep track of the number of
		boolean blackHasBishop = false; // knights and bishops on the board since 1
		boolean blackHasKnight = false; // is draw but 2 is not

		for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
		{
			int index = board.pieces[piecesIndex];
			if(index != -1)
			{
				switch(board.pieceTypeOnIndex(index))
				{
				case W_BISHOP:
					if(whiteHasBishop || whiteHasKnight) return false;
					whiteHasBishop = true;
					break;
				case B_BISHOP:
					if(blackHasBishop || blackHasKnight) return false;
					blackHasBishop = true;
					break;
				case W_KNIGHT:
					if(whiteHasBishop || whiteHasKnight) return false;
					whiteHasKnight = true;
					break;
				case B_KNIGHT:
					if(whiteHasBishop || whiteHasKnight) return false;
					blackHasKnight = true;
					break;
				}
			}
		}
		
		return true;
	}
	
//	public static int material(Board board)
//	{
//		// Go through all the pieces on the board
//		//
//		// Add up the values, and see if there is enough material left to force a mate
//		boolean whiteHasBishop = false; // Used by draw by material detection
//		boolean whiteHasKnight = false; // we need to keep track of the number of
//		boolean blackHasBishop = false; // knights and bishops on the board since 1
//		boolean blackHasKnight = false; // is draw but 2 is not
//		
//		// Count pieces below to see if we are at the ending
//		// queen 4 points, rook 2 and minor 1
//		//
//        // if total <=8 we are at the ending
//		// E.g. one queen on each side, or one rook and two minor pieces on each side
//		//
//		// if total >20 we are at opening
//		// E.g. two minor pieces exchanged, or all pieces still on board
//		// 
//		// if total >8 && <=20 we are at the middle game
//		// E.g. one queen, two rooks and a minor piece on each side
//		int gamePhaseCheck = 0;
//							    
//		                       
//
//		int evaluation = 0; // Initialize the evaluation
//		boolean drawn_by_material = true; // Initialize the draw check
//		
//		int whiteKingAttackMulti = 0;
//		int whiteKingAttackNumber = 0;
//		int blackKingAttackMulti = 0;
//		int blackKingAttackNumber = 0;
//		
//		int materialBalance = 0;
//
//		// First pass, determine pawn positions and pieces attacking the kings
//		// and material balance
//		for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
//		{
//			int i = board.pieces[piecesIndex];
//			if(i != -1)
//			{
//				
//				
//				// Add the value of the piece to the material balance
//				materialBalance += PIECE_VALUE_ARRAY[board.pieceTypeOnIndex(i) + 7];
//
//				// Special calculations for particular pieces
//				switch(board.pieceTypeOnIndex(i))
//				{
//					case EMPTY_SQUARE: break;
//					case W_KING:
//					{
//						break;
//					}
//					case B_KING:
//					{
//						break;
//					}
//					case W_QUEEN:
//					{
//						if(attacksBlackKing(W_QUEEN, i, board))
//						{
//							whiteKingAttackMulti += 4;
//							whiteKingAttackNumber += 1;							
//						}
//						drawn_by_material = false;
//						gamePhaseCheck += 4;
//						break;
//					}
//					case B_QUEEN:
//					{
//						if(attacksWhiteKing(B_QUEEN, i, board))
//						{
//							blackKingAttackMulti += 4;
//							blackKingAttackNumber += 1;							
//						}
//						drawn_by_material = false;
//						gamePhaseCheck += 4;
//						break;
//						
//					}
//					case W_ROOK:
//					{
//						if(attacksBlackKing(W_ROOK, i, board))
//						{
//							whiteKingAttackMulti += 2;
//							whiteKingAttackNumber += 1;							
//						}
//						drawn_by_material = false;
//						gamePhaseCheck += 2;
//						break;
//						
//					}
//					case B_ROOK:
//					{
//						if(attacksWhiteKing(B_ROOK, i, board))
//						{
//							blackKingAttackMulti += 2;
//							blackKingAttackNumber += 1;							
//						}
//						drawn_by_material = false;
//						gamePhaseCheck += 2;
//						break;
//						
//					}
//					case W_KNIGHT:
//					{
//						for(int q = 0; q < 8; q++)
//						{
//							if(((board.pieces[15] + king_delta[q]) & 0x88) == 0)
//							{
//								if(ATTACK_ARRAY[(board.pieces[15] + king_delta[q])-i+128] == ATTACK_N)
//								{
//									whiteKingAttackMulti += 1;
//									whiteKingAttackNumber += 1;
//									break;
//								}
//							}
//						}
//						gamePhaseCheck += 1;
//						break;
//					}
//					case B_KNIGHT:
//					{
//						for(int q = 0; q < 8; q++)
//						{
//							if(((board.pieces[31] + king_delta[q]) & 0x88) == 0)
//							{
//								if(ATTACK_ARRAY[(board.pieces[31] + king_delta[q])-i+128] == ATTACK_N)
//								{
//									blackKingAttackMulti += 1;
//									blackKingAttackNumber += 1;
//									break;
//								}
//							}
//						}
//						gamePhaseCheck += 1;
//						break;
//					}
//					case W_BISHOP:
//					{
//						if(attacksBlackKing(W_BISHOP, i, board))
//						{
//							whiteKingAttackMulti += 1;
//							whiteKingAttackNumber += 1;							
//						}
//						gamePhaseCheck += 1;
//						break;
//					}
//					case B_BISHOP:
//					{
//						if(attacksWhiteKing(B_BISHOP, i, board))
//						{
//							blackKingAttackMulti += 1;
//							blackKingAttackNumber += 1;							
//						}
//						gamePhaseCheck += 1;
//						break;
//					}
//					case W_PAWN:
//					{
//						drawn_by_material = false;
//						if(pawnEval[0][(i%16)+1] == 0 || pawnEval[0][(i%16)+1] > (i-(i%16))/16)
//						{
//							pawnEval[0][(i%16)+1] = (i-(i%16))/16; 
//						}
//						break;
//					}
//					case B_PAWN:
//					{
//						drawn_by_material = false;
//						if(pawnEval[1][(i%16)+1] == 0 || pawnEval[1][(i%16)+1] < (i-(i%16))/16)
//						{
//							pawnEval[1][(i%16)+1] = (i-(i%16))/16; 
//						}
//						break;
//					}
//				}
//				// Do the checks for drawn by material
//				if(drawn_by_material && board.pieceTypeOnIndex(i) != EMPTY_SQUARE)
//				{
//					if((whiteHasBishop || whiteHasKnight) && board.pieceTypeOnIndex(i) == W_BISHOP)
//						drawn_by_material = false;
//
//					else if(whiteHasBishop && board.pieceTypeOnIndex(i) == W_KNIGHT)
//						drawn_by_material = false;
//
//					else if(board.pieceTypeOnIndex(i) == W_BISHOP)
//						whiteHasBishop = true;
//
//					else if(board.pieceTypeOnIndex(i) == W_KNIGHT)
//						whiteHasKnight = true;
//
//					else if((blackHasBishop || blackHasKnight) && board.pieceTypeOnIndex(i) == B_BISHOP)
//						drawn_by_material = false;
//
//					else if(blackHasBishop && board.pieceTypeOnIndex(i) == B_KNIGHT)
//						drawn_by_material = false;
//
//					else if(board.pieceTypeOnIndex(i) == B_BISHOP)
//						blackHasBishop = true;
//
//					else if(board.pieceTypeOnIndex(i) == B_KNIGHT) {
//						blackHasKnight = true;
//					}
//
//				}
//
//			}
//		}
//		
//		// We now know what phase we are in
//		if(gamePhaseCheck == 0) gamePhase = PHASE_PAWN_ENDING;
//		else if(gamePhaseCheck <= 8) gamePhase = PHASE_ENDING;
//		else if(gamePhaseCheck >20) gamePhase = PHASE_OPENING;
//		else gamePhase = PHASE_MIDDLE;
//		
//		
//		int totalPawnEval = 0;
//		int totalRookEval = 0;
//		int[][] passers = new int[2][10]; // Keeps track of rows that contains passed pawns
//		int piecePositioning = 0;
//		int trappedPiece = 0;
//		
//		// Second pass, evaluate piece positioning, trapped pieces and passed pawns etc.
//		for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
//		{
//			int i = board.pieces[piecesIndex];
//			if(i != -1)
//			{
//				switch(board.pieceTypeOnIndex(i))
//				{
//					case EMPTY_SQUARE: break;
//					case W_KING:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_KING_POS[i];							
//						}
//						else
//						{
//							piecePositioning += KING_POS_ENDING[i];							
//						}
//						break;
//					}
//					case B_KING:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_KING_POS[i];							
//						}
//						else
//						{
//							piecePositioning -= KING_POS_ENDING[i];							
//						}
//						break;
//					}
//					case W_QUEEN:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_QUEEN_POS[i];							
//						}
//						else
//						{
//							piecePositioning += QUEEN_POS_ENDING[i];							
//						}
//						break;
//					}
//					case B_QUEEN:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_QUEEN_POS[i];							
//						}
//						else
//						{
//							piecePositioning -= QUEEN_POS_ENDING[i];							
//						}
//						break;
//						
//					}
//					case W_ROOK:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_ROOK_POS[i];							
//						}
//						else
//						{
//							piecePositioning += ROOK_POS_ENDING[i];							
//						}
//						// Rook on row with only enemy pawns
//						if(pawnEval[0][(i%16)+1] == 0 && pawnEval[1][(i%16)+1] != 0)
//						{
//							totalRookEval += ROOK_ON_SEMI;
//						}
//						// Rook on open row
//						else if(pawnEval[0][(i%16)+1] == 0)
//						{
//							totalRookEval += ROOK_ON_OPEN;
//						}
//
//						// Rook on seventh rank
//						if((i-(i%16))/16 == 6)
//						{
//							totalRookEval += ROOK_ON_SEVENTH;
//						}
//						
//						// Blocked rook, if rook is on say h1 or g1 and the white king is on f1 or g1 the rook is blocked
//						if((i == 0 || i == 1) && (board.pieces[31] == 1 || board.pieces[31] == 2)) trappedPiece -= 50;
//						else if((i == 6 || i == 7) && (board.pieces[31] == 5 || board.pieces[31] == 6)) trappedPiece -= 50;
//						break;
//						
//					}
//					case B_ROOK:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_ROOK_POS[i];							
//						}
//						else
//						{
//							piecePositioning -= ROOK_POS_ENDING[i];							
//						}
//						// Rook on row with only enemy pawns
//						if(pawnEval[1][(i%16)+1] == 0 && pawnEval[0][(i%16)+1] != 0)
//						{
//							totalRookEval -= ROOK_ON_SEMI;
//						}
//						// Rook on open row
//						else if(pawnEval[1][(i%16)+1] == 0)
//						{
//							totalRookEval -= ROOK_ON_OPEN;
//						}	
//						// Rook on second rank
//						if((i-(i%16))/16 == 1)
//						{
//							totalRookEval -= ROOK_ON_SEVENTH;
//						}
//						
//						if((i == 112 || i == 113) && (board.pieces[15] == 113 || board.pieces[15] == 114)) trappedPiece += 50;
//						else if((i == 118 || i == 119) && (board.pieces[15] == 117 || board.pieces[15] == 118)) trappedPiece += 50;
//						
//						break;
//						
//					}
//					case W_KNIGHT:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_KNIGHT_POS[i];							
//						}
//						else
//						{
//							piecePositioning += KNIGHT_POS_ENDING[i];							
//						}
//						
//						break;
//					}
//					case B_KNIGHT:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_KNIGHT_POS[i];							
//						}
//						else
//						{
//							piecePositioning -= KNIGHT_POS_ENDING[i];							
//						}
//						break;
//					}
//					case W_BISHOP:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_BISHOP_POS[i];							
//						}
//						else
//						{
//							piecePositioning += BISHOP_POS_ENDING[i];							
//						}
//						
//						// Checks for trapped bishop
//						// e.g. bishop on a7 and black pawn on b6 traps the bishop
//						if(i == 96 && board.pieceTypeOnIndex(81) == B_PAWN) trappedPiece -= 100; // a7, b6
//						else if(i == 113 && board.pieceTypeOnIndex(98) == B_PAWN) trappedPiece -= 100; // b8, c7
//						else if(i == 103 && board.pieceTypeOnIndex(86) == B_PAWN) trappedPiece -= 100; // h7, g6
//						else if(i == 118 && board.pieceTypeOnIndex(101) == B_PAWN) trappedPiece -= 100; // g8, f7
//						else if(i == 80 && board.pieceTypeOnIndex(65) == B_PAWN) trappedPiece -= 100; // a6, b5
//						else if(i == 87 && board.pieceTypeOnIndex(70) == B_PAWN) trappedPiece -= 100; // h6, g5
//						
//						// Blocked in piece
//						// If bishop on c1 or f1 and d2/e2 has white pawn and d3/e3 has white piece the bishop is blocked
//						else if(i == 2 && board.pieceTypeOnIndex(19) == W_PAWN && board.pieceTypeOnIndex(35) > 0) trappedPiece -= 50;
//						else if(i == 5 && board.pieceTypeOnIndex(20) == W_PAWN && board.pieceTypeOnIndex(36) > 0) trappedPiece -= 50;
//						
//						break;
//					}
//					case B_BISHOP:
//					{
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_BISHOP_POS[i];							
//						}
//						else
//						{
//							piecePositioning -= BISHOP_POS_ENDING[i];							
//						}
//						
//						if(i == 16 && board.pieceTypeOnIndex(33) == W_PAWN) trappedPiece += 100;
//						else if(i == 32 && board.pieceTypeOnIndex(49) == W_PAWN) trappedPiece += 100;
//						else if(i == 1 && board.pieceTypeOnIndex(18) == W_PAWN) trappedPiece += 100;
//						else if(i == 6 && board.pieceTypeOnIndex(21) == W_PAWN) trappedPiece += 100;
//						else if(i == 23 && board.pieceTypeOnIndex(38) == W_PAWN) trappedPiece += 100;
//						else if(i == 39 && board.pieceTypeOnIndex(54) == W_PAWN) trappedPiece += 100;
//						
//						else if(i == 114 && board.pieceTypeOnIndex(99) == W_PAWN && board.pieceTypeOnIndex(86) < 0) trappedPiece += 50;
//						else if(i == 117 && board.pieceTypeOnIndex(100) == W_PAWN && board.pieceTypeOnIndex(84) < 0) trappedPiece += 50;
//						break;
//					}
//					case W_PAWN:
//					{
//						// Add the positioning bonus
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning += W_PAWN_POS[i];
//						}
//						else
//						{
//							piecePositioning += W_PAWN_POS_ENDING[i];
//						}
//
//
//						// Check for doubled pawn
//						// If the rank recorded is not the same as this pawn which is
//						// on the same row, there is another pawn on the same row
//						// so the pawns are doubled
//						if(pawnEval[0][(i%16)+1] != (i-(i%16))/16)
//						{
//							totalPawnEval += DOUBLED_PAWN;						
//						}
//
//						// Check for isolated pawn
//						// If the row to the right and left of this row does not contain
//						// any friendly pawns, the pawn is isolated
//						if(pawnEval[0][(i%16)+1+1] == 0 &&
//								pawnEval[0][(i%16)+1-1] == 0)
//						{
//							totalPawnEval += ISOLATED_PAWN;						
//						}
//
//						// Check for passed pawn
//						// If the row does not contain an enemy pawn or the enemypawn is behind it
//						// and the rows to the right and left does not contain enemy pawns or they are behind
//						// the pawn is passed
//						if((pawnEval[1][(i%16)+1]   == 0 || pawnEval[1][(i%16)+1] < (i-(i%16))/16) &&
//								(pawnEval[1][(i%16)+1+1] == 0 || pawnEval[1][(i%16)+1+1] <= (i-(i%16))/16) &&
//								(pawnEval[1][(i%16)+1-1] == 0 || pawnEval[1][(i%16)+1-1] <= (i-(i%16))/16))
//						{
//							passers[0][(i%16)+1] = 1;
//							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
//							if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//							{
//								//totalPawnEval += PASSED_PAWN + PASSED_MULTI*(7-((i-(i%16))/16));
//								totalPawnEval += PASSED_PAWN + Math.pow((((i-(i%16))/16)), PASSED_MULTI);
//							}
//							else
//							{
//								totalPawnEval += PASSED_PAWN + Math.pow((((i-(i%16))/16)), PASSED_MULTI_ENDING);
//							}
//						}
//						break;
//					}
//					case B_PAWN:
//					{
//						// Add the positioning bonus
//						if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//						{
//							piecePositioning -= B_PAWN_POS[i];
//						}
//						else
//						{
//							piecePositioning -= B_PAWN_POS_ENDING[i];
//						}
//
//						// Check for doubled pawn
//						// If the rank recorded is not the same as this pawn which is
//						// on the same row, there is another pawn on the same row
//						// so the pawns are doubled
//						if(pawnEval[1][(i%16)+1] != (i-(i%16))/16)
//						{
//							totalPawnEval -= DOUBLED_PAWN;						
//						}
//
//						// Check for isolated pawn
//						// If the row to the right and left of this row does not contain
//						// any friendly pawns, the pawn is isolated
//						if(pawnEval[1][(i%16)+1+1] == 0 &&
//								pawnEval[1][(i%16)+1-1] == 0)
//						{
//							totalPawnEval -= ISOLATED_PAWN;						
//						}
//
//						// Check for passed pawn
//						// If the row does not contain an enemy pawn or the enemypawn is behind it
//						// and the rows to the right and left does not contain enemy pawns or they are behind
//						// the pawn is passed
//						if((pawnEval[0][(i%16)+1]   == 0 || pawnEval[0][(i%16)+1] > (i-(i%16))/16) &&
//								(pawnEval[0][(i%16)+1+1] == 0 || pawnEval[0][(i%16)+1+1] >= (i-(i%16))/16) &&
//								(pawnEval[0][(i%16)+1-1] == 0 || pawnEval[0][(i%16)+1-1] >= (i-(i%16))/16))
//						{
//							passers[1][(i%16)+1] = 1;
//							// Add the passed pawn bonus, + an extra bonus for every rank it has moved
//							if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//							{
//								totalPawnEval -= PASSED_PAWN + Math.pow((7-((i-(i%16))/16)), PASSED_MULTI);
//							}
//							else
//							{
//								totalPawnEval -= PASSED_PAWN + Math.pow((7-((i-(i%16))/16)), PASSED_MULTI_ENDING);
//							}
//						}
//						break;
//					}
//				}
//
//			}
//		}
//		
//		// Give bonus for connected passed pawns
//		int whiteConnectedPassers = 0;
//		int blackConnectedPassers = 0;
//		int connectedEval = 0;
//		
//		for(int i = 0; i < 10; i++)
//		{
//			// If the row contains a passed white pawn increment
//			if(passers[0][i] == 1) whiteConnectedPassers++;
//			// If the row does not contain a passed whtie pawn there are no more connectors
//			else if(passers[0][i] == 0)
//			{
//				// Give bonus accordingly for number of passed connected pawns
//				// and reset the counter
//				if(whiteConnectedPassers == 2)
//				{
//					connectedEval += TWO_CONNECTED_PASSERS;
//				}
//				else if(whiteConnectedPassers >= 3)
//				{
//					connectedEval += THREE_CONNECTED_PASSERS;
//				}
//				whiteConnectedPassers = 0;
//			}
//			if(passers[1][i] == 1) blackConnectedPassers++;
//			else if(passers[1][i] == 0)
//			{
//				if(blackConnectedPassers == 2)
//				{
//					connectedEval -= TWO_CONNECTED_PASSERS;
//				}
//				else if(blackConnectedPassers >= 3)
//				{
//					connectedEval -= THREE_CONNECTED_PASSERS;
//				}
//				blackConnectedPassers = 0;
//			}
//		}
//		// Pawn shield for the kings, only in opening and middle game
//		int pawnShieldWhite = 0;
//		int pawnShieldBlack = 0;
//		if(gamePhase == PHASE_OPENING || gamePhase == PHASE_MIDDLE)
//		{
//			int pawnRank;
//
//			// White pawn shield
//			
//			// Find the rank the pawn in front of the king is on
//			pawnRank = pawnEval[0][board.pieces[31]%16+1];
//			// If there is no pawn in front of the king, penalize with 36
//			if(pawnRank == 0)
//			{
//				pawnShieldWhite -= 36;
//			}
//			// If there is a pawn in front of the king penalize with the number
//			// of ranks it has advanced
//			// e.g. advanced 2 ranks (on rank 4 (=3 on the board))
//			// 36 - (7-3)*(7-3) = 20 penalty 
//			else
//			{
//				pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
//			}
//			// Look for the pawn to the right in front of the king, make sure
//			// we are not off the board and do the same thing as above
//			if((board.pieces[31]%16+1+1) != 0 && (board.pieces[31]%16+1+1) != 9)
//			{
//				pawnRank = pawnEval[0][board.pieces[31]%16+1+1];
//				if(pawnRank == 0)
//				{
//					pawnShieldWhite -= 36;
//				}
//				else
//				{
//					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
//				}
//			}
//			if((board.pieces[31]%16) != 0 && (board.pieces[31]%16) != 9)
//			{
//				pawnRank = pawnEval[0][board.pieces[31]%16];
//				if(pawnRank == 0)
//				{
//					pawnShieldWhite -= 36;
//				}
//				else
//				{
//					pawnShieldWhite -= 36 - ((7-pawnRank)*(7-pawnRank));
//				}
//			}
//			
//			// Black pawn shield
//			
//			// Same as above but the formula is without '7-'
//			// e.g. pawn in front of king advanced 2 ranks (on rank 4 in the board array)
//			// 36 - 4*4 = 20 penalty
//			pawnRank = pawnEval[1][board.pieces[15]%16+1];
//			if(pawnRank == 0)
//			{
//				pawnShieldBlack += 36;
//			}
//			else
//			{
//				pawnShieldWhite += 36 - ((pawnRank)*(pawnRank));
//			}
//			if((board.pieces[15]%16+1+1) != 0 && (board.pieces[15]%16+1+1) != 9)
//			{
//				pawnRank = pawnEval[1][board.pieces[15]%16+1+1];
//				if(pawnRank == 0)
//				{
//					pawnShieldBlack += 36;
//				}
//				else
//				{
//					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
//				}
//			}
//			if((board.pieces[15]%16) != 0 && (board.pieces[15]%16) != 9)
//			{
//				pawnRank = pawnEval[1][board.pieces[15]%16];
//				if(pawnRank == 0)
//				{
//					pawnShieldBlack += 36;
//				}
//				else
//				{
//					pawnShieldBlack += 36 - ((pawnRank)*(pawnRank));
//				}
//			}
//			
//			// Account for back rank trouble
//			// if none of the pawns in front of the king advanced
//			// we add a small penalty for back rank threats
//			if(pawnShieldWhite == 0) pawnShieldWhite = -11;
//			if(pawnShieldBlack == 0) pawnShieldBlack = 11;
//
//		}
//		
//		int totalPawnShield = pawnShieldWhite + pawnShieldBlack;
//		int kingSafety = whiteKingAttackMulti*KING_ATTACK_WEIGHT[whiteKingAttackNumber] - blackKingAttackMulti*KING_ATTACK_WEIGHT[blackKingAttackNumber];
//		
//		/*if(gamePhase == PHASE_ENDING || gamePhase == PHASE_PAWN_ENDING)
//		{
//			kingSafety = (kingSafety - (kingSafety%3)) / 3;			
//		}*/
//		
//		
//	/*	System.out.println("Ks: " + kingSafety + " Mb: " + materialBalance + " Pp: " + piecePositioning);
//		System.out.println("Re: " + totalRookEval + " Tp: " + trappedPiece);
//		System.out.println("Ps: " + totalPawnShield + " C: " + connectedEval + " Pe: " + totalPawnEval);
//		*/
//		
//		evaluation += trappedPiece;
//		evaluation += piecePositioning;
//		evaluation += materialBalance;
//		evaluation += totalPawnShield;
//		evaluation += kingSafety;
//		evaluation += connectedEval;
//		evaluation += totalPawnEval;
//		evaluation += totalRookEval;
//	
//		return ( drawn_by_material ) ? DRAW_VALUE : evaluation; 
//	}
	// END evaluatePosition()
	
	public static boolean attacksBlackKing(int piece, int index, Board board)
	{
		boolean isAdjacent = false;
		int attackType;
		
		switch(piece)
		{
		case W_QUEEN:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[15] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[15] + king_delta[q])-index+128];
					if(attackType != ATTACK_N && attackType != ATTACK_NONE)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		case W_ROOK:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[15] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[15] + king_delta[q])-index+128];
					if(attackType == ATTACK_KQR || attackType == ATTACK_QR)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		case W_BISHOP:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[15] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[15] + king_delta[q])-index+128];
					if(attackType == ATTACK_KQBwP || attackType == ATTACK_KQBbP || attackType == ATTACK_QB)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		}
		
		if(isAdjacent)
		{
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[15] + 2*king_delta[q]) & 0x88) == 0)
				{
					if(board.pieceTypeOnIndex((board.pieces[15] + 2*king_delta[q])) == EMPTY_SQUARE)
					{
					if(board.traverseDelta(index, (board.pieces[15] + 2*king_delta[q])))
					{
						return true;							
					}
					}
				}
			}
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[15] + knight_delta[q]) & 0x88) == 0)
				{
					if(board.pieceTypeOnIndex((board.pieces[15] + knight_delta[q])) == EMPTY_SQUARE)
					{
					if(board.traverseDelta(index, (board.pieces[15] + knight_delta[q])))
					{
						return true;							
					}
					}
				}
			}
		}
		
		return false;
	}
	
	public static boolean attacksWhiteKing(int piece, int index, Board board)
	{
		boolean isAdjacent = false;
		int attackType;
		
		switch(piece)
		{
		case B_QUEEN:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[31] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[31] + king_delta[q])-index+128];
					if(attackType != ATTACK_N && attackType != ATTACK_NONE)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		case B_ROOK:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[31] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[31] + king_delta[q])-index+128];
					if(attackType == ATTACK_KQR || attackType == ATTACK_QR)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		case B_BISHOP:
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[31] + king_delta[q]) & 0x88) == 0)
				{
					attackType = ATTACK_ARRAY[(board.pieces[31] + king_delta[q])-index+128];
					if(attackType == ATTACK_KQBwP || attackType == ATTACK_KQBbP || attackType == ATTACK_QB)
					{
						isAdjacent = true;
						break;
					}
				}
			}
			break;
		}
		
		if(isAdjacent)
		{
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[31] + 2*king_delta[q]) & 0x88) == 0)
				{
					if(board.pieceTypeOnIndex((board.pieces[31] + 2*king_delta[q])) == EMPTY_SQUARE)
					{
					if(board.traverseDelta(index, (board.pieces[31] + 2*king_delta[q])))
					{
						return true;							
					}
					}

				}
			}
			for(int q = 0; q < 8; q++)
			{
				if(((board.pieces[31] + knight_delta[q]) & 0x88) == 0)
				{
					if(board.pieceTypeOnIndex((board.pieces[31] + knight_delta[q])) == EMPTY_SQUARE)
					{
					if(board.traverseDelta(index, (board.pieces[31] + knight_delta[q])))
					{
						return true;							
					}
					}
				}
			}
		}
		
		return false;
	}
	/**
	 *  This method returns the game phase, used if we need the game phase
	 *  without evaluating the board (like for contempt factor)
	 *  
	 *  This is integrated in the material evaluation for ordinary evaluation
	 * 
	 * @param board The board to decide game phase on
	 * @return gamePhase The phase the position on the board is in
	 */	
	public static int getGamePhase(Board board)
	{
		int phase = PHASE_OPENING; // Initialize to opening
		int gamePhaseCheck = 0; // Initialize the count
		
		for(int piecesIndex = 0; piecesIndex < 32; piecesIndex++)
		{
			int i = board.pieces[piecesIndex];
			if(i != -1)
			{
				switch(board.pieceTypeOnIndex(i))
				{
					case W_QUEEN: gamePhaseCheck += 4; break;
					case B_QUEEN: gamePhaseCheck += 4; break;
					case W_ROOK: gamePhaseCheck += 2; break;
					case B_ROOK: gamePhaseCheck += 2; break;
					case W_KNIGHT: gamePhaseCheck += 1; break;
					case B_KNIGHT: gamePhaseCheck += 1; break;
					case W_BISHOP: gamePhaseCheck += 1; break;
					case B_BISHOP: gamePhaseCheck += 1; break;
				}

			}
		}
		
		if(gamePhaseCheck == 0) phase = PHASE_PAWN_ENDING;
		else if(gamePhaseCheck <= 8) phase = PHASE_ENDING;
		else if(gamePhaseCheck >20) phase = PHASE_OPENING;
		else phase = PHASE_MIDDLE;
		
		return phase;		
	}
	// END getGamePhase()
	
}
