Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Discussion of chess software programming and technical issues.

Moderator: Ras

User030910
Posts: 2
Joined: Fri Jan 19, 2024 4:27 pm
Full name: Ethan Dailler

Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by User030910 »

Hello,
I use Quad-Bitboards, however looking at a lot of codebases online I could scarcely found any that used Q-B.
Has there been some discussions on the cost/benefit of Q-B, were them found to be too expensive ?
Does someone have a link which explains why they have been more or less "abandonned" ?

Thank you for your time.

P.S. a code snippet of my Position class
BB0: The pieces of the side to move OR the en-passant square
BB1: Queens OR Bishops OR Pawns OR Rooks which have castling right
BB2: Rooks OR Bishops OR Knights
BB3: Queens OR Rooks OR Kings

Code: Select all

class Position {
public:
	inline Position() = default;

	inline Bitboard all() const { return bb[1] | bb[2] | bb[3]; }

	inline Bitboard us() const { return bb[0] & all(); }

	inline Bitboard them() const { return ~bb[0] & all(); }

	inline Bitboard enpassant() const { return bb[0] & ~all(); }

	inline Bitboard castling() const { return bb[1] & bb[2] & bb[3]; }

	inline Bitboard kings() const { return ~bb[1] & ~bb[2] & bb[3]; }

	inline Bitboard queens() const { return bb[1] & ~bb[2] & bb[3]; }

	inline Bitboard rooks() const { return bb[2] & bb[3]; }

	inline Bitboard bishops() const { return bb[1] & bb[2] & ~bb[3]; }

	inline Bitboard knights() const { return ~bb[1] & bb[2] & ~bb[3]; }

	inline Bitboard pawns() const { return bb[1] & ~bb[2] & ~bb[3]; }

private:
	Bitboard bb[4];
};
smatovic
Posts: 3374
Joined: Wed Mar 10, 2010 10:18 pm
Location: Hamburg, Germany
Full name: Srdja Matovic

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by smatovic »

I use Quads in my Zeta engine cos of memory usage:

https://gitlab.com/smatovic/Zeta

Quad-Bitboards combine memory efficiency with Bitboard features.

A disadvantage might be the extracting costs of pieces and squares.

--
Srdja
User030910
Posts: 2
Joined: Fri Jan 19, 2024 4:27 pm
Full name: Ethan Dailler

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by User030910 »

Thank you,
Quad-Bitboards seem more common in GPU engines, ankan's perft program had a Q-B structure but I don't think he used it in the end.

You are using this, is the eighth bitboard empty ?

Code: Select all

Bitboard BOARD[8];
/* Quad-Bitboards++ array index definition
  0   pieces black
  1   piece type first bit
  2   piece type second bit
  3   piece type third bit
  5   piece moved flags, for castle rights
  6   64 bit board Zobrist hash
  7   lastmove + ep target + halfmove clock + move score
*/
smatovic
Posts: 3374
Joined: Wed Mar 10, 2010 10:18 pm
Location: Hamburg, Germany
Full name: Srdja Matovic

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by smatovic »

Yes, In Zeta Dva, CPU engine, I use that:

https://gitlab.com/smatovic/ZetaDva/-/b ... =heads#L75

Code: Select all

/* Quad-Bitboards++ array index definition */
#define QBBBLACK  0     /* pieces black */
#define QBBP1     1     /* piece type first bit */
#define QBBP2     2     /* piece type second bit */
#define QBBP3     3     /* piece type third bit */
#define QBBPMVD   4     /* piece moved flags, for castle rights */
#define QBBHASH   5     /* 64 bit board Zobrist hash */
#define QBBSCORE  6     /* 16 bit, signed board score , stored as u64 */
#define QBBLAST   7     /* lastmove + ep target + halfmove clock + move score */
In Zeta, GPU device, I use this:

Code: Select all

// QBB++ array index defintion
#define QBBBLACK        0     // pieces black
#define QBBP1           1     // piece type first bit
#define QBBP2           2     // piece type second bit
#define QBBP3           3     // piece type third bit
https://gitlab.com/smatovic/Zeta/-/blob ... heads#L885

With the rest of infos stored in arrays indexed by ply.

--
Srdja
Dmi3
Posts: 5
Joined: Thu Sep 11, 2025 11:15 am
Location: Russia
Full name: Dmitry Molodov

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by Dmi3 »

smatovic wrote: Wed Jul 23, 2025 3:18 pm I use Quads in my Zeta engine cos of memory usage:

https://gitlab.com/smatovic/Zeta

Quad-Bitboards combine memory efficiency with Bitboard features.

A disadvantage might be the extracting costs of pieces and squares.

--
Srdja
You can combine extremely high compactness and sufficient performance when using a universal position representation.
1) 6 bits for the position of the active king
2) 2 bits for castling the active king
3) 6 bits for the opponent's king position
4) 2 bits for castling the opponent's king
5) 64 bits for signs of occupied fields (up to 30 fields occupied by non-kings)
6) up to 30 bits for the pawn\non-pawn sign on an occupied field
7) up to 30 bits for indicating the activity (or color) of a piece on an occupied field
8) up to 16 bits to indicate a diagonal piece on a non-pawn-occupied square (B Q)
9) up to 16 bits to indicate a heavy piece on a non-pawn-occupied field (R Q)
10) up to 5 bits to encode the pawn/king pass field during castling
11) Multiple bits for alignment.

p.s. use PEXT \ PDEP instructions.
benvining
Posts: 44
Joined: Fri May 30, 2025 10:18 pm
Location: Chicago
Full name: Ben Vining

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by benvining »

User030910 wrote: Tue Jul 22, 2025 9:41 pm

Code: Select all

class Position {
public:
	inline Position() = default;

	inline Bitboard all() const { return bb[1] | bb[2] | bb[3]; }

	inline Bitboard us() const { return bb[0] & all(); }

	inline Bitboard them() const { return ~bb[0] & all(); }

	inline Bitboard enpassant() const { return bb[0] & ~all(); }

	inline Bitboard castling() const { return bb[1] & bb[2] & bb[3]; }

	inline Bitboard kings() const { return ~bb[1] & ~bb[2] & bb[3]; }

	inline Bitboard queens() const { return bb[1] & ~bb[2] & bb[3]; }

	inline Bitboard rooks() const { return bb[2] & bb[3]; }

	inline Bitboard bishops() const { return bb[1] & bb[2] & ~bb[3]; }

	inline Bitboard knights() const { return ~bb[1] & bb[2] & ~bb[3]; }

	inline Bitboard pawns() const { return bb[1] & ~bb[2] & ~bb[3]; }

private:
	Bitboard bb[4];
};
Not to derail this thread, but just a slight nitpick is that you don't need to specify inline on every class methods. Class methods defined within the class body are implicitly inline.
ZirconiumX
Posts: 1361
Joined: Sun Jul 17, 2011 11:14 am
Full name: Hannah Ravensloft

Re: Effectiveness of storing Pieces/En-passant/Castling in four bitboards

Post by ZirconiumX »

Position compactness just does not mean much in practice.

It's just as (if not more so) performant to represent a board with SIMD vectors with at least a byte per square as it is to represent a board as four bitboards.
tu ne cede malis, sed contra audentior ito