Skip to content
Permalink
Browse files

Merge pull request #8 from official-stockfish/master

Update to master
  • Loading branch information...
Chess13234 committed Jan 1, 2019
2 parents 06156b4 + eb6d7f5 commit 21e9d7f67501695feedf44c42a62075024359e38
Showing with 67 additions and 70 deletions.
  1. +2 −2 src/bitboard.cpp
  2. +4 −1 src/endgame.cpp
  3. +4 −3 src/evaluate.cpp
  4. +5 −6 src/movegen.cpp
  5. +3 −6 src/movepick.cpp
  6. +2 −2 src/movepick.h
  7. +1 −2 src/pawns.cpp
  8. +0 −2 src/pawns.h
  9. +5 −5 src/position.cpp
  10. +9 −9 src/psqt.cpp
  11. +31 −31 src/search.cpp
  12. +1 −1 tests/perft.sh
@@ -184,8 +184,8 @@ namespace {

// init_magics() computes all rook and bishop attacks at startup. Magic
// bitboards are used to look up attacks of sliding pieces. As a reference see
// chessprogramming.wikispaces.com/Magic+Bitboards. In particular, here we
// use the so called "fancy" approach.
// www.chessprogramming.org/Magic_Bitboards. In particular, here we use the so
// called "fancy" approach.

void init_magics(Bitboard table[], Magic magics[], Direction directions[]) {

@@ -131,7 +131,7 @@ Value Endgame<KBNK>::operator()(const Position& pos) const {
Square loserKSq = pos.square<KING>(weakSide);
Square bishopSq = pos.square<BISHOP>(strongSide);

// If our Bishop does not attack A1/H8, we flip the enemy king square
// If our Bishop does not attack A1/H8, we flip the enemy king square
// to drive to opposite corners (A8/H1).

Value result = VALUE_KNOWN_WIN
@@ -724,6 +724,9 @@ ScaleFactor Endgame<KNPK>::operator()(const Position& pos) const {
template<>
ScaleFactor Endgame<KNPKB>::operator()(const Position& pos) const {

assert(verify_material(pos, strongSide, KnightValueMg, 1));
assert(verify_material(pos, weakSide, BishopValueMg, 0));

Square pawnSq = pos.square<PAWN>(strongSide);
Square bishopSq = pos.square<BISHOP>(weakSide);
Square weakKingSq = pos.square<KING>(weakSide);
@@ -213,7 +213,7 @@ namespace {
// kingRing[color] are the squares adjacent to the king, plus (only for a
// king on its first rank) the squares two ranks in front. For instance,
// if black's king is on g8, kingRing[BLACK] is f8, h8, f7, g7, h7, f6, g6
// and h6. It is set to 0 when king safety evaluation is skipped.
// and h6.
Bitboard kingRing[COLOR_NB];

// kingAttackersCount[color] is the number of pieces of the given color
@@ -505,7 +505,7 @@ namespace {
Score score = SCORE_ZERO;

// Non-pawn enemies
nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(Them, PAWN);
nonPawnEnemies = pos.pieces(Them) & ~pos.pieces(PAWN);

// Squares strongly protected by the enemy, either because they defend the
// square with a pawn, or because they defend the square twice and we don't.
@@ -717,7 +717,8 @@ namespace {
behind |= (Us == WHITE ? behind >> 16 : behind << 16);

int bonus = popcount(safe) + popcount(behind & safe);
int weight = pos.count<ALL_PIECES>(Us) - 2 * pe->open_files();
int weight = pos.count<ALL_PIECES>(Us)
- 2 * popcount(pe->semiopenFiles[WHITE] & pe->semiopenFiles[BLACK]);

Score score = make_score(bonus * weight * weight / 16, 0);

@@ -28,6 +28,7 @@ namespace {
template<Color Us, CastlingSide Cs, bool Checks, bool Chess960>
ExtMove* generate_castling(const Position& pos, ExtMove* moveList) {

constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr CastlingRight Cr = Us | Cs;
constexpr bool KingSide = (Cs == KING_SIDE);

@@ -39,7 +40,7 @@ namespace {
Square kfrom = pos.square<KING>(Us);
Square rfrom = pos.castling_rook_square(Cr);
Square kto = relative_square(Us, KingSide ? SQ_G1 : SQ_C1);
Bitboard enemies = pos.pieces(~Us);
Bitboard enemies = pos.pieces(Them);

assert(!pos.checkers());

@@ -53,7 +54,7 @@ namespace {
// Because we generate only legal castling moves we need to verify that
// when moving the castling rook we do not discover some hidden checker.
// For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(~Us, ROOK, QUEEN)))
if (Chess960 && (attacks_bb<ROOK>(kto, pos.pieces() ^ rfrom) & pos.pieces(Them, ROOK, QUEEN)))
return moveList;

Move m = make<CASTLING>(kfrom, rfrom);
@@ -93,10 +94,8 @@ namespace {
template<Color Us, GenType Type>
ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) {

// Compute our parametrized parameters at compile time, named according to
// the point of view of white side.
// Compute some compile time parameters relative to the white side
constexpr Color Them = (Us == WHITE ? BLACK : WHITE);
constexpr Bitboard TRank8BB = (Us == WHITE ? Rank8BB : Rank1BB);
constexpr Bitboard TRank7BB = (Us == WHITE ? Rank7BB : Rank2BB);
constexpr Bitboard TRank3BB = (Us == WHITE ? Rank3BB : Rank6BB);
constexpr Direction Up = (Us == WHITE ? NORTH : SOUTH);
@@ -161,7 +160,7 @@ namespace {
}

// Promotions and underpromotions
if (pawnsOn7 && (Type != EVASIONS || (target & TRank8BB)))
if (pawnsOn7)
{
if (Type == CAPTURES)
emptySquares = ~pos.pieces();
@@ -31,9 +31,6 @@ namespace {
QSEARCH_TT, QCAPTURE_INIT, QCAPTURE, QCHECK_INIT, QCHECK
};

// Helper filter used with select()
const auto Any = [](){ return true; };

// partial_insertion_sort() sorts moves in descending order up to and including
// a given limit. The order of moves smaller than the limit is left unspecified.
void partial_insertion_sort(ExtMove* begin, ExtMove* end, int limit) {
@@ -225,7 +222,7 @@ Move MovePicker::next_move(bool skipQuiets) {
/* fallthrough */

case BAD_CAPTURE:
return select<Next>(Any);
return select<Next>([](){ return true; });

case EVASION_INIT:
cur = moves;
@@ -236,7 +233,7 @@ Move MovePicker::next_move(bool skipQuiets) {
/* fallthrough */

case EVASION:
return select<Best>(Any);
return select<Best>([](){ return true; });

case PROBCUT:
return select<Best>([&](){ return pos.see_ge(move, threshold); });
@@ -261,7 +258,7 @@ Move MovePicker::next_move(bool skipQuiets) {
/* fallthrough */

case QCHECK:
return select<Next>(Any);
return select<Next>([](){ return true; });
}

assert(false);
@@ -85,11 +85,11 @@ enum StatsParams { NOT_USED = 0 };
/// ButterflyHistory records how often quiet moves have been successful or
/// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by
/// the move's from and to squares, see chessprogramming.wikispaces.com/Butterfly+Boards
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) * int(SQUARE_NB)> ButterflyHistory;

/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see chessprogramming.wikispaces.com/Countermove+Heuristic
/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;

/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
@@ -115,7 +115,7 @@ namespace {
// not attacked more times than defended.
if ( !(stoppers ^ lever ^ leverPush)
&& popcount(support) >= popcount(lever) - 1
&& popcount(phalanx) >= popcount(leverPush))
&& popcount(phalanx) >= popcount(leverPush))
e->passedPawns[Us] |= s;

else if ( stoppers == SquareBB[s + Up]
@@ -185,7 +185,6 @@ Entry* probe(const Position& pos) {
e->key = key;
e->scores[WHITE] = evaluate<WHITE>(pos, e);
e->scores[BLACK] = evaluate<BLACK>(pos, e);
e->openFiles = popcount(e->semiopenFiles[WHITE] & e->semiopenFiles[BLACK]);
e->asymmetry = popcount( (e->passedPawns[WHITE] | e->passedPawns[BLACK])
| (e->semiopenFiles[WHITE] ^ e->semiopenFiles[BLACK]));

@@ -39,7 +39,6 @@ struct Entry {
Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
int weak_unopposed(Color c) const { return weakUnopposed[c]; }
int pawn_asymmetry() const { return asymmetry; }
int open_files() const { return openFiles; }

int semiopen_file(Color c, File f) const {
return semiopenFiles[c] & (1 << f);
@@ -73,7 +72,6 @@ struct Entry {
int semiopenFiles[COLOR_NB];
int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
int asymmetry;
int openFiles;
};

typedef HashTable<Entry, 16384> Table;
@@ -183,7 +183,7 @@ void Position::init() {
{
std::swap(cuckoo[i], key);
std::swap(cuckooMove[i], move);
if (move == 0) // Arrived at empty slot ?
if (move == MOVE_NONE) // Arrived at empty slot?
break;
i = (i == H1(key)) ? H2(key) : H1(key); // Push victim to alternative slot
}
@@ -465,16 +465,16 @@ const string Position::fen() const {
ss << (sideToMove == WHITE ? " w " : " b ");

if (can_castle(WHITE_OO))
ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | KING_SIDE))) : 'K');
ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OO ))) : 'K');

if (can_castle(WHITE_OOO))
ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE | QUEEN_SIDE))) : 'Q');
ss << (chess960 ? char('A' + file_of(castling_rook_square(WHITE_OOO))) : 'Q');

if (can_castle(BLACK_OO))
ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | KING_SIDE))) : 'k');
ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OO ))) : 'k');

if (can_castle(BLACK_OOO))
ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK | QUEEN_SIDE))) : 'q');
ss << (chess960 ? char('a' + file_of(castling_rook_square(BLACK_OOO))) : 'q');

