Crafty accused of copying Fruit PST

Discussion of anything and everything relating to chess playing software and machines.

Moderator: Ras

bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty accused of copying Fruit PST

Post by bob »

Roger Brown wrote:
JuLieN wrote:
Yet another disappointing post, Mr Ansari.

* You write "so you were one of the people accusing Vas". This is a lie: I wrote I was neutral until I read the ICGA's decision, that convinced me of Vad's guiltiness. Again, I'm a jurist, so for me everyone is innocent until proven guilty. I even wrote that I didn't like how people were throwing mud at Rybka during all those years. I even wasn't one of the prosecutors, I was just an observer whose sympathy was for Vas in the beginning. Until the gathered evidences made me reverse my opinion. And... until his hysteric sycophants made him look like the Guru of a sect of madmen.

* You write "You totally dismiss a setup that was used to accuse Vas of wrong doing because it is only one set of PST tables". This is a lie, as I wrote just the contrary, saying it was one of the points. But only one of the numerous points. I also said that I had no ideas of who copied whom in this bishop PST skirmish, and so couldn't even have an opinion regarding it, and so certainly not feel any authority to "dismiss" it, as you dared to write.

For the rest of your post, I have the feeling you were addressing someone else (like Bob?) instead of me...

You people scare me. I'm scared to see how easily passion can make people lose their objectivity and their rationality. In your hysteric madness you even turn neutral people against you. You spread hatred, lies and antagonism, making enemies of people who had nothing against you. You made fools of yourself, creating dissension and iniquity in the process. You use lies, give up rationality and resort to personal attacks. This is plain and simple madness.

If a cause is just and fair, then it doesn't need lies to get cleaned. No good can be done with bad. If you people are ready to resort to such methods, with such consequences among our once friendly community, for something as anecdotical as a chess program, what will you do with real life problems? This is the very root to why people like Hitler, Stalin and their likes can achieve such apocalyptical results. If I weren't a christian, I would despair, seeing how Mankind seems to never learn and always repeat the same mistakes, even in the smallest things.

I have no illusion at all when I write this, but I'll say it anyway: calm down, put yourself together and recover a few basic human attributes like: reason, politeness, friendship, kindness, objectivity. I am not, and have no reason to be, your enemy, so I'd like you and your likes to stop acting like you needed to have enemies you could fight. I don't even know you. I don't know who your family is, what principles they taught you, why your friends like you and other people don't. And the same for you with me. Yet you're putting words in my mouth I've never told, act aggressive with me and seem happily willing to turn me into an enemy. People who know me consider me as a friendly person, but think if I were to be otherwise, and, for instance, as sanguine as you seem to be: soon the most unpleasant names would be exchanged here in a growingly hideous caricature of a kindergarden. I have no interest in that.

I don't know exactly what you're trying to accomplish here, but I'm sure of something: nothing good and productive can be accomplished by trying to turn everyone into enemies in the process. If you are so sure that something unfair has been done, then learn to erase the bad with the good. Be gentle, be logic, be polite and that way maybe, *maybe*, you'll get people's sympathy and attention on your case instead of turning them against you.


Hello Julien,

I would have been proud to have been the author of that post above. Alas, it will make no difference to those whom it is addressed to. What is odd to me is that if one case condemns an open source program, how much more so do several cases condemn a closed source, commercial program?

You have written a beautiful piece of prose and I agree with it wholeheartedly.

+100 as they say.

Later.
You expose a contradiction that has been pointed out and dismissed several times. One similar PST in Crafty/Fruit. The counter-point is that the others are significantly different, one set doesn't even exist in Crafty, another set has 6 arrays in Crafty vs 2 in Fruit, with wildly different numbers. But that one set that matches (except for the offset) shows Crafty is a clone of Fruit. But ALL of the PST correlation between Fruit and Rybka just shows that the investigation was biased.

Talk about one giant leap of faith... and talk about ignoring the truth...
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty accused of copying Fruit PST

Post by bob »

Sven Schüle wrote:
JuLieN wrote:Hello Uri,

thanks for the precisions and corrections: points taken.

Regarding the protection of ideas, I don't think that's the point here. Nobody asks for that (or all our engines would be guilty as well, just by using the alpha-beta algorithm, for a start...).

If Fruit's ideas in Rybka were scrutinized it was, I believe, more to point out that the abnormally large amount of them present in Rybka was just another proof of code plagiarism. Which is a different idea than simple inspiration.

I think that what the panel tried to prove was that Vas took Fruit's eval.c and modified it, instead of what engines authors usually do: writing their own eval.c, later adding other engines' ideas if they find them interesting. The first case is plagiarism, the second one is inspiration.

Another proof of this fact was the finding of Crafty vestigial buggy code. A code only "useful" to older versions of Crafty and totally pointless in Rybka.
Hi Julien,

