Strelka Reverse Engineered from Rybka: Details Examined

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Guetti

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Guetti »

I don't know how others do it, but I assign them a score depending on the promoted piece, which makes them end up at the correct place during movesorting. This way I can generate the promotions together with the other pawn moves.
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Dann Corbit »

rfadden wrote:
Aleks Peshkov wrote:
rfadden wrote:In this thread I start by giving examples that show how Strelka is reverse engineered from Rybka.
It is a known fact, that was confirmed by Strelka's author from the very beginning about a year ago. Why should we waste time reading your long posts about reverse engineering of open source code?
The answer is: a few others were saying essentially "Show us the Details" and so as I wrote above I have started doing what these guys are asking.

In your case you don't have to read this.

Doesn't it seem that you have the choice to read or not to read...

Also, people have different interests.

I agree that you don't need to look at this at all. This is not a problem.

Thanks.

I'm continuing... I take the point about gen_captures not being the perfect example, but keep in mind that if we make it to example 89 then by that time you will see so many different routines all with this same pattern. All constants, all function arguments, the order that functions are called, the numeric constants passed to routines, they all come from the Rybka binary... I will continue showing this...

I'll be back
I want to see it. I am particularly interested in:
Things that are in Rybka and in Strelka but not in Fruit and which are unusual.
Uri Blass
Posts: 10282
Joined: Thu Mar 09, 2006 12:37 am
Location: Tel-Aviv Israel

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Uri Blass »

Guetti wrote:I don't know how others do it, but I assign them a score depending on the promoted piece, which makes them end up at the correct place during movesorting. This way I can generate the promotions together with the other pawn moves.
I think that captures by pawns should be generated before captures by other pieces because later captures by pawns have better chances to be ordered first.

The order of generating is also important because correct order of generating moves can save sorting later so the logical order is first promotions and after it captures by pawn and only after it captures by knights and other pieces.

Note that I did not test if changing the move ordering in this way cause strelka to become better and it is possible that things are counter intuitive.

Uri
User avatar
michiguel
Posts: 6401
Joined: Thu Mar 09, 2006 8:30 pm
Location: Chicago, Illinois, USA

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by michiguel »

Uri Blass wrote:
Guetti wrote:
Uri Blass wrote: The move generator of strelka generates captures in the following order:

1)Captures by knights
2)Captures by bishops
3)Captures by rooks
4)Captures by Queens
5)Captures by the king
6)promotions
7)promotions that are also captures
8)Captures by pawns.

I do not think that this order is the most logical order and if rybka has the same order then it is clearly an evidence for reverse engineering.

Uri
Sorry, but Crafty generates the moves in exactly the same order.
I do it the same in my engine. Why? The order can effect search efficiency, and since I read once Bob tested this, I simply chose the same order than him. Why invent the wheel from scratch?

Now, it is not my goal to defend a cloner, but I think you have to come up with better things for prove.
I did not look much at Crafty's code so I did not check the order that it generates captures but I see no reason to generate promotion after generating capture by small pieces.

You want the best move to be generated first because it can save you time later when you do not need to change order of moves in the move list when you pick first move to search.

A Capture that is a promotion is the best candidate to be generated first because it is probably better than other captures.

Uri
What you say is true if you have the moves in a list and you loop increasing the index to find the best. If you loop decreasing the index (from the end to the start), you will be better off generating promotions last.

Miguel
Guetti

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Guetti »

Uri Blass wrote:
Guetti wrote:I don't know how others do it, but I assign them a score depending on the promoted piece, which makes them end up at the correct place during movesorting. This way I can generate the promotions together with the other pawn moves.
I think that captures by pawns should be generated before captures by other pieces because later captures by pawns have better chances to be ordered first.

The order of generating is also important because correct order of generating moves can save sorting later so the logical order is first promotions and after it captures by pawn and only after it captures by knights and other pieces.

Note that I did not test if changing the move ordering in this way cause strelka to become better and it is possible that things are counter intuitive.

Uri
Maybe you're right. I simply did not care when I wrote this part, because I assumed the whole move list gets rearranged anyway when I sort with SEE later on.
So, to be precise I have to make a correction. The reason why I generate the captures in this order is because I simply copied the non-captures function and made the changes to generate captures. The functions are almost identical anyway with the exception of pawns.
And the reason why I generate Non-captures in this order is because Crafty does it in this order. Maybe Vas took a look at crafty too, and finally the same ended up in Strelka.
rfadden

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by rfadden »

Here is some further high level information that seemed amazing to me as I was discovering this.

I had tracked through functions in Rybka 1.0 just before I got the source to Strelka and I was looking for the information related to Node Count, since I was curious about that. I invented these function names based upon a few simple guesses such as "follow the call tree invoked by the UCI go command" and also, "functions that call themselves are likely the key recursive search routines."

I traced out the call sequence starting from the UCI "go" command and using my whacky names where I really was not "seeing" what was going on, here is some information from my notes that was later transformed surprisingly by Strlka Source:

Code: Select all

Calling Sequence

The_Go_Function
 Main_Search_Routine
  Search_Call_Lev1B
   Byte_Mask_Proc
   Long_Interesting_MaskingA
  Bi_Search_Lev1C
   Byte_Mask_Proc
  Bi_Search_Lev1D
   Byte_Mask_Proc
  Medium_MaskingA
   Sub_Something_FEN_Lev2C
  Search_Call_Lev1B
   Byte_Mask_Proc
   Long_Interesting_MaskingA
  Block_of_MaskingA
   Sub_Something_FEN_Lev2C
  Medium_MaskingA
   Sub_Something_FEN_Lev2C
  Search_Call_Lev1B
   Byte_Mask_Proc
   Long_Interesting_MaskingA
  Block_of_MaskingA
   Sub_Something_FEN_Lev2C
  Medium_MaskingA
   Sub_Something_FEN_Lev2C
  Search_Call_Lev1B
   Byte_Mask_Proc
   Long_Interesting_MaskingA
  Block_of_MaskingA
   Sub_Something_FEN_Lev2C

  Some_Search_Init
  ds:GetTickCount
  Per_Depth_Calc
   Per_Depth_Info_Disp
    Medium_MaskingA
     Sub_Something_FEN_Lev2C
    Search_Call_Lev1B
     Byte_Mask_Proc
     Long_Interesting_MaskingA
    Recurse_SearchC
     Recurse_SearchD
      Bi_Search_Lev1C
       Byte_Mask_Proc
      Major_MaskingA
       Byte_Mask_Proc
    Block_of_MaskingA
     Sub_Something_FEN_Lev2C
    Medium_MaskingA  
     Sub_Something_FEN_Lev2C
    Search_Call_Lev1B
     Byte_Mask_Proc
     Long_Interesting_MaskingA
    Recurse_SearchC
     Recurse_SearchD
      Bi_Search_Lev1C
       Byte_Mask_Proc
      Major_MaskingD
      Major_MaskingA
       Byte_Mask_Proc
      Recurse_SearchD
       Bi_Search_Lev1C
        Byte_Mask_Proc
      Recurse_SearchA
       Search_call_Lev1A
        Byte_Mask_Proc
       Recurse_SearchD
