Since the only way to insert an alpha bound in TT is if no move raised alpha and thus "best move" was never updated.

In this old post http://talkchess.com/forum3/viewtopic.p ... 10#p762826, I found that in Weini I was never using alpha bound in TT because I was never inserting something in TT without a "valid move". That is why the (bad) solution was to use the first move in list when an alpha bound in inserted inside TT so that alpha bound are in TT and TT scores might be returned more often. In Weini this indeed leads to solve fine70 way faster than before.

This morning I faced more or less the same issue in Minic, but the other way around. I was trying to get ride of the ugly line

Code: Select all

```
if (bestMove == INVALIDMOVE) bestMove = moves[0]; // so that B_alpha are stored in TT
```

I was expecting absolutely no change in playing strength but see a great -150elo !! and a totally new behavior in solving fine70.

I am quite confused with this ...

Let's take the simplest code

Code: Select all

```
ScoreType pvs(ScoreType alpha, ScoreType beta, const Position & p, DepthType depth, bool pvnode, unsigned int ply, std::vector<Move> & pv, DepthType & seldepth){
if ( std::max(1,(int)std::chrono::duration_cast<std::chrono::milliseconds>(Clock::now() - TimeMan::startTime).count()) > currentMoveMs ){
stopFlag = true;
return STOPSCORE;
}
if ((int)ply > seldepth) seldepth = ply;
if ( depth <= 0 ) return qsearch(alpha,beta,p,ply,seldepth);
const bool rootnode = ply == 1;
if (isDraw(p, pvnode)) return 0;
float gp = 0;
if (ply >= MAX_PLY - 1 || depth >= MAX_DEPTH - 1) return eval(p, gp);
alpha = std::max(alpha, (ScoreType)(-MATE + ply));
beta = std::min(beta, (ScoreType)( MATE - ply - 1));
if (alpha >= beta) return alpha;
TT::Entry e;
if (TT::getEntry(computeHash(p), depth, e)) {
if (e.h != 0 && !rootnode && std::abs(e.score) < MATE - MAX_DEPTH && !pvnode &&
( (e.b == TT::B_alpha && e.score <= alpha) || (e.b == TT::B_beta && e.score >= beta) || (e.b == TT::B_exact) ) ) {
if ( e.m != INVALIDMOVE) pv.push_back(e.m); // here e.m might be INVALIDMOVE if B_alpha
return e.score;
}
}
const bool isInCheck = isAttacked(p, kingSquare(p));
ScoreType val;
// IID
if ( (e.h == 0 /*|| e.d < depth/3*/) && pvnode && depth >= iidMinDepth){
std::vector<Move> iidPV;
pvs(alpha,beta,p,depth/2,pvnode,ply,iidPV,seldepth);
if ( !stopFlag) TT::getEntry(computeHash(p), depth, e);
if (stopFlag) return STOPSCORE;
}
int validMoveCount = 0;
bool alphaUpdated = false;
Move bestMove = INVALIDMOVE;
std::vector<Move> moves;
generate(p,moves);
if ( moves.empty() ) return isInCheck?-MATE + ply : 0;
sort(*this,moves,p,&e);
/// ????? if (bestMove == INVALIDMOVE) bestMove = moves[0]; // so that B_alpha are stored in TT
for(auto it = moves.begin() ; it != moves.end() && !stopFlag ; ++it){
Position p2 = p;
if ( ! apply(p2,*it) ) continue;
validMoveCount++;
val = -pvs(-beta,-alpha,p2,depth-1+extension,pvnode,ply+1,childPV,seldepth);
if ( !stopFlag && val > alpha ){
alphaUpdated = true;
if ( val >= beta ){
TT::setEntry({*it,val,TT::B_beta,depth,computeHash(p)});
return val;
}
alpha = val;
bestMove = *it;
}
}
if ( validMoveCount==0 && !stopFlag) return isInCheck?-MATE + ply : 0;
///@todo here validMoveCount shall not be present, this does not allow to store alpha bound !!!!
if ( !stopFlag && /*validMoveCount*/ bestMove != INVALIDMOVE ) TT::setEntry({bestMove,alpha,alphaUpdated?TT::B_exact:TT::B_alpha,depth,computeHash(p)});
return stopFlag?STOPSCORE:alpha;
```