I fully agree to the statements made by Uri. The part about "ideas should not be protected" is exactly the point that it is all about. Regarding the evaluation function, what Vas obviously did, like almost all other chess programmers, was that he defined which evaluation criteria (Mark Watkins called it "features" in his paper) he wanted to use for R1beta, and found the criteria from Fruit (which are not especially unique) very useful. For each single criterion you define something like a formula or "evaluation logic" that describes how exactly you apply that criterion. Then you implement it, usually in the most straightforward, efficient and "strong" way that suits your needs for your engine.

Now evaluation criteria are clearly "ideas" or "concepts", and the formulas describing their application are on the level of "algorithms". Both "ideas" and "algorithms" are accepted, also by you, as not protectable.

When it comes to implementing these formulas that you have defined so far, you are now entering the level of "code". But in case of the evaluation function there is not much to do anymore for you, since in the vast majority of cases you have no choices left for your implementation, you immediately derive it from your logical formulas. In another post I am going to give a couple of real examples, just one for you here so that you get the idea:

Evaluation criterion = "knight mobility"

Fruit formula = "count the number of pseudo-legal moves for a given rook and assign a bonus linear in that number, with a constant offset"

R1beta formula = "count the number of pseudo-legal moves for a given rook and assign a bonus linear in that number"

Algorithm behind both, in general words: "count squares the knight can move to based on specific board representation, then do multiplication with predefined bonus and possibly addition of constant offset"

Fruit implementation (straightforward):

Code: Select all

mob = -KnightUnit;

mob += unit[board->square[from-33]];
mob += unit[board->square[from-31]];
mob += unit[board->square[from-18]];
mob += unit[board->square[from-14]];
mob += unit[board->square[from+14]];
mob += unit[board->square[from+18]];
mob += unit[board->square[from+31]];
mob += unit[board->square[from+33]];

op[me] += mob * KnightMobOpening;
eg[me] += mob * KnightMobEndgame;
R1beta implementation (straightforward with bitboards - example for white only, taken from the commented assembler listing by Mark Watkins):

Code: Select all

0x4018d0: bsf    %r8,%rax                       looping over white knights
0x4018d4: mov    0x249b40(%rbx,%rax,8),%rdx      get square this N attacks
0x4018dc: or     %rdx,%r14                       OR with squares Wh attacks
0x4018df: test   %rdx,%r15                       if attacks around bK
0x4018e2: je     0x4018ee
0x4018e4: add    $0x1,%ebp                        add 1 to attackers
0x4018e7: add    $0x3ad,%r12d                     and 941 to attack weight
0x4018ee: and    %r10,%rdx                       AND with Wh occupied
0x4018f1: mov    %rdx,%rax                       [mobility computation]
0x4018f4: shr    %rax
0x4018f7: and    %r11,%rax
0x4018fa: sub    %rax,%rdx
0x4018fd: mov    %rdx,%rax
0x401900: and    %r9,%rdx
0x401903: shr    $0x2,%rax
0x401907: and    %r9,%rax
0x40190a: add    %rdx,%rax
0x40190d: mov    %rax,%rcx
0x401910: shr    $0x4,%rcx
0x401914: add    %rax,%rcx
0x401917: mov    $0x101010101010101,%rax         [popcnt]
0x401921: and    %r13,%rcx
0x401924: imul   %rax,%rcx
0x401928: shr    $0x38,%rcx
0x40192c: mov    %ecx,%eax
0x40192e: imul   $0x79,%ecx,%ecx                 121 in the opening
0x401931: imul   $0xe,%eax,%eax                   14 in the endgame
0x401934: add    %ecx,%edi                        for each mobility
0x401936: add    %eax,%esi
0x401938: lea    -0x1(%r8),%rax
0x40193c: and    %rax,%r8
0x40193f: jne    0x4018d0                       END White Knights Loop
Note that the R1beta code above contains the whole loop over all white knights while the Fruit code only shows the part for one single knight.

You will most probably not find a serious chess programmer who implements the formula given above with significantly different code for a bitboard engine, apart from the bonus values like 121 (opening), 14 (endgame). So there is practically zero information you add beyond the definition of the evaluation formula when implementing it. This is the case for practically all kinds of evaluation criteria, also including the "piece square tables" which have become a hot topic recently, and for which Miguel has confirmed a similar point.

Btw, "knight mobility" has been assigned a feature overlap value of 0.8 in the document EVAL_COMP.pdf by Mark Watkins (page 5). My judgement would be: yes, R1beta contains the same feature, and yes, it uses a very similar formula, but no, there was no code copied since there was nothing to be copied.


The bottom line is: it has been stated that the ICGA investigation had provided a proof that Vas had copied evaluation code from Fruit 2.1 into R1beta. But as some engine programmers like Uri, Miguel, myself and some others have pointed out various times in various discussions, what actually happened was only a heavy but legal reuse of ideas and algorithms.

