tcusr wrote: ↑Mon Dec 13, 2021 10:25 pm
it's sad to see kogge stone perform so poorly (btw why it's the only algo not sorted correclty?)
where did you take the code for it? one mistake i've seen in other engines (to avoid typing 8 functions) is that they use a general shift function and when they fill one direction they also consider wraps, which they shouldn't since they are already taken care of by the propagator
in my engine 'queen_attacks' is exactly 200 branchless instructions. the funny thing is that i never use it, when i generate attacks for bishops/rook i also add the queen bitboards so i only use rook/bishop attacks.
Kogge was from this thread where i was given the sourcecode to Elephant_1_07_remains.
Sourcecode: (Maybe not that I look at it nothing is marked as constexpr..)
Not a single one of the algos has "Queen Attacks". I always add Queen() return Rook | Bishop. Because that tests both codepaths and is more rigurous testing.
You want to send me your engines sliding piece algorithm?
Code: Select all
namespace Chess_Lookup::KoggeStone {
/*******************************************************************/
#include <stdint.h>
#define C64 uint64_t
#define BitBoard uint64_t
///////////////////////////////////////////////////////////////////////////
BitBoard ShiftUp(BitBoard b) { return b << 8; }
BitBoard ShiftDown(BitBoard b) { return b >> 8; }
BitBoard ShiftLeft(BitBoard b) { return (b << 1) & C64(0xfefefefefefefefe); }
BitBoard ShiftRight(BitBoard b) { return (b >> 1) & C64(0x7f7f7f7f7f7f7f7f); }
BitBoard ShiftUpLeft(BitBoard b) { return (b << 9) & C64(0xfefefefefefefefe); }
BitBoard ShiftUpRight(BitBoard b) { return (b << 7) & C64(0x7f7f7f7f7f7f7f7f); }
BitBoard ShiftDownLeft(BitBoard b) { return (b >> 7) & C64(0xfefefefefefefefe); }
BitBoard ShiftDownRight(BitBoard b) { return (b >> 9) & C64(0x7f7f7f7f7f7f7f7f); }
///////////////////////////////////////////////////////////////////////////
/**
The routine FillUpOccluded() smears the set bits of bitboard g upwards, but only
along set bits of p; a reset bit in p is enough to halt a smear. RookAttacksUp()
uses this routine to find all squares rooks may occupy by either staying still
or moving up along empty squares (no captures allowed). Shifting this last
result up by 1 square gives the squares all rooks can attack by moving upwards
(which _does_ include captures).
*/
BitBoard FillUpOccluded(BitBoard g, BitBoard p)
{
g |= p & (g << 8);
p &= (p << 8);
g |= p & (g << 16);
p &= (p << 16);
return g |= p & (g << 32);
}
BitBoard FillDownOccluded(BitBoard g, BitBoard p)
{
g |= p & (g >> 8);
p &= (p >> 8);
g |= p & (g >> 16);
p &= (p >> 16);
return g |= p & (g >> 32);
}
BitBoard FillLeftOccluded(BitBoard g, BitBoard p)
{
p &= C64(0xfefefefefefefefe);
g |= p & (g << 1);
p &= (p << 1);
g |= p & (g << 2);
p &= (p << 2);
return g |= p & (g << 4);
}
BitBoard FillRightOccluded(BitBoard g, BitBoard p)
{
p &= C64(0x7f7f7f7f7f7f7f7f);
g |= p & (g >> 1);
p &= (p >> 1);
g |= p & (g >> 2);
p &= (p >> 2);
return g |= p & (g >> 4);
}
BitBoard FillUpLeftOccluded(BitBoard g, BitBoard p)
{
p &= C64(0xfefefefefefefefe);
g |= p & (g << 9);
p &= (p << 9);
g |= p & (g << 18);
p &= (p << 18);
return g |= p & (g << 36);
}
BitBoard FillUpRightOccluded(BitBoard g, BitBoard p)
{
p &= C64(0x7f7f7f7f7f7f7f7f);
g |= p & (g << 7);
p &= (p << 7);
g |= p & (g << 14);
p &= (p << 14);
return g |= p & (g << 28);
}
BitBoard FillDownLeftOccluded(BitBoard g, BitBoard p)
{
p &= C64(0xfefefefefefefefe);
g |= p & (g >> 7);
p &= (p >> 7);
g |= p & (g >> 14);
p &= (p >> 14);
return g |= p & (g >> 28);
}
BitBoard FillDownRightOccluded(BitBoard g, BitBoard p)
{
p &= C64(0x7f7f7f7f7f7f7f7f);
g |= p & (g >> 9);
p &= (p >> 9);
g |= p & (g >> 18);
p &= (p >> 18);
return g |= p & (g >> 36);
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a bishop, rook or queen on the square moving in the direction.
*/
uint64_t direction_attacks(int square, int dir, uint64_t occ)
{
uint64_t seed = 1ull << square;
uint64_t free = ~occ;
// 4 3 2
// 5 0 1
// 6 7 8
switch (dir)
{
case 1:
return ShiftRight(FillRightOccluded(seed, free));
case 5:
return ShiftLeft(FillLeftOccluded(seed, free));
case 7:
return ShiftDown(FillDownOccluded(seed, free));
case 3:
return ShiftUp(FillUpOccluded(seed, free));
case 8:
return ShiftDownRight(FillDownRightOccluded(seed, free));
case 4:
return ShiftUpLeft(FillUpLeftOccluded(seed, free));
case 2:
return ShiftUpRight(FillUpRightOccluded(seed, free));
case 6:
return ShiftDownLeft(FillDownLeftOccluded(seed, free));
default:
return 0;
}
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a rook or queen on the square.
*/
uint64_t attacks_rook(int square, uint64_t occ)
{
uint64_t seed = 1ull << square;
uint64_t free = ~occ;
return ShiftRight(FillRightOccluded(seed, free))
| ShiftLeft(FillLeftOccluded(seed, free))
| ShiftUp(FillUpOccluded(seed, free))
| ShiftDown(FillDownOccluded(seed, free));
}
/*******************************************************************/
/**
Get a bitboard with all positions set to 1 which can be attacked
from a bishop or queen on the square.
*/
BitBoard attacks_bishop(int square, uint64_t occ)
{
uint64_t seed = 1ull << square;
uint64_t free = ~occ;
return ShiftUpRight(FillUpRightOccluded(seed, free))
| ShiftUpLeft(FillUpLeftOccluded(seed, free))
| ShiftDownLeft(FillDownLeftOccluded(seed, free))
| ShiftDownRight(FillDownRightOccluded(seed, free));
}
uint64_t Queen(int square, uint64_t occ) {
return attacks_bishop(square, occ) | attacks_rook(square, occ);
}
}