Hashing and mate scores

Discussion of chess software programming and technical issues.

Moderator: Ras

User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Hashing and mate scores

Post by hgm »

bob wrote:First, infinity means infinity, which is simply the largest number possible. In 16 bit ints, +infinity becomes 32767 because no numbers are larger.
Well, it could mean that here. But, as I explained, that dos not mean that -INFINITY would be the most negative number possible. That would be -INFINITY-1...
But my point here is that the term itself, means a number such that there is no larger number as in infinity+1. If infinity+1 is possible, then "infinity" is being incorrectly used. In the case of a tree search +infinity (by definition in alpha/beta tree searching as defined by Newell, Shaw and Simon) is a value that bounds all possible scores, so that no score can ever be greater than or even equal to +infinity.
Same here. No score can ever be greater than infinity or smaller than -INFINITY. That is quite another definition that the one you gave in the sentence before, though. Which is just as well, as the first one seems to make little sense. On a computer there are always larger integers. If not in the current type, then in a longer type, or an unsigned one. Any mathematician knows that infinity is not a an element of the set of natural numbers, and a number with the propertyy you require simply does not exist.
And note that even equal to is critical else you would get fail highs you could not resolve.

I just want to use a term in its correct sense because if I were looking at something and saw a number represented to be larger than +infinity, I would have to scratch my head and wonder what on earth they are talking about.
Well, as INFINITY here is compatible with +32767 I have _no idea_ what you are fussing about. Starts to look more and more like simple stalking / harassment.
BTW, in the alpha/beta framework, going from +32767 to -32768 by adding +1 is not "quite ok". It will totally screw up searches that use that way wrong bound.
Totally _wrong_! If -INFINITY satisfies your second definition (any score is strictly larger) then -INFINITY-1 satisfies it too. Only if you would also pass your Search() arguments Alpha and Beta as short int, you would have to be careful not to push it to the limit, and make sure you don't pass an unrepresentable value for Beta. uMax would never do that, as it passes minus the maximum of Alpha and BestScore, and BestScore would nbnever be lower than -INFINITY. (I don't want to up Alpha there, as I need it for the next IID iteration.) And of course it passes Beta as in int, so everything upto 2G would be representable.
User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Hashing and mate scores

Post by hgm »

Karlo Bala wrote:I think that best way for testing hash tables is testing with KRK endgames.
Lot of engines can not find shortest mate in analyze mode.


It seems that uMax have problem to find shortest mate....
Yes, you are right. But that is not because of the mentioned mechanism (which I included mainly not for finding shortest path to mate, but make it more decisive in cashing gains before it lets them evaporate). Like Chan Rasjid I also stop deepening after the first mate score, by setting the iteration number to 98 (the highest allowed number, after which deepening stops):
C:if(m>I-M|m<-I+M)d=98; /* mate is indep. of depth */
which is uMax speak for:
cutoff:
if(BestScore > MATESCORES | BestScore < -MATESCORES) IterDepth = 98;
I did this to make sure that mate scores would give hash hits to any depth. But it basically makes it stop deepening at the first mate it finds. And the shortest mate is not always found first. In the older uMax versions this was hardly ever a problem, as they did clear the hash between moves, and ID starting from scratch usually finds the fastest mates first, as the slower mates are simply beyond the horizon (especially in the versions that have no check-extension either). But now that implemented KeepHash it gets easily confused:

If there is a mate-in-3, and it plays the first move, the d=1 iteration of the next move might hit upon a mate-in-5 hash entry from a previous search. And then it immediately plays that move, without ever deepening to the d=3 that would be needed to find the (now) mate-in-2. Note that the move leading to this mate might experience a hash miss at d=1, because the entry is overwritten.

Also note that uMax does not implement the full mechanism described here: it refrains from adapting Beta, to safe some characters. And it decrements Alpha unconditionally. That means the search window might be unnecessary large, but that never leads to fatal errors. Just to a bit of performance loss in unlucky cases.

In Joker I really implemented the full mechanism as described here. There I stop deepening as soon as the reported DTM is equal to the number of ply searched. Even this is not a hard guarantee, as with LMR and NMP there might still be mates beyond the horizon. But I have never seen this cause any problem.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Hashing and mate scores

Post by bob »