Sven
Quite the contrary, there are OTHER approaches. We actually consider the square itself, that is, it is more important to have mobility that passes thru center squares and mobility that hits a square on your own edge/corner of the board. In Cray Blitz we computed the value of each square as we did the evaluation, so that our mobility calculation included a bonus for each square that was a dynamic term computed during an evaluation cycle. Then we could produce a bigger bonus for attacking squares near the opponent's king, or for attacking squares in front of an opponent's passed pawn, or for attacking squares on the opponent's side of the board that are weak so that we could safely post a piece on them, etc.

There is not just ONE way to do mobility. Some exclude squares attacked by enemy pawns, some do not.

the list goes on.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Crafty accused of copying Fruit PST

Post by bob »

michiguel wrote:
JuLieN wrote:
M ANSARI wrote: It seems that at one point some of Fruit's PST values were copied by Crafty and tuned with a constant. While that may seem reasonable and part of a tuning process, this is exactly what Vas has been accused of.
Not at all. Vas has been accused (and proven guilty) of copying large chunks of other programs, including both algorithms and data structures, to the point that it became obvious that rybka 1.0 was just a tuned version of Fruit's sources with chunks of Crafty in it.

Here, what the zealots at rybkaforum are trying to accomplish is to desperately throw suspicion above Bob and Crafty. What they found was one single data structure: the bishop PST. As I don't know if Crafty got it from Fruit, or by Bob's team own research, or if, at the contrary, Fruit got it from Crafty, I won't comment this. What I'll say anyway is that it is NOT at all what Vas did, not in spirit, nor in scale. So your statement "this is what Vas did" can't stand, not even taking into account your "exactly"...
Hi, this is the zealot who found a Crafty table (duplicated as midgame and endgame) identical to Fruit. You have no idea why this was done, and you should read the whole thread before discrediting other people. The reason I looked at Crafty was because Bob CHALLENGED me to find a similarity between a Fruit table and Crafty. This basically demonstrated, in a really ironic way, the commonality between some of these type of structures, which was my whole point all along. I even wrote code about it trying to illustrate this and I was carefully analyzing the data. You may disagree or not, but you (all people at talkchess) are not better or worse than the posters at Rybka forum. Most here already jumped at the yellowish sarcastic headline without even looking at what was going on.

Miguel
That's correct. However, my original point still stands. Look at the others, where one is missing, one has 6 arrays rather than 2, others have wildly different values...

One was a surprise. And after looking at my code to produce it, your point was well-taken... for ONE table, however. I also generated all the other tables in Crafty, and didn't hit anywhere near fruit either when creating them nor when tuning them. Which supports the point in the ICGA report that all the matches make it unlikely the two are independent...
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: protection of ideas?

Post by Sven »

bob wrote:
Sven Schüle wrote:[...]The part about "ideas should not be protected" is exactly the point that it is all about. Regarding the evaluation function, what Vas obviously did, like almost all other chess programmers, was that he defined which evaluation criteria (Mark Watkins called it "features" in his paper) he wanted to use for R1beta, and found the criteria from Fruit (which are not especially unique) very useful. For each single criterion you define something like a formula or "evaluation logic" that describes how exactly you apply that criterion. Then you implement it, usually in the most straightforward, efficient and "strong" way that suits your needs for your engine.

Now evaluation criteria are clearly "ideas" or "concepts", and the formulas describing their application are on the level of "algorithms". Both "ideas" and "algorithms" are accepted, also by you, as not protectable.

When it comes to implementing these formulas that you have defined so far, you are now entering the level of "code". But in case of the evaluation function there is not much to do anymore for you, since in the vast majority of cases you have no choices left for your implementation, you immediately derive it from your logical formulas. [...]
Quite the contrary, there are OTHER approaches. We actually consider the square itself, that is, it is more important to have mobility that passes thru center squares and mobility that hits a square on your own edge/corner of the board. In Cray Blitz we computed the value of each square as we did the evaluation, so that our mobility calculation included a bonus for each square that was a dynamic term computed during an evaluation cycle. Then we could produce a bigger bonus for attacking squares near the opponent's king, or for attacking squares in front of an opponent's passed pawn, or for attacking squares on the opponent's side of the board that are weak so that we could safely post a piece on them, etc.

There is not just ONE way to do mobility. Some exclude squares attacked by enemy pawns, some do not.

the list goes on.
Hi Bob,

my point was not that there were only one way to do mobility. It was all about "concept" vs. "implementation".

If you would take your time to actually read and try to understand what people write then replies like the one I am writing now would be redundant :-) I can accept that you are (maybe?) quite excited these days, given that topic that we can also read as the original title of this thread. Actually I changed the title of this post since we are in a slightly different subtopic here which is not about Crafty but about posts of Uri and Julien upon which I replied. And I am also not here to say anything about that "Crafty-Fruit PST" topic, my point was a different one, and I definitely want you to read again my post above.

However, if you additionally need a very brief summary I'll give it to you:

