/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2012 Marco Costalba, Joona Kiiski, Tord Romstad
+ Copyright (C) 2008-2013 Marco Costalba, Joona Kiiski, Tord Romstad
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Pawns::Entry* pi;
// attackedBy[color][piece type] is a bitboard representing all squares
- // attacked by a given color and piece type, attackedBy[color][0] contains
- // all squares attacked by the given color.
+ // attacked by a given color and piece type, attackedBy[color][ALL_PIECES]
+ // contains all squares attacked by the given color.
Bitboard attackedBy[COLOR_NB][PIECE_TYPE_NB];
// kingRing[color] is the zone around the king which is considered
const int GrainSize = 8;
// Evaluation weights, initialized from UCI options
- enum { Mobility, PassedPawns, Space };
- Score Weights[3];
+ enum { Mobility, PassedPawns, Space, KingDangerUs, KingDangerThem };
+ Score Weights[6];
typedef Value V;
#define S(mg, eg) make_score(mg, eg)
//
// Values modified by Joona Kiiski
const Score WeightsInternal[] = {
- S(252, 344), S(216, 266), S(46, 0)
+ S(289, 344), S(221, 273), S(46, 0), S(271, 0), S(307, 0)
};
// MobilityBonus[PieceType][attacked] contains mobility bonuses for middle and
#undef S
- Score BishopPinBonus = make_score(66, 11);
+ const Score BishopPinBonus = make_score(66, 11);
// Bonus for having the side to move (modified by Joona Kiiski)
const Score Tempo = make_score(24, 11);
// the strength of the enemy attack are added up into an integer, which
// is used as an index to KingDangerTable[].
//
- // King safety evaluation is asymmetrical and different for us (root color)
- // and for our opponent. These values are used to init KingDangerTable.
- const int KingDangerWeights[] = { 259, 247 };
-
// KingAttackWeights[PieceType] contains king attack weights by piece type
const int KingAttackWeights[] = { 0, 0, 2, 2, 3, 5 };
void init() {
- Weights[Mobility] = weight_option("Mobility (Middle Game)", "Mobility (Endgame)", WeightsInternal[Mobility]);
- Weights[PassedPawns] = weight_option("Passed Pawns (Middle Game)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
- Weights[Space] = weight_option("Space", "Space", WeightsInternal[Space]);
-
- int KingDanger[] = { KingDangerWeights[0], KingDangerWeights[1] };
-
- // If running in analysis mode, make sure we use symmetrical king safety.
- // We do so by replacing both KingDanger weights by their average.
- if (Options["UCI_AnalyseMode"])
- KingDanger[0] = KingDanger[1] = (KingDanger[0] + KingDanger[1]) / 2;
+ Weights[Mobility] = weight_option("Mobility (Middle Game)", "Mobility (Endgame)", WeightsInternal[Mobility]);
+ Weights[PassedPawns] = weight_option("Passed Pawns (Middle Game)", "Passed Pawns (Endgame)", WeightsInternal[PassedPawns]);
+ Weights[Space] = weight_option("Space", "Space", WeightsInternal[Space]);
+ Weights[KingDangerUs] = weight_option("Cowardice", "Cowardice", WeightsInternal[KingDangerUs]);
+ Weights[KingDangerThem] = weight_option("Aggressiveness", "Aggressiveness", WeightsInternal[KingDangerThem]);
const int MaxSlope = 30;
const int Peak = 1280;
{
t = std::min(Peak, std::min(int(0.4 * i * i), t + MaxSlope));
- KingDangerTable[0][i] = apply_weight(make_score(t, 0), make_score(KingDanger[0], 0));
- KingDangerTable[1][i] = apply_weight(make_score(t, 0), make_score(KingDanger[1], 0));
+ KingDangerTable[1][i] = apply_weight(make_score(t, 0), Weights[KingDangerUs]);
+ KingDangerTable[0][i] = apply_weight(make_score(t, 0), Weights[KingDangerThem]);
}
-
- BishopPinBonus = make_score(Options["pin_open"], Options["pin_end"]);
}
// Init king safety tables only if we are going to use them
if ( pos.piece_count(Us, QUEEN)
- && pos.non_pawn_material(Us) >= QueenValueMg + RookValueMg)
+ && pos.non_pawn_material(Us) > QueenValueMg + PawnValueMg)
{
ei.kingRing[Them] = (b | (Us == WHITE ? b >> 8 : b << 8));
b &= ei.attackedBy[Us][PAWN];
// of threat evaluation must be done later when we have full attack info.
if (ei.attackedBy[Them][PAWN] & s)
score -= ThreatenedByPawnPenalty[Piece];
- else if (Piece == BISHOP && (PseudoAttacks[Piece][pos.king_square(Them)] & s)) {
- const Bitboard between = BetweenBB[s][pos.king_square(Them)] & pos.pieces();
- if (!more_than_one(between))
+
+ // Otherwise give a bonus if we are a bishop and can pin a piece or
+ // can give a discovered check through an x-ray attack.
+ else if ( Piece == BISHOP
+ && (PseudoAttacks[Piece][pos.king_square(Them)] & s)
+ && !more_than_one(BetweenBB[s][pos.king_square(Them)] & pos.pieces()))
score += BishopPinBonus;
- }
+
+ // Penalty for bishop with same coloured pawns
+ if (Piece == BISHOP)
+ score -= make_score(8, 12) * ei.pi->same_colored_pawn_count(s, Us);
// Bishop and knight outposts squares
if ( (Piece == BISHOP || Piece == KNIGHT)
// Undefended minors get penalized even if not under attack
undefendedMinors = pos.pieces(Them)
& (pos.pieces(BISHOP) | pos.pieces(KNIGHT))
- & ~ei.attackedBy[Them][0];
+ & ~ei.attackedBy[Them][ALL_PIECES];
if (undefendedMinors)
score += UndefendedMinorPenalty;
// Enemy pieces not defended by a pawn and under our attack
weakEnemies = pos.pieces(Them)
& ~ei.attackedBy[Them][PAWN]
- & ei.attackedBy[Us][0];
+ & ei.attackedBy[Us][ALL_PIECES];
if (!weakEnemies)
return score;
score += evaluate_pieces<QUEEN, Us, Trace>(pos, ei, mobility, mobilityArea);
// Sum up all attacked squares
- ei.attackedBy[Us][0] = ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
- | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
- | ei.attackedBy[Us][QUEEN] | ei.attackedBy[Us][KING];
+ ei.attackedBy[Us][ALL_PIECES] = ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
+ | ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
+ | ei.attackedBy[Us][QUEEN] | ei.attackedBy[Us][KING];
return score;
}
{
// Find the attacked squares around the king which has no defenders
// apart from the king itself
- undefended = ei.attackedBy[Them][0] & ei.attackedBy[Us][KING];
+ undefended = ei.attackedBy[Them][ALL_PIECES] & ei.attackedBy[Us][KING];
undefended &= ~( ei.attackedBy[Us][PAWN] | ei.attackedBy[Us][KNIGHT]
| ei.attackedBy[Us][BISHOP] | ei.attackedBy[Us][ROOK]
| ei.attackedBy[Us][QUEEN]);
}
// Analyse enemy's safe distance checks for sliders and knights
- safe = ~(pos.pieces(Them) | ei.attackedBy[Us][0]);
+ safe = ~(pos.pieces(Them) | ei.attackedBy[Us][ALL_PIECES]);
b1 = pos.attacks_from<ROOK>(ksq) & safe;
b2 = pos.attacks_from<BISHOP>(ksq) & safe;
if (pos.is_empty(blockSq))
{
squaresToQueen = forward_bb(Us, s);
- defendedSquares = squaresToQueen & ei.attackedBy[Us][0];
+ defendedSquares = squaresToQueen & ei.attackedBy[Us][ALL_PIECES];
// If there is an enemy rook or queen attacking the pawn from behind,
// add all X-ray attacks by the rook or queen. Otherwise consider only
&& (forward_bb(Them, s) & pos.pieces(Them, ROOK, QUEEN) & pos.attacks_from<ROOK>(s)))
unsafeSquares = squaresToQueen;
else
- unsafeSquares = squaresToQueen & (ei.attackedBy[Them][0] | pos.pieces(Them));
+ unsafeSquares = squaresToQueen & (ei.attackedBy[Them][ALL_PIECES] | pos.pieces(Them));
// If there aren't enemy attacks or pieces along the path to queen give
// huge bonus. Even bigger if we protect the pawn's path.
// Compute plies to queening and check direct advancement
movesToGo = rank_distance(s, queeningSquare) - int(relative_rank(c, s) == RANK_2);
oppMovesToGo = square_distance(pos.king_square(~c), queeningSquare) - int(c != pos.side_to_move());
- pathDefended = ((ei.attackedBy[c][0] & queeningPath) == queeningPath);
+ pathDefended = ((ei.attackedBy[c][ALL_PIECES] & queeningPath) == queeningPath);
if (movesToGo >= oppMovesToGo && !pathDefended)
continue;
Bitboard safe = SpaceMask[Us]
& ~pos.pieces(Us, PAWN)
& ~ei.attackedBy[Them][PAWN]
- & (ei.attackedBy[Us][0] | ~ei.attackedBy[Them][0]);
+ & (ei.attackedBy[Us][ALL_PIECES] | ~ei.attackedBy[Them][ALL_PIECES]);
// Find all squares which are at most three squares behind some friendly pawn
Bitboard behind = pos.pieces(Us, PAWN);