hgm wrote:
bob wrote:First, infinity means infinity, which is simply the largest number possible. In 16 bit ints, +infinity becomes 32767 because no numbers are larger.
Well, it could mean that here. But, as I explained, that dos not mean that -INFINITY would be the most negative number possible. That would be -INFINITY-1...
:)

As my old calc teacher rolls over in his grave. :)


But my point here is that the term itself, means a number such that there is no larger number as in infinity+1. If infinity+1 is possible, then "infinity" is being incorrectly used. In the case of a tree search +infinity (by definition in alpha/beta tree searching as defined by Newell, Shaw and Simon) is a value that bounds all possible scores, so that no score can ever be greater than or even equal to +infinity.
Same here. No score can ever be greater than infinity or smaller than -INFINITY. That is quite another definition that the one you gave in the sentence before, though. Which is just as well, as the first one seems to make little sense. On a computer there are always larger integers. If not in the current type, then in a longer type, or an unsigned one. Any mathematician knows that infinity is not a an element of the set of natural numbers, and a number with the propertyy you require simply does not exist.

The mathematical term for infinity means one thing. For things like alpha/beta it means something similar but not exactly the same thing. In the general sense, -infinity is the smallest number that is possible, and for obvious reasons in the theoretical world it is not a specific value else one could always subtract 1 from it. But for alpha/beta, the -infinity,+infinity bounds are simply defined as two values that are guaranteed to bracket all scores produced in the tree search. So that no score can be outside that window, nor even equal to either of the two edge boundaries.

I have had occasions where my program would produce scores outside that bound, and it would produce an infinite number of fail lows or fail highs until time was exhausted. It was always the result of an undefined variable (usually a subscript that was computed) that produced an evaluation that was technically impossible. If a real search produces a value outside this window, the results of alpha/beta are undefined, which was my main concern.
And note that even equal to is critical else you would get fail highs you could not resolve.

I just want to use a term in its correct sense because if I were looking at something and saw a number represented to be larger than +infinity, I would have to scratch my head and wonder what on earth they are talking about.
Well, as INFINITY here is compatible with +32767 I have _no idea_ what you are fussing about. Starts to look more and more like simple stalking / harassment.
Not trying to stalk or harass at all. But when you use an expression like -INFINITY-1, I find that difficult to understand and I would certainly not encourage a beginner to use a methodology where that happens. As the old 15th century sea maps use to say "here there be dragons..."



BTW, in the alpha/beta framework, going from +32767 to -32768 by adding +1 is not "quite ok". It will totally screw up searches that use that way wrong bound.
Totally _wrong_! If -INFINITY satisfies your second definition (any score is strictly larger) then -INFINITY-1 satisfies it too. Only if you would also pass your Search() arguments Alpha and Beta as short int, you would have to be careful not to push it to the limit, and make sure you don't pass an unrepresentable value for Beta. uMax would never do that, as it passes minus the maximum of Alpha and BestScore, and BestScore would nbnever be lower than -INFINITY. (I don't want to up Alpha there, as I need it for the next IID iteration.) And of course it passes Beta as in int, so everything upto 2G would be representable.
Not totally wrong. alpha/beta is undefined for values outside the initial search window, which is in this case -INF, +INF. Just because you like to muck around with your bounds and have found a way to make it work doesn't make it logical, or natural, and when I look at a tree dump and see values outside the initial window, I immediately start searching for the bug that produced such a score because it just doesn't happen in a real alpha/beta framework. Apparently you have a "sorta-alpha-beta search" which is OK if it works. But it certainly is not clear when you see such values.
User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Hashing and mate scores

Post by hgm »

Yes, if you don't aspirate, no score should ever lie outside the initial window. INFINITY is chosen to guarantee that. If you now enlarge the window, this will certainly remain true. So I don't see whyou try to make such a fuss out of this. Evry pseudo-code I have seen on this uses the name INFINITY for this. Everyone knows that computers do not support this for integers, and that INFINITY thus must be some finite numner, and that INFINITY+1 thus exists. If not in this integer type, then in a longer one.

I have _no_ scores in my tree outside the range (-INFINITY, +INFINITY).

