hyatt wrote:I am hoping you meant
val = - alphabeta(-beta, -alpha, etc)???
If so, that should not be a problem. I would re-factor your code so that you only have one call to alphabet(), not one for in check and one for not in check, which is a good way to introduce bugs that are hard to find...
yes, its -alphabeta. I just wanted to show how the arguments were passed in that specific case, and I don't have different alphabeta calls. I also disabled quiescent search in my tests to see if the problem was there, but it wasn't.
Check my code (I did some changes to reduce the line count, hope no typos). It's about 80 lines, you should copy it to some text editor to read it better:
Code: Select all
int mated_in(int ply){ return -MATE+ply; }
int new_depth(Chessboard *b, int depth){
return depth-1 + is_check(b, b->occ); /* is_check returns 1 if chessboard is in check */
}
int value_to_tt(int score, int ply){
if(score >= MATE - MAX_PLY)
return score + ply;
else if(score <= -MATE + MAX_PLY)
return score - ply;
return score;
}
int value_from_tt(int score, int ply){
if(score >= MATE - MAX_PLY)
return score - ply;
else if(score <= -MATE + MAX_PLY)
return score + ply;
return score;
}
bool can_tt_prune(table_t *entry, int alpha, int beta, int depth, int ply){
if(entry == nullptr || entry->depth < depth)
return false;
int score = value_from_tt(entry->score, ply);
if((entry->flag == ALL && score <= alpha)
|| (entry->flag == CUT && score >= beta)
|| (entry->flag == PV))
return true;
return false;
}
table_t *tt_probe(Chessboard *b){
uint64_t pos = b->key % hashblocks;
return tt_table[pos].key == b->key ? tt_table+pos : NULL;
}
void tt_store(Chessboard *b, int bestscore, int alpha, int beta, int depth){
uint64_t pos = b->key % hash_blocks;
int flag = bestscore <= alpha ? ALL : bestscore >= beta ? CUT : PV;
tt_table[pos] = {b->key, bestscore, depth, flag};
}
int alphabeta(Chessboard *b, int alpha, int beta, int depth, int ply){
const int orig_alpha = alpha;
table_t *entry = tt_probe(b);
if(can_tt_prune(entry, alpha, beta, depth, ply))
return value_from_tt(entry->score, ply);
if(depth <= 0)
return evaluate(b); //quiescent(b, alpha, beta, depth, ply);
Info info = empty_info;
Move mlist[MAX_MOVES], *end = gen_moves(b, mlist, &info, false /* true is to generate moves for quiescent, false here because not in quiescent */);
for(Move *it = mlist; it != end; ++it){
make_move(b, it);
int val = -alphabeta(b, -beta, -alpha, new_depth(b, depth), ply+1);
undo_move(b, it);
if(val > alpha){
alpha = val;
if(val >= beta)
break;
update_pv(it, ply);
}
}
if(!moves_left(mlist, end) /* if end - mlist == 0, if this position has no moves */ )
alpha = info.checkers ? mated_in(ply) : DRAW /* 0 */;
tt_store(b, value_to_tt(alpha, ply), orig_alpha, beta, depth);
return alpha;
}