If I define that my engine shall use an evaluation feature E (say "knight mobility") and shall calculate it with the formula F (say "count pseudolegal knight moves and multiply by a bonus") then I have defined a concept on the logical level. This is not copyrightable. 10000 or more different chess programs on this planet are allowed to do knight mobility evaluation with this concept, using formula F, without touching any copyright or originality issues. But the key point is: once you have fixed that formula F, its implementation is almost forced, given a concrete board representation and data structures, and with the requirement of being efficient. So the implementation adds practically zero information to the concept, and therefore "code copying" does not apply.

There are really plenty of such examples in the given case, I'll show them in the near future (but everyone can already see them).

Your implementation of (knight) mobility is different as you pointed out, the reason being that you are using a formula "G". Now please try to write down that formula in words (or call it "concept" if you like), and then tell me how many different efficient ways you see to implement "G" in your engine. I would bet you always end up with the same code as soon as "G" is fixed. Maybe someone else would implement it slightly differently in your case but that highly depends on the complexity of your concept. You will surely agree, though, that the concept F is a fairly simple one for which you will not find substantially different bitboard implementations, for instance, most will look like this (assuming the opening-endgame value system):

Code: Select all

    int mobCount = POPCNT(allKnightAttacksFrom(sq) & ~board.occupied(color));
    opening[color] += KnightMobilityFactorOpening * mobCount;
    endgame[color] += KnightMobilityFactorEndgame * mobCount;
I think that is a common property of the domain of evaluation in chess: it is almost all about selecting eval criteria, defining their calculation formula, and finding optimal parameters. The implementation itself is quite trivial once the concepts are settled. (Of course there may be bugs, no doubt.) That does not apply for many other domains of chess programming. It certainly does not apply for things like pruning techniques or hash table implementation.

Sven
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: protection of ideas?

Post by bob »

Sven Schüle wrote:
bob wrote:
Sven Schüle wrote:[...]The part about "ideas should not be protected" is exactly the point that it is all about. Regarding the evaluation function, what Vas obviously did, like almost all other chess programmers, was that he defined which evaluation criteria (Mark Watkins called it "features" in his paper) he wanted to use for R1beta, and found the criteria from Fruit (which are not especially unique) very useful. For each single criterion you define something like a formula or "evaluation logic" that describes how exactly you apply that criterion. Then you implement it, usually in the most straightforward, efficient and "strong" way that suits your needs for your engine.

Now evaluation criteria are clearly "ideas" or "concepts", and the formulas describing their application are on the level of "algorithms". Both "ideas" and "algorithms" are accepted, also by you, as not protectable.

When it comes to implementing these formulas that you have defined so far, you are now entering the level of "code". But in case of the evaluation function there is not much to do anymore for you, since in the vast majority of cases you have no choices left for your implementation, you immediately derive it from your logical formulas. [...]
Quite the contrary, there are OTHER approaches. We actually consider the square itself, that is, it is more important to have mobility that passes thru center squares and mobility that hits a square on your own edge/corner of the board. In Cray Blitz we computed the value of each square as we did the evaluation, so that our mobility calculation included a bonus for each square that was a dynamic term computed during an evaluation cycle. Then we could produce a bigger bonus for attacking squares near the opponent's king, or for attacking squares in front of an opponent's passed pawn, or for attacking squares on the opponent's side of the board that are weak so that we could safely post a piece on them, etc.

There is not just ONE way to do mobility. Some exclude squares attacked by enemy pawns, some do not.

the list goes on.
Hi Bob,

my point was not that there were only one way to do mobility. It was all about "concept" vs. "implementation".

If you would take your time to actually read and try to understand what people write then replies like the one I am writing now would be redundant :-) I can accept that you are (maybe?) quite excited these days, given that topic that we can also read as the original title of this thread. Actually I changed the title of this post since we are in a slightly different subtopic here which is not about Crafty but about posts of Uri and Julien upon which I replied. And I am also not here to say anything about that "Crafty-Fruit PST" topic, my point was a different one, and I definitely want you to read again my post above.

However, if you additionally need a very brief summary I'll give it to you:

If I define that my engine shall use an evaluation feature E (say "knight mobility") and shall calculate it with the formula F (say "count pseudolegal knight moves and multiply by a bonus") then I have defined a concept on the logical level. This is not copyrightable. 10000 or more different chess programs on this planet are allowed to do knight mobility evaluation with this concept, using formula F, without touching any copyright or originality issues. But the key point is: once you have fixed that formula F, its implementation is almost forced, given a concrete board representation and data structures, and with the requirement of being efficient. So the implementation adds practically zero information to the concept, and therefore "code copying" does not apply.

There are really plenty of such examples in the given case, I'll show them in the near future (but everyone can already see them).

Your implementation of (knight) mobility is different as you pointed out, the reason being that you are using a formula "G". Now please try to write down that formula in words (or call it "concept" if you like), and then tell me how many different efficient ways you see to implement "G" in your engine. I would bet you always end up with the same code as soon as "G" is fixed. Maybe someone else would implement it slightly differently in your case but that highly depends on the complexity of your concept. You will surely agree, though, that the concept F is a fairly simple one for which you will not find substantially different bitboard implementations, for instance, most will look like this (assuming the opening-endgame value system):

Code: Select all

    int mobCount = POPCNT(allKnightAttacksFrom(sq) & ~board.occupied(color));
    opening[color] += KnightMobilityFactorOpening * mobCount;
    endgame[color] += KnightMobilityFactorEndgame * mobCount;
I think that is a common property of the domain of evaluation in chess: it is almost all about selecting eval criteria, defining their calculation formula, and finding optimal parameters. The implementation itself is quite trivial once the concepts are settled. (Of course there may be bugs, no doubt.) That does not apply for many other domains of chess programming. It certainly does not apply for things like pruning techniques or hash table implementation.

Sven
I get the point. But what you are saying is occurring way too late. You are saying "OK, I have an idea, I have designed it, I have flow-charted the code, so now there is only one way to write it."

But if you stop above the level of what is commonly called the architectural design (or detailed design) then your statement makes no sense. Because at that level, you have decided on what you are going to do, and what you want to test to pull this off, but you have not gotten to the how. Which means there are many possible choices.

This would apply to most any evaluation term. Because even good chess books generally don't define an evaluation concept at a level low enough to let us convert it to code directly.

I agree, once you have an architectural design, your hands are pretty much tied. But just deciding to evaluate some concept like a weak pawn, or more specifically a backward/isolated pawn, most definitely does _not_ tie your hands as to how it will / can be implemented.

Simple idea: I want to implement "square of the king" where if a passed pawn is inside the square of the enemy king, it can't run in and promote, while if it is outside the square of the king, it can. Well known idea. Now how to implement it? Two different approaches, one for bitboard, one for mailbox. But you are not done, because there are another few wrinkles to deal with. What about the case where both sides have a passed pawn that can't be caught? But one queens with check? A wrinkle. How to implement this detail? Several choices. Another wrinkle, once you get to the detailed design stage. Are you certain that if the pawn is in the square of the king, the king can reach it? Worst case is king is on a diagonal that is the only way to catch the pawn. What if there is a friendly pawn on the diagonal? King is blocked and can't catch it even though it is technically in the square of the king. What if there is an enemy pawn on that diagonal? Ah, you can capture it and continue chasing and catching the pawn. But what if the pawn is defended? Shoot. Blocked again.

That single piece of code has a ton of different implementations. Your hand is not tied until the very end.

Yes, for a simple term, like "is this rook on an open file?" You might just have one way to answer that. With bitboards, an AND with the right mask will do the trick. With mailbox, you can scan the file to see if there are any pawns on it. Or you can do as we did in Cray Blitz and update a set of file flags to identify which files are open/closed, when we Make/Unmake moves, which saves time. So maybe rook on open file is not so "forced"? :)

And this goes on and on, somethings done in eval, some done in make/unmake, and some have even counted mobility in the move generator. So saying that once you decide on an idea, you are stuck as to how to implement it doesn't make a lot of sense to me... In fact, we often add new ideas in Crafty "quick and dirty" for testing. If the results look promising, I go back and rewrite "fast and clean" which should make the results even better. And it is not uncommon to later find a better way to implement that idea that is even faster. Or more accurate. Or both.

I don't buy this "one way to write something" argument for anything but the simplest of chess-specific ideas...

For knight mobility, since you asked, I have done it in the following ways in Crafty over the years:

(1) I started with slate's attacks-from and attacks-to bitboards. I just extracted the attacks-from for the square the knight was on, which already had all the attack bit set, and popcnt'ed that and multiplied by a constant C.

(2) Later, I added a second table that contained the popcnt() values for all knight attacks on all squares. Now a table lookup and I get the answer without the popcnt() cost (back prior to the hardware popcnt instruction of course.

(3) Later I decided that mobility is not just about how many moves you have, but about which squares you are attacking (we do this today). We have a set of 4 weights. I AND away all bits but the center 4 squares, and multiply by the center square weight. I then AND away all bits but the next 'ring" and multiply the popcnt of that with that ring's weight. Repeated 4 times.

(4) early on, I removed squares from the mobility for pieces if the square was attacked by a piece. That was easy with the "attacks-to" bitboard from Slate's book chapter, where for any square, I can obtain a bitmap that shows all other squares that are attacking that square, both friend and foe. From that I can determine how many attacks by each side, and by which pieces. Lots of choices to play games here. Mobility to a square you attack less than the opponent is not very useful. Mobility to a square attacked by an enemy pawn is certainly not very useful.

Do I need to continue?

This is like saying that once you know you need to sort something, there is only one way to sort it. Not so fast. Bubble sort. Heap sort. Even an insertion/selection sort will work depending on the other details of how it is used...

I simply don't buy this "once you specify the idea, the implementation details become fixed." My experience is completely the opposite. I rarely see just one way to do anything. The trick is to see the "best way". Hopefully the first time you implement it, otherwise the second, or the third.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: protection of ideas and formulas?

Post by Sven »

bob wrote:I get the point. But what you are saying is occurring way too late. You are saying "OK, I have an idea, I have designed it, I have flow-charted the code, so now there is only one way to write it."

But if you stop above the level of what is commonly called the architectural design (or detailed design) then your statement makes no sense. Because at that level, you have decided on what you are going to do, and what you want to test to pull this off, but you have not gotten to the how. Which means there are many possible choices.

This would apply to most any evaluation term. Because even good chess books generally don't define an evaluation concept at a level low enough to let us convert it to code directly.

I agree, once you have an architectural design, your hands are pretty much tied. But just deciding to evaluate some concept like a weak pawn, or more specifically a backward/isolated pawn, most definitely does _not_ tie your hands as to how it will / can be implemented.

Simple idea: I want to implement "square of the king" where if a passed pawn is inside the square of the enemy king, it can't run in and promote, while if it is outside the square of the king, it can. Well known idea. Now how to implement it? Two different approaches, one for bitboard, one for mailbox. But you are not done, because there are another few wrinkles to deal with. What about the case where both sides have a passed pawn that can't be caught? But one queens with check? A wrinkle. How to implement this detail? Several choices. Another wrinkle, once you get to the detailed design stage. Are you certain that if the pawn is in the square of the king, the king can reach it? Worst case is king is on a diagonal that is the only way to catch the pawn. What if there is a friendly pawn on the diagonal? King is blocked and can't catch it even though it is technically in the square of the king. What if there is an enemy pawn on that diagonal? Ah, you can capture it and continue chasing and catching the pawn. But what if the pawn is defended? Shoot. Blocked again.

That single piece of code has a ton of different implementations. Your hand is not tied until the very end.

Yes, for a simple term, like "is this rook on an open file?" You might just have one way to answer that. With bitboards, an AND with the right mask will do the trick. With mailbox, you can scan the file to see if there are any pawns on it. Or you can do as we did in Cray Blitz and update a set of file flags to identify which files are open/closed, when we Make/Unmake moves, which saves time. So maybe rook on open file is not so "forced"? :)

And this goes on and on, somethings done in eval, some done in make/unmake, and some have even counted mobility in the move generator. So saying that once you decide on an idea, you are stuck as to how to implement it doesn't make a lot of sense to me... In fact, we often add new ideas in Crafty "quick and dirty" for testing. If the results look promising, I go back and rewrite "fast and clean" which should make the results even better. And it is not uncommon to later find a better way to implement that idea that is even faster. Or more accurate. Or both.

I don't buy this "one way to write something" argument for anything but the simplest of chess-specific ideas...

For knight mobility, since you asked, I have done it in the following ways in Crafty over the years:

(1) I started with slate's attacks-from and attacks-to bitboards. I just extracted the attacks-from for the square the knight was on, which already had all the attack bit set, and popcnt'ed that and multiplied by a constant C.

(2) Later, I added a second table that contained the popcnt() values for all knight attacks on all squares. Now a table lookup and I get the answer without the popcnt() cost (back prior to the hardware popcnt instruction of course.

(3) Later I decided that mobility is not just about how many moves you have, but about which squares you are attacking (we do this today). We have a set of 4 weights. I AND away all bits but the center 4 squares, and multiply by the center square weight. I then AND away all bits but the next 'ring" and multiply the popcnt of that with that ring's weight. Repeated 4 times.

(4) early on, I removed squares from the mobility for pieces if the square was attacked by a piece. That was easy with the "attacks-to" bitboard from Slate's book chapter, where for any square, I can obtain a bitmap that shows all other squares that are attacking that square, both friend and foe. From that I can determine how many attacks by each side, and by which pieces. Lots of choices to play games here. Mobility to a square you attack less than the opponent is not very useful. Mobility to a square attacked by an enemy pawn is certainly not very useful.

Do I need to continue?

This is like saying that once you know you need to sort something, there is only one way to sort it. Not so fast. Bubble sort. Heap sort. Even an insertion/selection sort will work depending on the other details of how it is used...

I simply don't buy this "once you specify the idea, the implementation details become fixed." My experience is completely the opposite. I rarely see just one way to do anything. The trick is to see the "best way". Hopefully the first time you implement it, otherwise the second, or the third.
I am sure that you don't get the point yet, unless you prove that you have understood the meaning of the term "formula" in my post above.

I am tired to repeat these simple things over and over again. I did not ask for different ways to implement the same eval criterion but to implement a specific formula that has been chosen for that criterion.

Criterion = "knight mobility"
Formula = "count all pseudo-legal moves of the knight and multiply by a bonus"

Your approaches (3) and (4) do not implement that formula but a different one. And your approach (2) is nothing but an optimization attempt from past times which most people will no longer use today.

Your obvious misunderstanding of the concept "formula" as I use it makes most of your post void.

The point is also that many evaluation formulas are that simple. Few are more complex than that, like formulas in the domains "king safety" or "passed pawns". But complex eval features like "passed pawns" are divided into simpler and smaller parts, and for each part you define a formula on the logical level which is simple enough to implement it.

Here is a complete and realistic example:

Eval criterion = "passed pawn"
Precondition: pawn has been found to be a passer

The following sub terms and the following calculation formulas are selected by the programmer:


Sub term 1 = "initial bonus"
Formula = "assign rank-based bonus, where lower distance to promotion square leads to higher bonus and vice versa"


Sub term 2 = "king support of passer"
Formula = "multiply distance of king to square in front of the pawn by a constant bonus; use different constants for friendly and enemy king"

NOTE: The above formula is from Fruit 2.1. I just found that Mark Watkins missed that Fruit does _not_ use a rank-based bonus constant in this case, despite Rybka, when he wrote in EVAL_COMP.pdf on page 33:
Mark Watkins wrote:Fruit 2.1, Rybka 1.0 Beta, and Rybka 2.3.2a give a rank-based bonus/penalty (with 10-30-60-100 scaling) times the distance of the square in front of the pawn to the respective kings.
Fruit 2.1, eval.cpp:

Code: Select all

// king-distance bonus

delta -= pawn_att_dist(sq,KING_POS(board,att),att) * AttackerDistance;
delta += pawn_def_dist(sq,KING_POS(board,def),att) * DefenderDistance;
where "pawn_att_dist(pawn, king, colour)" and pawn_def_dist(...) both simply return "DISTANCE(king, pawn + PAWN_MOVE_INC(colour))".


Sub term 3 = "freedom of passer to advance"

Sub term 3.1 = "lack of any friendly piece on promotion path"
Formula = "assign rank-based bonus if condition is true"

Sub term 3.2 = "lack of any enemy piece on promotion path"
Formula = "assign rank-based bonus if condition is true"

Sub term 3.3 = "every square on promotion path is defended at least as much as it is attacked"
Formula = "assign rank-based bonus if condition is true"


Sub term 4 = "unstoppable passer"
Precondition: enemy has only the king left

Sub term 4.1 = "enemy king is outside the 'pawn square'"
Formula = "assign constant high bonus if the condition is true"

Sub term 4.2 = "friendly king suffficiently guards the passer"
Formula = "assign constant high bonus if this condition is true and condition 4.1 is false"

NOTE: the choice of the formulas 4.1 and 4.2 includes the logical decision to ignore the level of advancement of unstoppable passers in case both sides have one. Taking this into account would mean to use a different formula, as in Rybka2.3.2a.

I agree that the implementation of terms 4.1 and 4.2 is relatively more complex and "non-intuitive" than all others mentioned here. But nevertheless you will not find copied code for these two in Rybka, it is only the formula that you may find.


Are these formulas protected by copyright? I say "no".

Sven
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Curious !

Post by Desperado »

i am just ...

Code: Select all

IMPLEMENTATION A:
=================

if(!ruleOfSquare(opponentKing,Passer)) score += 800;

IMPLEMENTATION B:
=================

static const int rank[8] = {0,800,800,800,800,800,800,0};

if(!ruleOfSquare(opponentKing,Passer)) score += rank[Passer];


Formular A:
===========

add "promotion value" if king cannot catch passer

Formular B:
===========

add "pawn race promotion value" depending on rank, and king cannot catch passer

conclusion ? (but dont forget to look at the values!):
==================================

Now is case "B" a copy of "A" ?

Is anybody able to construct the "formulars,ideas" behind the code in reverse and can distinct them ?

Or is "B" an improvement of "A" ?

Or is code "B" a poor try to obfuscate code ?

Are the values placeholders, until tunig gives desired results for formular "B" ?

What is the conclusion reverse engineered such a code chunk ?

How many snippets of these type exist in evaluation code ?

Does not everybody _start always_ with the _most simple_ formular (like case "A") , and will change it _only_ for a good reason ?

How important is the (code) frame, preconditions to execute that code ?

What happens if it is add to a temporary variable, which is processed somewhere else ?

Isnt this only one scenario for one simple coded expression ?

How about more complex scenarios ?

Can a pixel make a picture ? How many pixels make the picture ? What pixels are important to get a picture ?

Can someone else fill up the next 1000 questions here please ?

Can someone else fill up the next scenarios, with diefferent code contents as the example ?

...curious

Michael
Last edited by Desperado on Wed Aug 17, 2011 1:55 pm, edited 1 time in total.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: protection of ideas and formulas?

Post by Sven »

Sven Schüle wrote:Sub term 4 = "unstoppable passer"
Precondition: enemy has only the king left
I hastily used the same words as Mark Watkins in EVAL_COMP.pdf where he wrote on page 35:
Mark Watkins wrote:Fruit 2.1 and Rybka 1.0 Beta have only a constant "unstoppable" bonus when the opponent has only a king left.
But what I meant was:

Precondition: enemy has only the king and (possibly) pawns left

which is how Fruit 2.1 defines it, and which intuitively makes more sense. I do not know whether R1beta has the same definition of that precondition since the commented assembler listing of the R1beta evaluation published by Mark Watkins seems not to include some of the pawn eval parts.

Sven
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Curious !

Post by Sven »

Desperado wrote:i am just ...

Code: Select all

IMPLEMENTATION A:
=================

if(!ruleOfSquare(opponentKing,Passer)) score += 800;

IMPLEMENTATION B:
=================

static const int rank[8] = {0,800,800,800,800,800,800,0};

if(!ruleOfSquare(opponentKing,Passer)) score += rank[Passer];


Formular A:
===========

add "promotion value" if king cannot catch passer

Formular B:
===========

add "pawn race promotion value" depending on rank, and king cannot catch passer

conclusion ? (but dont forget to look at the values!):
==================================

Now is case "B" a copy of "A" ?

[... other questions omitted here ...]
Hi Michael,

formula B is logically different from formula A by introducing rank dependency (of the passer). Whether it is an improvement is a complex question which cannot be answered without testing. Common understanding of "rank dependency" is that the bonus is not always the same for different ranks. Knowing that ranks 1 and 8 (index 0 and 7) are impossible for pawns, the implementation B does not follow that principle so it is in fact another implementation of A that has identical semantics. It is also inefficient (unless the optimizer could be made aware that the rank can never have the values 0 or 7), and will therefore not appear in strong engine code.

For the reason above, it is not straightforward to derive formula B by RE from impl. B, although detecting the "obfuscating" array might tell that the intention may have been to introduce a rank dependency.

As to your many subsequent questions, I am not sure whether it makes sense trying to answer these in the given context. I am also not sure what you are trying to point out. My point was that evaluation formulas are logical concepts that are not copyrightable, what is your position about that?

Sven
User avatar
Desperado
Posts: 879
Joined: Mon Dec 15, 2008 11:45 am

Re: Curious !

Post by Desperado »

Sven Schüle wrote:
Desperado wrote:i am just ...

Code: Select all

IMPLEMENTATION A:
=================

if(!ruleOfSquare(opponentKing,Passer)) score += 800;

IMPLEMENTATION B:
=================

static const int rank[8] = {0,800,800,800,800,800,800,0};

if(!ruleOfSquare(opponentKing,Passer)) score += rank[Passer];


Formular A:
===========

add "promotion value" if king cannot catch passer

Formular B:
===========

add "pawn race promotion value" depending on rank, and king cannot catch passer

conclusion ? (but dont forget to look at the values!):
==================================

Now is case "B" a copy of "A" ?

[... other questions omitted here ...]
Hi Michael,

formula B is logically different from formula A by introducing rank dependency (of the passer). Whether it is an improvement is a complex question which cannot be answered without testing. Common understanding of "rank dependency" is that the bonus is not always the same for different ranks. Knowing that ranks 1 and 8 (index 0 and 7) are impossible for pawns, the implementation B does not follow that principle so it is in fact another implementation of A that has identical semantics. It is also inefficient (unless the optimizer could be made aware that the rank can never have the values 0 or 7), and will therefore not appear in strong engine code.

For the reason above, it is not straightforward to derive formula B by RE from impl. B, although detecting the "obfuscating" array might tell that the intention may have been to introduce a rank dependency.

As to your many subsequent questions, I am not sure whether it makes sense trying to answer these in the given context. I am also not sure what you are trying to point out. My point was that evaluation formulas are logical concepts that are not copyrightable, what is your position about that?

Sven

What i want to point out is this:

"Most" of these question are simply of _rhetorical_ nature.
_Nobody_ on this planet should even try to answer them,
because there doesnt exist unique answers !

I can follow of course your argumentation of the rank dependancy,
i want to add that you dont know if it is part of an automatic tuning set
which needs arrays of size 8 to be conform with other tuning elements,
and if it turns out to be 800 for each rank someone will hard-code it again ? No chance to recognize intentions like that, and to conclude
on the fomular, because of the code snippet. Or countless other reasons.

I agree with you fully that formulars are not copyrightable, and i add
that reversed engineered ideas,formulas are a matter of interpretation, opinion.
It is not possible to give 100% centainty that what someone interprets is inteded to be the point.

Even such a losy example will/can split a community as i further tried
to point out with _conflictive questions_ like
- poor try of obfuscation or code-improvement
- different idea/formular or different implementation (my intention to use the rank dependancy)

* each question is matter of personal interpretation!

Well i stop it here, think you know what i mean now.

cheers

Michael