📄 jcboardevaluator.java
字号:
/************************************************************************* * jcBoardEvaluator - Analyzes and evaluates a chess board position * by F.D. Laramee * * History * 07.08.00 Creation * *********************************************************************/package javachess;import javachess.jcBoard;public class jcBoardEvaluator{ /********************************************************************** * DATA MEMBERS **********************************************************************/ // Data counters to evaluate pawn structure int MaxPawnFileBins[]; int MaxPawnColorBins[]; int MaxTotalPawns; int PawnRams; int MaxMostAdvanced[]; int MaxPassedPawns[]; int MinPawnFileBins[]; int MinMostBackward[]; // The "graininess" of the evaluation. MTD(f) works a lot faster if the // evaluation is relatively coarse private static final int Grain = 3; /********************************************************************** * PUBLIC METHODS *********************************************************************/ // Construction public jcBoardEvaluator() { MaxPawnFileBins = new int[ 8 ]; MaxPawnColorBins = new int[ 2 ]; MaxMostAdvanced = new int[ 8 ]; MaxPassedPawns = new int[ 8 ]; MinPawnFileBins = new int[ 8 ]; MinMostBackward = new int[ 8 ]; } // int EvaluateQuickie( jcBoard theBoard, int FromWhosePerspective ) // A simple, fast evaluation based exclusively on material. Since material // is overwhelmingly more important than anything else, we assume that if a // position's material value is much lower (or much higher) than another, // then there is no need to waste time on positional factors because they // won't be enough to tip the scales the other way, so to speak. public int EvaluateQuickie( jcBoard theBoard, int fromWhosePerspective ) { return ( ( theBoard.EvalMaterial( fromWhosePerspective ) >> Grain ) << Grain ); } // int EvaluateComplete( jcBoard theBoard ) // A detailed evaluation function, taking into account several positional // factors public int EvaluateComplete( jcBoard theBoard, int fromWhosePerspective ) { AnalyzePawnStructure( theBoard, fromWhosePerspective ); return(((theBoard.EvalMaterial( fromWhosePerspective ) + EvalPawnStructure( fromWhosePerspective ) + EvalBadBishops( theBoard, fromWhosePerspective ) + EvalDevelopment( theBoard, fromWhosePerspective ) + EvalRookBonus( theBoard, fromWhosePerspective ) + EvalKingTropism( theBoard, fromWhosePerspective ) ) >> Grain ) << Grain ); } /*************************************************************************** * PRIVATE METHODS **************************************************************************/ // private EvalKingTropism // All other things being equal, having your Knights, Queens and Rooks close // to the opponent's king is a good thing // This method is a bit slow and dirty, but it gets the job done private int EvalKingTropism( jcBoard theBoard, int fromWhosePerspective ) { int score = 0; // Square coordinates int kingRank = 0, kingFile = 0; int pieceRank = 0, pieceFile = 0; if ( fromWhosePerspective == jcPlayer.SIDE_WHITE ) { // Look for enemy king first! for( int i = 0; i < 64; i++ ) { if ( theBoard.FindBlackPiece( i ) == jcBoard.BLACK_KING ) { kingRank = i >> 8; kingFile = i % 8; break; } } // Now, look for pieces which need to be evaluated for( int i = 0; i < 64; i++ ) { pieceRank = i >> 8; pieceFile = i % 8; switch( theBoard.FindWhitePiece( i ) ) { case jcBoard.WHITE_ROOK: score -= ( Math.min( Math.abs( kingRank - pieceRank ), Math.abs( kingFile - pieceFile ) ) << 1 ); break; case jcBoard.WHITE_KNIGHT: score += 5 - Math.abs( kingRank - pieceRank ) - Math.abs( kingFile - pieceFile ); break; case jcBoard.WHITE_QUEEN: score -= Math.min( Math.abs( kingRank - pieceRank ), Math.abs( kingFile - pieceFile ) ); break; default: break; } } } else { // Look for enemy king first! for( int i = 0; i < 64; i++ ) { if ( theBoard.FindWhitePiece( i ) == jcBoard.WHITE_KING ) { kingRank = i >> 8; kingFile = i % 8; break; } } // Now, look for pieces which need to be evaluated for( int i = 0; i < 64; i++ ) { pieceRank = i >> 8; pieceFile = i % 8; switch( theBoard.FindBlackPiece( i ) ) { case jcBoard.BLACK_ROOK: score -= ( Math.min( Math.abs( kingRank - pieceRank ), Math.abs( kingFile - pieceFile ) ) << 1 ); break; case jcBoard.BLACK_KNIGHT: score += 5 - Math.abs( kingRank - pieceRank ) - Math.abs( kingFile - pieceFile ); break; case jcBoard.BLACK_QUEEN: score -= Math.min( Math.abs( kingRank - pieceRank ), Math.abs( kingFile - pieceFile ) ); break; default: break; } } } return score; } // private EvalRookBonus // Rooks are more effective on the seventh rank, on open files and behind // passed pawns private int EvalRookBonus( jcBoard theBoard, int fromWhosePerspective ) { long rookboard = theBoard.GetBitBoard( jcBoard.ROOK + fromWhosePerspective ); if ( rookboard == 0 ) return 0; int score = 0; for( int square = 0; square < 64; square++ ) { // Find a rook if ( ( rookboard & jcBoard.SquareBits[ square ] ) != 0 ) { // Is this rook on the seventh rank? int rank = ( square >> 3 ); int file = ( square % 8 ); if ( ( fromWhosePerspective == jcPlayer.SIDE_WHITE ) && ( rank == 1 ) ) score += 22; if ( ( fromWhosePerspective == jcPlayer.SIDE_BLACK ) && ( rank == 7 ) ) score += 22; // Is this rook on a semi- or completely open file? if ( MaxPawnFileBins[ file ] == 0 ) { if ( MinPawnFileBins[ file ] == 0 ) score += 10; else score += 4; } // Is this rook behind a passed pawn? if ( ( fromWhosePerspective == jcPlayer.SIDE_WHITE ) && ( MaxPassedPawns[ file ] < square ) ) score += 25; if ( ( fromWhosePerspective == jcPlayer.SIDE_BLACK ) && ( MaxPassedPawns[ file ] > square ) ) score += 25; // Use the bitboard erasure trick to avoid looking for additional // rooks once they have all been seen rookboard ^= jcBoard.SquareBits[ square ]; if ( rookboard == 0 ) break; } } return score; } // private EvalDevelopment // Mostly useful in the opening, this term encourages the machine to move // its bishops and knights into play, to control the center with its queen's // and king's pawns, and to castle if the opponent has many major pieces on // the board private int EvalDevelopment( jcBoard theBoard, int fromWhosePerspective ) { int score = 0; if ( fromWhosePerspective == jcPlayer.SIDE_WHITE ) { // Has the machine advanced its center pawns? if ( theBoard.FindWhitePiece( 51 ) == jcBoard.WHITE_PAWN ) score -= 15; if ( theBoard.FindWhitePiece( 52 ) == jcBoard.WHITE_PAWN ) score -= 15; // Penalize bishops and knights on the back rank for( int square = 56; square < 64; square++ ) { if ( ( theBoard.FindWhitePiece( square ) == jcBoard.WHITE_KNIGHT ) || ( theBoard.FindWhitePiece( square ) == jcBoard.WHITE_BISHOP ) ) score -= 10; } // Penalize too-early queen movement long queenboard = theBoard.GetBitBoard( jcBoard.WHITE_QUEEN ); if ( ( queenboard != 0 ) && ( ( queenboard & jcBoard.SquareBits[ 59 ] ) == 0 ) ) { // First, count friendly pieces on their original squares int cnt = 0; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_BISHOP ) & jcBoard.SquareBits[ 58 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_BISHOP ) & jcBoard.SquareBits[ 61 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_KNIGHT ) & jcBoard.SquareBits[ 57 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_KNIGHT ) & jcBoard.SquareBits[ 62 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_ROOK ) & jcBoard.SquareBits[ 56 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_ROOK ) & jcBoard.SquareBits[ 63 ] ) != 0 ) cnt++; if ( ( theBoard.GetBitBoard( jcBoard.WHITE_KING ) & jcBoard.SquareBits[ 60 ] ) != 0 ) cnt++; score -= ( cnt << 3 ); } // And finally, incite castling when the enemy has a queen on the board // This is a slightly simpler version of a factor used by Cray Blitz if ( theBoard.GetBitBoard( jcBoard.BLACK_QUEEN ) != 0 ) { // Being castled deserves a bonus if ( theBoard.GetHasCastled( jcPlayer.SIDE_WHITE ) ) score += 10; // small penalty if you can still castle on both sides else if ( theBoard.GetCastlingStatus( jcPlayer.SIDE_WHITE + jcBoard.CASTLE_QUEENSIDE ) && theBoard.GetCastlingStatus( jcPlayer.SIDE_WHITE + jcBoard.CASTLE_QUEENSIDE ) ) score -= 24; // bigger penalty if you can only castle kingside else if ( theBoard.GetCastlingStatus( jcPlayer.SIDE_WHITE + jcBoard.CASTLE_KINGSIDE ) ) score -= 40; // bigger penalty if you can only castle queenside else if ( theBoard.GetCastlingStatus( jcPlayer.SIDE_WHITE + jcBoard.CASTLE_QUEENSIDE ) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -