|
Did Vasik really copied Fruit's time control ?
Mark Watkins
6.3.2 Time management
In this section, I largely refer to Rick Fadden's 32-bit Rybka 1.0 Beta disassembly
efforts at http://www.talkchess.com/forum/viewtopic.php?p=187290.
I find Fadden's decompilation to be very precise. For instance, he keeps all the variables (such as btime/wtime/binc/winc) in the same order as in the ASM code.
First of all we like to point out 3 errors in the reversed engineered Fadden code.
Handling "wtime" and "btime" doesn't mention 5 seconds (5000) are subtracted as the assembler shows
.text:0040961F mov edi, offset aWtime ; "wtime" .text:00409624 mov esi, ebp .text:00409626 mov ecx, 6 .text:0040962B xor eax, eax .text:0040962D repe cmpsb .text:0040962F jnz short loc_409653 .text:00409631 push offset asc_661F8C .text:00409636 push ebx .text:00409637 call _strtok .text:0040963C push eax .text:0040963D call j__atol .text:00409642 add esp, 0Ch .text:00409645 sub eax, 1388h ; 5000 .text:0040964A mov [esp+2Ch+var_C], eax ; wtime - 5000 (not in Fadden decompile) .text:0040964E jmp loc_4097AC ; FRUIT : wtime = double(atoi(ptr)) / 1000.0;
Same for "btime", Fadden only states:
if (!strcmp (ptr,"btime")) { ptr = strtok (NULL," "); btime = atoi (ptr);
And does not mention the 5000 subtraction.
The second error we notable find in the most discussed instruction of Rybka 1.0 case the notorious 0.0 comparison.
Mark Watkins - The subsequent lines in Fadden's Rybka 1.0 Beta decompilation have:
// Rybka compares movetime with a double precision value: 0.0
if (movetime >= 0.0) {
time_limit_1 = 5 * movetime;
time_limit_2 = 1000 * movetime;
However the assembler code tells us otherwise, the right interpreation of the code is not
if (movetime >= 0.0) but
if (movetime > 0.0) as the hex-rays decomplie also shows.
.text:004097E6 fild [esp+2Ch+var_14] ; if (movetime > 0.0) .text:004097EA fcomp ds:dbl_6623D0 .text:004097F0 fnstsw ax
.text:004097F2 test ah, 41h ; test CO and C3 flags FPU status word .text:004097F5 jnz short x10 ; take jump when <= .text:004097F7 lea ecx, [esi+esi*4] ; time_limit_1 = 5 * movetime; .text:004097FA imul esi, 3E8h ; time_limit_2 = 1000 * movetime; .text:00409800 mov dword_667A18, ecx ; store time_limit_1 to memory .text:00409806 mov dword_667A1C, esi ; store time_limit_2 to memory .text:0040980C jmp short x50 ; done
For those not familiar with FPU instructions we like to point to the 64 compile that uses the more common PC flags and states a JBE (jump when less or equal).
And as already pointed out elsewhere 0.0 can not be proven only 0. or .0
That makes 2 problems on the most hottest discussed instruction that was undeniable proof for code theft.
Third error is another sign mistake and again in a part that makes Rybka more Fruitish.
FADDEN decomplie Real Rybka code
|
alloc = (time_max + inc * (movestogo - 1)) / 2; if (alloc < time_limit_1) alloc = time_limit_1; if (alloc > time_max) alloc = time_max; time_limit_2 = alloc; |
time_max = time - 5000; // not in Fruit
alloc = (inc * (movestogo - 1) + time_max)) / 2; if (alloc <= time_limit_1) alloc = time_limit_1; if (alloc >= time_max) alloc = time_max; time_limit_2 = alloc;
|
FRUIT
alloc = (time_max + inc * double(movestogo-1)) * 0.5; if (alloc < SearchInput->time_limit_1) alloc = SearchInput->time_limit_1; if (alloc > time_max) alloc = time_max; SearchInput->time_limit_2 = alloc;
|
Furthermore we like to stress out the differences between the Fruit and Rybka time control.
-
The initialization code at the start, Fruit uses -1, Rybka 0.
-
Fruit while parsing immediately converts to seconds (/1000) (wtime/btime/winc/binc).
-
Fruit does not subtract 5 seconds from wtime/btime as Rybka does. Why Rybka does this remains a mystery for the moment. There is another odd 5 seconds subtraction in Rybka's movestogo part [ time_max = time - 5000; ] which clearly makes it unique to Fruit's way of handling things.
-
Fruit has the UCI options Mate, nodes, searchmoves coded. Rybka has no such code.
-
Fruit reports error messages, Rybka has no such code.
-
Fruit has: if (string_equal(ptr,"infinite")) While Rybka checks for "is_infinite";
-
Rybka's special sentinel baptized by Fadden as depthLimit = 0x7FFFFFFF is as also found in the pre-Rybka's but not in Fruit, another sign the time control code is original.
-
But most important the order of coding is totally different and does not show an obvious trace of code copying.
RYBKA PARSING ORDER FRUIT PARSING ORDER 1. winc binc (/1000) 2. wtime (-5000) btime (/1000) 3. binc depth 4. btime (-5000) infinite 5. depth mate not in Rybka 6. infinite movestogo 7. movestogo movetime 8. movetime nodes not in Rybka 9. ponder ponder 10. searchmoves not in Rybka 11. winc (/1000) 12. wtime (/1000)
If we look at the initialization code of these UCI parameters we get:
RYBKA FRUIT
winc = 0; binc = -1.0; wtime = 0; btime = -1.0; binc = 0; movetime = -1.0; btime = 0; winc = -1.0; movetime = 0; wtime = -1.0;
Also not the same order.
Same for the initialization code of the UCI option "movestogo", it is initialized different and also the final calculated timers for search();
RYBKA FRUIT
movestogo = 25; movestogo = -1; time_limit_1 = -1; no code
time_limit_2 = -1; no code
Lastly, Rybka uses a lot of variables in its time control Fruit does not use at all. Although given fancy names by Fadden (ignoreClockFlag, depthLimit, stopSearch etc.) no reference nor description is given to its meaning.
RYBKA FRUIT
ignoreClockFlag no such code
depthLimit no such code
stopSearch no such code
nodeTickLow = 1024; no such code
bestMove = 0; no such code
moveScore = 0; no such code
depthScore = 0; no such code
bad_1 = 0; no such code
bad_2 = 0; no such code
change = 0; no such code
easy = 0; no such code
clackFlag = 0; no such code
nodeTickHigh = 1; no such code
Ironic
BUG 1 - We pitched the 2 rivals Rybka 1.0 beta and Fruit 2.1 at a time control of 1 minute for the whole game and after 32 games Rybka had lost 6 games of time forfeit while Fruit lost none.
As for an educated guess, it feels as if Vasik was trying to fix a bad time control concept creating an extra 5 seconds buffer (the odd 5 second subtractions) that would solve most (but never all) of the time forfeit problems. It does not feel as a copy and paste job at all.
BUG 2 - Furthermore set the time control to "5 seconds fixed time" and notice Rybka 1.0 doesn't move after 5 seconds. Fruit does.
The Rybka time_limit_2 = 1000 * movetime; instruction is definitely wrong.
Copy Fruit and then introduce 2 bugs in 10 lines of code is hardly a valid accusation.
Mark Watkins - The first item to mention is that it already seems not completely natural to place the time management code at the end of the "go" parser as done in both Fruit 2.1 and Rybka 1.0 Beta.
We might agree with Watkins it is quite well possible that Vas borrowed the "start search" idea from Fruit, perhaps the movestogo formula as well but to conclude that the Fruit time control was copied is a couple of bridges too far to our taste, what immediately springs in mind here are not the similarities [ we all use some sort of minimum, average and maximum time variables] but the differences, the frequent losses on time forfeit, this aside of the decompiltaion errors that were made.
|