Rarely is that true. If I have a better position, I clearly do _not_ want to draw. So it is bad from my perspective. But if I have a better position, you, by definition, have a worse position, and you would be happy to take a draw given the opportunity.Carey wrote:I don't think I happen to have that article. I only have a few from back then. And I don't see it posted on your website.bob wrote:Before you go on, you should read the paper Harry Nelson wrote titled "The draw heuristic in Cray Blitz". We addressed this very issue,Carey wrote:Let me start off by saying that I'm an idiot. That seems to be the best explanation for why I'm having trouble with this.
I've written a few very minor chess programs over the years. I don't like playing chess, only programming chess, so I never really cared how well they played. I just had fun writing them.
Now I'm trying to make my new one work properly, so I now care about the little details.... like draw scores.
Solving one issue brings up another problem. Solving that one creates ye another, etc. My simple problem has ballooned into several issues and fixing them has become a problem all to itself.
By the time I do all the solutions, it's one heck of a kludge. A wart on a wart.
Obviously I'm doing something wrong. I'm missing something obvious.
When a solution to a simple problem becomes this complicated, something is wrong.
Issue 1)
If you do a draw score of zero, then the program can not tell the difference between a draw in 3 moves from a draw in 33 moves. One draw looks as good as another to the search, so it just picks randomly among them.
Well, hashing is its own problem. That the failure of the hash and too small of a draw window and not limiting its max draw score.but it has its own set of issues as you mentioned. We uses real scores that had a "gap" between 0 and 100 (pawn = 1000 in Cray Blitz), and we squeezed the draw scores into that range based on the ply where they are discovered. The problem is that draw scores (except for insufficient material) are path-dependent, and hashing ignores the path. So we were seeing scores like draw in 90 plies, even though CB had a max depth of 64 plies. We just accepted that, knowing that some draws were getting pushed out to appear that they happened beyond 100 plies, making them move into the real (non-draw score) area.
That's not relevant to the basic search issues I was asking about.
Admittedly I hadn't thought about hashing issues for draw scores. But I haven't added hashing to this program yet, so it's not relevant.
Right.This is really a non-issue. if you reserve scores between -1000 and +1000 for draws, it will work, in that anything in that range is a draw.
In cases where there are multiple draws at the root (and even in the search), the program picks randomly among them. Leading to the possibility of the program playing back & forth between them and never actually getting around to doing the draw. This is similar to why programs give a bonus to mates that are closer to the root than others.
There are a few infamous games where a program couldn't choose between several mates and ended up loosing the game. The draw problem seems to be the same issue.
The solution, of course, is to give a bonus to draws that are closer to the root. Say, 1000-Ply. (That assumes we have a 1000 point window around zero just for draw scores. Don't have to, it just makes this discussion easier.) That leads to issue 2.
Issue 2)
If you give a draw score a non-zero value, then that means a draw can have a negative score, after its been backed up the search and negated by NegaMax.
That seems to be absurd. It shouldn't be negative. A draw is a draw, no matter who plays it. It's not bad or good. It simply 'is'.
You can ignore that, but that leads to issue 3.
Issue 3)
If you allow a draw score to be negative, then that causes problems for the search. You end up with cases where shorter or longer draws appear better because of the sign.
Assume, for example, that we search ply 1 move 1 and discover that it has a draw score of "draw in 2 moves", or 9998 in this scoring system. That score backs up to the first ply and it becomes -9998 because of the NegaMax negation.
Don't worry about the score issue. That was just off my head scores while I was writing the message.Note that more distant draws for white are favorable according to your definition, so for black less distant (more immediate) draws are more favorable, and that is what will happen. But you still have the hash issue to deal with and that is significant.
I was more concerned about trying to be clear rather than making sure I had crossed by T's and dotted my I's.
But the issue still exists whether the score is that way or the other way.
But point taken. When I do the draw scoring in my program, I'll make sure they are right.
Not within the minimax framework. If a draw in 10 is good for me, a draw in less than 10 is better for my opponent, otherwise the min-max approach won't work at all. However, I think it better to ignore the idea with one exception that we use in Crafty explained below.That sets Alpha to -9998 and beta is still at +Infinity.
Ply 1 move 2. It has a=-9998 & B=+Inf. It makes the move and recurses.
Ply 2 move 1. It has a=-inf & b=+9998. It makes the move and recurses.
Ply 3... alpha=-9998 & beta=+Inf.
We discover it's a draw. we return the score 1000-Ply = 9997
Back at ply 2 move 1, we negate that return score of 9997 to -9997. That becomes the best move.
There are no more moves at ply 2, so we back up to ply 1.
Back at ply 1, that score of -9997 gets negated by NegaMax and becomes 9997.
So, now at ply 1, we have a case where a draw in two moves has a score of -9998 and a draw in 3 moves has a score of 9997.
Because the draws happened on different plies, they got negated a different number of times and the result is the signs are different.
This causes the search to pick draws at odd plies over draws at even plies. In other words, with this method, it prefers a draw at ply 33 over a draw at ply 2.
That's not right behavior. A draw is a draw. It doesn't matter who does it. (ie: what ply.)
Draw in 10 moves vs. draw in 20 moves or some such is one thing.
But when you start getting into negative draw scores (because of NegaMax), then something isn't right.
That's the issue... Draws *aren't* bad. They simply are. They are the same to both sides.
So - draw scores are perfectly OK, they just represent cases where the _other side_ is forcing the draw, probably meaning you are unhappy about it. That is exactly how positional scores work if you think about it.
Sure, one side may want to postpone it, and pick the furthest. That's to be expected and NegaMax works fine for that.
But when it start negating it, that's when other problems start to show up.
You are way over-analyzing this. Minmax simply finds the best score for me, period. If a draw is better than everything else, it will find it. If a draw is worse than everything else, it will not follow that path. And the same logic works for the opponent as well. So in reality, it is exactly like checkmate, or any other positional score. You want the largest score you can force your opponent to accept, he wants the smallest score he can force you to accept.
It's not like checkmate, where it's important who gets mated. A draw simply 'is'. It happens equally to both players.
mate. draw. or positional. They all work exactly the same.
What do you base that on? Can mate scores be negative? Why? What about positional scores? If those can be negative, what is different about a draw?
A draw score should never be negative.
The only exception I have to drawscore = 0 happens for two conditions:
Issue 4)
Fixing #3 means not negating draw scores. Leaving draw scores always positive. Solves that. We have to keep a draw score always seperate from a heuristic score, hence the use of the 1000 point window around zero. We could use a flag passed back. That'd work just as well.
However, doing that fix also means we have to *always* be sure and not negate the draw scores. Including where we recurse and swap & negate the alpha & beta scores.
At this point I've got 3 fixes for what seemed to be a simple issue.
It's starting to get complicated and when a solution starts getting this complicated, you know something is wrong with your original thought. It's time to rethink. Or ask for help.
So, if something is wrong with my reasoning, then I must be an idiot because it looks like the reasoning is sound.
I've gone through the search process and looked at the bounds and what the scores can be (including fail-soft), and it sure looks to me like getting the right draw score is not an easy thing to do.
I know most programs don't bother with all this. (I haven't checked all of them, but a few. I don't really like browsing other programs to see how they do things, though.)
And I haven't seen any discussion about these kinds of problems. (I did browse through the CCC archives and didn't see anything there or on other web sites. I did, however, see a comment by Prof. Hyatt about draw scores getting very deep because of the hash table. But artificially limiting draw depth scores to 100 plies should solve that. You end up with issue 1 above, but for draws 100 plies away that's not really a big problem.)
So maybe the other programs just don't bother to fix the initial problem? Figuring that it's such a small problem that it's not worth the complicated fixes to make sure it always picks the best draw move?
Do they figure one draw is as good as the next, or do they not care the program will prefer draws at odd plies over even plies?
Or have I missed something obvious. (That's most likely...)
I looked for articles on dealing with exact vs. inexact scores, but all I found were a few references to some papers by Beal and to one by Slate.
This whole thing just doesn't seem to be discussed much.
(1) my draw score is dynamic (and the user can adjust it also as in "contempt setting".) But, in general, a draw score should reflect the preferred outcome based on your and your opponent's ratings. For crafty, against a weaker opponent, I have more "contempt" and will work harder to avoid draws because the drawscore goes more negative as crafty's rating goes above the opponent's rating. Ditto for the inverse case where I would prefer to draw a much higher rated opponent.
2. For endgame table draws, I would prefer a drawn KRP vs KR over a drawn KR vs KR ending. And often crafty gets to make that decision. In crafty a drawscore of 0 means drawn, material is even. A drawscore of +1 means draw, program is ahead in material. A score of -1 (-.01 of course) says the program is behind in material. The idea is that given the choice of two draws, I'd like to either take the one where my opponent has the chance to make mistakes and actually lose, or where he has to at least think and perhaps get into a bit of time trouble and then make a more serious mistake.
Alright. So if I understand you, because all draws are 0 (with the above exceptions), you are willing to allow a draw in 3 moves to have the same backed up score as a draw in 33 moves?
correct.
With hashing, I can't find the shortest draw, because we don't hash path information into the signature. So it isn't a matter of "don't care" but a matter of "simply no can do..."
You don't care whether you find the shortest draw or not?
Unless you have a bug, a draw is a draw is a draw. Doesn't matter whether it is a repetition, a 50-move rule draw, or an insufficient material draw...
You accept that in a game that if you play a move with a draw score, that for your next move you may not be able to find the same drawing line? That you might pick a longer drawing line?
By not going toward the shortest mate, they made a mistake. But what could go wrong with not going toward _any_ draw? You might draw the game another way??? Again, a draw is a draw is a draw. Against humans we were trying to capitalize on "meat makes mistakes" and go for the longest draw to give our opponent the most chances to make a mistake. But even that didn't work reliably as I have mentioned.
To me, that seems almost as dangerous as the mate problem that made CoKo III loose because it had so many choices. It passed up a mate in 1 to try for other mates. And kept going back & forth.
Trust me, it is OK. negamax is a mind-bending algorithm until you get comfortable with it. Then it is like breathing or eating, it seems natural.
I don't dispute your program's ability. If I'm lucky, my program might play half as well as yours by the time I'm done.
You are the better programmer. You are the better chess player. You have far more chess programming experience than I do.
But it still seems like it's wrong.