Skip to content

Commit

Permalink
Attempt #1
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonnold committed May 24, 2021
1 parent 48546fb commit 93c2985
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 75 deletions.
5 changes: 3 additions & 2 deletions src/movegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,9 @@ void GenerateAllMoves(MoveList* moveList, Board* board, SearchData* data) {
}

// Get the hash move for sorting
TTValue ttValue = TTProbe(board->zobrist); // TODO: Don't I know this already from the search?
Move hashMove = TTMove(ttValue);
int ttHit;
TTEntry* tt = TTProbe(&ttHit, board->zobrist); // TODO: Don't I know this already from the search?
Move hashMove = ttHit ? tt->move : NULL_MOVE;

for (int i = 0; i < moveList->count; i++) {
Move move = moveList->moves[i];
Expand Down
55 changes: 28 additions & 27 deletions src/search.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,16 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {

// check the transposition table for previous info
// we ignore the tt on singular extension searches
TTValue ttValue = skipMove ? NO_ENTRY : TTProbe(board->zobrist);
int ttHit = 0;
TTEntry* tt = skipMove ? NULL : TTProbe(&ttHit, board->zobrist);

// if the TT has a value that fits our position and has been searched to an equal or greater depth, then we accept
// this score and prune
if (!isPV && ttValue && TTDepth(ttValue) >= depth) {
int ttScore = TTScore(ttValue, data->ply);
int flag = TTFlag(ttValue);
if (!isPV && ttHit && tt->depth >= depth) {
int ttScore = TTScore(tt, data->ply);

if (flag == TT_EXACT || (flag == TT_LOWER && ttScore >= beta) || (flag == TT_UPPER && ttScore <= alpha))
if ((tt->flags & TT_EXACT) || ((tt->flags & TT_LOWER) && ttScore >= beta) ||
((tt->flags & TT_UPPER) && ttScore <= alpha))
return ttScore;
}

Expand Down Expand Up @@ -248,14 +249,14 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {
}

// if the tablebase gives us what we want, then we accept it's score and return
if (flag == TT_EXACT || (flag == TT_LOWER && score >= beta) || (flag == TT_UPPER && score <= alpha)) {
if ((flag & TT_EXACT) || ((flag & TT_LOWER) && score >= beta) || ((flag & TT_UPPER) && score <= alpha)) {
TTPut(board->zobrist, depth, score, flag, 0, data->ply, 0);
return score;
}

// for pv node searches we adjust our a/b search accordingly
if (isPV) {
if (flag == TT_LOWER) {
if (flag & TT_LOWER) {
bestScore = score;
alpha = max(alpha, score);
} else
Expand All @@ -265,7 +266,7 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {
}

// pull previous static eval from tt - this is depth independent
int eval = data->evals[data->ply] = (ttValue ? TTEval(ttValue) : Evaluate(board, thread));
int eval = data->evals[data->ply] = (ttHit ? tt->eval : Evaluate(board, thread));
// getting better if eval has gone up
int improving = data->ply >= 2 && (data->evals[data->ply] > data->evals[data->ply - 2]);

Expand All @@ -276,9 +277,9 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {

if (!isPV && !board->checkers) {
// Our TT might have a more accurate evaluation score, use this
if (ttValue && TTDepth(ttValue) >= depth) {
int ttScore = TTScore(ttValue, data->ply);
if (TTFlag(ttValue) == (ttScore > eval ? TT_LOWER : TT_UPPER))
if (ttHit && tt->depth >= depth) {
int ttScore = TTScore(tt, data->ply);
if (tt->flags & (ttScore > eval ? TT_LOWER : TT_UPPER))
eval = ttScore;
}

Expand Down Expand Up @@ -311,7 +312,7 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {
// less than beta + margin, then we run a shallow search to look
int probBeta = beta + 100;
if (depth > 4 && abs(beta) < MATE_BOUND &&
!(ttValue && TTDepth(ttValue) >= depth - 3 && TTScore(ttValue, data->ply) < probBeta)) {
!(ttHit && tt->depth >= depth - 3 && TTScore(tt, data->ply) < probBeta)) {
MoveList moveList;
GenerateTacticalMoves(&moveList, board);

Expand Down Expand Up @@ -339,7 +340,7 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {

// IIR by Ed Schroder
// http://talkchess.com/forum3/viewtopic.php?f=7&t=74769&sid=64085e3396554f0fba414404445b3120
if (depth >= 4 && !ttValue && !skipMove)
if (depth >= 4 && !ttHit && !skipMove)
depth--;

MoveList moveList;
Expand Down Expand Up @@ -385,9 +386,9 @@ int Negamax(int alpha, int beta, int depth, ThreadData* thread, PV* pv) {
// moves at a shallow depth on a nullwindow that is somewhere below the tt evaluation
// implemented using "skip move" recursion like in SF (allows for reductions when doing singular search)
int extension = 0;
if (depth >= 8 && !skipMove && !isRoot && move == TTMove(ttValue) && TTDepth(ttValue) >= depth - 3 &&
abs(TTScore(ttValue, data->ply)) < MATE_BOUND && TTFlag(ttValue) == TT_LOWER) {
int sBeta = max(TTScore(ttValue, data->ply) - depth * 2, -CHECKMATE);
if (depth >= 8 && !skipMove && !isRoot && ttHit && move == tt->move && tt->depth >= depth - 3 &&
abs(TTScore(tt, data->ply)) < MATE_BOUND && (tt->flags & TT_LOWER)) {
int sBeta = max(TTScore(tt, data->ply) - depth * 2, -CHECKMATE);
int sDepth = depth / 2 - 1;

data->skipMove[data->ply] = move;
Expand Down Expand Up @@ -529,23 +530,23 @@ int Quiesce(int alpha, int beta, ThreadData* thread, PV* pv) {
return Evaluate(board, thread);

// check the transposition table for previous info
TTValue ttValue = TTProbe(board->zobrist);
int ttHit = 0;
TTEntry* tt = TTProbe(&ttHit, board->zobrist);
// TT score pruning - no depth check required since everything in QS is depth 0
if (ttValue) {
int score = TTScore(ttValue, data->ply);
int flag = TTFlag(ttValue);

if (flag == TT_EXACT || (flag == TT_LOWER && score >= beta) || (flag == TT_UPPER && score <= alpha))
return score;
if (ttHit) {
int ttScore = TTScore(tt, data->ply);
if ((tt->flags & TT_EXACT) || ((tt->flags & TT_LOWER) && ttScore >= beta) ||
((tt->flags & TT_UPPER) && ttScore <= alpha))
return ttScore;
}

// pull cached eval if it exists
int eval = data->evals[data->ply] = (ttValue ? TTEval(ttValue) : Evaluate(board, thread));
int eval = data->evals[data->ply] = (ttHit ? tt->eval : Evaluate(board, thread));

// can we use an improved evaluation from the tt?
if (ttValue) {
int ttEval = TTScore(ttValue, data->ply);
if (TTFlag(ttValue) == (ttEval > eval ? TT_LOWER : TT_UPPER))
if (ttHit) {
int ttEval = TTScore(tt, data->ply);
if (tt->flags & (ttEval > eval ? TT_LOWER : TT_UPPER))
eval = ttEval;
}

Expand Down
54 changes: 26 additions & 28 deletions src/transposition.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ size_t TTInit(int mb) {
uint64_t keySize = (uint64_t)log2(mb) + (uint64_t)log2(MEGABYTE / sizeof(TTBucket));

#if defined(__linux__) && !defined(__ANDROID__)
// On Linux systems we align on 2MB boundaries and request Huge Pages
// On Linux systems we align on 2MB boundaries and request Huge Pages
TT.buckets = aligned_alloc(2 * MEGABYTE, (1ULL << keySize) * sizeof(TTBucket));
madvise(TT.buckets, (1ULL << keySize) * sizeof(TTBucket), MADV_HUGEPAGE);
#else
Expand All @@ -57,56 +57,56 @@ void TTFree() { free(TT.buckets); }

inline void TTClear() { memset(TT.buckets, 0, (TT.mask + 1ULL) * sizeof(TTBucket)); }

inline int TTScore(TTValue value, int ply) {
int score = (int)((int16_t)((value & 0x0000FFFF00000000) >> 32));

return score > MATE_BOUND ? score - ply : score < -MATE_BOUND ? score + ply : score;
inline int TTScore(TTEntry* e, int ply) {
return e->score > MATE_BOUND ? e->score - ply : e->score < -MATE_BOUND ? e->score + ply : e->score;
}

inline void TTPrefetch(uint64_t hash) { __builtin_prefetch(&TT.buckets[TT.mask & hash]); }

inline TTValue TTProbe(uint64_t hash) {
#ifdef TUNE
return NO_ENTRY;
#else
TTBucket bucket = TT.buckets[TT.mask & hash];
inline TTEntry* TTProbe(int* hit, uint64_t hash) {
#ifndef TUNE
TTBucket* bucket = &TT.buckets[TT.mask & hash];
uint32_t shortHash = hash >> 32;

for (int i = 0; i < BUCKET_SIZE; i++)
if (bucket.entries[i].hash == hash)
return bucket.entries[i].value;

return NO_ENTRY;
if (bucket->entries[i].hash == shortHash) {
*hit = 1;
return &bucket->entries[i];
}
#endif

return 0;
}

inline TTValue TTPut(uint64_t hash, int depth, int score, int flag, Move move, int ply, int eval) {
inline void TTPut(uint64_t hash, uint8_t depth, int16_t score, uint8_t flag, Move move, int ply, int16_t eval) {
#ifdef TUNE
return NO_ENTRY;
return;
#else

TTBucket* bucket = &TT.buckets[TT.mask & hash];
TTBucket bucket = TT.buckets[TT.mask & hash];
uint32_t shortHash = hash >> 32;

int replacementDepth = INT32_MAX;
int replacementIdx = 0;

for (int i = 0; i < BUCKET_SIZE; i++) {
TTEntry entry = bucket->entries[i];
TTEntry entry = bucket.entries[i];
if (!entry.hash) {
replacementIdx = i;
break;
}

int currDepth = TTDepth(entry.value);
if (entry.hash == hash) {
if (currDepth > depth && flag != TT_EXACT)
return entry.value;
if (entry.hash == shortHash) {
if (entry.depth > depth && !(flag & TT_EXACT))
return;

replacementIdx = i;
break;
}

if (currDepth < replacementDepth) {
if (entry.depth < replacementDepth) {
replacementIdx = i;
replacementDepth = currDepth;
replacementDepth = entry.depth;
}
}

Expand All @@ -116,10 +116,8 @@ inline TTValue TTPut(uint64_t hash, int depth, int score, int flag, Move move, i
else if (score < -MATE_BOUND)
adjustedScore -= ply;

bucket->entries[replacementIdx].hash = hash;
TTValue tt = bucket->entries[replacementIdx].value = TTEntry(adjustedScore, flag, depth, move, eval);

return tt;
TTEntry* entry = &bucket.entries[replacementIdx];
*entry = (TTEntry){.flags = flag, .depth = depth, .eval = eval, .score = score, .hash = shortHash, .move = move};
#endif
}

Expand Down
28 changes: 10 additions & 18 deletions src/transposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@

#include "types.h"



#define NO_ENTRY 0ULL
#define MEGABYTE 0x100000ULL
#define BUCKET_SIZE 3

typedef uint64_t TTValue;

typedef struct {
uint64_t hash;
TTValue value;
uint8_t flags;
uint8_t depth;
int16_t eval;
int16_t score;
uint32_t hash;
Move move;
} TTEntry;

typedef struct {
Expand All @@ -44,25 +44,17 @@ typedef struct {
uint64_t size;
} TTTable;

enum { TT_LOWER, TT_UPPER, TT_EXACT };
enum { TT_LOWER = 1, TT_UPPER = 2, TT_EXACT = 4 };

extern TTTable TT;

#define TTEntry(score, flag, depth, move, eval) \
((TTValue)((uint16_t)(eval)) << 48) | ((TTValue)((uint16_t)(score)) << 32) | ((TTValue)(flag) << 30) | \
((TTValue)(depth) << 24) | ((TTValue)(move))
#define TTFlag(value) ((int)((unsigned)((value)&0xC0000000) >> 30))
#define TTMove(value) ((Move)((value)&0xFFFFFF))
#define TTDepth(value) ((int)((value)&0x3F000000) >> 24)
#define TTEval(value) ((int)((int16_t)((value) >> 48)))

size_t TTInit(int mb);
void TTFree();
void TTClear();
void TTPrefetch(uint64_t hash);
TTValue TTProbe(uint64_t hash);
int TTScore(TTValue value, int ply);
TTValue TTPut(uint64_t hash, int depth, int score, int flag, Move move, int ply, int eval);
TTEntry* TTProbe(int* hit, uint64_t hash);
int TTScore(TTEntry* e, int ply);
void TTPut(uint64_t hash, uint8_t depth, int16_t score, uint8_t flag, Move move, int ply, int16_t eval);
int TTFull();

#endif

0 comments on commit 93c2985

Please sign in to comment.