if (!can_castle(ANY_CASTLING))
ss << '-';
@@ -90,15 +90,15 @@ constexpr Score Bonus[][RANK_NB][int(FILE_NB) / 2] = {
}
};

constexpr Score PBonus[RANK_NB][FILE_NB] =
{ // Pawn
{ S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0), S( 0, 0) },
{ S( 0,-11), S( -3, -4), S( 13, -1), S( 19, -4), S( 16, 17), S( 13, 7), S( 4, 4), S( -4,-13) },
{ S(-16, -8), S(-12, -6), S( 20, -3), S( 21, 0), S( 25,-11), S( 29, 3), S( 0, 0), S(-27, -1) },
{ S(-11, 3), S(-17, 6), S( 11,-10), S( 21, 1), S( 32, -6), S( 19,-11), S( -5, 0), S(-14, -2) },
{ S( 4, 13), S( 6, 7), S( -8, 3), S( 3, -5), S( 8,-15), S( -2, -1), S(-19, 9), S( -5, 13) },
{ S( -5, 25), S(-19, 20), S( 7, 16), S( 8, 12), S( -7, 21), S( -2, 3), S(-10, -4), S(-16, 15) },
{ S(-10, 6), S( 9, -5), S( -7, 16), S(-12, 27), S( -7, 15), S( -8, 11), S( 16, -7), S( -8, 4) }
constexpr Score PBonus[RANK_NB][FILE_NB] =
{ // Pawn (asymmetric distribution)
{ },
{ S( 0,-11), S( -3,-4), S(13, -1), S( 19, -4), S(16, 17), S(13, 7), S( 4, 4), S( -4,-13) },
{ S(-16, -8), S(-12,-6), S(20, -3), S( 21, 0), S(25,-11), S(29, 3), S( 0, 0), S(-27, -1) },
{ S(-11, 3), S(-17, 6), S(11,-10), S( 21, 1), S(32, -6), S(19,-11), S( -5, 0), S(-14, -2) },
{ S( 4, 13), S( 6, 7), S(-8, 3), S( 3, -5), S( 8,-15), S(-2, -1), S(-19, 9), S( -5, 13) },
{ S( -5, 25), S(-19,20), S( 7, 16), S( 8, 12), S(-7, 21), S(-2, 3), S(-10, -4), S(-16, 15) },
{ S(-10, 6), S( 9,-5), S(-7, 16), S(-12, 27), S(-7, 15), S(-8, 11), S( 16, -7), S( -8, 4) }
};