So that's the day I found the Strelka 2.0 source. So with the above as my status at that moment I went to the Strelka "go_command" and I started following the C functions that it was calling and as I walked along I used the above Rybka call sequence and at every step along the way I ran into Strelka source code that matched the Rybka binary code!

In other words I would reach a search routine in Strelka, look at it, and then look at the binary routine that is called next in Rybka and I would then see that all of the constants were the same and the code was the same, and so with that information I would then rename the Rybka function to match the Strelka name and here is what the above list turned into (actually below there are three different ways of looking at this exact matching between Rybka functions and Strelka functions).

Code: Select all

Strelka Naming

Main_Search_Routine -> Start_Search
Some_Search_init -> Setjmp
Search_call_Lev1B -> Evaluate
Long_MaskingA -> Eval_Mob     <Evaluate Mobility>

  It looks like Rybka's Eval calls Eval_Mob and Strelka includes Eval_Mob but it includes this code within its Evaluate function to avoid the call or to obfuscate.

Recurse_SearchD -> Qu_Search
Long_Interesting_MaskingA -> Pawn_Get_Info
The_Go_Function -> Start_Go
Search_Call_Lev1A -> Gen_Evasions
Bi_Search_Lev1C -> Gen_Captures
Bi_Search_Lev1D -> Gen_Quiet_Moves
Medium_MaskingA -> Move_Do
Block_of_MaskingA -> Move_Undo
Per_Depth_Calc -> Full_Root_Base  <This code is not in Strelka!>

<< Important.  Full Root Base accesses the massive 2 Megabyte Lookup Table>>

Blob_of_MaskingA -> Move_Do_Castle
Sub_Something_FEN_Lev2C -> Shift_Left_Double
Blob_of_MaskingB -> Move_Undo_Castle
Per_Depth_Info_Disp -> Full_Root
Byte_Mask_Proc -> Shift_Right_Double
Major_MaskingD -> SEE_Move
Recurse_SearchC -> Full_PV_Search
Recurse_Major_NodeTick -> Full_Search
Recurse_SearchB - > Full_Check_Search
Small_MaskingA -> Move_Do_Null
Med_LogicA -> Trans_Min_Store
Major_MaskingC -> Next_Move
Major_MaskingB -> Move_Is_Legal
nodeTickLow -> check_nb   << check_nb-- >>
Medium_LogicB -> Trans_Max_Store
Test_Proc_Command -> Search_Check
Block_of_LogicA -> Trans_Move_Store
Recurse_SearchA -> Qu_Check_Search
Major_MaskingA -> Gen_Checks
Sub_Something_FEN_Lev1E -> Strstr
Something_FEN -> Parse_Position
Sub_Something_FEN_Lev1A -> Board_From_Fen
Sub_Something_FEN_Lev1B -> Board_Init
Sub_Something_FEN_Lev2A -> Mem_Fill_X
Sub_Something_FEN_Lev2B -> Mem_Fill_Y
Sub_Something_FEN_Lev1C -> Unknown_X
Sub_Something_FEN_Lev1D -> Unknown_Y
Small_LogicA -> History_Store
Blob_of_LogicA -> Trans_Store
Blob_of_LogicC -> Trans_Clear
Init_for_Commands -> Trans_Alloc
Unknown_Heap_Alloc -> Malloc
Big_Glob_of_MaskingA -> Board_Init_MaskingA
Big_Glob_of_MaskingB -> Board_Init_MaskingB
The above is my translation chart as I discovered that my "unknown" functions exactly matched up with Strelka functions, with the binary code in these functions doing the same thing as the Strelka source code!

With all of this exacty match from Strelka my call tree with the names updated looks like this:

Code: Select all

Calling Sequence

Start_Go
 Start_Search
  Evaluate
   Shift_Right_Double
   Pawn_Get_Info
  Gen_Captures
   Shift_Right_Double
  Gen_Quiet_Moves
   Shift_Right_Double
  Move_Do
   Shift_Left_Double
  Evaluate
   Shift_Right_Double
   Pawn_Get_Info
  Move_Undo
   Shift_Left_Double
  Move_Do
   Shift_Left_Double
  Evaluate
   Shift_Right_Double
   Pawn_Get_Info
  Move_Undo
   Shift_Left_Double
  Move_Do
   Shift_Left_Double
  Evaluate
   Shift_Right_Double
   Pawn_Get_Info
  Move_Undo
   Shift_Left_Double

  Setjmp
  ds&#58;GetTickCount
  Full_Root_Base
   Full_Root
    Move_Do
     Shift_Left_Double
    Evaluate
     Shift_Right_Double
     Pawn_Get_Info
    Full_PV_Search
     Qu_Search
      Gen_Captures
       Shift_Right_Double
      Major_MaskingA
       Shift_Right_Double
    Move_Undo
     Shift_Left_Double
    Move_Do  
     Shift_Left_Double
    Evaluate
     Shift_Right_Double
     Pawn_Get_Info
    Full_PV_Search
     Qu_Search
      Gen_Captures
       Shift_Right_Double
      SEE_Move
      Major_MaskingA
       Shift_Right_Double
      Qu_Search
       Gen_Captures
        Shift_Right_Double
      Recurse_SearchA
       Gen_Evasions
        Shift_Right_Double
       Qu_Search
I need to be clear, using the above technique I found each of the mostly unknown Rybka functions in Strelka. I read the assembly language and it exactly matched the code in each of these Strelka functions in turn.

Caveat: Everything was matching so beautifully of course I could easily have missed a few modified lines of code. I'm just saying this perfect correlation was amazing to me! It became so clear to me that Strelka is a pure Reverse Engineer of Rybka. All of the above exactly matches.

So then there were a few of my "unknown" functions left (important search related functions) so I then decided to finish finding each of my unknown functions in the Strelka source by matching up the following.

I made a list of each key function and named subroutines that are called from each of these functions. Much to my amazement these lists exactly matched between Rybka and Strelka. This then completely filled out all of Rybkas search, eval, and chess support functions. I found every single one of these in Strelka, and also by the way there were no Strelka functions that were not in Rybka.

