Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update buckets branch #490

Merged
merged 5 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/makemove.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,6 @@ void MakeMove(const Move move, Position* pos) {
HashKey(pos->posKey, SideKey);
// Update pinmasks and checkers
UpdatePinsAndCheckers(pos, pos->side);
// If we are in check get the squares between the checking piece and the king
if (pos->getCheckers()) {
const int kingSquare = KingSQ(pos, pos->side);
const int pieceLocation = GetLsbIndex(pos->getCheckers());
pos->state.checkMask = (1ULL << pieceLocation) | RayBetween(pieceLocation, kingSquare);
}
else
pos->state.checkMask = fullCheckmask;

// Figure out if we need to refresh the accumulator
if constexpr (UPDATE) {
Expand Down
16 changes: 7 additions & 9 deletions src/movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ static inline void PseudoLegalPawnMoves(Position* pos, int color, MoveList* list
if (genQuiet) {
Bitboard push = NORTH(ourPawns, color) & freeSquares & ~0xFF000000000000FFULL;
Bitboard doublePush = NORTH(push, color) & freeSquares & rank4BB;
push &= pos->getCheckmask();
doublePush &= pos->getCheckmask();
while (push) {
const int to = popLsb(push);
AddMove(encode_move(to - north, to, pawnType, Movetype::Quiet), list);
Expand All @@ -88,7 +86,7 @@ static inline void PseudoLegalPawnMoves(Position* pos, int color, MoveList* list

if (genNoisy) {
// Push promotions
Bitboard pushPromo = NORTH(ourPawns, color) & freeSquares & 0xFF000000000000FFULL & pos->getCheckmask();
Bitboard pushPromo = NORTH(ourPawns, color) & freeSquares & 0xFF000000000000FFULL;
while (pushPromo) {
const int to = popLsb(pushPromo);
AddMove(encode_move(to - north, to, pawnType, Movetype::queenPromo | Movetype::Quiet), list);
Expand All @@ -98,8 +96,8 @@ static inline void PseudoLegalPawnMoves(Position* pos, int color, MoveList* list
}

// Captures and capture-promotions
Bitboard captBB1 = (NORTH(ourPawns, color) >> 1) & ~0x8080808080808080ULL & enemy & pos->getCheckmask();
Bitboard captBB2 = (NORTH(ourPawns, color) << 1) & ~0x101010101010101ULL & enemy & pos->getCheckmask();
Bitboard captBB1 = (NORTH(ourPawns, color) >> 1) & ~0x8080808080808080ULL & enemy;
Bitboard captBB2 = (NORTH(ourPawns, color) << 1) & ~0x101010101010101ULL & enemy;
while (captBB1) {
const int to = popLsb(captBB1);
const int from = to - north + 1;
Expand Down Expand Up @@ -156,7 +154,7 @@ static inline void PseudoLegalKnightMoves(Position* pos, int color, MoveList* li

while (knights) {
const int from = popLsb(knights);
Bitboard possible_moves = knight_attacks[from] & moveMask & pos->getCheckmask();
Bitboard possible_moves = knight_attacks[from] & moveMask;
while (possible_moves) {
const int to = popLsb(possible_moves);
const Movetype movetype = pos->PieceOn(to) != EMPTY ? Movetype::Capture : Movetype::Quiet;
Expand Down Expand Up @@ -185,7 +183,7 @@ static inline void PseudoLegalSlidersMoves(Position *pos, int color, MoveList *l
while (pieces) {
const int from = popLsb(pieces);
Bitboard possible_moves =
pieceAttacks(piecetype, from, boardOccupancy) & moveMask & pos->getCheckmask();
pieceAttacks(piecetype, from, boardOccupancy) & moveMask;
while (possible_moves) {
const int to = popLsb(possible_moves);
const Movetype movetype = pos->PieceOn(to) != EMPTY ? Movetype::Capture : Movetype::Quiet;
Expand Down Expand Up @@ -297,7 +295,7 @@ bool IsPseudoLegal(Position* pos, Move move) {
if (isCastle(move) && pieceType != KING)
return false;

if ((CountBits(pos->getCheckers()) >= 2) && pieceType != KING)
if (pieceType != KING && CountBits(pos->getCheckers()) >= 2)
return false;

const int NORTH = pos->side == WHITE ? -8 : 8;
Expand Down Expand Up @@ -460,7 +458,7 @@ bool IsLegal(Position* pos, Move move) {
return !pos->getCheckers() && (((1ULL << to) & RayBetween(ksq, from)) || ((1ULL << from) & RayBetween(ksq, to)));
}
else if (pos->getCheckers()) {
return (1ULL << to) & pos->getCheckmask();
return (1ULL << to) & (pos->getCheckers() | RayBetween(GetLsbIndex(pos->getCheckers()), ksq));
}
else
return true;
Expand Down
23 changes: 17 additions & 6 deletions src/movepicker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void partialInsertionSort(MoveList* moveList, const int moveNum) {
std::swap(moveList->moves[moveNum], moveList->moves[bestNum]);
}

void InitMP(Movepicker* mp, Position* pos, SearchData* sd, SearchStack* ss, const Move ttMove, const MovepickerType movepickerType, const bool rootNode) {
void InitMP(Movepicker* mp, Position* pos, SearchData* sd, SearchStack* ss, const Move ttMove, const int SEEThreshold, const MovepickerType movepickerType, const bool rootNode) {

const Move killer = ss->searchKiller;
const Move counter = sd->counterMoves[FromTo((ss - 1)->move)];
Expand All @@ -56,6 +56,7 @@ void InitMP(Movepicker* mp, Position* pos, SearchData* sd, SearchStack* ss, cons
mp->stage = mp->ttMove ? PICK_TT : GEN_NOISY;
mp->killer = killer != ttMove ? killer : NOMOVE;
mp->counter = counter != ttMove && counter != killer ? counter : NOMOVE;
mp->SEEThreshold = SEEThreshold;
}

Move NextMove(Movepicker* mp, const bool skip) {
Expand All @@ -73,18 +74,29 @@ Move NextMove(Movepicker* mp, const bool skip) {
&& mp->stage > PICK_GOOD_NOISY) {
return NOMOVE;
}

// In probcut, we only search captures that pass the threshold
if ( mp->movepickerType == PROBCUT
&& mp->stage > PICK_GOOD_NOISY) {
return NOMOVE;
}
}
switch (mp->stage) {
case PICK_TT:
++mp->stage;
// If we are in qsearch and not in check, skip quiet TT moves
if (mp->movepickerType == QSEARCH && skip && !isTactical(mp->ttMove))
goto top;
// If we are in qsearch and not in check, or we are in probcut, skip quiet TT moves
if ((mp->movepickerType == PROBCUT || (mp->movepickerType == QSEARCH && skip))
&& !isTactical(mp->ttMove))
goto top;

// If the TT move if not pseudo legal we skip it too
if (!IsPseudoLegal(mp->pos, mp->ttMove))
goto top;

// If we are in probcut and the TT move does not pass SEE, we skip it
if (mp->movepickerType == PROBCUT && !SEE(mp->pos, mp->ttMove, -1))
goto top;

return mp->ttMove;

case GEN_NOISY:
Expand All @@ -98,7 +110,7 @@ Move NextMove(Movepicker* mp, const bool skip) {
partialInsertionSort(&mp->moveList, mp->idx);
const Move move = mp->moveList.moves[mp->idx].move;
const int score = mp->moveList.moves[mp->idx].score;
const int SEEThreshold = -score / 32 + 236;
const int SEEThreshold = mp->movepickerType == PROBCUT ? mp->SEEThreshold : -score / 32 + 236;
++mp->idx;
if (move == mp->ttMove)
continue;
Expand Down Expand Up @@ -157,7 +169,6 @@ Move NextMove(Movepicker* mp, const bool skip) {

case PICK_BAD_NOISY:
while (mp->idx < mp->badCaptureList.count) {
partialInsertionSort(&mp->badCaptureList, mp->idx);
const Move move = mp->badCaptureList.moves[mp->idx].move;
++mp->idx;
if (move == mp->ttMove)
Expand Down
6 changes: 4 additions & 2 deletions src/movepicker.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ enum {

enum MovepickerType : uint8_t {
SEARCH,
QSEARCH
QSEARCH,
PROBCUT
};

struct Movepicker {
Expand All @@ -33,9 +34,10 @@ struct Movepicker {
Move counter;
int idx;
int stage;
int SEEThreshold;
bool rootNode;
};

void InitMP(Movepicker* mp, Position* pos, SearchData* sd, SearchStack* ss, const Move ttMove, const MovepickerType movepickerType, const bool rootNode);
void InitMP(Movepicker* mp, Position* pos, SearchData* sd, SearchStack* ss, const Move ttMove, const int SEEThreshold, const MovepickerType movepickerType, const bool rootNode);
Move NextMove(Movepicker* mp, const bool skip);

12 changes: 3 additions & 9 deletions src/position.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,12 @@ void ParseFen(const std::string& command, Position* pos) {
// Update pinmasks and checkers
UpdatePinsAndCheckers(pos, pos->side);

// If we are in check get the squares between the checking piece and the king
if (pos->getCheckers()) {
const int kingSquare = KingSQ(pos, pos->side);
const int pieceLocation = GetLsbIndex(pos->getCheckers());
pos->state.checkMask = (1ULL << pieceLocation) | RayBetween(pieceLocation, kingSquare);
}
else
pos->state.checkMask = fullCheckmask;

// Update nnue accumulator to reflect board state
nnue.accumulate(pos->accumStack[0], pos);
pos->accumStackHead = 1;

// Clear vector of played positions
pos->played_positions.clear();
}

std::string GetFen(const Position* pos) {
Expand Down
5 changes: 0 additions & 5 deletions src/position.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ struct BoardState {
int fiftyMove = 0;
int plyFromNull = 0;
Bitboard checkers = 0ULL;
Bitboard checkMask = fullCheckmask;
Bitboard pinned;
}; // stores a move and the state of the game before that move is made
// for rollback purposes
Expand Down Expand Up @@ -111,10 +110,6 @@ struct Position {
return state.checkers;
}

[[nodiscard]] inline Bitboard getCheckmask() const {
return state.checkMask;
}

[[nodiscard]] inline Bitboard getPinnedMask() const {
return state.pinned;
}
Expand Down
51 changes: 49 additions & 2 deletions src/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,53 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td,
}
}

const int pcBeta = beta + 300 - 50 * improving;
if ( !pvNode
&& depth > 4
&& abs(beta) < MATE_FOUND
&& (ttScore == SCORE_NONE || (ttBound & HFLOWER))
&& (ttScore == SCORE_NONE || tte.depth < depth - 3 || ttScore >= pcBeta))
{
Movepicker mp;
Move move;
InitMP(&mp, pos, sd, ss, NOMOVE, pcBeta - ss->staticEval, PROBCUT, rootNode);
while ((move = NextMove(&mp, true)) != NOMOVE) {

if (!IsLegal(pos, move))
continue;

if (move == excludedMove)
continue;

// Speculative prefetch of the TT entry
TTPrefetch(keyAfter(pos, move));

ss->move = move;
ss->contHistEntry = &sd->contHist[PieceTo(move)];

// increment nodes count
info->nodes++;

// Play the move
MakeMove<true>(move, pos);

int pcScore = -Quiescence<false>(-pcBeta, -pcBeta + 1, td, ss + 1);
if (pcScore >= pcBeta)
pcScore = -Negamax<false>(-pcBeta, -pcBeta + 1, depth - 3 - 1,
!cutNode, td, ss + 1);

// Take move back
UnmakeMove(move, pos);

if (pcScore >= pcBeta) {
StoreTTEntry(pos->posKey, MoveToTT(move),
ScoreToTT(pcScore, ss->ply), rawEval, HFLOWER,
depth - 3, pvNode, ttPv);
return pcScore;
}
}
}

// IIR by Ed Schroder (That i find out about in Berserk source code)
// http://talkchess.com/forum3/viewtopic.php?f=7&t=74769&sid=64085e3396554f0fba414404445b3120
// https://github.com/jhonnold/berserk/blob/dd1678c278412898561d40a31a7bd08d49565636/src/search.c#L379
Expand All @@ -576,7 +623,7 @@ int Negamax(int alpha, int beta, int depth, const bool cutNode, ThreadData* td,
bool skipQuiets = false;

Movepicker mp;
InitMP(&mp, pos, sd, ss, ttMove, SEARCH, rootNode);
InitMP(&mp, pos, sd, ss, ttMove, SCORE_NONE,SEARCH, rootNode);

// Keep track of the played quiet and noisy moves
MoveList quietMoves, noisyMoves;
Expand Down Expand Up @@ -905,7 +952,7 @@ int Quiescence(int alpha, int beta, ThreadData* td, SearchStack* ss) {

Movepicker mp;
// If we aren't in check we generate just the captures, otherwise we generate all the moves
InitMP(&mp, pos, sd, ss, ttMove, QSEARCH, false);
InitMP(&mp, pos, sd, ss, ttMove, SCORE_NONE,QSEARCH, false);

Move bestmove = NOMOVE;
Move move;
Expand Down
3 changes: 1 addition & 2 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// include the tune stuff here to give it global visibility
#include "tune.h"

#define NAME "Alexandria-7.1.1"
#define NAME "Alexandria-7.1.2"

inline int reductions[2][64][64];
inline int lmp_margin[64][2];
Expand All @@ -28,7 +28,6 @@ constexpr int MATE_SCORE = 32000;
constexpr int MATE_FOUND = MATE_SCORE - MAXPLY;
constexpr int SCORE_NONE = 32001;
constexpr int MAXSCORE = 32670;
constexpr Bitboard fullCheckmask = 0xFFFFFFFFFFFFFFFF;

// board squares
enum {
Expand Down