Pinned Pieces With Bitboards

Discussion of chess software programming and technical issues.

Moderator: Ras

StackFish5
Posts: 18
Joined: Fri Dec 24, 2021 5:48 pm
Full name: Andrew Zhuo

Pinned Pieces With Bitboards

Post by StackFish5 »

While reading an article on CPW regarding checks and pinned pieces: https://www.chessprogramming.org/Checks ... Bitboards)
I didn't fully understand this function:

Code: Select all

 pinned = 0;
pinner = xrayRookAttacks(occupiedBB, ownPieces, squareOfKing) & opRQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}
pinner = xrayBishopAttacks(occupiedBB, ownPieces, squareOfKing) & opBQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}

My question is what the function obstructed() does. Moreover, I would like to know whether opRQ refers to the rooks and queens. And whether opBQ refers to the bishops and queens.

Thanks.
dangi12012
Posts: 1062
Joined: Tue Apr 28, 2020 10:03 pm
Full name: Daniel Infuehr

Re: Pinned Pieces With Bitboards

Post by dangi12012 »

I found the CPW to be not up do date with some implementations.
There is a more efficient way to resolve pins and checks which in essence literally takes one & instruction.

A pinned knight cannot move.
A pinned slider can only move along its pinned direction including the enemy piece that pins it.
No piece can be pinned multiple times.

Special piece:
Pawns. Pins for move and take work like sliders.
EP has some special extra pins.

The trick is that pins are two bitboards: HV, D12 - its the absolute optimum I found.
I also have some optimal code regarding check evasion. IMO I really solved BBs like no one else.

So a full legal only knight move BB looks like this:
uint64_t moves = Lookup[knightsquare] & EnemyOrEmpty & checkmask & ~(pinHV | pinD12)

Translated:
From all Knightsquares take those which are enemy or empty. Take those who stop a check if it exists. But only if the knight is not pinned.
Adding an "if" makes this 10x slower.

Please check out the URL in my signature for exactly the question you are asking!
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: Pinned Pieces With Bitboards

Post by tcusr »

StackFish5 wrote: Fri Apr 01, 2022 4:15 am While reading an article on CPW regarding checks and pinned pieces: https://www.chessprogramming.org/Checks ... Bitboards)
I didn't fully understand this function:

Code: Select all

 pinned = 0;
pinner = xrayRookAttacks(occupiedBB, ownPieces, squareOfKing) & opRQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}
pinner = xrayBishopAttacks(occupiedBB, ownPieces, squareOfKing) & opBQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}

My question is what the function obstructed() does. Moreover, I would like to know whether opRQ refers to the rooks and queens. And whether opBQ refers to the bishops and queens.

Thanks.
yes opRQ contains both opposite rooks and queens, it's useful because the queen is just a rook + bishop, so you can save computation.
obstructed returns the bits between sq (the possible pinner) and squareOfKing
StackFish5
Posts: 18
Joined: Fri Dec 24, 2021 5:48 pm
Full name: Andrew Zhuo

Re: Pinned Pieces With Bitboards

Post by StackFish5 »

tcusr wrote: Fri Apr 01, 2022 3:59 pm
StackFish5 wrote: Fri Apr 01, 2022 4:15 am While reading an article on CPW regarding checks and pinned pieces: https://www.chessprogramming.org/Checks ... Bitboards)
I didn't fully understand this function:

Code: Select all

 pinned = 0;
pinner = xrayRookAttacks(occupiedBB, ownPieces, squareOfKing) & opRQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}
pinner = xrayBishopAttacks(occupiedBB, ownPieces, squareOfKing) & opBQ;
while ( pinner ) {
   int sq  = bitScanForward(pinner);
   pinned |= obstructed(sq, squareOfKing) & ownPieces;
   pinner &= pinner - 1;
}

My question is what the function obstructed() does. Moreover, I would like to know whether opRQ refers to the rooks and queens. And whether opBQ refers to the bishops and queens.

Thanks.
yes opRQ contains both opposite rooks and queens, it's useful because the queen is just a rook + bishop, so you can save computation.
obstructed returns the bits between sq (the possible pinner) and squareOfKing
So the obstructed function is the same function as the one under Pure Calculation from https://www.chessprogramming.org/Square ... tackBySide ?
tcusr
Posts: 325
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: Pinned Pieces With Bitboards

Post by tcusr »

yes
StackFish5
Posts: 18
Joined: Fri Dec 24, 2021 5:48 pm
Full name: Andrew Zhuo

Re: Pinned Pieces With Bitboards

Post by StackFish5 »

Thank you to everyone that responded!
ericlangedijk
Posts: 23
Joined: Thu Aug 08, 2013 5:13 pm

Re: Pinned Pieces With Bitboards

Post by ericlangedijk »

Me responding to old post....
Currently investigating optimizing pins.
I think the "fastest bitboard move generator" could maybe add one more compiletime known boolean: "has_pins".
If there are no pins on the board (which is often the case) we could omit all pinchecks. No clue if it would speedup but I thought it is an idea worth mentioning.
OliverBr
Posts: 818
Joined: Tue Dec 18, 2007 9:38 pm
Location: Munich, Germany
Full name: Dr. Oliver Brausch

Re: Pinned Pieces With Bitboards

Post by OliverBr »

This is how OliThink does it.
I invented this about 20 years ago, along with OliThink's Kindergarten Bitboards (the name didn't exist then).

int k: Everything views from the King (k=square).
u64 occ: Bitboard representation of every occupied square.
P.color[oc]: Bitboard representation of all enemy squares.
RQU: Bitboard representation of all Rooks and Queens.

Now they are u64 Bitboard functions like the "Rook-rays" and "Rook-x-rays":
RATT(k, occ) represents all possible straight sliding moves from King(k) to the first occupied square. (and including)
RXRAY(k, occ) represents all possible straight sliding moves behind the occupied square to the next occupier. Therefore the name "X-Ray".

Now if there are pinner candidates for "Rook moves" they will be represented in the following BB:

Code: Select all

u64 b = (RXRAY(k, occ) & P.color[oc]) & RQU;
Why are they only candidates? Because the piece between them and the King must be have the King's color in order to be pinned.
This is checked while collecting the pinned pieces:

Code: Select all

while (b) {
	int t = pullLsb(&b);
	pin |= RATT(k, occ) & RATT(t, occ) & P.color[oc^1];
}
They same must be done for the Bishop moves.
Chess Engine OliThink: http://brausch.org/home/chess
OliThink GitHub:https://github.com/olithink
ericlangedijk
Posts: 23
Joined: Thu Aug 08, 2013 5:13 pm

Re: Pinned Pieces With Bitboards

Post by ericlangedijk »

BTW: we can determine pinned pieces and checkers in one go.