The search window can shift outside this range, though. This is exactly why / how it works. At some point you will need an _impossible_ score to NOT get a fail low or fail high, as the window has shifted entirely to below -INF or above +INF. So you can take the beta cutoff or a super-deep futility pruning without searching annything, as the score cannot possilbly reach the window. So you know on which side of the window all scores are going to be, and return an maximum or minimum allowed score. Note that scores are only mucked _towards_ CurEval, which always is far away from the MATINGSCORE range, somewhere in the interior of the window.

If I debug, I print the window in any node I examine. I have to do that anyway, as not every node has the same window as the root. I never experienced this as a problem. I catch invalid evals as easily as you do.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Hashing and mate scores

Post by bob »

hgm wrote:Yes, if you don't aspirate, no score should ever lie outside the initial window. INFINITY is chosen to guarantee that. If you now enlarge the window, this will certainly remain true. So I don't see whyou try to make such a fuss out of this. Evry pseudo-code I have seen on this uses the name INFINITY for this. Everyone knows that computers do not support this for integers, and that INFINITY thus must be some finite numner, and that INFINITY+1 thus exists. If not in this integer type, then in a longer one.

I have _no_ scores in my tree outside the range (-INFINITY, +INFINITY).

What about the -infinity-1 that showed up previously???

The search window can shift outside this range, though. This is exactly why / how it works. At some point you will need an _impossible_ score to NOT get a fail low or fail high, as the window has shifted entirely to below -INF or above +INF. So you can take the beta cutoff or a super-deep futility pruning without searching annything, as the score cannot possilbly reach the window. So you know on which side of the window all scores are going to be, and return an maximum or minimum allowed score. Note that scores are only mucked _towards_ CurEval, which always is far away from the MATINGSCORE range, somewhere in the interior of the window.

That is what I don't like. In order to interpret a tree dump from such a program, you have to work your way from the root down to see how the bounds are either being mucked with by the search, or backed up. That looks confusing compared to a normal alpha/beta searcher where you can look at the root to see the bounds, and then you see those same identical bounds everywhere in the tree dump unless a new score is getting backed up. Makes it much easer to follow. And as I mentioned, should someone want to try mtd(f) it makes it _far_ easier to do.


If I debug, I print the window in any node I examine. I have to do that anyway, as not every node has the same window as the root. I never experienced this as a problem. I catch invalid evals as easily as you do.
Hmm... I can scroll thru several thousand lines of tree dump and quickly pick out the very few places where a window is changed. I only have two values to look for, anything else represents something backing up. How can you do that when your bounds change every level downward n the tree?
User avatar
hgm
Posts: 28354
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Hashing and mate scores

Post by hgm »

bob wrote:What about the -infinity-1 that showed up previously???
That did not show up as a score. It showed up as a window bound.

The search window can shift outside this range, though. This is exactly why / how it works. At some point you will need an _impossible_ score to NOT get a fail low or fail high, as the window has shifted entirely to below -INF or above +INF. So you can take the beta cutoff or a super-deep futility pruning without searching annything, as the score cannot possilbly reach the window. So you know on which side of the window all scores are going to be, and return an maximum or minimum allowed score. Note that scores are only mucked _towards_ CurEval, which always is far away from the MATINGSCORE range, somewhere in the interior of the window.

That is what I don't like. In order to interpret a tree dump from such a program, you have to work your way from the root down to see how the bounds are either being mucked with by the search, or backed up. That looks confusing compared to a normal alpha/beta searcher where you can look at the root to see the bounds, and then you see those same identical bounds everywhere in the tree dump unless a new score is getting backed up. Makes it much easer to follow. And as I mentioned, should someone want to try mtd(f) it makes it _far_ easier to do.

Hmm... I can scroll thru several thousand lines of tree dump and quickly pick out the very few places where a window is changed.
That is probably because you use PVS. On alpha-beta they change much more often.
I only have two values to look for, anything else represents something backing up. How can you do that when your bounds change every level downward n the tree?
I haven't done such things for a very long time, once I got it working. (probably because I haven't tried my hand at SMP yet... :lol: ) I simply never have errors related to window bounds. Even when I am sure that I must have a search error, as the score in the root makes no sense at all, when I finally follow the branch it turns out that it was indeed the (mucked up!) score f the evaluation that made no sense whatsoever.
Chan Rasjid
Posts: 588
Joined: Thu Mar 09, 2006 4:47 pm
Location: Singapore

