Don wrote:Hi Joshua,
Don't let the comments discourage you. Take what you have and try to build a simple chess playing program out of it, one that does not search but finds a move heuristically. This is a good exercise because it will help you determine what issues are involved in selecting a good move and you will have great fun in doing this.
But here is what I think you will discover. You will continue to make rules that prevent blunders. It will be all about tactics. I assume that you want to find moves in master style, based on plans and what the position calls for. But every game is going to be overwhelmed by tactically issues. Still, consider it a success of sorts if you manage to make it play moves that look attractive most of the time and can compete with a 1 or 2 ply search from a strong chess program. (I suspect you will find this very difficult to do without a search.)
Since you are looking at things from a completely different point of view there is always a good chance that you can learn something that could be applied to a "regular" chess program, perhaps discovering simple tactical rules that helps a lot but is not obvious, something that could be integrated into a typical chess program as an evaluation feature or extension.
There was a program called Paradise which exactly is doing what gets proposed here. It was written in a functional programming language and i did checkout the program bigtime.
So where we completely agree of course on the principle that brute force always wins it, it is completely unclear what to do the last few plies of the search.
Rybka simply is doing the same what 9 years ago already got done by Omid David Tabibi, namely a hard form of razoring using a pawn window.
This misses a lot of tactics.
Yet to quote Frans Morsch on the last few plies: "if you get that huge nps you simply don't have the system time to be clever".
So for Rybka & clones this is the case.
Yet for the Diep type engines selecting a bunch of moves, instead of doing an expensive nullmove, might be very interesting those last few plies.
A big problem thereby is the positional score swings.
For example picking up a pawn at a7 is maybe improving the evaluation by 0.2 pawn, but moving a knight from a3 to c4, so from the edge of the board to the semi-center, might improve the evaluation function 1.5 pawn.
So the big question is: what do we want to pick up last few plies and how selective do we want to be there?
What i already experiment since 2004, start 2005, so before Rybka had it, was a nullmove where the reduction factor is dependant upon the difference between eval and beta.
I used 0.5 pawn there, Rybka uses 1.0 pawn there; so:
if( eval >= beta + 0.5 ) then R=4; else R=3;
That's the nullmove reduction factor. I used it basically for the last few plies, as the overhead from nullmoves in the mainsearch already is such a tiny fraction of nodes that going to R=4 there wasn't worth it back then (diep didn't search so deep back then).
Yet all this is really primitive. So having some chessknowledge based upon which you do a better job the last few plies, is a real interesting research question.
I'd argue that it is a fulltime job to be busy with it though, which is why i didn't really research it after the failed experiment of 2005.
I really lost nearly a full year to experiments from short after world champs 2004 until world champs 2005, trying to really search plies deeper with Diep using dubious search methods. Yet it gave a lot of insights and also produced some ideas from which i still feel they could work.
After doing this you will likely become dissatisfied with the code (I always feel this way about my code) and may want to start again from scratch. Figure out what needs to change and don't be afraid to start over, even more than once. That will make you a better programmer.
By the way, you didn't do everything wrong, it was obvious for instance that you tried to lay out the code to be understandable and you chose easy to understand names for variables and such. Keep up that good practice.
Here are a couple of tips - just a couple so as not to overwhelm you:
In general you don't want to call external programs using the system call when you can easily write your own pause function. You should figure out how to do that.
You almost always want to use an array to represent sets of things (or some other other data structure but let's keep it simple.) The chess board should be some sort of array for instance. Chessprogramming wiki gives good examples of data structures to use for representing the chess position.
The sample code snippet someone posted may not do what you thought. It's the one that says, "if(a != 0 || 1 || 2 ...." That statement will always be true and you could have just said, "a = 0" but I don't think you meant that. Did you mean: if (a < 60) { a = 0; } ??