using Eval::evaluate;
using namespace Search;
+// For some reason argument-dependent lookup (ADL) doesn't work for Android's
+// STLPort, so explicitly qualify following functions.
+using std::count;
+using std::find;
+
namespace {
// Set to true to force running with one thread. Used for debugging
const Depth RazorDepth = 4 * ONE_PLY;
// Dynamic razoring margin based on depth
- inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * int(d)); }
+ inline Value razor_margin(Depth d) { return Value(512 + 16 * int(d)); }
// Maximum depth for use of dynamic threat detection when null move fails low
const Depth ThreatDepth = 5 * ONE_PLY;
// At Non-PV nodes we do an internal iterative deepening search
// when the static evaluation is bigger then beta - IIDMargin.
- const Value IIDMargin = Value(0x100);
+ const Value IIDMargin = Value(256);
// Minimum depth for use of singular extension
const Depth SingularExtensionDepth[] = { 8 * ONE_PLY, 6 * ONE_PLY };
// Futility margin for quiescence search
- const Value FutilityMarginQS = Value(0x80);
+ const Value FutilityMarginQS = Value(128);
// Futility lookup tables (initialized at startup) and their access functions
Value FutilityMargins[16][64]; // [depth][moveNumber]
// 'dangerous' moves so that we avoid to prune it.
FORCE_INLINE bool is_dangerous(const Position& pos, Move m, bool captureOrPromotion) {
- // Test for a pawn pushed to 7th or a passed pawn move
- if (type_of(pos.piece_moved(m)) == PAWN)
- {
- Color c = pos.side_to_move();
- if ( relative_rank(c, to_sq(m)) == RANK_7
- || pos.pawn_is_passed(c, to_sq(m)))
- return true;
- }
+ // Test for a passed pawn move
+ if ( type_of(pos.piece_moved(m)) == PAWN
+ && pos.pawn_is_passed(pos.side_to_move(), to_sq(m)))
+ return true;
// Test for a capture that triggers a pawn endgame
if ( captureOrPromotion
&& type_of(pos.piece_on(to_sq(m))) != PAWN
- && !is_special(m)
+ && type_of(m) == NORMAL
&& ( pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK)
- PieceValueMidgame[pos.piece_on(to_sq(m))] == VALUE_ZERO))
return true;
StateInfo st;
int64_t cnt = 0;
- MoveList<MV_LEGAL> ml(pos);
+ MoveList<LEGAL> ml(pos);
// At the last ply just return the number of moves (leaf nodes)
if (depth == ONE_PLY)
&& (ss-1)->eval != VALUE_NONE
&& ss->eval != VALUE_NONE
&& !pos.captured_piece_type()
- && !is_special(move))
+ && type_of(move) == NORMAL)
{
Square to = to_sq(move);
H.update_gain(pos.piece_on(to), to, -(ss-1)->eval - ss->eval);
ss->currentMove = MOVE_NULL;
// Null move dynamic reduction based on depth
- int R = 3 + (depth >= 5 * ONE_PLY ? depth / 8 : 0);
+ Depth R = 3 * ONE_PLY + depth / 4;
// Null move dynamic reduction based on value
if (refinedValue - PawnValueMidgame > beta)
- R++;
+ R += ONE_PLY;
pos.do_null_move<true>(st);
(ss+1)->skipNullMove = true;
- nullValue = depth-R*ONE_PLY < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
- : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R*ONE_PLY);
+ nullValue = depth-R < ONE_PLY ? -qsearch<NonPV>(pos, ss+1, -beta, -alpha, DEPTH_ZERO)
+ : - search<NonPV>(pos, ss+1, -beta, -alpha, depth-R);
(ss+1)->skipNullMove = false;
pos.do_null_move<false>(st);
// Do verification search at high depths
ss->skipNullMove = true;
- Value v = search<NonPV>(pos, ss, alpha, beta, depth-R*ONE_PLY);
+ Value v = search<NonPV>(pos, ss, alpha, beta, depth-R);
ss->skipNullMove = false;
if (v >= beta)
&& !inCheck
&& !dangerous
&& move != ttMove
- && !is_castle(move)
+ && type_of(move) != CASTLE
&& (bestValue > VALUE_MATED_IN_MAX_PLY || bestValue == -VALUE_INFINITE))
{
// Move count based pruning
&& !isPvMove
&& !captureOrPromotion
&& !dangerous
- && !is_castle(move)
+ && type_of(move) != CASTLE
&& ss->killers[0] != move
&& ss->killers[1] != move)
{
// Step 19. Check for split
if ( !SpNode
&& depth >= Threads.min_split_depth()
- && depth - reduction<PvNode>(depth, moveCount) >= Threads.min_split_depth()
&& bestValue < beta
&& Threads.available_slave_exists(thisThread)
&& !Signals.stop
&& !givesCheck
&& move != ttMove
&& enoughMaterial
- && !is_promotion(move)
+ && type_of(move) != PROMOTION
&& !pos.is_passed_pawn_push(move))
{
futilityValue = futilityBase
+ PieceValueEndgame[pos.piece_on(to_sq(move))]
- + (is_enpassant(move) ? PawnValueEndgame : VALUE_ZERO);
+ + (type_of(move) == ENPASSANT ? PawnValueEndgame : VALUE_ZERO);
if (futilityValue < beta)
{
if ( !PvNode
&& (!inCheck || evasionPrunable)
&& move != ttMove
- && !is_promotion(move)
+ && type_of(move) != PROMOTION
&& pos.see_sign(move) < 0)
continue;
while (b)
{
// Note that here we generate illegal "double move"!
- if (futilityBase + PieceValueEndgame[pos.piece_on(pop_1st_bit(&b))] >= beta)
+ if (futilityBase + PieceValueEndgame[pos.piece_on(pop_lsb(&b))] >= beta)
return true;
}