oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
1) I had an idea of skipping any move with a negative SEE value in qsearch. According to my tests, this approach is faster but leads to missed mates. Has anyone tried this, and is it worth it?
Do you recognize checkmates in qsearch? The reason I'm asking is that usually, this shouldn't happen. The only reason quiescence search is used is to limit the horizon effect. An example of the horizon effect could be that if captures aren't resolved, engines will tend to just delay big material losses such that they happen later. If they can extend this postponing of material loss so far down the tree, that they can't see it due to depth-limitations, the loss "doesn't happen".
I don't resolve checkmates in quiescence since I believe it should be left for the main search function. I would suggest testing for elo instead of mate-finding capability.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
2) Where exactly should I use SEE in my engine? I already have a working implementation that returns the SEE value relative to the side whose turn it is.
I use SEE in three places:
- Pruning bad captures in quiescence search. I got around 56 elo points from this IIRC.
- Move ordering for captures (mix of SEE and MVV/LVA).
- Depth reductions for bad captures in main search.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
3) How should I go about testing the strength (and elo gains) of my engine? I’m using a mac and currently just running tournaments against other engines on ScidvsMac.
I would strongly advice you to run SPRT tournaments whenever you add a feature (then play a match between the version without the feature and the one with the feature). The good thing about SPRT is that it stops the test automatically, whenever there is enough statistical significance in the results.
OpenBench, written by Andrew Grant, is a great framework for testing your engine during development. It has support for multiple clients (machines) testing the same engine and you can also stop/restart your tests whenever you want to.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
4) Would anyone be willing to have a look at my code and give me feedback? (DM me
Just share your Github repo in this thread and I can take a look at it.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
5) I’ve been experimenting with different move ordering schemes. which one has worked best for you, and what are the top engines using?
The most simple, and probably the most rewarding is the following (ordered by best to worst moves):
- Best move from the transposition table.
- MVV/LVA for captures. Promotions should be scored as highly as captures.
- Killer moves.
- History heuristic
The last two only being applied to quiet moves.
SEE is also good for move ordering (better at predicting captures's values than static MVV/LVA), but comes at a speed cost; therefore, I use a mix of the two.
The top engines use a lot of other, less important methods, so I wouldn't relly worry about that until your engine is above 2900 elo.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
6) Delta pruning: my implementation is slightly different than the CPW implementation. Does this make sense?
Code: Select all
best_case = see(move) + (MOVE_IS_PROMOTION(move) ? 900 : 0);
if (eval + best_case < alpha) return alpha;
You shouldn't return from the function unless you have a beta cutoff. You should do this instead:
Code: Select all
best_case = see(move) + (MOVE_IS_PROMOTION(move) ? 900 : 0);
if (eval + best_case <= alpha) continue; /* Note less than or equal instead of less than */
This is better since you don't skip all the remaining, potentially good moves when you encounter a bad one early.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
7) Should I be focusing more on pruning or on improving evaluation? Out of curiosity, which do you think (on the more advanced level) provides more of an improvement?
This is a hard question, and I'm not sure if it even has an answer. As others have said, they are
very dependent on each other. If you have a bad evaluation, late move reductions should be limited since you would otherwise risk not seeing very good/bad moves (this is also true for insufficient move ordering). The point is that if you have a really good, well-tuned search, it wont really matter if your evaluation function is sloppy and can't guide the former to good positions, but it will still be way better than plain alpha-beta.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
8) What kinds of advanced evaluation improvements should I add? I'm currently using tapered evaluation, bishop pair, doubled/isolated/passed pawns, semi/fully open rook files, piece mobility, and king safety.
If your engine's rating is still just 2350 (if you're not running long tournaments when testing, you can't be certain on this by the way. 1000 games should be played at least), I would advice you to remove all evaluation terms, including tapering, except material and piece-square tables. Then, starting with tapered evaluation, re-add all of them one by one, thoroughly testing each term. This will take some time, but it will be worth it. I'm suggesting you do this since I would expect the rating of your engine to be significantly higher with said features.
After having made sure that none of the terms lose elo, you can implement texel tuning (see texel's tuning method on CPW).
Actually, I would suggest you do this to your search as well if you have more than null move pruning and simple move ordering. Material, PSQT, NMP and said simple move ordering can oftentimes get an engine into the 2200-range.
oriyonay wrote: ↑Wed Aug 25, 2021 8:01 am
9) What should be the next steps for the development of my engine? I’d estimate its current playing strength at 2350 elo.
Even though it might be slow testing a lot (and feeling like you're back at the starting line), I really think you should do what I suggested in point 8. Also, the SPRT testing method in part 3 is nearly a must for efficient engine development.