How strong should an engine be with various features implemented?
Moderator: Ras
-
Henk
- Posts: 7251
- Joined: Mon May 27, 2013 10:31 am
Re: How strong should an engine be with various features implemented?
If your engine is below 1800 Elo you better do woodcounting + small random value as a start.
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: How strong should an engine be with various features implemented?
I have also noted something else, after giving your code a very cursory scan. Please note that I'm pointing out a difference here, not making a judgement, because everybody has his or her own coding style.jmcd wrote: ↑Fri Apr 17, 2020 8:37 pmI think this is what I will end up doing soon. Some features I feel I have implemented very cleanly, and some I am not proud of at all. I definitely have a better understanding of all the concepts I've used now than I did when I first wrote them.
I will be sure to follow your development as well!
Your engine has about 2250 lines of code, and no comments.
Of those 2250 lines, 1800 are in bot.cpp/hpp and board.cpp/hpp. Board.cpp is 1200 lines long. That is 80% of your engine, residing in two files.
It seems you have no testing features except for maybe perft (seems to be commented out... or they're in board.cpp for example; I said I only did a cursory scan).
Your engine has 62 commits.
If I compare that to my setup:
2150 lines of code, split over 33 files, none of which is longer than 200 lines. I have 500 lines of comments.
Of the 2150 lines, 720 are used for debugging and testing purposes (not all of those will end up in the final executable); so only 1430 lines are actually used for playing chess. (I haven't got a UCI-interface or even a search yet; one of them is due to be started this weekend.)
My engine has over 250 commits.
What I'm trying to say is:
If this is your first engine, you might be going too fast, too soon. You're changing huge chunks of codes (lots of lines per commit), without doing enough testing and refactoring. You have, for my taste, files that are becoming way too long to handle.
My advice would be to slow down. Copy your engine and put it somewhere. Strip everything out, down to the part where it only does Perft. Refactor everything and make it as consistent as possible. Test Perft, and post the speed you're reaching. On a i7-6700K, both Weiss (by Terje) and Rustic (by me) reach 36 million moves/sec (perft 7 in 88.xx seconds).
Our engines follow the exact same premise: fancy magic bitboards, full make/unmake to ply 0 in perft (no bulk counting), no hash table, no tricks in the move generator. Both seem to have no redundant or inefficient code in the move generator or perft function. C and Rust are both compiled languages and compile to roughly the same machine code (Rustic is compiled using rustc/LLVM while, Weiss is compiled using clang/LLVM or GCC).
The result is that they have EXACTLY the same speed +/- about 0.5 seconds fluctuations, which is exactly within expectation.
If I'd run your perft function on my machine and it runs at 200 seconds, the conclusion would be: it's slow. You start at a 50-70 ELO disadvantage before you even BEGIN to add features to play chess. If you run at 55 seconds (like Crafty on my system, which probably has a more sophisticated move generator than Weiss and Rustic, as it has been in development for a very long time), you start at a 50-70 ELO advantage before you begin adding features.
The point is: perft speed gives you a very good way to determine where your initial expectations could and should be. If your perft speed is three times as long as that of a similar engine, adding new features will obviously improve it, but the faster engine will improve MORE by adding the same feature.
If you want, I can send you a preliminary copy (compiled for your machine) of Rustic's perft routine. You can download and compile Weiss from Github.
After you know where your engine is starting out, then either improve the move generator / make / unmake to catch up if you're behind (I did, when I noticed I was like 40 seconds behind Weiss, even though we use the same techniques), or accept where you are now, and improve this later. This is your own choice. Then add in each feature one by one, keeping it consistent (naming, variable orders, commenting...) with what you have, until you have a bare-bones playing engine again. Establish a base ELO-rating. It doesn't matter if it turns out only to be 1200 ELO. Add features one by one, doing a thousand test games with a pool of other engines, and note down the new rating.
Rinse, repeat...
At least, that's how I'm going to do it.
The only thing I can say is that I've written all of my current code this way, testing function by function as I go, with only 2 bugs; and they weren't even really bugs but omissions of edge cases I've never encountered in an over the board game, so I didn't take into account to check them during make move.
As jdart said: If this is your first engine, focus on correctness first.
Don't fall into the trap of writing an engine with a gazillion features, and then ending up with 5.000 lines of unmaintainable, buggy code. That would be a waste of time and the waste of a chess engine, as you'd have to start over again to fix it.
PS: Yes, Rustic is my first chess engine as well, but I've been writing embedded software for almost two decades. That software has to be tiny, super-fast, it needs to live in a machine for maybe 10-20 years, and, sometimes, after not being touched for five years or longer, suddenly needs to be adapted, because a part in the machine is being replaced after a failure and the original part can't be obtained for whatever reason. In such a case, the program needs to be clear and maintainable. I'm writing this chess engine the same way; as if it is intended to last for 30 years with off-and-on development.
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
-
Henk
- Posts: 7251
- Joined: Mon May 27, 2013 10:31 am
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: How strong should an engine be with various features implemented?
Nightmare and Knightmare both already exist.
Deathwish if a good name if you start a new chess engine in C in 2020
(Just kidding
-
jmcd
- Posts: 58
- Joined: Wed Mar 18, 2020 10:00 pm
- Full name: Jonathan McDermid
Re: How strong should an engine be with various features implemented?
Thanks for the criticisms. I am in exam season right now and will be giving your points more thought later, but I'd like to address this now as it is a nagging thought that I've already had.mvanthoor wrote: ↑Fri Apr 17, 2020 9:37 pm
Your engine has about 2250 lines of code, and no comments.
Of those 2250 lines, 1800 are in bot.cpp/hpp and board.cpp/hpp. Board.cpp is 1200 lines long. That is 80% of your engine, residing in two files.
It seems you have no testing features except for maybe perft (seems to be commented out... or they're in board.cpp for example; I said I only did a cursory scan).
Your engine has 62 commits.
The length of bot.cpp and board.cpp is a result of see and the splitting of move generation into 3 functions (gen all moves, gen captures, gen non captures). After reading the mediocre chess blog, he states that saving work that doesnt need to be done until it absolutely does is effective, and it improved my engine when I implemented it. If i remove the reduncancy, the see method is slower (because the work can be done in the standard move generation), and the engine generates moves that likely wont be used, but bot.cpp is now 400 lines, and board.cpp is now 800 lines. The engine is cleaner, but slower. Is it really worth it to remove the redundancy?
As for comments, yes I definitely need to add more.
Clovis GitHub
-
Dann Corbit
- Posts: 12816
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: How strong should an engine be with various features implemented?
Best names for an engine are quirky and unassuming,
witness: Stockfish, Fruit, Yace, Fizbo, Booot, Arasan, Gull.
witness: Stockfish, Fruit, Yace, Fizbo, Booot, Arasan, Gull.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
-
Dann Corbit
- Posts: 12816
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: How strong should an engine be with various features implemented?
Now is not the time to worry about fast. Your goals should be:jmcd wrote: ↑Fri Apr 17, 2020 10:45 pm {snip}
The length of bot.cpp and board.cpp is a result of see and the splitting of move generation into 3 functions (gen all moves, gen captures, gen non captures). After reading the mediocre chess blog, he states that saving work that doesnt need to be done until it absolutely does is effective, and it improved my engine when I implemented it. If i remove the reduncancy, the see method is slower (because the work can be done in the standard move generation), and the engine generates moves that likely wont be used, but bot.cpp is now 400 lines, and board.cpp is now 800 lines. The engine is cleaner, but slower. Is it really worth it to remove the redundancy?
As for comments, yes I definitely need to add more.
1. Correctness. Read the source of Fruit for a tutorial on how to do this
2. Clarity. Make it easy to read and understand. Limit the jobs of a single function to exactly one function.
3. Robustness - aim for code that can handle surprises
After a super simple chess program implements those things, use the same principles to improve it.
If you want to make your program faster, quirky things like inlining all the code or splotches of assembly are a last resort and generally not a good idea,
Instead, find a better algorithm. Don't use a tree when you can use a hash, aim for good big-O properties but ONLY AFTER you have correct code and you have verified that the code you are trying to improve is the bottleneck with a profiler.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
-
Dann Corbit
- Posts: 12816
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: How strong should an engine be with various features implemented?
One minor point - malloc and new are not your friends in a chess program, so use dynamic allocation when needed but not willy-nilly. Beware of data structures that do lots of memory allocation for you, because this is expensive in a chess program.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
-
Henk
- Posts: 7251
- Joined: Mon May 27, 2013 10:31 am
Re: How strong should an engine be with various features implemented?
If it uses bitboards and programmer starts debugging one can call it Deathwish II