Typical white knight capture routine

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

benstoker
Posts: 342
Joined: Tue Jan 19, 2010 2:05 am

Typical white knight capture routine

Post by benstoker »

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 ...

Code: Select all


for (bb_t knights = Board.pieces [WN]; knights; knights &= knights-1)
{
    int knight_sq = bit_scan (knights);
    for (bb_t captures = knight_moves [knight_sq] & opponent_pieces; captures; captures &= captures - 1)
    {
        int capture_sq = bit_scan (captures);
        *moves ++ = move (knight_sq, capture_sq);
        *values ++ = Board.sq [capture_sq] * 256 + 192;
    }
}

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

Re: Typical white knight capture routine

Post by bob »

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 ...

Code: Select all


for (bb_t knights = Board.pieces [WN]; knights; knights &= knights-1)
{
    int knight_sq = bit_scan (knights);
    for (bb_t captures = knight_moves [knight_sq] & opponent_pieces; captures; captures &= captures - 1)
    {
        int capture_sq = bit_scan (captures);
        *moves ++ = move (knight_sq, capture_sq);
        *values ++ = Board.sq [capture_sq] * 256 + 192;
    }
}

Does this look somewhat familiar? :) This is from Crafty, movgen.c, GenerateCaptures()...

Code: Select all

  for (piecebd = Knights(wtm); piecebd; Clear(from, piecebd)) {
    from = Advanced(wtm, piecebd);
    moves = knight_attacks[from] & Occupied(btm);
    temp = from + &#40;knight << 12&#41;;
    Unpack&#40;wtm, move, moves, temp&#41;;
  &#125;
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.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Typical white knight capture routine

Post by mcostalba »

The only interesting (but I don't like) thing is that the scores are updated during move generation (*values = ....) according to a MVV/LVA scheme.
Edsel Apostol
Posts: 803
Joined: Mon Jul 17, 2006 5:53 am
Full name: Edsel Apostol

Re: Typical white knight capture routine

Post by Edsel Apostol »

It is common except that it scored it immediately while other programs scored it later.

Here's from my engine:

Code: Select all

    pc_bits = pos->knights & allies;
    while &#40;pc_bits&#41; &#123;
        from = popFirstBit&#40;&pc_bits&#41;;
        mv_bits = KnightMoves&#91;from&#93; & mask;
        while &#40;mv_bits&#41; &#123;
            to = popFirstBit&#40;&mv_bits&#41;;
            sort->list&#91;sort->size++&#93;.m = GenKnightMove&#40;from, to, getPiece&#40;pos, to&#41;);
        &#125;
    &#125;
Mincho Georgiev
Posts: 454
Joined: Sat Apr 04, 2009 6:44 pm
Location: Bulgaria

Re: Typical white knight capture routine

Post by Mincho Georgiev »

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.
mcostalba
Posts: 2684
Joined: Sat Jun 14, 2008 9:17 pm

Re: Typical white knight capture routine

Post by mcostalba »

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.
You have an additional probe to board table:

Code: Select all

*values ++ = Board.sq &#91;capture_sq&#93; * 256 + 192; 
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:

Code: Select all

- moves generation &#40;movegen.cpp&#41;
- moves scoring &#40;movepick.cpp&#41;
- moves sorting &#40;movepick.cpp&#41;
- next move picking logic &#40;movepick.cpp&#41;
- search loop  &#40;search.cpp&#41;
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.
Mincho Georgiev
Posts: 454
Joined: Sat Apr 04, 2009 6:44 pm
Location: Bulgaria

Re: Typical white knight capture routine

Post by Mincho Georgiev »

As i said, it is a matter of preference.
BubbaTough
Posts: 1154
Joined: Fri Jun 23, 2006 5:18 am

Re: Typical white knight capture routine

Post by BubbaTough »

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 :oops:.

-Sam
User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 4:27 pm

Re: Typical white knight capture routine

Post by Don »

BubbaTough wrote:
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 :oops:.

-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.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Typical white knight capture routine

Post by bob »

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.

But it is an OK thing to do, just not optimal.