Author: Gerd Isenberg
Date: 12:21:07 02/27/04
Go up one level in this thread
<snip>
>>Sharing source code for left-right mirrored files and patterns is another issue.
>>I like the idea of using C++ template int(kingwing|queenwing)-parameter with two
>>function incarnations, rather than using an actual parameter with one single
>>function.
>
>I'm a big fan of writing general code which with a single for loop can mirror
>quickly.
>
>However, in practice this is not so easy, because many simple patterns simply
>execute way faster when written out for black & white and left & right.
>
>Additionally understand very well that programs like Fritz basically castle
>short and basically never need those king safety patterns at the queenside.
>
>So it saves out another few hundreds of cycles and you know how happy Frans is
>with another 100 cycles. I can't blame him there.
>
>I do understand it fully.
>
>But back to implementation level, source code above all must be very readable.
>
>If you cannot write readable code then it is very hard to improve your code,
>especially when the total size gets pretty big.
>
>Today i'm toying again with my own EGTBs again. In contradiction to my
>evaluation function i can easily write some very neat general easy to use and
>very portable code, which simply is not as fast as it could be!
>
>Let's take a simple bishop pattern and write it out simple in the bishop
>evaluation:
>
> if( sq == sq_d3
> && snelbord[sq_d2] == pawn
> && snelbord[sq_c1] == bishop ) {
> s += PAWN_BLOKT2ERIJ;
> }
>
>Now black:
> if( sq == sq_d6
> && snelbord[sq_d7] == bpawn
> && snelbord[sq_c8] == bbishop ) {
> s += PAWN_BLOKT2ERIJ;
> }
>
>The above code is very easy to understand and read. No confusion possible.
>
>Additionally it's very fast to write. If datastructures get extended you don't
>need to worry about weird variables or defines or whatever mirrorring.
>
>Easy clear code.
>
>Chance is like 95% that the first branch gives a misprediction.
>
>So it's very fast code too, especially in PGO'ed executables.
>
Yes, written once, copied and pasted 3 times and replacing d3 by e3,d6,e6,
pawn by bpawn etc. Some testing with mirrored positions - ok, fine.
I did that too, but it's always a pain if you change something and you have to
consider up to four places in your source. Meanwhile i prefere macros or inline
functions, since msc6.0 (or the linker) has some problems with int-templates.
One possible template approach may look like this:
enum
{
a1, b1, c1, d1, e1, f1, g1, h1,
a2, b2, c2, d2, e2, f2, g2, h2,
a3, b3, c3, d3, e3, f3, g3, h3,
//...
};
enum WING {quwi=0, kiwi};
enum COLOR{white=0, black};
enum
{
pawn = 2,
bpawn,
bishop,
bbishop, // ...
};
int snelbord[64];
template <COLOR c> bool isPawn(int sq) {
return snelbord[sq] == pawn+c;}
template <COLOR c> bool isBishop(int sq) {
return snelbord[sq] == bishop+c;}
template<WING w, COLOR c> int mirr(int sq) {
return sq ^ (7*w) ^ ((7*c)<<3);}
// some "template constants"
template<WING w, COLOR c> int C1() {return mirr<w,c>(c1);}
template<WING w, COLOR c> int D2() {return mirr<w,c>(d2);}
template<WING w, COLOR c> int D3() {return mirr<w,c>(d3);}
template<WING w, COLOR c>
bool isPattern_PAWN_BLOCKt2ERIJ(int sq)
{
return sq == D3<w,c>()
&& isPawn<c>( D2<w,c>() )
&& isBishop<c>( C1<w,c>() );
}
That should produce the same machine code as your ones:
if ( isPattern_PAWN_BLOCKt2ERIJ<quwi,white>(sq) )
s += PAWN_BLOKT2ERIJ;
if ( isPattern_PAWN_BLOCKt2ERIJ<quwi,black>(sq) )
s += PAWN_BLOKT2ERIJ;
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.