Re: Hashing and mate scores

Post by Chan Rasjid »

The following is simple reading and does not need much thinking.

An idea is easy after we have the understanding and difficult when we do not yet grasp it in proper perspective. I wish to add another easy approach to understand Muller's pseudo codes that involve shifting mate scores, alpha, beta by +1 / -1 and also some other things.

Alpha-beta search() uses a range of integers (-infi, +inf) to represent something call "scores". Scores have a non-mate range where :-
100 = 1 pawn advantage,
-300 = a bishop disadvantage, ....
and they represent likelihood of winning or losing the game. search() is recursive and passes a score on return and on calling search(), it passes up two score arguments in alpha, beta which are score bounds. Passing non-mate scores around in search() present no inherent problem as they may be interpreted consistently relative to any nodes in the chess tree. But this is true only generally.

Say we made a great discovery about evaluation in chess programming. It involves using a huge 8MB tables that is used to scale the value of pieces. And it need to scale in strange manners. Besides other conditions, a queen = 900 at root and scales to 1800 at ply 127. Rook scales downwards, worth 500 at ply 127 and worth 350 at root. Bishops... Knights...etc.
We call score= eval(ply) and then we got stuck. This number can neither be passed downwards nor upwards in the usual manner. If alpha = 125 is passed up as argument and it travels 20 plies up, then when interpreted, the number 125 has another meaning. Numbers don't get passed around together with consistent meaning. We may need to do score mappings ,and maybe inverse mappings, to get our great idea to work with alpha-beta.

Getting back to mate scores. In the consistent score method(10000 - D), x =-infi + 50 represent a checkmate node at ply 50 relative to root. If x is passed around by search(), it is ok as it can be interpreted consistently at every node of the chess tree. In the inconsistent score method, -infi = checkmate, mate in 1/2/3/4... is -inf+1,-inf+2,-inf+3,-inf+4, but relative to a node. If search() at ply = 7 somehow got hold of a number x =-infi + 50 and passed x upwards, and if it propagates 25 plies up and got interpreted as mate-in-fifty relative to that node, the meaning is wrong by 25 mates. This explains why in Muller's pseudo codes, there is a need to adjust scores with x = x+1 and x = x-1

Best Regards,
Rasjid
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Hashing and mate scores

Post by Karlo Bala »

hgm wrote:
Karlo Bala wrote:I think that best way for testing hash tables is testing with KRK endgames.
Lot of engines can not find shortest mate in analyze mode.


It seems that uMax have problem to find shortest mate....
Yes, you are right. But that is not because of the mentioned mechanism (which I included mainly not for finding shortest path to mate, but make it more decisive in cashing gains before it lets them evaporate). Like Chan Rasjid I also stop deepening after the first mate score, by setting the iteration number to 98 (the highest allowed number, after which deepening stops):
C:if(m>I-M|m<-I+M)d=98; /* mate is indep. of depth */
which is uMax speak for:
cutoff:
if(BestScore > MATESCORES | BestScore < -MATESCORES) IterDepth = 98;
I did this to make sure that mate scores would give hash hits to any depth. But it basically makes it stop deepening at the first mate it finds. And the shortest mate is not always found first. In the older uMax versions this was hardly ever a problem, as they did clear the hash between moves, and ID starting from scratch usually finds the fastest mates first, as the slower mates are simply beyond the horizon (especially in the versions that have no check-extension either). But now that implemented KeepHash it gets easily confused:

If there is a mate-in-3, and it plays the first move, the d=1 iteration of the next move might hit upon a mate-in-5 hash entry from a previous search. And then it immediately plays that move, without ever deepening to the d=3 that would be needed to find the (now) mate-in-2. Note that the move leading to this mate might experience a hash miss at d=1, because the entry is overwritten.

Also note that uMax does not implement the full mechanism described here: it refrains from adapting Beta, to safe some characters. And it decrements Alpha unconditionally. That means the search window might be unnecessary large, but that never leads to fatal errors. Just to a bit of performance loss in unlucky cases.

In Joker I really implemented the full mechanism as described here. There I stop deepening as soon as the reported DTM is equal to the number of ply searched. Even this is not a hard guarantee, as with LMR and NMP there might still be mates beyond the horizon. But I have never seen this cause any problem.
To be honest, my intention was to test Joker, but I couldn't setup position within arena.

