For C experts

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: For C experts

Post by wgarvin »

Anybody who cares about speed and isn't too fussed about having 80 bits of precision should be compiling with /arch:SSE2 or equivalent. I don't know if rybka was compiled that way or not.

If it was, then all of these snippets would probably load it into an xmm register, I guess with some instruction like MOVQ or MOVSD. The way to tell whether the variable x was an int or a double, would be to look for a CVTSI2SD ("convert scalar int to scalar double") instruction between the load and compare. Snippet C would generate one, the other two snippets would not.
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: For C experts

Post by Zach Wegner »

michiguel wrote:
UncombedCoconut wrote:Well, that's a different matter entirely!
The logical snippet to write in this context, if your time management variables are integers, is

Code: Select all

D) 

int x; 
if (x > 0) { 
    /* code here */ 
} 
This would never generate assembly instructions to do a floating point compare. So, assuming the assembly is the way BB+ said it is, it is strange. Proof of copying? Absolutely not. But it would deserve consideration as part of a big picture, and is not completely meaningless either.
Why do you we have to assume x is an integer?

Miguel
Because it's the return value of atoi?
Because there's a fild instruction (converting int to double)?
IQ
Posts: 162
Joined: Thu Dec 17, 2009 10:46 am

Re: For C experts

Post by IQ »

michiguel wrote:
wgarvin wrote:Yes. The magic phrase to google for about this is "usual arithmetic conversions" which describes the implicit conversions the compiler will do to the arguments of a binary operator before applying the operator.

See section 6.5.4 (Relational Operators) on this page, for example.

