Problem with bitboard knight attack generator

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problem with bitboard knight attack generator

Post by lucasart »

Aleks Peshkov wrote:

Code: Select all

    template <> Bb attack<Knight>&#40;Square sq&#41; &#123;
        return sq&#40;-2, -1&#41; + sq&#40;-2, +1&#41; + sq&#40;-1, -2&#41; + sq&#40;-1, +2&#41;
             + sq&#40;+2, +1&#41; + sq&#40;+2, -1&#41; + sq&#40;+1, +2&#41; + sq&#40;+1, -2&#41;;
    &#125;

Code: Select all

Bb Square&#58;&#58;operator&#40;) &#40;signed fileOffset, signed rankOffset&#41; const &#123;
    signed x88 = *this + (*this & 070&#41; + fileOffset + 16*rankOffset;
    if &#40;x88 & 0x88&#41; &#123;
        return Bb&#58;&#58;empty&#40;); //offside
    &#125; else &#123;
        Square sq = static_cast<square_t>(&#40;x88 + &#40;x88 & 7&#41;) >> 1&#41;;
        return Bb&#40;sq&#41;;
    &#125;
&#125;
Woaw, that real C++ wizardry !
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Problem with bitboard knight attack generator

Post by ZirconiumX »

I take your point.

I just use C++ for STL and stuff like that (the <algorithm> header has come in handy). But even I use C++ better than a certain author of Fruit. (From reading the code in Fruit 2.1 he doesn't seem to have heard of classes or templates, *makes a mental note to upgrade Fruit 2.1 so it uses modern features*).

I use a (probably) strange method of determining pawn captures.

Code: Select all

void InitPawnAttacks&#40;)
&#123;
	const Bitboard a = 0x5ULL;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;0&#93;&#91;i&#93; = a << i + 8;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;1&#93;&#91;i&#93; = a << i - 8;
&#125;		
I just take 5 and right shift it by the square + (for white) or - (for black) 8.


Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problem with bitboard knight attack generator

Post by lucasart »

ZirconiumX wrote: But even I use C++ better than a certain author of Fruit. (From reading the code in Fruit 2.1 he doesn't seem to have heard of classes or templates, *makes a mental note to upgrade Fruit 2.1 so it uses modern features*).
It was always unclear to my why Fabien wrote Fruit in C++ and not in C. His code would probably compile (with a few trivial modifications) with any ISO C99 compiler. He doesn't use any C++ feature, but just called his source files *.cpp and compiled with g++ i/o gcc.

But I really like his code, and I think that Fruit 2.1's source code has been the greatest contribution to the computer chess community of all times! Second on "my list" is of course Glaurung/StockFish. The point is that these programs are very well constructed, and their code is cristal clear. Everything is nicely separated and testable separately.

The (first) key to a good chess program is probably to eliminate bugs, and an easy way to achieve it is by making the code as banal as possible, and program very defensively (put assert everywhere for example, never make dubious assumptions). And that was the lesson that Fabien gave to everyone when he published his code, and spanked almost all other programs, even though those programs had a lot more "features" than Fruit, which had a relatively simple eval and straight forward search algorithm.

Ippolit however, as strong as it may be, is one the most obfuscated and illegible code ever written. A good candidate for the famous IOCCC ;-)
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Problem with bitboard knight attack generator

Post by ZirconiumX »

Yup Fruit 2.1 is great , and yup, Fruit 2.1 compiles with GCC without any modifications... It makes you wonder, doesn't it?

What makes me laugh is the IPPOLIT wiki always calls us "capitalists" (not all the countries are capitalist over here, some are royal capitalist)

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problem with bitboard knight attack generator

Post by lucasart »

ZirconiumX wrote:

Code: Select all

void InitPawnAttacks&#40;)
&#123;
	const Bitboard a = 0x5ULL;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;0&#93;&#91;i&#93; = a << i + 8;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;1&#93;&#91;i&#93; = a << i - 8;
&#125;		
I like your pawn attack code. It's very elegant !
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problem with bitboard knight attack generator

Post by lucasart »

ZirconiumX wrote:Yup Fruit 2.1 is great , and yup, Fruit 2.1 compiles with GCC without any modifications... It makes you wonder, doesn't it?

What makes me laugh is the IPPOLIT wiki always calls us "capitalists" (not all the countries are capitalist over here, some are royal capitalist)

Matthew:out
I think the IPPOLIT wiki is just a big joke. The developpers of IPPOLIT are probably people like you and me, just having fun and disguising their names under ridiculous peudonyms (taken from Dostoievsky's litterature). I think the capitalist that they flame are the developpers of proprietary and/or commercial engines. Of course, this capitalist / socialist stuff is a big joke, but I do agree that proprietary software is the devil's inventions.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Problem with bitboard knight attack generator

Post by lucasart »

lucasart wrote:
ZirconiumX wrote:

Code: Select all

void InitPawnAttacks&#40;)
&#123;
	const Bitboard a = 0x5ULL;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;0&#93;&#91;i&#93; = a << i + 8;
	for &#40;int i = a2; i < h7; i++) &#123;
		PawnAttacks&#91;1&#93;&#91;i&#93; = a << i - 8;
&#125;		
I like your pawn attack code. It's very elegant !
Unfortunately it's incorrect. Have you tested it ?
For example 5ULL << A2 + 8 is actually the value that you should get for B2 not for A2.
And when i = H2, can you guess what happens ?

Also the compiler generates a warning and invites you to clarify operator associativity. And I agree with the compiler that

Code: Select all

PawnAttacks&#91;0&#93;&#91;i&#93; = a << &#40;i + 8&#41;;
is somewhat easier to read.
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Problem with bitboard knight attack generator

Post by ZirconiumX »

Yes, it was an attempt by a noob to try and get a decent attack generator with as few lines as possible...

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.
User avatar
sje
Posts: 4675
Joined: Mon Mar 13, 2006 7:43 pm

CookieCat's advance and onboard arrays

Post by sje »

CookieCat's advance and onboard arrays:

Code: Select all

  var

    advance&#58; array &#91;sqtype, dirtype&#93; of sqxtype; &#123; Next square along any direction &#125;
    onboard&#58; array &#91;sqtype, dirtype&#93; of Boolean; &#123; True if next square is on the board &#125;

  function CalcAdvance&#40;sq&#58; sqtype; dir&#58; dirtype&#41;&#58; sqxtype;
    var
      fval, rval&#58; si8type;
  begin
    fval &#58;= Ord&#40;MapSqToBfile&#40;sq&#41;) + dirtobfiledelta&#91;dir&#93;;
    rval &#58;= Ord&#40;MapSqToBrank&#40;sq&#41;) + dirtobrankdelta&#91;dir&#93;;
    if &#40;fval < 0&#41; or &#40;fval > bfilemax&#41; or &#40;rval < 0&#41; or &#40;rval > brankmax&#41; then
      CalcAdvance &#58;= sqnil
    else
      CalcAdvance &#58;= MapBfileBrankToSq&#40;bfiletype&#40;fval&#41;, branktype&#40;rval&#41;)
  end; &#123; CalcAdvance &#125;

      procedure InitializeAdvance;
        var
          sq&#58; sqtype;
          dir&#58; dirtype;
      begin
        for sq &#58;= 0 to sqmax do
          for dir &#58;= 0 to dirmax do
            advance&#91;sq, dir&#93; &#58;= CalcAdvance&#40;sq, dir&#41;
      end; &#123; InitializeAdvance &#125;

      procedure InitializeOnBoard;
        var
          sq&#58; sqtype;
          dir&#58; dirtype;
          flag&#58; Boolean; &#123; Needed for compiler bug work-around &#125;
      begin
        for sq &#58;= 0 to sqmax do
          for dir &#58;= 0 to dirmax do
            begin
              flag &#58;= advance&#91;sq, dir&#93; <> sqnil;
              onboard&#91;sq, dir&#93; &#58;= flag
            end
      end; &#123; InitializeAdvance &#125;
ZirconiumX
Posts: 1334
Joined: Sun Jul 17, 2011 11:14 am

Re: Problem with bitboard knight attack generator

Post by ZirconiumX »

In theory, it would have worked. In practice however...

The error for being ahead of the square should be fixed by replacing 8 with 7, and wraparound by ANDing with the file ahead. So we get this:

Code: Select all

void InitPawnAttacks&#40;)
&#123;
   const Bitboard a = 0x5ULL;
   for &#40;int i = a2; i < h7; i++) &#123;
      PawnAttacks&#91;0&#93;&#91;i&#93; = &#40;a << &#40;i + 7&#41;) bitand &#40;FileMaskForSquare&#40;i&#41; + 1&#41;;
   for &#40;int i = a2; i < h7; i++) &#123;
      PawnAttacks&#91;1&#93;&#91;i&#93; = &#40;a << &#40;i - 7&#41;) bitand &#40;FileMaskForSquare&#40;i&#41; - 1&#41;;
&#125;
Which is somewhat less elegant...

Matthew:out
Some believe in the almighty dollar.

I believe in the almighty printf statement.