Here is the list of the key Chess functions in Rybka, and this diagram also is the diagram of function calls in Strelka, and note there is only one exception to this, and I will write about this one difference, next.

Code: Select all

Start ->
  Init_for_Commands ->
    Command_Interpretter

Command_Interpretter ->
  Start_Go ->
    Start_Search

Start_Search ->
  Full_Root_Base ->
    Full_Root

Full_Root ->
  *Full_Search
  *Full_Check_Search
  *Full_PV_Search
  Move_Do
  Evaluate
  SEE_Move
  Move_Undo
  GetTickCount
  fprintf

*Full_Search ->
  *Full_Search
  *Full_Check_Search
  *Full_PV_Search
  *Qu_Search
  GetTickCount
  Move_Do_Null
  Move_Do
  Next_Move
  Evaluate
  Trans_Move_Store
  Trans_Max_Store
  Move_Undo
  SetJump_Return
  Search_Check

*Full_Check_Search ->
  *Full_Check_Search
  *Full_Search
  *Qu_Search
  Gen_Evasions
  Move_Do
  Evaluate
  Trans_Min_Store
  Trans_Move_Store
  Trans_Max_Store
  Move_Undo

*Full_PV_Search ->
  *Full_PV_Search
  *Full_Search
  *Full_Check_Search
  *Qu_Search
  Gen_Evasions
  Move_Do
  Next_Move
  Evaluate
  SEE_Move
  Trans_Move_Store
  Trans_Max_Store
  Trans_Min_Store
  History_Store
  Trans_Store
  Move_Undo
  
*Qu_Search ->
  *Qu_Search
  *Qu_Check_Search
  Gen_Captures
  Gen_Checks
  Move_Do
  Evaluate
  Eval_Mobility
  SEE_Move
  Move_Undo

*Qu_Check_Search ->
  *Qu_Check_Search
  *Qu_Search
  Gen_Evasions
  Move_Do
  Evaluate
  Move_Undo
Skip the first two lines, there is a difference there and it's not too important so I can mention the details of this in a later posting.

Here is a difference between Rybka and Strelka that I found: look at the lines above for Start_Search -> Full_Root_Base -> Full_Root. This is Rybka, and Full_Root_Base just had a handful of lines of C in it apparently, and this is where the massive (or one of the large) lookup tables is accessed in Rybka. Recall that we heard reports from Vasic that the earlier Strelka used his large tables with a minor obfuscation of the table contents, and then later Jury Osipov removed this use of the large table and he replaced this with a function that fills the table (a function in place of a large data table, and this function technique is what is now in Strelka 2.0).

So it looks like in the later version of Strelka, Jury cut out the small piece of logic that is in "Full_Root_Base" (the code that Vasic uses to access his huge table).