[Edit: I assumed you meant the assembly for the comparison part... the memory load and conversion of "int x" versus "float x" might be different if the compiler doesn't completely optimize it away. But in all cases the comparison is between two doubles.]
Because in the document in which is shown how Rybka 1.0 was disassembled, it was inferred that the R1 code had a snippet like "C". Then, in the context, it looks weird that a comparison was done to 0.0. Explicitly, it is said that it only made sense when you looked at Fruit code that had a similar comparison to 0.0 (it made sense there). So, it is inferred that this was a sloppy cut, paste and modification and the 0.0 remained.

This is the danger of this type of techniques in which the answer is degenerate (several options possible). You find what you are looking for. The whole point is valid if the source code is actually "C", but we do not know what the source code is. It could actually be like "A". In that case the compiler (following the C rules) may place the 0.0 there and the whole point is invalid.

Miguel
This is a valid concern. The proper methodology would be to include a number (let's say 2) of known non-clones programs in the analysis. These serve as a true negative reference. For example if they also were to have these strange float variables in similar places, it might well be a compiler/optimization issue. It is probably not necessary to validate all findings in this way, but some findings should be corroborated.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: For C experts

Post by bob »

IQ wrote:
michiguel wrote:
wgarvin wrote:Yes. The magic phrase to google for about this is "usual arithmetic conversions" which describes the implicit conversions the compiler will do to the arguments of a binary operator before applying the operator.

See section 6.5.4 (Relational Operators) on this page, for example.

[Edit: I assumed you meant the assembly for the comparison part... the memory load and conversion of "int x" versus "float x" might be different if the compiler doesn't completely optimize it away. But in all cases the comparison is between two doubles.]
Because in the document in which is shown how Rybka 1.0 was disassembled, it was inferred that the R1 code had a snippet like "C". Then, in the context, it looks weird that a comparison was done to 0.0. Explicitly, it is said that it only made sense when you looked at Fruit code that had a similar comparison to 0.0 (it made sense there). So, it is inferred that this was a sloppy cut, paste and modification and the 0.0 remained.

This is the danger of this type of techniques in which the answer is degenerate (several options possible). You find what you are looking for. The whole point is valid if the source code is actually "C", but we do not know what the source code is. It could actually be like "A". In that case the compiler (following the C rules) may place the 0.0 there and the whole point is invalid.

Miguel
This is a valid concern. The proper methodology would be to include a number (let's say 2) of known non-clones programs in the analysis. These serve as a true negative reference. For example if they also were to have these strange float variables in similar places, it might well be a compiler/optimization issue. It is probably not necessary to validate all findings in this way, but some findings should be corroborated.
This is really not that difficult to deal with. Any good C programmer would, beyond a shadow of a doubt, know to _never_ compare an integer expression/value with a value of 0.0. That kind of bug is something that slips in during development, when you originally decide to use floats for timing, then discover that it is faster/easier to use ints. And you just forget about that occasional comparison to 0.0. To find that in two programs, at the same place, is _WAY_ beyond a coincidence.

I do not see why this can't be revealed now, so here's a _real_ cute example of this happening...

First, code from Crafty version 19.0, module "init.c":

Code: Select all

  for &#40;i=0;i<pawn_hash_table_size;i++) &#123;
    &#40;pawn_hash_table+i&#41;->key=0;
    &#40;pawn_hash_table+i&#41;->p_score=0;
    &#40;pawn_hash_table+i&#41;->protected=0;
    &#40;pawn_hash_table+i&#41;->black_defects_k=0;
    &#40;pawn_hash_table+i&#41;->black_defects_q=0;
    &#40;pawn_hash_table+i&#41;->white_defects_k=0;
    &#40;pawn_hash_table+i&#41;->white_defects_q=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->outside=0;
    &#40;pawn_hash_table+i&#41;->candidates_w=0;
    &#40;pawn_hash_table+i&#41;->candidates_b=0;
  &#125;
Do you see the rather obvious bug?

Look here:

Code: Select all

    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
Does that make any sense? Obviously one of those should be _b to clear the passed pawn flags for black. Notice that any variable that has a white or _w in the name is matched with the same variable with black or _b.

Simple bug, correct?

What if you found this identical code in a different program? Say, for example, a pre-fruit version of Rybka? What would you conclude?

Here's another one from iterate.c:

Code: Select all

  TB_use_ok=1;
  if &#40;TotalWhitePawns && TotalBlackPawns&#41; &#123;
    wpawn=FirstOne&#40;WhitePawns&#41;;
    bpawn=FirstOne&#40;BlackPawns&#41;;
    if &#40;FileDistance&#40;wpawn,bpawn&#41; == 1&#41; &#123;
      if&#40;(&#40;Rank&#40;wpawn&#41;==RANK2&#41; && &#40;Rank&#40;bpawn&#41;>RANK3&#41;) ||
         (&#40;Rank&#40;bpawn&#41;==RANK7&#41; && &#40;Rank&#40;wpawn&#41;<RANK6&#41;) ||
         EnPassant&#40;1&#41;) TB_use_ok=0;
    &#125;
  &#125;
That code was added to iterate.c when I first started to use the EGTB files from Steven Edwards. I do not believe they were used after Eugene's files were released on my ftp machine, for several reasons. Eugene's were compressed and then decompressed on the fly as they were probed. Steven's were not. As a result, Eugene's files were _far_ smaller. Steven did not, at least while I was using them, release anything other than 3-4 piece files as they took forever (Eugene spent a ton of time optimizing his build speed). Steven did, for me, build krnkr and krbkr. But that was all.

His kpkp file had one major short-coming, in that it did not consider en passant pawn captures. As a result, I had to add the above code to disable EGTB probes if an en passant capture could be a possibility anywhere in the tree. What the code does is to check to see if there are opposite-colored pawns on adjacent files, if one of the pawns is on its own second rank (so that it can move two squares at once), and the other pawn has not yet advanced past the 5th rank so that a double pawn push would allow an en passant capture. If all of those were true, I had to disable egtb probes. Once Eugene's egtb files were released, which was first used in Crafty version 16.0, support for the Edward's tablebases was removed. But somehow this small vestige of the old support remained.

What if you looked at that pre-fruit version of Rybka and found the above code in a module that looks very similar to crafty's iterate.c? Pure random chance?

There is a lot of effort going into this investigation. The more we look, the worse this mess smells. Zach found the above code since we thought it would be useful to get a feel for the pre-fruit Rybka's structure since the claim has been that Rybka 1 beta took ideas but not code. The structure of Rybka changed _dramatically_ from the early version to the "fruity" version. And everywhere we look for these glitches (I have been looking at older versions of Crafty to discover what bugs might have been present for a while, and which would _not_ have been a normal mistake if someone had written their own code (the passed_w twice above is an example).

If you try to take any single piece of evidence, say the 0.0 and say it doesn't mean much, I might agree. But when you take _all_ the evidence, it says a _lot_. And I do mean a _lot_...

So just let this play out on the ICGA WIKI, with everyone looking carefully, and there is no doubt that enough evidence is going to be shown to create a _lot_ of new discussion. Whether Vas will respond to this evidence or not is, at present, unknown. He's been invited to come to the WIKI for this and contribute. I hope he will accept. And hope he can either come up with some rational/believable explanation for how one program of his has a lot of Crafty in it, while the next has a lot of Fruit. And perhaps at least offer his rationale for why this is acceptable, if he can't somehow explain away the obvious copying.

This investigation is not going to be rushed. Our goal is to leave no stone unturned in the search for the truth. And we plan on accepting evidence or comments from anyone that is interested. We are not going to let everyone join the "panel" because we don't want that discussion to turn into the kind of discussion we see here over and over. But if you post something here that is of interest, we will follow up and take it to the wiki discussion if appropriate...
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: For C experts

Post by sje »

bob wrote:Here's another one from iterate.c:

Code: Select all

  TB_use_ok=1;
  if &#40;TotalWhitePawns && TotalBlackPawns&#41; &#123;
    wpawn=FirstOne&#40;WhitePawns&#41;;
    bpawn=FirstOne&#40;BlackPawns&#41;;
    if &#40;FileDistance&#40;wpawn,bpawn&#41; == 1&#41; &#123;
      if&#40;(&#40;Rank&#40;wpawn&#41;==RANK2&#41; && &#40;Rank&#40;bpawn&#41;>RANK3&#41;) ||
         (&#40;Rank&#40;bpawn&#41;==RANK7&#41; && &#40;Rank&#40;wpawn&#41;<RANK6&#41;) ||
         EnPassant&#40;1&#41;) TB_use_ok=0;
    &#125;
  &#125;
That code was added to iterate.c when I first started to use the EGTB files from Steven Edwards. I do not believe they were used after Eugene's files were released on my ftp machine, for several reasons. Eugene's were compressed and then decompressed on the fly as they were probed. Steven's were not. As a result, Eugene's files were _far_ smaller. Steven did not, at least while I was using them, release anything other than 3-4 piece files as they took forever (Eugene spent a ton of time optimizing his build speed). Steven did, for me, build krnkr and krbkr. But that was all.

His kpkp file had one major short-coming, in that it did not consider en passant pawn captures. As a result, I had to add the above code to disable EGTB probes if an en passant capture could be a possibility anywhere in the tree. What the code does is to check to see if there are opposite-colored pawns on adjacent files, if one of the pawns is on its own second rank (so that it can move two squares at once), and the other pawn has not yet advanced past the 5th rank so that a double pawn push would allow an en passant capture. If all of those were true, I had to disable egtb probes. Once Eugene's egtb files were released, which was first used in Crafty version 16.0, support for the Edward's tablebases was removed. But somehow this small vestige of the old support remained.
All of the above is true. I apologize for not having en passant support, but at the time I got interested in making tablebases (early 1990s), my main machine was a 1986 vintage Macintosh Plus with 4 MB RAM and a pair of 20 MD SCSI drives. I could not build any of the five man files that had pawns because of machine limitations; instead, I published the generator source so that others could build their own. And they did. It was only many years after writing the generator that I actually built KRPKR myself.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: For C experts

Post by bob »

sje wrote:
bob wrote:Here's another one from iterate.c:

Code: Select all

  TB_use_ok=1;
  if &#40;TotalWhitePawns && TotalBlackPawns&#41; &#123;
    wpawn=FirstOne&#40;WhitePawns&#41;;
    bpawn=FirstOne&#40;BlackPawns&#41;;
    if &#40;FileDistance&#40;wpawn,bpawn&#41; == 1&#41; &#123;
      if&#40;(&#40;Rank&#40;wpawn&#41;==RANK2&#41; && &#40;Rank&#40;bpawn&#41;>RANK3&#41;) ||
         (&#40;Rank&#40;bpawn&#41;==RANK7&#41; && &#40;Rank&#40;wpawn&#41;<RANK6&#41;) ||
         EnPassant&#40;1&#41;) TB_use_ok=0;
    &#125;
  &#125;
That code was added to iterate.c when I first started to use the EGTB files from Steven Edwards. I do not believe they were used after Eugene's files were released on my ftp machine, for several reasons. Eugene's were compressed and then decompressed on the fly as they were probed. Steven's were not. As a result, Eugene's files were _far_ smaller. Steven did not, at least while I was using them, release anything other than 3-4 piece files as they took forever (Eugene spent a ton of time optimizing his build speed). Steven did, for me, build krnkr and krbkr. But that was all.

His kpkp file had one major short-coming, in that it did not consider en passant pawn captures. As a result, I had to add the above code to disable EGTB probes if an en passant capture could be a possibility anywhere in the tree. What the code does is to check to see if there are opposite-colored pawns on adjacent files, if one of the pawns is on its own second rank (so that it can move two squares at once), and the other pawn has not yet advanced past the 5th rank so that a double pawn push would allow an en passant capture. If all of those were true, I had to disable egtb probes. Once Eugene's egtb files were released, which was first used in Crafty version 16.0, support for the Edward's tablebases was removed. But somehow this small vestige of the old support remained.
All of the above is true. I apologize for not having en passant support, but at the time I got interested in making tablebases (early 1990s), my main machine was a 1986 vintage Macintosh Plus with 4 MB RAM and a pair of 20 MD SCSI drives. I could not build any of the five man files that had pawns because of machine limitations; instead, I published the generator source so that others could build their own. And they did. It was only many years after writing the generator that I actually built KRPKR myself.
And as I told you at the time, I greatly appreciated the KRBKR and KRNKR cases you built for me (they took a long while as I remember, maybe a week each or something?)

Those were the days when things were not so damned messy...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: For C experts

Post by bob »

Zach Wegner wrote:
michiguel wrote:
UncombedCoconut wrote:Well, that's a different matter entirely!
The logical snippet to write in this context, if your time management variables are integers, is

Code: Select all

D&#41; 

int x; 
if &#40;x > 0&#41; &#123; 
    /* code here */ 
&#125; 
This would never generate assembly instructions to do a floating point compare. So, assuming the assembly is the way BB+ said it is, it is strange. Proof of copying? Absolutely not. But it would deserve consideration as part of a big picture, and is not completely meaningless either.
Why do you we have to assume x is an integer?

Miguel
Because it's the return value of atoi?
Because there's a fild instruction (converting int to double)?
I don't see why we keep having to "go here". The assembly language is generally unambiguous for simple issues like this. FILD only gives you one choice for the single operand. An integer 2's complement value. To do the floating compare, one could do a couple of different things, from fldz, to flid from an int word containing zero. No compiler would do the latter if 0.0 was used, unless the programmer forced it by loading from a variable containing 0.0 that was initialized elsewhere so that it can't be discovered at compile time.

Some seem to think that assembly language and C comparisons are some sort of voodoo, done in a circle inside a tent, with incense burning, chanting, strange noises, little light, etc. It is a straightforward process. Time-consuming at times. But my CS330 students can do this because I spend a lot of time showing them C control structures (switch, while, for, etc) and how to implement them in assembly language. It is not some secret practice only performed by 3 people in the world...
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

Re: For C experts

Post by sje »

bob wrote:
sje wrote:I apologize for not having en passant support, but at the time I got interested in making tablebases (early 1990s), my main machine was a 1986 vintage Macintosh Plus with 4 MB RAM and a pair of 20 MD SCSI drives. I could not build any of the five man files that had pawns because of machine limitations; instead, I published the generator source so that others could build their own. And they did. It was only many years after writing the generator that I actually built KRPKR myself.
And as I told you at the time, I greatly appreciated the KRBKR and KRNKR cases you built for me (they took a long while as I remember, maybe a week each or something?)

Those were the days when things were not so damned messy...
Those were slow days, though. My first successful attempt at a five man class tablebase (KBNKN) took 89 days on a slow 486DX machine running Coherent (A pre-Linux commercial Unix-like OS). And then three more days to verify.

At that time, I think my only access to the Internet was via my trusty 2,400 bps modem. As communicating any significant amount of data was out of the question, I released the generator source instead.

A big difficulty at the time is that there were no correct data I could access that had the "right" answers. I did manage to get a copy of Ken Thompson's EGDB CD-ROMs, but I had no CD-ROM reader. Only much later did I get to read his data and directly compare results. However, early on I did have access to his maximum mating distance numbers for several classes and these few stats were actually very helpful. Indeed, it was only after doing the distance to mate tablebases that I could truly appreciate Ken's pioneering efforts where he had *no* earlier results.

Unix historians might recall that the very first releases form Bell Labs had a special system idle routine that soaked up unused cycles. What did the routine do? It was Ken's distance to conversion KRKN EGDB generator! Who knows how many millions of times KRKN was built? And this was all back in the early 1970s.
micron
Posts: 155
Joined: Mon Feb 15, 2010 9:33 am
Location: New Zealand

Re: For C experts

Post by micron »

bob wrote:I don't see why we keep having to "go here". The assembly language is generally unambiguous for simple issues like this. FILD only gives you one choice for the single operand. An integer 2's complement value. To do the floating compare, one could do a couple of different things, from fldz, to flid from an int word containing zero. No compiler would do the latter if 0.0 was used, unless the programmer forced it by loading from a variable containing 0.0 that was initialized elsewhere so that it can't be discovered at compile time.

Some seem to think that assembly language and C comparisons are some sort of voodoo...
The voodoo aspects, and more importantly the difficulties of comparing disassemblies, are increased when you throw different compilers into the mix. Here gcc 4.0 and gcc 4.2 produce two arrangements of the same instructions, whereas clang is completely different; it converts 0.0 to 0 at compile time.

Code: Select all

int test&#40; int x ) 
&#123; 
  if ( x > 0.0 ) return 1;
  return 0; 
&#125;  

gcc 4.0
LC0&#58;
	.long	0
	.long	0
_test&#58;
	pushl	%ebp
	xorl	%eax, %eax
	movl	%esp, %ebp
	cvtsi2sd	8&#40;%ebp&#41;, %xmm0
	ucomisd	LC0, %xmm0
	leave
	seta	%al
	ret

gcc 4.2
_test&#58;
	pushl	%ebp
	movl	%esp, %ebp
	cvtsi2sd	8&#40;%ebp&#41;, %xmm0
	xorl	%eax, %eax
	ucomisd	LC0, %xmm0
	seta	%al
	leave
	ret
LC0&#58;
	.long	0
	.long	0

clang
_test&#58;
	pushl	%ebp
	movl	%esp, %ebp
	cmpl	$0, 8&#40;%ebp&#41;
	setg	%al
	movzbl	%al, %eax
	popl	%ebp
	ret
IQ
Posts: 162
Joined: Thu Dec 17, 2009 10:46 am

Re: For C experts

Post by IQ »

Hi Bob,
I agree to most of what you have said - although the majority of examples is not quite in the same vain as the original posters. Also i am not saying that any of these compiler/optimization issues invalidates any of the "evidence" put forward. What i am saying is this: In order to be thorough and make the argument water-tight, one should not dismiss these issues off-hand. I have seen compiler optimization do all kind of stuff - mostly due to a bug in the optimization itself (see the recent microsoft bulletin on visual c for example). While the amount of evidence which would be subject this is very _very_ small, it should still be investigated to preempt any claims in this direction.

Apart from compiler issues the inclusion of a reference true negative has another advantage. One can convey just _how_ unlikely the "coincidences" are. If the reference programs vary wildly and in just about every instruction, this would make a much stronger case against the similarities in rybka. A third party could then verify that these matching "fingerprints" are not normal for chess programs - a conclusion one could not make easily from comparing just the clone to the original (at least for non programmers). The reference programs should ideally be similar to the programs under investigation architecturally (bitboards etc.)
bob wrote:
IQ wrote:
michiguel wrote:
wgarvin wrote:Yes. The magic phrase to google for about this is "usual arithmetic conversions" which describes the implicit conversions the compiler will do to the arguments of a binary operator before applying the operator.

See section 6.5.4 (Relational Operators) on this page, for example.

[Edit: I assumed you meant the assembly for the comparison part... the memory load and conversion of "int x" versus "float x" might be different if the compiler doesn't completely optimize it away. But in all cases the comparison is between two doubles.]
Because in the document in which is shown how Rybka 1.0 was disassembled, it was inferred that the R1 code had a snippet like "C". Then, in the context, it looks weird that a comparison was done to 0.0. Explicitly, it is said that it only made sense when you looked at Fruit code that had a similar comparison to 0.0 (it made sense there). So, it is inferred that this was a sloppy cut, paste and modification and the 0.0 remained.

This is the danger of this type of techniques in which the answer is degenerate (several options possible). You find what you are looking for. The whole point is valid if the source code is actually "C", but we do not know what the source code is. It could actually be like "A". In that case the compiler (following the C rules) may place the 0.0 there and the whole point is invalid.

Miguel
This is a valid concern. The proper methodology would be to include a number (let's say 2) of known non-clones programs in the analysis. These serve as a true negative reference. For example if they also were to have these strange float variables in similar places, it might well be a compiler/optimization issue. It is probably not necessary to validate all findings in this way, but some findings should be corroborated.
This is really not that difficult to deal with. Any good C programmer would, beyond a shadow of a doubt, know to _never_ compare an integer expression/value with a value of 0.0. That kind of bug is something that slips in during development, when you originally decide to use floats for timing, then discover that it is faster/easier to use ints. And you just forget about that occasional comparison to 0.0. To find that in two programs, at the same place, is _WAY_ beyond a coincidence.

I do not see why this can't be revealed now, so here's a _real_ cute example of this happening...

First, code from Crafty version 19.0, module "init.c":

Code: Select all

  for &#40;i=0;i<pawn_hash_table_size;i++) &#123;
    &#40;pawn_hash_table+i&#41;->key=0;
    &#40;pawn_hash_table+i&#41;->p_score=0;
    &#40;pawn_hash_table+i&#41;->protected=0;
    &#40;pawn_hash_table+i&#41;->black_defects_k=0;
    &#40;pawn_hash_table+i&#41;->black_defects_q=0;
    &#40;pawn_hash_table+i&#41;->white_defects_k=0;
    &#40;pawn_hash_table+i&#41;->white_defects_q=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->outside=0;
    &#40;pawn_hash_table+i&#41;->candidates_w=0;
    &#40;pawn_hash_table+i&#41;->candidates_b=0;
  &#125;
Do you see the rather obvious bug?

Look here:

Code: Select all

    &#40;pawn_hash_table+i&#41;->passed_w=0;
    &#40;pawn_hash_table+i&#41;->passed_w=0;
Does that make any sense? Obviously one of those should be _b to clear the passed pawn flags for black. Notice that any variable that has a white or _w in the name is matched with the same variable with black or _b.

Simple bug, correct?

What if you found this identical code in a different program? Say, for example, a pre-fruit version of Rybka? What would you conclude?

Here's another one from iterate.c:

Code: Select all

  TB_use_ok=1;
  if &#40;TotalWhitePawns && TotalBlackPawns&#41; &#123;
    wpawn=FirstOne&#40;WhitePawns&#41;;
    bpawn=FirstOne&#40;BlackPawns&#41;;
    if &#40;FileDistance&#40;wpawn,bpawn&#41; == 1&#41; &#123;
      if&#40;(&#40;Rank&#40;wpawn&#41;==RANK2&#41; && &#40;Rank&#40;bpawn&#41;>RANK3&#41;) ||
         (&#40;Rank&#40;bpawn&#41;==RANK7&#41; && &#40;Rank&#40;wpawn&#41;<RANK6&#41;) ||
         EnPassant&#40;1&#41;) TB_use_ok=0;
    &#125;
  &#125;
That code was added to iterate.c when I first started to use the EGTB files from Steven Edwards. I do not believe they were used after Eugene's files were released on my ftp machine, for several reasons. Eugene's were compressed and then decompressed on the fly as they were probed. Steven's were not. As a result, Eugene's files were _far_ smaller. Steven did not, at least while I was using them, release anything other than 3-4 piece files as they took forever (Eugene spent a ton of time optimizing his build speed). Steven did, for me, build krnkr and krbkr. But that was all.

His kpkp file had one major short-coming, in that it did not consider en passant pawn captures. As a result, I had to add the above code to disable EGTB probes if an en passant capture could be a possibility anywhere in the tree. What the code does is to check to see if there are opposite-colored pawns on adjacent files, if one of the pawns is on its own second rank (so that it can move two squares at once), and the other pawn has not yet advanced past the 5th rank so that a double pawn push would allow an en passant capture. If all of those were true, I had to disable egtb probes. Once Eugene's egtb files were released, which was first used in Crafty version 16.0, support for the Edward's tablebases was removed. But somehow this small vestige of the old support remained.

What if you looked at that pre-fruit version of Rybka and found the above code in a module that looks very similar to crafty's iterate.c? Pure random chance?

There is a lot of effort going into this investigation. The more we look, the worse this mess smells. Zach found the above code since we thought it would be useful to get a feel for the pre-fruit Rybka's structure since the claim has been that Rybka 1 beta took ideas but not code. The structure of Rybka changed _dramatically_ from the early version to the "fruity" version. And everywhere we look for these glitches (I have been looking at older versions of Crafty to discover what bugs might have been present for a while, and which would _not_ have been a normal mistake if someone had written their own code (the passed_w twice above is an example).

If you try to take any single piece of evidence, say the 0.0 and say it doesn't mean much, I might agree. But when you take _all_ the evidence, it says a _lot_. And I do mean a _lot_...

So just let this play out on the ICGA WIKI, with everyone looking carefully, and there is no doubt that enough evidence is going to be shown to create a _lot_ of new discussion. Whether Vas will respond to this evidence or not is, at present, unknown. He's been invited to come to the WIKI for this and contribute. I hope he will accept. And hope he can either come up with some rational/believable explanation for how one program of his has a lot of Crafty in it, while the next has a lot of Fruit. And perhaps at least offer his rationale for why this is acceptable, if he can't somehow explain away the obvious copying.

This investigation is not going to be rushed. Our goal is to leave no stone unturned in the search for the truth. And we plan on accepting evidence or comments from anyone that is interested. We are not going to let everyone join the "panel" because we don't want that discussion to turn into the kind of discussion we see here over and over. But if you post something here that is of interest, we will follow up and take it to the wiki discussion if appropriate...