📄 evaluate.java
字号:
boolean inEndgame = Math.min(vlWhite, vlBlack) <= 6 && Math.abs(vlWhite - vlBlack) >= 2;
// 2. Calculate Attacking Values for Each Squares (Both Sides)
byte[] whiteAttack = new byte[128], blackAttack = new byte[128];
for (int sq = 0; sq < 128; sq ++) {
whiteAttack[sq] = blackAttack[SQUARE_FLIP(sq)] = (byte)
(RANK_IMPORTANCE[sq] * Math.max(vlWhite + vlBlack - 24, 8) / 32 + CENTER_IMPORTANCE[sq]);
}
for (int i = 0; i < 8; i ++) {
int importance = 12 * Math.max(vlWhite + vlBlack - 24, 8) / 32;
int sq = sqWhiteKing + Position.KING_DELTA[i];
if (IN_BOARD(sq)) {
blackAttack[sq] += importance;
}
sq = sqBlackKing + Position.KING_DELTA[i];
if (IN_BOARD(sq)) {
whiteAttack[sq] += importance;
}
}
// 3. Calculate Control Table for Each Squares
byte[] whiteRookControl = new byte[128], whiteBishopControl = new byte[128];
byte[] blackRookControl = new byte[128], blackBishopControl = new byte[128];
for (int sq = 0; sq < 128; sq ++) {
if (IN_BOARD(sq)) {
whiteRookControl[sq] = (byte) calcRookControl(pos, sq, whiteAttack);
blackRookControl[sq] = (byte) calcRookControl(pos, sq, blackAttack);
whiteBishopControl[sq] = (byte) calcBishopControl(pos, sq, whiteAttack);
blackBishopControl[sq] = (byte) calcBishopControl(pos, sq, blackAttack);
}
}
// 4. Calculate Piece Value Table for Each Squares and Each Piece-Types
for (int sq = 0; sq < 128; sq ++) {
if (!IN_BOARD(sq)) {
continue;
}
int edgePenalty = EDGE_PENALTY[sq];
if (inEndgame) {
if (vlWhite < vlBlack) {
// 4.1. In Endgames, the Losing King should be Close to Center and Distant to Bottom
pos.vlWhitePiecePos[PIECE_KING][sq] = (short) losingKingValue(sq);
// 4.2. In Endgames, the Winning King should be Close to the Losing King and Distant to Border
pos.vlBlackPiecePos[PIECE_KING][sq] = (short) winningKingValue(sq, sqWhiteKing);
} else {
// 4.1. ...
pos.vlBlackPiecePos[PIECE_KING][sq] = (short) losingKingValue(sq);
// 4.2. ...
pos.vlWhitePiecePos[PIECE_KING][sq] = (short) winningKingValue(sq, sqBlackKing);
}
// 4.3. In Endgames, Other Pieces are independent to their Positions
for (int i = PIECE_QUEEN; i <= PIECE_KNIGHT; i ++) {
pos.vlWhitePiecePos[i][sq] = pos.vlBlackPiecePos[i][sq] =
(short) (PIECE_VALUE[i] * 100);
}
} else {
// 4.4. King should be Close to Center in Midgames or Endgames
if (vlWhite + vlBlack <= 32) {
pos.vlWhitePiecePos[PIECE_KING][sq] =
pos.vlBlackPiecePos[PIECE_KING][sq] = (short) -edgePenalty;
} else {
pos.vlWhitePiecePos[PIECE_KING][sq] =
pos.vlBlackPiecePos[PIECE_KING][sq] = 0;
}
// 4.5. Queen, Rook, Bishop should Favor their Control Values
pos.vlWhitePiecePos[PIECE_QUEEN][sq] = (short)
(PIECE_VALUE[PIECE_QUEEN] * 100 + (whiteRookControl[sq] + whiteBishopControl[sq]) / 8);
pos.vlBlackPiecePos[PIECE_QUEEN][sq] = (short)
(PIECE_VALUE[PIECE_QUEEN] * 100 + (blackRookControl[sq] + blackBishopControl[sq]) / 8);
pos.vlWhitePiecePos[PIECE_ROOK][sq] = (short)
(PIECE_VALUE[PIECE_ROOK] * 100 + whiteRookControl[sq] / 2);
pos.vlBlackPiecePos[PIECE_ROOK][sq] = (short)
(PIECE_VALUE[PIECE_ROOK] * 100 + blackRookControl[sq] / 2);
pos.vlWhitePiecePos[PIECE_BISHOP][sq] = (short)
(PIECE_VALUE[PIECE_BISHOP] * 100 + whiteBishopControl[sq] / 2);
pos.vlBlackPiecePos[PIECE_BISHOP][sq] = (short)
(PIECE_VALUE[PIECE_BISHOP] * 100 + blackBishopControl[sq] / 2);
// 4.6. Knight should Favor its Attack Value
int whiteKnightAttack = 0, blackKnightAttack = 0;
for (int i = 0; i < 8; i ++) {
int sqDst = sq + Position.KNIGHT_DELTA[i];
if (IN_BOARD(sqDst)) {
whiteKnightAttack += whiteAttack[sqDst];
blackKnightAttack += blackAttack[sqDst];
}
}
pos.vlWhitePiecePos[PIECE_KNIGHT][sq] = (short)
(PIECE_VALUE[PIECE_KNIGHT] * 100 + whiteKnightAttack / 4 - edgePenalty * 3 / 2);
pos.vlBlackPiecePos[PIECE_KNIGHT][sq] = (short)
(PIECE_VALUE[PIECE_KNIGHT] * 100 + blackKnightAttack / 4 - edgePenalty * 3 / 2);
}
// 4.7. Pawn should Favor its Position Value
pos.vlWhitePiecePos[PIECE_PAWN][sq] = pos.vlBlackPiecePos[PIECE_PAWN][SQUARE_FLIP(sq)] =
(short) (PIECE_VALUE[PIECE_PAWN] * 100 + PAWN_VALUE[sq] / 2 - 6);
}
/* 5. Calculate Piece Value Table for Pawn Structure
*
* Self:
* x P x - P = brForward, x = brLeftCover/brRightCover
* ^ x P x - P = brSelf, x = brSide
* | x P x - P = brSelf(Last), x = brChain
*
* Opponent:
* . . .
* ^ . x . - x = brOppPass, or BehindOppPass if a Pawn in Front
* | o o o - o = ~brSelf/brSide(Last)
*/
for (int sd = 0; sd < 2; sd ++) {
int brSelf = 0, brSide = 0, brBehindOppPass = 0;
int brOppPass = FULL_BIT_RANK;
for (int i = 1; i <= 6; i ++) {
int y = (sd == 0 ? 7 - i : i);
int brOpp = (sd == 0 ? pos.brBlackPawn[y] : pos.brWhitePawn[y]);
brOppPass &= ~(brSelf | brSide);
brBehindOppPass |= (brOppPass & brOpp);
int brChain = brSide;
brSelf = (sd == 0 ? pos.brWhitePawn[y] : pos.brBlackPawn[y]);
brSide = ((brSelf >> 1) | (brSelf << 1)) & FULL_BIT_RANK;
int brForward = (sd == 0 ? pos.brWhitePawn[y + 1] : pos.brBlackPawn[y + 1]);
int brLeftCover = (brForward >> 1) & FULL_BIT_RANK;
int brRightCover = (brForward << 1) & FULL_BIT_RANK;
for (int x = Position.FILE_LEFT; x <= Position.FILE_RIGHT; x ++) {
int sq = Position.COORD_XY(x, y);
int brSquare = 1 << x;
// 5.1. Bonus for Parallel and Protected Pawns
int value = ((brSide & brSquare) != 0 ? 3 : 0) + ((brChain & brSquare) != 0 ? 2 : 0);
// 5.2. Bonus for the Pawn which can Protect Other Pawns
value += ((brLeftCover & brSquare) != 0 ? 2 : 0) + ((brRightCover & brSquare) != 0 ? 2 : 0);
// 5.3. Bonus for Self (Penalty for Moving)
value += ((brSelf & brSquare) != 0 ? 1 : 0);
if (sd == 0) {
pos.vlWhitePiecePos[PIECE_PAWN][sq] += value;
} else {
pos.vlBlackPiecePos[PIECE_PAWN][sq] += value;
}
if (vlWhite + vlBlack <= 32) {
// 5.4. Bonus for Passed Pawn
if ((brOppPass & brSquare) != 0) {
if (sd == 0) {
pos.vlBlackPiecePos[PIECE_PAWN][sq] += PASS_PAWN[i];
} else {
pos.vlWhitePiecePos[PIECE_PAWN][sq] += PASS_PAWN[i];
}
}
// 5.5. Bonus for Rook (Both Sides) Behind Pawn
if ((brBehindOppPass & brSquare) != 0) {
pos.vlWhitePiecePos[PIECE_ROOK][sq] += 8;
pos.vlBlackPiecePos[PIECE_ROOK][sq] += 8;
if (i == 6) {
int sqBottom = sq + Position.FORWARD_DELTA(sd);
pos.vlWhitePiecePos[PIECE_ROOK][sqBottom] += 8;
pos.vlBlackPiecePos[PIECE_ROOK][sqBottom] += 8;
}
}
}
}
}
}
// 6. Calculate Penalty for Blocking Center Pawns with a Bishop
for (int sq = 0x67; sq <= 0x68; sq ++) {
if (pos.squares[sq] == 8 + PIECE_PAWN) {
pos.vlWhitePiecePos[PIECE_BISHOP][sq - 16] -= 10;
}
}
for (int sq = 0x17; sq <= 0x18; sq ++) {
if (pos.squares[sq] == 16 + PIECE_PAWN) {
pos.vlBlackPiecePos[PIECE_BISHOP][sq + 16] -= 10;
}
}
// 7. Update "vlWhite" and "vlBlack" in "pos"
pos.vlWhite = pos.vlBlack = 0;
for (int sq = 0; sq < 128; sq ++) {
int pc = pos.squares[sq];
if (pc > 0) {
if (pc < 16) {
pos.vlWhite += pos.vlWhitePiecePos[pc - 8][sq];
} else {
pos.vlBlack += pos.vlBlackPiecePos[pc - 16][sq];
}
}
}
}
public static int evaluate(Position pos, int vlAlpha, int vlBeta) {
// 1. Material (with Position) Value
int vl = pos.material();
if (vl + LAZY_MARGIN <= vlAlpha) {
return vl + LAZY_MARGIN;
} else if (vl - LAZY_MARGIN >= vlBeta) {
return vl - LAZY_MARGIN;
}
// 2. Pawn Structure Value
for (int sd = 0; sd < 2; sd ++) {
int brSingle = 0, brDouble = 0;
int[] brs = (sd == 0 ? pos.brWhitePawn : pos.brBlackPawn);
for (int i = 1; i <= 6; i ++) {
brDouble |= brSingle & brs[i];
brSingle |= brs[i];
}
int brIsolated = brSingle & ~((brSingle << 1) | (brSingle >> 1));
int penalty = Util.POP_COUNT_16(brDouble) * DOUBLE_PENALTY +
Util.POP_COUNT_16(brIsolated) * ISOLATED_PENALTY +
Util.POP_COUNT_16(brIsolated & brDouble) * ISOLATED_PENALTY * 2;
vl += (pos.sdPlayer == sd ? -penalty : penalty);
}
return vl;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -