Question: does this appear to be an ordinary, common knight capture routine employed in any of the current top of the crop engines. Or is this particularly unique, and if so, how? Followup question later ...
benstoker wrote:Question: does this appear to be an ordinary, common knight capture routine employed in any of the current top of the crop engines. Or is this particularly unique, and if so, how? Followup question later ...
for (piecebd = Knights(wtm); piecebd; Clear(from, piecebd)) {
from = Advanced(wtm, piecebd);
moves = knight_attacks[from] & Occupied(btm);
temp = from + (knight << 12);
Unpack(wtm, move, moves, temp);
}
Unpack() simply takes a set of knight moves and unpacks them into the move list...
One note: I don't do the p & p - 1 trick because I don't necessarily want to take the lowest bit (knight) first. I try to generate moves in the same order for both sides, which could be either the most advanced knight first, or least advanced. But not most advanced for one side and least advanced for the other.
It is a matter of taste. There is nothing wrong to assign static scoring during generate, as long as it is superseded properly by the dynamic factors later. I like that.
xcomponent wrote:It is a matter of taste. There is nothing wrong to assign static scoring during generate, as long as it is superseded properly by the dynamic factors later. I like that.
So it is a bit slower, of course you avoid another scoring loop so at the end can be a bit faster in this way, but just a bit IMHO and I prefer a layered design where you have the following independent and well defined modules:
This well modularized and disjoint set of functions is for me more important then a bit of (theoretical) extra speed. I have already done the mistake with unified middlegame and endgame scores (two values in one integer) where I spent almost one week of development and testing and we had very subtle bugs even after release (take a look at value.h) just for a very minimal speed increase.
The point is that because you can score in that way only captures you end up scoring the captures in one file and in one way and scoring non-captures in another file: I want all the scoring stuff to be easily accessible and clear to read and not spread across many files.
mcostalba wrote:
I have already done the mistake with unified middlegame and endgame scores (two values in one integer) where I spent almost one week of development and testing and we had very subtle bugs even after release (take a look at value.h) just for a very minimal speed increase.
This is a useful comment. I have been seriously considering adding this myself, but you have convinced me its not worth the bother and potential bugs. My last engine was darn fast, but bug ridden. The bugs are not worth it .
mcostalba wrote:
I have already done the mistake with unified middlegame and endgame scores (two values in one integer) where I spent almost one week of development and testing and we had very subtle bugs even after release (take a look at value.h) just for a very minimal speed increase.
This is a useful comment. I have been seriously considering adding this myself, but you have convinced me its not worth the bother and potential bugs. My last engine was darn fast, but bug ridden. The bugs are not worth it .
-Sam
I do the unified scores and it took a good day of work getting it all in place and it turned out to be less than a 1 percent speedup. However, in my opinion I get cleaner code out of it and when I add things now it's less likely to have bugs. I guess the devil is in the details.
xcomponent wrote:It is a matter of taste. There is nothing wrong to assign static scoring during generate, as long as it is superseded properly by the dynamic factors later. I like that.
Efficiency. Never do now what you can postpone until later, as with alpha/beta, later may never come.