For those with an interest in bitboard database coding, I'm presenting some code snippets from Symbolic. The source is all original other than the theft of some identifiers from the Slate and Atkin report of Chess 4.x written some forty years ago.
Symbolic's code is different from some other programs in that it maintains the full attack-to-square bitboard vector at each node, and that it makes use of pre-computed tables as much as possible for the various square scanning loops.
First, from the Bitboard class definition in the bitboard database header file:
Code: Select all
void AttackAdd(const Sq sq, const Color color, const Man man);
void AttackDel(const Sq sq, const Color color);
void AttackPro(const Sq sq);
void AttackCut(const Sq sq);
Bitboard merge; // All men merged
Bitboard sweep; // Sweeper men merged (bishops, rooks, queens)
Bitboard locbm[ManRCLen]; // Locus by man
Bitboard locbc[ColorRCLen]; // Locus by color
Bitboard atkbc[ColorRCLen]; // Attacked by color
Bitboard atkfs[SqLen]; // Attacks from a square
Bitboard atkts[SqLen]; // Attacks to a square
Code: Select all
void BBDB::Reset(void)
{
merge.Reset();
sweep.Reset();
ForEachManRC(man)
locbm[man].Reset();
ForEachColorRC(color)
{
locbc[color].Reset();
atkbc[color].Reset();
};
ForEachSq(sq)
{
atkfs[sq].Reset();
atkts[sq].Reset();
};
}
Code: Select all
void BBDB::AttackAdd(const Sq sq, const Color color, const Man man)
{
BitboardPtr const atkfsptr = &atkfs[sq];
BitboardPtr const atkbcptr = &atkbc[color];
switch (CvManToPiece[man])
{
case PiecePawn:
{
const Sq *scanptr = PawnRunPtrs[color][sq];
Sq afssq;
while (IsSqNotNil(afssq = *scanptr++))
{
atkts[afssq].SetSq(sq);
atkfsptr->SetSq(afssq);
atkbcptr->SetSq(afssq);
};
};
break;
case PieceKnight:
{
const Sq *scanptr = KnightRunPtrs[sq];
Sq afssq;
while (IsSqNotNil(afssq = *scanptr++))
{
atkts[afssq].SetSq(sq);
atkfsptr->SetSq(afssq);
atkbcptr->SetSq(afssq);
};
};
break;
case PieceBishop:
case PieceRook:
case PieceQueen:
{
const Dir dir1 = CvManToDir1[man];
for (Dir dir = CvManToDir0[man]; dir <= dir1; IncrDir(dir))
if (Bitboard::ShadowBBVec[dir].IsSqSet(sq))
{
const Bitboard stopbb = merge | Bitboard::EdgeBBVec[dir];
const si delta = CvDirToSqDelta[dir];
Sq afssq = sq;
do
{
ApplySqDelta(afssq, delta);
atkts[afssq].SetSq(sq);
atkfsptr->SetSq(afssq);
atkbcptr->SetSq(afssq);
} while (stopbb.IsSqReset(afssq));
};
};
break;
case PieceKing:
{
const Sq *scanptr = KingRunPtrs[sq];
Sq afssq;
while (IsSqNotNil(afssq = *scanptr++))
{
atkts[afssq].SetSq(sq);
atkfsptr->SetSq(afssq);
atkbcptr->SetSq(afssq);
};
};
break;
default:
SwitchFault("BBDB::AttackAdd");
break;
};
}
Code: Select all
void BBDB::AttackDel(const Sq sq, const Color color)
{
const Bitboard locbb = locbc[color];
BitboardPtr const atkbcptr = &atkbc[color];
Sq atssq;
while (IsSqNotNil(atssq = atkfs[sq].NextSq()))
{
atkts[atssq].ResetSq(sq);
if ((atkts[atssq] & locbb).IsReset())
atkbcptr->ResetSq(atssq);
};
}
Code: Select all
void BBDB::AttackPro(const Sq sq)
{
const Bitboard atrbb = atkts[sq] & sweep;
ForEachColorRC(atsco)
{
BitboardPtr const atkbcptr = &atkbc[atsco];
Bitboard atsbb = atrbb & locbc[atsco];
Sq atssq;
while (IsSqNotNil(atssq = atsbb.NextSq()))
{
const Dir dir = SqSqDir[atssq][sq];
if (Bitboard::ShadowBBVec[dir].IsSqSet(sq))
{
BitboardPtr const atkfsptr = &atkfs[atssq];
const Bitboard stopbb = merge | Bitboard::EdgeBBVec[dir];
const si delta = CvDirToSqDelta[dir];
Sq raysq = sq;
do
{
ApplySqDelta(raysq, delta);
atkts[raysq].SetSq(atssq);
atkfsptr->SetSq(raysq);
atkbcptr->SetSq(raysq);
}
while (stopbb.IsSqReset(raysq));
};
};
};
}
Code: Select all
void BBDB::AttackPro(const Sq sq)
{
const Bitboard atrbb = atkts[sq] & sweep;
ForEachColorRC(atsco)
{
BitboardPtr const atkbcptr = &atkbc[atsco];
Bitboard atsbb = atrbb & locbc[atsco];
Sq atssq;
while (IsSqNotNil(atssq = atsbb.NextSq()))
{
const Dir dir = SqSqDir[atssq][sq];
if (Bitboard::ShadowBBVec[dir].IsSqSet(sq))
{
BitboardPtr const atkfsptr = &atkfs[atssq];
const Bitboard stopbb = merge | Bitboard::EdgeBBVec[dir];
const si delta = CvDirToSqDelta[dir];
Sq raysq = sq;
do
{
ApplySqDelta(raysq, delta);
atkts[raysq].SetSq(atssq);
atkfsptr->SetSq(raysq);
atkbcptr->SetSq(raysq);
}
while (stopbb.IsSqReset(raysq));
};
};
};
}