I was a bit curious about this function since it is one of the key rare differences in this pure reverse engineering effort so I started converting this function to C for my own viewing (I'll can write more about this below).

So this is the one difference in the way that Strelka/Rybka functions call the other functions. In Strelka, the call to Full_Root_Base is deleted, so instead you simply see "Start_Search -> Full_Root"

Everything else exactly matches. By the way, all of these functions have the exact same arguments and they are called in exactly the same order and with the same arguments, they return the same values and all of the other code matches also ("all" meaning all you see as you compare for hours is nothing but exact match of Rybka Binary to Strelka C).

So I will stop this post now, send it, and I'm pretty excited about the work I did for the next post since the first core part of chess search is an exact match between Rybka and Strelka with all constants matching up, and I will show you a comparison of this code next.
Dann Corbit
Posts: 12540
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Dann Corbit »

Guetti wrote:
Uri Blass wrote:
Guetti wrote:I don't know how others do it, but I assign them a score depending on the promoted piece, which makes them end up at the correct place during movesorting. This way I can generate the promotions together with the other pawn moves.
I think that captures by pawns should be generated before captures by other pieces because later captures by pawns have better chances to be ordered first.

The order of generating is also important because correct order of generating moves can save sorting later so the logical order is first promotions and after it captures by pawn and only after it captures by knights and other pieces.

Note that I did not test if changing the move ordering in this way cause strelka to become better and it is possible that things are counter intuitive.

Uri
Maybe you're right. I simply did not care when I wrote this part, because I assumed the whole move list gets rearranged anyway when I sort with SEE later on.
So, to be precise I have to make a correction. The reason why I generate the captures in this order is because I simply copied the non-captures function and made the changes to generate captures. The functions are almost identical anyway with the exception of pawns.
And the reason why I generate Non-captures in this order is because Crafty does it in this order. Maybe Vas took a look at crafty too, and finally the same ended up in Strelka.
I think that the most pertinant question is:
Is the move order generation of Stelka both the same as Rybka and also different from fruit.

Anything that is the same as Fruit is not evidence that Strelka copied from Rybka. We already know that Strelka was derived from Fruit ideas. So anything that is the same as Fruit is explained from that origin. However, anything that is the same as Rybka but is *different* from how Fruit does it will be interesting in showing that Strelka copied from Rybka.
Guetti

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by Guetti »

Dann Corbit wrote:
Guetti wrote:
Uri Blass wrote:
Guetti wrote:I don't know how others do it, but I assign them a score depending on the promoted piece, which makes them end up at the correct place during movesorting. This way I can generate the promotions together with the other pawn moves.
I think that captures by pawns should be generated before captures by other pieces because later captures by pawns have better chances to be ordered first.

The order of generating is also important because correct order of generating moves can save sorting later so the logical order is first promotions and after it captures by pawn and only after it captures by knights and other pieces.

Note that I did not test if changing the move ordering in this way cause strelka to become better and it is possible that things are counter intuitive.

Uri
Maybe you're right. I simply did not care when I wrote this part, because I assumed the whole move list gets rearranged anyway when I sort with SEE later on.
So, to be precise I have to make a correction. The reason why I generate the captures in this order is because I simply copied the non-captures function and made the changes to generate captures. The functions are almost identical anyway with the exception of pawns.
And the reason why I generate Non-captures in this order is because Crafty does it in this order. Maybe Vas took a look at crafty too, and finally the same ended up in Strelka.
I think that the most pertinant question is:
Is the move order generation of Stelka both the same as Rybka and also different from fruit.

Anything that is the same as Fruit is not evidence that Strelka copied from Rybka. We already know that Strelka was derived from Fruit ideas. So anything that is the same as Fruit is explained from that origin. However, anything that is the same as Rybka but is *different* from how Fruit does it will be interesting in showing that Strelka copied from Rybka.
Well, and there is your problem if you look at move generation, because Rybka/Strelka is bitboard and Fruit is not. That probably implies that not much Fruit ideas are in the move generation of Strelka/Rybka.
Since Vas mentioned once he uses rotated bitboards a la (former) crafty, I think the move generation routines are probably more influenced from crafty. And not much from Fruit could help Strelka there. And the similar order of the functions in generate_captures as in crafty would support that, as I pointed out.
Now if we look at evaluation, search and TT implementation it's probably different and I would search for Fruit influence there.
rfadden

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by rfadden »

To trace the Chess engine in Rybka or other UCI engines, start at the Command Interpretter, the function which waits for and then processes UCI commands. Then follow the function that is called when the UCI "go" command is entered. All chess computation will be traversed by following the program from this point.

Since the UCI "go" command includes optional arguments, most chess programs parse these optional arguments in a function that is called when the go command is detected. This is the technique in Rybka/Strelka.

The function that is called is named: "start_go" and it initializes the chess move search process, it parses any optional commands that were supplied with the UCI "go" command and then it sets up and invokes "start_search ()".

I previously mentioned preparing the material to present Rybka and Strelka's "start_search ()" function, and I mentioned that this is core chess search logic with Strelka essentially identical to Rybka here. In preparing this material (coming up next) I decided I had better first show the comparison of "start_go ()".

(Instead of jumping in to the second function in sequence we might as well start with the first function.)

I just spent about 4+ hours walking through this assembly language and producing a C version of all of the details. Now that this work is done I can show the unmodified Rybka function in C and show the Strelka version which has a few lines of code moved to different locations and which has a modified "time limit" calculation.

First, here is the Rybka C version:

Code: Select all


double gTimeDouble;
int    time_limit_1, time_limit_2;
int    depthLimit;
int    nodeTickHigh, nodeTickLow;
int    bestMove, moveScore, depthScore;

bool   bad_1, bad2, change, easy, clockFlag;

bool   StopSearch, IgnoreClockFlag, Searching, Infinite, Delay;


// start_go.c - Process the UCI go command
void start_go &#40;char string &#91;&#93;)
&#123;
  const char *ptr;

  bool ponder, infinite;
  int  movestogo, movetime, btime, wtime, binc, winc;

  // Initialize global search variables
  // Initialize a global floating point time related variable
  gTimeDouble = 0.0;

  time_limit_1 = -1;
  time_limit_2 = -1;

  ignoreClockFlag = 0;

  depthLimit = 0x7FFFFFFF;
  stopSearch = 0;

  nodeTickLow = 1024;

  bestMove   = 0;
  moveScore  = 0;
  depthScore = 0;

  bad_1     = 0;
  bad_2     = 0;
  change    = 0;
  easy      = 0;
  clackFlag = 0;

  nodeTickHigh = 1;

  // Initialize local variables
  infinite  = 0;
  ponder    = 0;
  movestogo = 25;
  winc  = 0;
  wtime = 0;
  binc  = 0;
  btime = 0;
  movetime = 0;

  ptr = strtok &#40;string," ");
  for &#40;ptr = strtok &#40;NULL," "); ptr != NULL; ptr = strtok &#40;NULL," ")) &#123;
    if (!strcmp &#40;ptr,"winc" )) &#123; ptr = strtok &#40;NULL," "); winc  = atoi &#40;ptr&#41;; &#125;
    if (!strcmp &#40;ptr,"wtime")) &#123; ptr = strtok &#40;NULL," "); wtime = atoi &#40;ptr&#41;; &#125;
    if (!strcmp &#40;ptr,"binc" )) &#123; ptr = strtok &#40;NULL," "); binc  = atoi &#40;ptr&#41;; &#125;
    if (!strcmp &#40;ptr,"btime")) &#123; ptr = strtok &#40;NULL," "); btime = atoi &#40;ptr&#41;; &#125;
    if (!strcmp &#40;ptr,"depth")) &#123;
      ptr   = strtok &#40;NULL," ");

      // This is where Rybka adds 2 to the depth that is entered
      // Rybka uses "atoi&#40;)" twice, and so the following matches the binary.
      if (&#40;atoi &#40;ptr&#41; + 2&#41; < -1&#41;
        depthLimit = -1;
      &#125; else &#123;
        depthLimit = atoi &#40;ptr&#41; + 2;
      &#125;
    &#125;
    if (!strcmp &#40;ptr,"infinite"))  &#123; infinite = 1; &#125;
    if (!strcmp &#40;ptr,"movestogo")) &#123;
      ptr = strtok &#40;NULL," ");
      movestogo = atoi &#40;ptr&#41;;
      if &#40;movestogo > 30&#41; movestogo = 30;
      if &#40;movestogo <  1&#41; movestogo =  1;
    &#125;
    else if (!strcmp &#40;ptr,"movetime"))  &#123; ptr = strtok &#40;NULL," "); movetime = atoi &#40;ptr&#41;; &#125;
    else if (!strcmp &#40;ptr,"ponder"  ))  &#123; ponder = 1; &#125;
  &#125;

  // Temporary variables just used in the following calc of time_limt_1, time_limit_2
  int time, inc, time_max, alloc;

  if (&#40;Board->turn&#41; == 0&#41; &#123; time = wtime; inc = winc; &#125;
  else                    &#123; time = btime; inc = binc; &#125;

  // Rybka compares movetime with a double precision value&#58; 0.0
  if &#40;movetime >= 0.0&#41; &#123;
    time_limit_1 =    5 * movetime;
    time_limit_2 = 1000 * movetime;
  &#125; else if &#40;time > 0&#41; &#123;
    time_max = time - 5000;
    alloc = &#40;time_max + inc * &#40;movestogo - 1&#41;) / movestogo;
    if &#40;alloc >= time_max&#41; alloc = time_max;
    time_limit_1 = alloc;
    alloc = &#40;time_max + inc * &#40;movestogo - 1&#41;) / 2;
    if &#40;alloc < time_limit_1&#41; alloc = time_limit_1;
    if &#40;alloc > time_max&#41; alloc = time_max;
    time_limit_2 = alloc;
  &#125;

  if &#40;infinite || ponder&#41; ignoreClockFlag = 1;

  Searching = 1;

  Infinite = 0;
  if &#40;infinite || ponder&#41; Infinite = 1;
  Delay = 0;
  start_search ();
  Searching = 0;
  Delay = Infinite;
  if (!Infinite&#41; Send_Best_Move ();
&#125;


Here is the Strelka version:

Code: Select all

void start_go&#40;char string&#91;&#93;)
&#123; const char * ptr;
  int infinite, ponder;
  int depth, mate, movestogo, zapas;
  __int64 nodes;
  int binc, btime, movetime, winc, wtime;
  int time, inc, alloc;
  struct board_t BoardSave&#91;1&#93;;

  infinite = 0;
  ponder = 0;
  depth = -1;
  mate = -1;
  movestogo = -1;
  nodes = -1;
  binc = -1;
  btime = -1;
  movetime = -1;
  winc = -1;
  wtime = -1;
  ptr = strtok&#40;string," ");
  for &#40;ptr = strtok&#40;NULL," "); ptr != NULL; ptr = strtok&#40;NULL," ")) &#123;
    if      (!strcmp&#40;ptr,"binc"))      &#123; ptr = strtok&#40;NULL," "); binc  = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"btime"))     &#123; ptr = strtok&#40;NULL," "); btime = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"depth"))     &#123; ptr = strtok&#40;NULL," "); depth = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"infinite"))  &#123; infinite = 1; &#125;
    else if (!strcmp&#40;ptr,"mate"))      &#123; ptr = strtok&#40;NULL," "); mate  = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"movestogo")) &#123; ptr = strtok&#40;NULL," "); movestogo = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"movetime"))  &#123; ptr = strtok&#40;NULL," "); movetime = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"nodes"))     &#123; ptr = strtok&#40;NULL," "); sscanf&#40;ptr,"%I64d",&nodes&#41;; &#125;
    else if (!strcmp&#40;ptr,"ponder"))    &#123; ponder = 1; &#125;
    else if (!strcmp&#40;ptr,"winc"))      &#123; ptr = strtok&#40;NULL," "); winc = atoi&#40;ptr&#41;; &#125;
    else if (!strcmp&#40;ptr,"wtime"))     &#123; ptr = strtok&#40;NULL," "); wtime = atoi&#40;ptr&#41;; &#125;
  &#125;
  best_move = 0;
  best_score = 0;
  depth_score = 0;
  check_nb = 1024;
  start_time = GetTickCount&#40;);
  can_stop = 0;
  bad_1 = bad_2 = change = easy = flag = 0;
  *pv_str = 0;
  stop_search = 0;
  depth_is_limited = time_is_limited = 0;
  if &#40;depth >= 0&#41; &#123;
    depth_is_limited = 1;
    depth_limit = depth;
  &#125;
  else if &#40;mate >= 0&#41; &#123;
    depth_is_limited = 1;
    depth_limit = mate * 2 - 1;
  &#125;
  if (&#40;Board->turn&#41; == 0&#41; &#123; time = wtime; inc = winc; &#125;
                     else &#123; time = btime; inc = binc; &#125;
  zapas = 0;
  if &#40;movestogo <= 0&#41; movestogo = 30;
  if &#40;movestogo > 30&#41; &#123; movestogo = 30; zapas = 1; &#125;
  time_max = 100000;
  if &#40;inc < 0&#41; inc = 0;
  if &#40;movetime >= 0&#41; &#123;
    time_is_limited = 1;
    time_max = movetime;
    time_limit_1 = movetime * 5;
    time_limit_2 = movetime;
  &#125;
  else if &#40;time >= 0&#41; &#123;   // êîíòðîëü âðåìåíè
    time_is_limited = 1;
    if &#40;zapas&#41; time_max = (&#40;time / 10&#41; * 9&#41; - 5000;   // ìàêñèìàëüíîå âðåìÿ
    else time_max = time - 2000;
    if &#40;time_max < 0&#41; time_max = 0;
    alloc = &#40;time_max + inc * &#40;movestogo - 1&#41;) / movestogo;
    if &#40;alloc > time_max&#41; alloc = time_max;
    time_limit_1 = alloc;   // íèæíÿÿ ãðàíèöà êîíòðîëÿ âðåìåíè
    alloc = &#40;time_max + inc * &#40;movestogo - 1&#41;) / 2;  // ïîëîâèíà îò îñòàâøåãîñÿ
    if &#40;alloc < time_limit_1&#41; alloc = time_limit_1;
    if &#40;alloc > time_max&#41; alloc = time_max;
    time_limit_2 = alloc;   // âåðõíÿÿ ãðàíèöà êîíòðîëÿ
    // Åñòü ìûñëü âåðõíþþ ãðàíèöó áðàòü íå 1/2 à 1/3 îò îñòàâøåãîñÿ,
    // à òî áûâàåò äîëãî äóìàåò â òàêèõ ñëó÷àÿõ, è ïîòîì ïîïàäàåò â öåéòíîò.
  &#125;
  Infinite = 0;
  if &#40;infinite || ponder&#41; Infinite = 1;
  Searching = 1;
  Delay = 0;
  memcpy&#40;BoardSave, Board, sizeof&#40;struct board_t&#41;);
  start_search&#40;);
  memcpy&#40;Board, BoardSave, sizeof&#40;struct board_t&#41;);
  search_time = GetTickCount&#40;) - start_time;
  if &#40;search_time < 0&#41; search_time = 0;
  Searching = 0;
  Delay = Infinite;
  if (!Delay&#41; send_best_move&#40;);
&#125;


Note the modest Modifications in Strelka 2.0. I believe if we look at the source code to Strelka 1.0 we will see Strelka 1.0 to be an exact match with Rybka 1.0 Beta (we can find out by looking inside the Strelka 1.0 binary)


Notice that Strelka 2.0 is a reverse engineered version of Rybka. So many details match that there is no way that all of this identical code could be coincidental.


Looking at the Strelka 2.0 changes I actually like the Rybka 1.0 code better. Strelka's modifications look haphazard to me.

----------------

Some folks could question the Rybka C, so here is the material that I translated into C.

Code: Select all

.text&#58;00409520 Start_Go        proc near               ; CODE XREF&#58; Command_Interpretter+2FFp
.text&#58;00409520
.text&#58;00409520 ponder          = byte ptr -1Ah
.text&#58;00409520 infinite        = byte ptr -19h
.text&#58;00409520 movestogo       = dword ptr -18h
.text&#58;00409520 movetime        = dword ptr -14h
.text&#58;00409520 btime           = dword ptr -10h
.text&#58;00409520 wtime           = dword ptr -0Ch
.text&#58;00409520 binc            = dword ptr -8
.text&#58;00409520 winc            = dword ptr -4
.text&#58;00409520 arg_pString     = dword ptr  4
.text&#58;00409520
.text&#58;00409520                 sub     esp, 1Ch
.text&#58;00409523                 fldz
.text&#58;00409525                 push    ebx
.text&#58;00409526                 xor     ebx, ebx
.text&#58;00409528                 fstp    gTimeDouble
.text&#58;0040952E                 push    ebp
.text&#58;0040952F                 push    esi
.text&#58;00409530                 or      eax, 0FFFFFFFFh
.text&#58;00409533                 push    edi
.text&#58;00409534                 mov     time_limit_1, eax
.text&#58;00409539                 mov     time_limit_2, eax
.text&#58;0040953E                 mov     eax, &#91;esp+2Ch+arg_pString&#93;
.text&#58;00409542                 push    offset asc_661F8C ; " "
.text&#58;00409547                 mov     edi, 19h        ; 19h = 25 Decimal
.text&#58;0040954C                 xor     esi, esi
.text&#58;0040954E                 push    eax
.text&#58;0040954F                 mov     IgnoreClockFlag, bl
.text&#58;00409555                 mov     depthLimit, 7FFFFFFFh
.text&#58;0040955F                 mov     StopSearch, bl
.text&#58;00409565                 mov     nodeTickLow, 400h
.text&#58;0040956F                 mov     bestMove, ebx
.text&#58;00409575                 mov     moveScore, ebx
.text&#58;0040957B                 mov     depthScore, ebx
.text&#58;00409581                 mov     bad_1, bl
.text&#58;00409587                 mov     bad_2, bl
.text&#58;0040958D                 mov     change, bl
.text&#58;00409593                 mov     easy, bl
.text&#58;00409599                 mov     clockFlag, bl
.text&#58;0040959F                 mov     nodeTickHigh, 1
.text&#58;004095A9                 mov     &#91;esp+34h+infinite&#93;, bl
.text&#58;004095AD                 mov     &#91;esp+34h+ponder&#93;, bl
.text&#58;004095B1                 mov     &#91;esp+34h+movestogo&#93;, edi
.text&#58;004095B5                 mov     &#91;esp+34h+winc&#93;, ebx
.text&#58;004095B9                 mov     &#91;esp+34h+wtime&#93;, ebx
.text&#58;004095BD                 mov     &#91;esp+34h+binc&#93;, ebx
.text&#58;004095C1                 mov     &#91;esp+34h+btime&#93;, ebx
.text&#58;004095C5                 mov     &#91;esp+34h+movetime&#93;, esi
.text&#58;004095C9                 call    strtok
.text&#58;004095CE                 push    offset asc_661F8C ; " "
.text&#58;004095D3                 push    ebx
.text&#58;004095D4                 call    strtok
.text&#58;004095D9                 mov     ebp, eax
.text&#58;004095DB                 add     esp, 10h
.text&#58;004095DE                 cmp     ebp, ebx
.text&#58;004095E0                 jz      loc_4097CC
.text&#58;004095E6                 jmp     short loc_4095F0
.text&#58;004095E6 ; ---------------------------------------------------------------------------
.text&#58;004095E8                 align 10h
.text&#58;004095F0
.text&#58;004095F0 loc_4095F0&#58;                             ; CODE XREF&#58; Start_Go+C6j
.text&#58;004095F0                                         ; Start_Go+29Ej
.text&#58;004095F0                 mov     edi, offset aWinc ; "winc"
.text&#58;004095F5                 mov     esi, ebp
.text&#58;004095F7                 mov     ecx, 5
.text&#58;004095FC                 xor     edx, edx
.text&#58;004095FE                 repe cmpsb
.text&#58;00409600                 jnz     short loc_40961F
.text&#58;00409602                 push    offset asc_661F8C ; " "
.text&#58;00409607                 push    ebx
.text&#58;00409608                 call    strtok
.text&#58;0040960D                 push    eax
.text&#58;0040960E                 call    atoi
.text&#58;00409613                 add     esp, 0Ch
.text&#58;00409616                 mov     &#91;esp+2Ch+winc&#93;, eax
.text&#58;0040961A                 jmp     loc_4097AC
.text&#58;0040961F ; ---------------------------------------------------------------------------
.text&#58;0040961F
.text&#58;0040961F loc_40961F&#58;                             ; CODE XREF&#58; Start_Go+E0j
.text&#58;0040961F                 mov     edi, offset aWtime ; "wtime"
.text&#58;00409624                 mov     esi, ebp
.text&#58;00409626                 mov     ecx, 6
.text&#58;0040962B                 xor     eax, eax
.text&#58;0040962D                 repe cmpsb
.text&#58;0040962F                 jnz     short loc_409653
.text&#58;00409631                 push    offset asc_661F8C ; " "
.text&#58;00409636                 push    ebx
.text&#58;00409637                 call    strtok
.text&#58;0040963C                 push    eax
.text&#58;0040963D                 call    atoi
.text&#58;00409642                 add     esp, 0Ch
.text&#58;00409645                 sub     eax, 1388h
.text&#58;0040964A                 mov     &#91;esp+2Ch+wtime&#93;, eax
.text&#58;0040964E                 jmp     loc_4097AC
.text&#58;00409653 ; ---------------------------------------------------------------------------
.text&#58;00409653
.text&#58;00409653 loc_409653&#58;                             ; CODE XREF&#58; Start_Go+10Fj
.text&#58;00409653                 mov     edi, offset aBinc ; "binc"
.text&#58;00409658                 mov     esi, ebp
.text&#58;0040965A                 mov     ecx, 5
.text&#58;0040965F                 xor     edx, edx
.text&#58;00409661                 repe cmpsb
.text&#58;00409663                 jnz     short loc_409682
.text&#58;00409665                 push    offset asc_661F8C ; " "
.text&#58;0040966A                 push    ebx
.text&#58;0040966B                 call    strtok
.text&#58;00409670                 push    eax
.text&#58;00409671                 call    atoi
.text&#58;00409676                 add     esp, 0Ch
.text&#58;00409679                 mov     &#91;esp+2Ch+binc&#93;, eax
.text&#58;0040967D                 jmp     loc_4097AC
.text&#58;00409682 ; ---------------------------------------------------------------------------
.text&#58;00409682
.text&#58;00409682 loc_409682&#58;                             ; CODE XREF&#58; Start_Go+143j
.text&#58;00409682                 mov     edi, offset aBtime ; "btime"
.text&#58;00409687                 mov     esi, ebp
.text&#58;00409689                 mov     ecx, 6
.text&#58;0040968E                 xor     eax, eax
.text&#58;00409690                 repe cmpsb
.text&#58;00409692                 jnz     short loc_4096B6
.text&#58;00409694                 push    offset asc_661F8C ; " "
.text&#58;00409699                 push    ebx
.text&#58;0040969A                 call    strtok
.text&#58;0040969F                 push    eax
.text&#58;004096A0                 call    atoi
.text&#58;004096A5                 add     esp, 0Ch
.text&#58;004096A8                 sub     eax, 1388h
.text&#58;004096AD                 mov     &#91;esp+2Ch+btime&#93;, eax
.text&#58;004096B1                 jmp     loc_4097AC
.text&#58;004096B6 ; ---------------------------------------------------------------------------
.text&#58;004096B6
.text&#58;004096B6 loc_4096B6&#58;                             ; CODE XREF&#58; Start_Go+172j
.text&#58;004096B6                 mov     edi, offset aDepth ; "depth"
.text&#58;004096BB                 mov     esi, ebp
.text&#58;004096BD                 mov     ecx, 6
.text&#58;004096C2                 xor     edx, edx
.text&#58;004096C4                 repe cmpsb
.text&#58;004096C6                 jnz     short loc_40970B
.text&#58;004096C8                 push    offset asc_661F8C ; " "
.text&#58;004096CD                 push    ebx
.text&#58;004096CE                 call    strtok
.text&#58;004096D3                 mov     esi, eax
.text&#58;004096D5                 push    esi
.text&#58;004096D6                 call    atoi
.text&#58;004096DB                 add     eax, 2
.text&#58;004096DE                 add     esp, 0Ch
.text&#58;004096E1                 cmp     eax, 0FFFFFFFFh
.text&#58;004096E4                 jge     short loc_4096F5
.text&#58;004096E6                 mov     depthLimit, 0FFFFFFFFh
.text&#58;004096F0                 jmp     loc_4097AC
.text&#58;004096F5 ; ---------------------------------------------------------------------------
.text&#58;004096F5
.text&#58;004096F5 loc_4096F5&#58;                             ; CODE XREF&#58; Start_Go+1C4j
.text&#58;004096F5                 push    esi
.text&#58;004096F6                 call    atoi
.text&#58;004096FB                 add     esp, 4
.text&#58;004096FE                 add     eax, 2
.text&#58;00409701                 mov     depthLimit, eax
.text&#58;00409706                 jmp     loc_4097AC
.text&#58;0040970B ; ---------------------------------------------------------------------------
.text&#58;0040970B
.text&#58;0040970B loc_40970B&#58;                             ; CODE XREF&#58; Start_Go+1A6j
.text&#58;0040970B                 mov     edi, offset aIs_infinite ; "is_infinite"
.text&#58;00409710                 mov     esi, ebp
.text&#58;00409712                 mov     ecx, 0Ch
.text&#58;00409717                 xor     eax, eax
.text&#58;00409719                 repe cmpsb
.text&#58;0040971B                 jnz     short loc_409727
.text&#58;0040971D                 mov     &#91;esp+2Ch+infinite&#93;, 1
.text&#58;00409722                 jmp     loc_4097AC
.text&#58;00409727 ; ---------------------------------------------------------------------------
.text&#58;00409727
.text&#58;00409727 loc_409727&#58;                             ; CODE XREF&#58; Start_Go+1FBj
.text&#58;00409727                 mov     ecx, offset aMovestogo ; "movestogo"
.text&#58;0040972C                 mov     eax, ebp
.text&#58;0040972E                 call    StringCompare
.text&#58;00409733                 test    al, al
.text&#58;00409735                 jz      short loc_40976D
.text&#58;00409737                 push    offset asc_661F8C ; " "
.text&#58;0040973C                 push    ebx
.text&#58;0040973D                 call    strtok
.text&#58;00409742                 push    eax
.text&#58;00409743                 call    atoi
.text&#58;00409748                 add     esp, 0Ch
.text&#58;0040974B                 cmp     eax, 1Eh        ; 1Eh = 30 Decimal
.text&#58;0040974E                 mov     &#91;esp+2Ch+movestogo&#93;, eax
.text&#58;00409752                 jle     short loc_40975E
.text&#58;00409754                 mov     &#91;esp+2Ch+movestogo&#93;, 1Eh
.text&#58;0040975C                 jmp     short loc_4097AC
.text&#58;0040975E ; ---------------------------------------------------------------------------
.text&#58;0040975E
.text&#58;0040975E loc_40975E&#58;                             ; CODE XREF&#58; Start_Go+232j
.text&#58;0040975E                 cmp     eax, 1
.text&#58;00409761                 jge     short loc_4097AC
.text&#58;00409763                 mov     &#91;esp+2Ch+movestogo&#93;, 1
.text&#58;0040976B                 jmp     short loc_4097AC
.text&#58;0040976D ; ---------------------------------------------------------------------------
.text&#58;0040976D
.text&#58;0040976D loc_40976D&#58;                             ; CODE XREF&#58; Start_Go+215j
.text&#58;0040976D                 mov     ecx, offset aMovetime ; "movetime"
.text&#58;00409772                 mov     eax, ebp
.text&#58;00409774                 call    StringCompare
.text&#58;00409779                 test    al, al
.text&#58;0040977B                 jz      short loc_409797
.text&#58;0040977D                 push    offset asc_661F8C ; " "
.text&#58;00409782                 push    ebx
.text&#58;00409783                 call    strtok
.text&#58;00409788                 push    eax
.text&#58;00409789                 call    atoi
.text&#58;0040978E                 add     esp, 0Ch
.text&#58;00409791                 mov     &#91;esp+2Ch+movetime&#93;, eax
.text&#58;00409795                 jmp     short loc_4097AC
.text&#58;00409797 ; ---------------------------------------------------------------------------
.text&#58;00409797
.text&#58;00409797 loc_409797&#58;                             ; CODE XREF&#58; Start_Go+25Bj
.text&#58;00409797                 mov     ecx, offset aPonder ; "ponder"
.text&#58;0040979C                 mov     eax, ebp
.text&#58;0040979E                 call    StringCompare
.text&#58;004097A3                 test    al, al
.text&#58;004097A5                 jz      short loc_4097AC
.text&#58;004097A7                 mov     &#91;esp+2Ch+ponder&#93;, 1
.text&#58;004097AC
.text&#58;004097AC loc_4097AC&#58;                             ; CODE XREF&#58; Start_Go+FAj
.text&#58;004097AC                                         ; Start_Go+12Ej ...
.text&#58;004097AC                 push    offset asc_661F8C ; " "
.text&#58;004097B1                 push    ebx
.text&#58;004097B2                 call    strtok
.text&#58;004097B7                 mov     ebp, eax
.text&#58;004097B9                 add     esp, 8
.text&#58;004097BC                 cmp     ebp, ebx
.text&#58;004097BE                 jnz     loc_4095F0
.text&#58;004097C4                 mov     edi, &#91;esp+2Ch+movestogo&#93;
.text&#58;004097C8                 mov     esi, &#91;esp+2Ch+movetime&#93;
.text&#58;004097CC
.text&#58;004097CC loc_4097CC&#58;                             ; CODE XREF&#58; Start_Go+C0j
.text&#58;004097CC                 cmp     Board_turn, ebx
.text&#58;004097D2                 jz      short loc_4097DE
.text&#58;004097D4                 mov     ecx, &#91;esp+2Ch+btime&#93;
.text&#58;004097D8                 mov     edx, &#91;esp+2Ch+binc&#93;
.text&#58;004097DC                 jmp     short loc_4097E6
.text&#58;004097DE ; ---------------------------------------------------------------------------
.text&#58;004097DE
.text&#58;004097DE loc_4097DE&#58;                             ; CODE XREF&#58; Start_Go+2B2j
.text&#58;004097DE                 mov     ecx, &#91;esp+2Ch+wtime&#93;
.text&#58;004097E2                 mov     edx, &#91;esp+2Ch+winc&#93;
.text&#58;004097E6
.text&#58;004097E6 loc_4097E6&#58;                             ; CODE XREF&#58; Start_Go+2BCj
.text&#58;004097E6                 fild    &#91;esp+2Ch+movetime&#93;
.text&#58;004097EA                 fcomp   ds&#58;dbl_6623D0
.text&#58;004097F0                 fnstsw  ax
.text&#58;004097F2                 test    ah, 41h         ; 41h = 65 Decimal
.text&#58;004097F5                 jnz     short loc_40980E
.text&#58;004097F7                 lea     ecx, &#91;esi+esi*4&#93;
.text&#58;004097FA                 imul    esi, 3E8h       ; 3E8h = 1000 Decimal
.text&#58;00409800                 mov     time_limit_1, ecx
.text&#58;00409806                 mov     time_limit_2, esi
.text&#58;0040980C                 jmp     short loc_409846
.text&#58;0040980E ; ---------------------------------------------------------------------------
.text&#58;0040980E
.text&#58;0040980E loc_40980E&#58;                             ; CODE XREF&#58; Start_Go+2D5j
.text&#58;0040980E                 cmp     ecx, ebx
.text&#58;00409810                 jle     short loc_409846
.text&#58;00409812                 lea     eax, &#91;edi-1&#93;
.text&#58;00409815                 imul    eax, edx
.text&#58;00409818                 lea     esi, &#91;ecx-1388h&#93; ; 1388h = 5000 Decimal
.text&#58;0040981E                 lea     ecx, &#91;eax+esi&#93;
.text&#58;00409821                 xor     edx, edx
.text&#58;00409823                 mov     eax, ecx
.text&#58;00409825                 div     edi
.text&#58;00409827                 cmp     eax, esi
.text&#58;00409829                 jb      short loc_40982D
.text&#58;0040982B                 mov     eax, esi
.text&#58;0040982D
.text&#58;0040982D loc_40982D&#58;                             ; CODE XREF&#58; Start_Go+309j
.text&#58;0040982D                 shr     ecx, 1
.text&#58;0040982F                 cmp     ecx, eax
.text&#58;00409831                 mov     time_limit_1, eax
.text&#58;00409836                 ja      short loc_40983A
.text&#58;00409838                 mov     ecx, eax
.text&#58;0040983A
.text&#58;0040983A loc_40983A&#58;                             ; CODE XREF&#58; Start_Go+316j
.text&#58;0040983A                 cmp     ecx, esi
.text&#58;0040983C                 jb      short loc_409840
.text&#58;0040983E                 mov     ecx, esi
.text&#58;00409840
.text&#58;00409840 loc_409840&#58;                             ; CODE XREF&#58; Start_Go+31Cj
.text&#58;00409840                 mov     time_limit_2, ecx
.text&#58;00409846
.text&#58;00409846 loc_409846&#58;                             ; CODE XREF&#58; Start_Go+2ECj
.text&#58;00409846                                         ; Start_Go+2F0j
.text&#58;00409846                 mov     al, &#91;esp+2Ch+infinite&#93;
.text&#58;0040984A                 cmp     al, bl
.text&#58;0040984C                 jnz     short loc_409854
.text&#58;0040984E                 cmp     &#91;esp+2Ch+ponder&#93;, bl
.text&#58;00409852                 jz      short loc_40985B
.text&#58;00409854
.text&#58;00409854 loc_409854&#58;                             ; CODE XREF&#58; Start_Go+32Cj
.text&#58;00409854                 mov     IgnoreClockFlag, 1
.text&#58;0040985B
.text&#58;0040985B loc_40985B&#58;                             ; CODE XREF&#58; Start_Go+332j
.text&#58;0040985B                 cmp     al, bl
.text&#58;0040985D                 mov     Searching, 1
.text&#58;00409864                 jnz     short loc_409872
.text&#58;00409866                 cmp     &#91;esp+2Ch+ponder&#93;, bl
.text&#58;0040986A                 mov     Infinite, bl
.text&#58;00409870                 jz      short loc_409879
.text&#58;00409872
.text&#58;00409872 loc_409872&#58;                             ; CODE XREF&#58; Start_Go+344j
.text&#58;00409872                 mov     Infinite, 1
.text&#58;00409879
.text&#58;00409879 loc_409879&#58;                             ; CODE XREF&#58; Start_Go+350j
.text&#58;00409879                 mov     Delay, bl
.text&#58;0040987F                 call    Start_Search
.text&#58;00409884                 mov     al, Infinite
.text&#58;00409889                 pop     edi
.text&#58;0040988A                 pop     esi
.text&#58;0040988B                 pop     ebp
.text&#58;0040988C                 mov     Searching, bl
.text&#58;00409892                 cmp     al, bl
.text&#58;00409894                 mov     Delay, al
.text&#58;00409899                 pop     ebx
.text&#58;0040989A                 jnz     short loc_4098A4
.text&#58;0040989C                 add     esp, 1Ch
.text&#58;0040989F                 jmp     Send_Best_Move
.text&#58;004098A4 ; ---------------------------------------------------------------------------
.text&#58;004098A4
.text&#58;004098A4 loc_4098A4&#58;                             ; CODE XREF&#58; Start_Go+37Aj
.text&#58;004098A4                 add     esp, 1Ch
.text&#58;004098A7                 retn
.text&#58;004098A7 Start_Go        endp
[/code]
F. Bluemers
Posts: 868
Joined: Thu Mar 09, 2006 11:21 pm
Location: Nederland

Re: Strelka Reverse Engineered from Rybka: Details Examined

Post by F. Bluemers »

looks almost exactly like the fruit/toga code to me
protocol.cpp if i remember well
strelka using integers instead of (slower) double
Best
Fonzy