algerbrex wrote: ↑Wed Sep 08, 2021 11:09 pm
tcusr wrote: ↑Wed Sep 08, 2021 10:34 pm
tcusr wrote: ↑Wed Sep 08, 2021 10:22 pm
Ras wrote: ↑Wed Sep 08, 2021 9:10 pm
tcusr wrote: ↑Wed Sep 08, 2021 2:03 pmthis seems correct but i have no way to detect stalemate in quiescence
You mostly don't need that. I only use a special stalemate verification in QS that if the side to move is down to the bare king and not in check. That's helpful for some endgames with K+Q:K+P. During normal game, I defer that to main search only, not QS.
My QS mate detection works quite simple. First, I don't transition from main search to QS if I'm in check (check extension). Within QS, I don't verify for in-check in the first QS level because there cannot be a check.
The next three QS levels have the in-check detection. Assuming that I'm in check, then if alpha is below -MATE+ply, I set alpha to -MATE+ply. If none of the check evasions (special movegen) gets out of check, alpha stays at -MATE+ply, hence returning a proper mate score with correct distance.
Conversely, if alpha is already above -MATE+ply, then there's still no move that would improve alpha because there's no legal move at all, hence I return the node's score as alpha, which is a fail-low. The kicker is that it doesn't matter how low it fails because that branch will be discarded anyway.
i don't think i understand.
lithander said that when in check he generates all the moves. if none of the move tried are legal it has to be checkmate.
but you have check extension at root, so you check if you are in check after the search. but since you have not tried all the moves you still don't know if it's checkmate, so you have to generate the rest and try them right?
lithander's approach seems simpler, i will still skip checking for stalemate because you said i don't need to
sorry i only saw now that you use a special move generator when in check. i understand now
i'm still worried about my engine speed though
it takes 8 seconds to reach depth 10 here 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -. i suppose this is mostly an evaluation problem or maybe some pruning techniques (which i don't have) improve speed a lot here. i'm curious on how long it takes for algerbrex's engine to reach depth 10 (my evaluation function is basically his)
Hi Pier, here's the output I get from the position you gave:
Code: Select all
info depth 1 seldepth 1 score cp 89 time 2 nodes 33
info depth 2 seldepth 4 score cp 96 time 7 nodes 290
info depth 3 seldepth 4 score cp 82 time 7 nodes 728
info depth 4 seldepth 4 score cp 85 time 4 nodes 2663
info depth 5 seldepth 5 score cp 37 time 6 nodes 12187
info depth 6 seldepth 5 score cp 33 time 5 nodes 11549
info depth 7 seldepth 5 score cp 33 time 13 nodes 28609
info depth 8 seldepth 5 score cp 30 time 33 nodes 69833
info depth 9 seldepth 6 score cp 30 time 53 nodes 180832
info depth 10 seldepth 5 score cp 37 time 80 nodes 268286
...
Keep in mind however that I'm using several features which are making my engine faster. To name a few:
- Killer moves
- Transposition table (64 MB)
- Null-move pruning
- Static null-move pruning
See what kind of performance you get after you start adding some of those features. The time to depth 10 should start to drop pretty dramatically, especially after implementing a transposition table, since the position you gave is an endgame position with few pieces on the board and so there are a ton of transpositions that will keep occuring.
hi algerbrex, thank you for bothering trying it! i overestimated the role of the evaluation function i guess
i'll study your code for now on because my goal is to reach 2000, also your code seems really clean and easy to follow.
btw, do you see anything wrong with this implementation of your evaluation function? sometimes it suggests weak moves even at medium depths
Code: Select all
template<int C>
void eval_color(const Board& board, int *mg, int *eg, int& phase)
{
for (int p = KING; p <= QUEEN; ++p) {
uint64_t us = board.piece(p, C);
while (us) {
int s = poplsb(&us);
if (C == BLACK)
s ^= 56;
*mg += mg_psqt[p][s];
*eg += eg_psqt[p][s];
phase -= phase_value[p];
}
}
}
template<int C>
int eval(const Board& board)
{
constexpr int total_phase = 24;
int phase = total_phase;
int mg_scores[2] = {{0}, {0}};
int eg_scores[2] = {{0}, {0}};
eval_color<WHITE>(board, mg_scores + WHITE, eg_scores + WHITE, phase);
eval_color<BLACK>(board, mg_scores + BLACK, eg_scores + BLACK, phase);
const int mg = mg_scores[C] - mg_scores[C ^ 1];
const int eg = eg_scores[C] - eg_scores[C ^ 1];
phase = (phase * 256 + (total_phase / 2)) / total_phase;
return ((mg * (256 - phase)) + (eg * phase)) / 256;
}
the value for the pieces is this: KING = 1, PAWN, KNIGHT, BISHOP, ROOK, QUEEN. yours is different and maybe when i modified it i forgot to change it somewhere