how to continue

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: how to continue

Post by lithander »

algerbrex wrote: Wed Sep 08, 2021 1:54 pm Have you considered yet trying to tune any more tables for something like passed pawns or what not? It sounds like those results would be interesting at least.
Adding more evaluation terms like passed pawns would probably help improve the eval. No doubt about it. But that's some very specific concept whereas the current evaluation is based on machine learning. I kinda like to keep that self-learning approach where I only gave the engine only the means to encode information about what's a good position but didn't hardcode that knowledge.

There are promising extension possible in that direction, too. For example I was thinking about a version where I use different PSTs based on the king location. It probably makes a difference whether you castled left or right but currently the PSTs have to encoding knowledge that has to work equally well (or bad) for both cases.

But I'm already at the very limits of what I consider a "minimal" engine and so this is something I may only try in Minimal Chess' successor if I decide to do one. (I'm still on the fence)
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: how to continue

Post by lithander »

tcusr wrote: Wed Sep 08, 2021 10:34 pm i'm curious on how long it takes for algerbrex's engine to reach depth 10 (my evaluation function is basically his)
download it. run it. in the CLI you type

Code: Select all

position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1
go
you will get an output looking like this

Code: Select all

position fen 8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1
go
info depth 1 seldepth 1 score cp 89 time 0 nodes 33
info depth 2 seldepth 4 score cp 96 time 0 nodes 290
info depth 3 seldepth 4 score cp 82 time 0 nodes 819
info depth 4 seldepth 3 score cp 85 time 1 nodes 2616
info depth 5 seldepth 5 score cp 37 time 3 nodes 12784
info depth 6 seldepth 5 score cp 33 time 3 nodes 12606
info depth 7 seldepth 5 score cp 33 time 6 nodes 31566
info depth 8 seldepth 5 score cp 30 time 16 nodes 73943
info depth 9 seldepth 6 score cp 30 time 35 nodes 189320
info depth 10 seldepth 5 score cp 37 time 57 nodes 312301
time 57 would mean it took 57ms to search to depth 10 from the point where the go command was received.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: how to continue

Post by Ras »

tcusr wrote: Wed Sep 08, 2021 10:22 pmlithander said that when in check he generates all the moves. if none of the move tried are legal it has to be checkmate.
I don't generate all moves in check, only those that have any hope of getting out of check. But if you don't have such a special evasion move generator yet, you can just generate all moves - it will only be a minor performance impact that you can ignore for now.
but you have check extension at root
Not at root - in main search. That would be your Negamax, as opposed to your quiescence. But I thought we were only talking about quiescence specifically.
Rasmus Althoff
https://www.ct800.net
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

Ras wrote: Wed Sep 08, 2021 10:48 pm
but you have check extension at root
Not at root - in main search. That would be your Negamax, as opposed to your quiescence. But I thought we were only talking about quiescence specifically.
sorry, my bad. i said root but i meant main search.
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: how to continue

Post by Ras »

tcusr wrote: Wed Sep 08, 2021 10:34 pmit 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
It's not eval because that gives you only linear speed-up. The problem is your branching factor, which you can address by better move sorting, pruning, and reductions. But for now, I wouldn't worry about that and focus on correctness first.

My eval is really heavy, and I still need only 60ms for that because I'm only visiting 34k nodes due to pruning and stuff. The seemingly low speed of only 573k NPS is because the CPU cores need to ramp up their clock speed. If I search the position until depth 20, I get 2M NPS because the search takes 3.3 seconds so that the core speed has ramped up.
Rasmus Althoff
https://www.ct800.net
User avatar
algerbrex
Posts: 596
Joined: Sun May 30, 2021 5:03 am
Location: United States
Full name: Christian Dean

Re: how to continue

Post by algerbrex »

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.
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

Ras wrote: Wed Sep 08, 2021 10:58 pm
tcusr wrote: Wed Sep 08, 2021 10:34 pmit 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
It's not eval because that gives you only linear speed-up. The problem is your branching factor, which you can address by better move sorting, pruning, and reductions. But for now, I wouldn't worry about that and focus on correctness first.

My eval is really heavy, and I still need only 60ms for that because I'm only visiting 34k nodes due to pruning and stuff. The seemingly low speed of only 573k NPS is because the CPU cores need to ramp up their clock speed. If I search the position until depth 20, I get 2M NPS because the search takes 3.3 seconds so that the core speed has ramped up.
yes you're right, i tested it again with a material only evaluation and it takes a bit more than 1 second.
i agree with your approach, i much rather test and debug all this basic stuff so that they won't bite me when i'll implement more fancy stuff.

i've been looking at your eval.c code and i can't comprehend how you are able to keep track of everything. my whole engine now is 1200 LOC and i have trouble managing that!
i have two questions if you don't mind, why did you decide to split the code for white and black? for speed or something else?
second, did you use texel tuning to generate your tables? i ask because i see that you added a lot of hand crafted and specific evaluations, which is what i want to do
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

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
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: how to continue

Post by Ras »

tcusr wrote: Wed Sep 08, 2021 11:12 pmyes you're right, i tested it again with a material only evaluation and it takes a bit more than 1 second.
That's not because of the faster eval, but because many different positions have the same eval. That means your alpha-beta will cut a lot more branches. The downside is that the overall play is probably worse.
i've been looking at your eval.c code and i can't comprehend how you are able to keep track of everything.
That accumulated over the years, piece by piece.
why did you decide to split the code for white and black? for speed or something else?
Basically because the engine that I forked from (NG-Play) had that architecture. It does make things a bit easier to code, although generic code (i.e. same for both sides) is the cleaner way.
second, did you use texel tuning to generate your tables?
No, I hand-tuned that early on when I witnessed a lot of games manually. I tweaked the parameters until they would move the engine in the direction I wanted.
Rasmus Althoff
https://www.ct800.net
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

Ras wrote: Wed Sep 08, 2021 11:26 pm No, I hand-tuned that early on when I witnessed a lot of games manually. I tweaked the parameters until they would move the engine in the direction I wanted.
that's admirable. i still don't understand how i am supposed to choose the values for the bonuses though.
is there a mathematical formula to find out these values?