I have lot to say, but my English is limited :-(
Best Regards,
Karlo Balla Jr.
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Hashing and mate scores

Post by Karlo Bala »

Chan Rasjid wrote:The following is simple reading and does not need much thinking.

An idea is easy after we have the understanding and difficult when we do not yet grasp it in proper perspective. I wish to add another easy approach to understand Muller's pseudo codes that involve shifting mate scores, alpha, beta by +1 / -1 and also some other things.

Alpha-beta search() uses a range of integers (-infi, +inf) to represent something call "scores". Scores have a non-mate range where :-
100 = 1 pawn advantage,
-300 = a bishop disadvantage, ....
and they represent likelihood of winning or losing the game. search() is recursive and passes a score on return and on calling search(), it passes up two score arguments in alpha, beta which are score bounds. Passing non-mate scores around in search() present no inherent problem as they may be interpreted consistently relative to any nodes in the chess tree. But this is true only generally.

Say we made a great discovery about evaluation in chess programming. It involves using a huge 8MB tables that is used to scale the value of pieces. And it need to scale in strange manners. Besides other conditions, a queen = 900 at root and scales to 1800 at ply 127. Rook scales downwards, worth 500 at ply 127 and worth 350 at root. Bishops... Knights...etc.
We call score= eval(ply) and then we got stuck. This number can neither be passed downwards nor upwards in the usual manner. If alpha = 125 is passed up as argument and it travels 20 plies up, then when interpreted, the number 125 has another meaning. Numbers don't get passed around together with consistent meaning. We may need to do score mappings ,and maybe inverse mappings, to get our great idea to work with alpha-beta.

Getting back to mate scores. In the consistent score method(10000 - D), x =-infi + 50 represent a checkmate node at ply 50 relative to root. If x is passed around by search(), it is ok as it can be interpreted consistently at every node of the chess tree. In the inconsistent score method, -infi = checkmate, mate in 1/2/3/4... is -inf+1,-inf+2,-inf+3,-inf+4, but relative to a node. If search() at ply = 7 somehow got hold of a number x =-infi + 50 and passed x upwards, and if it propagates 25 plies up and got interpreted as mate-in-fifty relative to that node, the meaning is wrong by 25 mates. This explains why in Muller's pseudo codes, there is a need to adjust scores with x = x+1 and x = x-1

Best Regards,
Rasjid
Yes, that is perfectly OK in plain AB, but I'm curios how it interacts with HT?
Not just how to put score int HT but also how to retrieve?
Best Regards,
Karlo Balla Jr.
Karlo Bala
Posts: 373
Joined: Wed Mar 22, 2006 10:17 am
Location: Novi Sad, Serbia
Full name: Karlo Balla

Re: Hashing and mate scores

Post by Karlo Bala »

BTW the output you posted certainly suggests serious bugs in the hashing he is using. You should never see M5, M3, M4, M5 type results. That is broken and can lead to draws.
Yes, that was one of my points.
But it seems that old crafty have some problems also. First it found +mate 24, than +mate 29, than +mate 26
My program had similar problems when using aspiration windows, but you probably know better why it is.

Code: Select all

FEN: 8/8/8/8/3k4/8/8/4K2R w - - 0 1 

Crafty_1919:
   8	00:00	     125.029	1.136.627	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2
   9	00:00	     133.183	887.886	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Rg8
   9	00:00	     252.341	1.009.364	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Rg8
  10	00:00	     262.385	1.009.173	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Rg8 Ka1
  10	00:00	     516.534	1.033.068	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Rg8 Ka1
  11	00:00	     531.918	1.042.976	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Kd2 Kb1 6. Kc3
  11	00:01	     977.753	1.086.392	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Kd2 Kb1 6. Kc3
  12	00:01	   1.035.219	1.089.704	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Kd2 Kb1 6. Kc3 Ka2
  12	00:01	   1.684.849	1.059.653	+6.21	1. Rh8 Kc3 2. Rg8 Kb2 3. Rf8 Ka1 4. Rh8 Ka2 5. Kd2 Kb1 6. Kc3 Ka2
  13	00:01	   1.769.949	1.047.307	+6.21	1. Rh8 Kc3 2. Rg8 Kb3 3. Rg4 Kc3 4. Ke2 Kc2 5. Kf3 Kc1 6. Ra4 Kc2 7. Ke3
  13	00:02	   2.568.902	954.982	+6.21	1. Rh8 Kc3 2. Rg8 Kb3 3. Rg4 Kc3 4. Ke2 Kc2 5. Kf3 Kc1 6. Ra4 Kc2 7. Ke3
  14	00:03	   2.674.075	958.449	+6.21	1. Rh8 Kc3 2. Rg8 Kd3 3. Rf8 Kc4 4. Kd2 Kb4 5. Rf5 Kc4 6. Ke3 Kb3 7. Kd3 Ka2
  14	00:04	   4.764.055	954.720	+6.21	1. Rh8 Kc3 2. Rg8 Kd3 3. Rf8 Kc4 4. Kd2 Kb4 5. Rf5 Kc4 6. Ke3 Kb3 7. Kd3 Ka2
  15	00:05	   5.383.331	980.570	+6.21	1. Rh8 Kc4 2. Rg8 Kd4 3. Rf8 Kc4 4. Kd2 <HT>
  15	00:07	   7.822.778	1.009.390	+6.61	1. Rh5!!
  15	00:08	   8.360.881	1.014.670	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kh2 5. Ke3 Kg3 6. Rb8 Kh2 7. Kf3 Kg1 8. Rb4
  15	00:08	   8.841.488	1.011.611	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kh2 5. Ke3 Kg3 6. Rb8 Kh2 7. Kf3 Kg1 8. Rb4
  16	00:08	   8.874.108	1.015.344	+6.61	1. Rh5!!
  16	00:09	   9.426.450	1.019.075	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kh2 5. Ke3 Kg3 6. Rb8 Kg2 7. Rf8 Kg1 8. Kd3 Kh1
  16	00:17	  17.738.093	1.028.295	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kh2 5. Ke3 Kg3 6. Rb8 Kg2 7. Rf8 Kg1 8. Kd3 Kh1
  17	00:17	  17.960.830	1.041.207	+6.61	1. Rh5!!
  17	00:17	  18.023.258	1.044.826	+7.61	1. Rh5!!
  17	00:18	  19.313.514	1.043.973	+9.61	1. Rh5!!
  17	00:30	  29.609.275	986.975	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kf3 5. Kd3 Kf2 6. Kc3 Kg2 7. Kd4 Kg1 8. Ke3 Kf1 9. Kd3
  17	03:39	 244.739.193	1.117.530	+6.21	1. Rh5 Ke3 2. Rh4 Kf3 3. Kd2 Kg3 4. Rb4 Kf3 5. Kd3 Kf2 6. Kc3 Kg2 7. Kd4 Kg1 8. Ke3 Kf1 9. Kd3
  18	03:40	 245.249.179	1.114.768	+6.61	1. Rh5!!
  18	03:40	 245.288.661	1.114.948	+7.61	1. Rh5!!
  18	03:40	 245.356.639	1.115.257	+9.61	1. Rh5!!
  18	03:59	 267.181.341	1.117.913	+M24	1. Rh5 Ke4 2. Kf2 Kf4 3. Rc5 Ke4 4. Kg3 Kd4 5. Rg5 Ke4 6. Rh5 <HT>
  18	05:51	 379.323.950	1.080.695	+M24	1. Rh5 Ke4 2. Kf2 Kf4 3. Rc5 Ke4 4. Kg3 Kd4 5. Rg5 Ke4 6. Rh5 <HT>
  19	08:51	 545.326.189	1.026.979	+M29	1. Rh5 Ke4 2. Kf2 Kf4 3. Rc5 Ke4 4. Rg5 Kf4 5. Rh5 Kg4 <HT>
  19	18:15	 950.415.453	867.959	+M29	1. Rh5 Ke4 2. Kf2 Kf4 3. Rc5 Ke4 4. Rg5 Kf4 5. Rh5 Kg4 <HT>
  20	21:10	1.091.913.646	859.774	+M26	1. Rh5 Ke4 2. Kf2 Kf4 3. Ra5 Ke4 4. Kg3 Ke3 5. Re5+ Kd4 6. Kf4 Kd3 7. Kf3 <HT>

Best Regards,
Karlo Balla Jr.