#undef S
@@ -113,8 +113,8 @@ namespace {
Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietCount, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCount, int bonus);

inline bool gives_check(const Position& pos, Move move) {
Color us = pos.side_to_move();
@@ -498,32 +498,32 @@ void Thread::search() {
if ( Limits.use_time_management()
&& !Threads.stop
&& !Threads.stopOnPonderhit)
{
double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
fallingEval = std::max(0.5, std::min(1.5, fallingEval));

// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = 1.0;
for (int i : {3, 4, 5})
if (lastBestMoveDepth * i < completedDepth)
timeReduction *= 1.25;

// Use part of the gained time from a previous stable move for the current move
double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;

// Stop the search if we have only one legal move, or if available time elapsed
if ( rootMoves.size() == 1
|| Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
{
double fallingEval = (306 + 119 * failedLow + 6 * (mainThread->previousScore - bestValue)) / 581.0;
fallingEval = std::max(0.5, std::min(1.5, fallingEval));

// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = 1.0;
for (int i : {3, 4, 5})
if (lastBestMoveDepth * i < completedDepth)
timeReduction *= 1.25;

// Use part of the gained time from a previous stable move for the current move
double bestMoveInstability = 1.0 + mainThread->bestMoveChanges;
bestMoveInstability *= std::pow(mainThread->previousTimeReduction, 0.528) / timeReduction;

// Stop the search if we have only one legal move, or if available time elapsed
if ( rootMoves.size() == 1
|| Time.elapsed() > Time.optimum() * bestMoveInstability * fallingEval)
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
if (Threads.ponder)
Threads.stopOnPonderhit = true;
else
Threads.stop = true;
}
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
if (Threads.ponder)
Threads.stopOnPonderhit = true;
else
Threads.stop = true;
}
}
}

if (!mainThread)
@@ -1481,7 +1481,7 @@ namespace {
// update_capture_stats() updates move sorting heuristics when a new capture best move is found

void update_capture_stats(const Position& pos, Move move,
Move* captures, int captureCnt, int bonus) {
Move* captures, int captureCount, int bonus) {

CapturePieceToHistory& captureHistory = pos.this_thread()->captureHistory;
Piece moved_piece = pos.moved_piece(move);
@@ -1491,7 +1491,7 @@ namespace {
captureHistory[moved_piece][to_sq(move)][captured] << bonus;

// Decrease all the other played capture moves
for (int i = 0; i < captureCnt; ++i)
for (int i = 0; i < captureCount; ++i)
{
moved_piece = pos.moved_piece(captures[i]);
captured = type_of(pos.piece_on(to_sq(captures[i])));
@@ -1503,7 +1503,7 @@ namespace {
// update_quiet_stats() updates move sorting heuristics when a new quiet best move is found

void update_quiet_stats(const Position& pos, Stack* ss, Move move,
Move* quiets, int quietsCnt, int bonus) {
Move* quiets, int quietCount, int bonus) {

if (ss->killers[0] != move)
{
@@ -1523,7 +1523,7 @@ namespace {
}

// Decrease all the other played quiet moves
for (int i = 0; i < quietsCnt; ++i)
for (int i = 0; i < quietCount; ++i)
{
thisThread->mainHistory[us][from_to(quiets[i])] << -bonus;
update_continuation_histories(ss, pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
@@ -1666,7 +1666,7 @@ bool RootMove::extract_ponder_from_tt(Position& pos) {

assert(pv.size() == 1);

if (!pv[0])
if (pv[0] == MOVE_NONE)
return false;

pos.do_move(pv[0], st);
@@ -1,5 +1,5 @@
#!/bin/bash
# verify perft numbers (positions from https://chessprogramming.wikispaces.com/Perft+Results)
# verify perft numbers (positions from www.chessprogramming.org/Perft_Results)

error()
{

0 comments on commit 21e9d7f

Please sign in to comment.
You can’t perform that action at this time.