Code: Select all
u64 empty = ~occ;
u64 bb = wPawnMoves[fs] & empty;
// What is the fastest way (branchless) to remove the bit if there is one
// for fs + 16 if there is a piece on fs + 8
Moderator: Ras
Code: Select all
u64 empty = ~occ;
u64 bb = wPawnMoves[fs] & empty;
// What is the fastest way (branchless) to remove the bit if there is one
// for fs + 16 if there is a piece on fs + 8
You could just OR the existing "occ" mask with the "occ" mask shifted up by one board line. Basically pretending that the piece blocking the double step isn't right before the pawn, but instead on the target square of the double step.Mike Sherwin wrote: ↑Sun Mar 13, 2022 12:39 am// What is the fastest way (branchless) to remove the bit if there is one for fs + 16 if there is a piece on fs + 8
You left a small detail out.Ras wrote: ↑Sun Mar 13, 2022 2:34 amYou could just OR the existing "occ" mask with the "occ" mask shifted up by one board line. Basically pretending that the piece blocking the double step isn't right before the pawn, but instead on the target square of the double step.Mike Sherwin wrote: ↑Sun Mar 13, 2022 12:39 am// What is the fastest way (branchless) to remove the bit if there is one for fs + 16 if there is a piece on fs + 8
I'm storing the ts bits in a bit table (u64 genbb[ply][fs]) and not spinning them into a move list.dangi12012 wrote: ↑Sun Mar 13, 2022 3:28 am BB move = pawns & (occ << 8)
BB push = pawns & FirstRank & move & (occ << 16)
This selects the pawns which can move 1 or 2 squares forward as 2 bitboards. Taking and promotion look very similar.
Notice how that solves 16 pawnmoves in 6 instructions. Impossible with mailbox.
When you also want to do check evasion and pin handling check my signature.
Yeah, I don't even know your board geometry, and that determines whether to shift left or right, and whether by 1 or by 8 bits. So I figured just posting the general idea would do the trick because you'd know your implementation best, and it would also be most helpful for people who later find that via the forum search function.
Transforming a BB into a list always takes a loop.Mike Sherwin wrote: ↑Sun Mar 13, 2022 12:48 pmI'm storing the ts bits in a bit table (u64 genbb[ply][fs]) and not spinning them into a move list.dangi12012 wrote: ↑Sun Mar 13, 2022 3:28 am BB move = pawns & (occ << 8)
BB push = pawns & FirstRank & move & (occ << 16)
This selects the pawns which can move 1 or 2 squares forward as 2 bitboards. Taking and promotion look very similar.
Notice how that solves 16 pawnmoves in 6 instructions. Impossible with mailbox.
When you also want to do check evasion and pin handling check my signature.
so that means I'd have to have two while loops to store all the bits. That is why it is done one pawn at a time.
genbb[ply][fs] = wPawnMoves[fs] ^ (occ | ((occ ^ (1ull << fs)) << 8));
So I'm not sure which way is faster?![]()
Code: Select all
#define Bitloop(X) for(;X; X = _blsr_u64(X))
Code: Select all
BB pmove = pawns & (occ << 8);
BB ppush = pawns & FirstRank & pmove & (occ << 16);
BitLoop(pmove)
{
//*movelist++ = ...
//Normally you dont need to go back to integer representation like this from BB (you only loose speed) but i included it here:
//int squareFrom = SquareOf(pmove);
//int squareTo = squareFrom +8;
}
BitLoop(ppush)
{
//*movelist++ = ...
}
But but but I do not spin the bits into a bulk move list. I store the raw bits into genbb[ply][fs] for later use that still won't make a bulk move list. No move list.dangi12012 wrote: ↑Sun Mar 13, 2022 4:35 pmTransforming a BB into a list always takes a loop.Mike Sherwin wrote: ↑Sun Mar 13, 2022 12:48 pmI'm storing the ts bits in a bit table (u64 genbb[ply][fs]) and not spinning them into a move list.dangi12012 wrote: ↑Sun Mar 13, 2022 3:28 am BB move = pawns & (occ << 8)
BB push = pawns & FirstRank & move & (occ << 16)
This selects the pawns which can move 1 or 2 squares forward as 2 bitboards. Taking and promotion look very similar.
Notice how that solves 16 pawnmoves in 6 instructions. Impossible with mailbox.
When you also want to do check evasion and pin handling check my signature.
so that means I'd have to have two while loops to store all the bits. That is why it is done one pawn at a time.
genbb[ply][fs] = wPawnMoves[fs] ^ (occ | ((occ ^ (1ull << fs)) << 8));
So I'm not sure which way is faster?![]()
I found the fastest loop was this (instead of _blsr_u64 you can use (x-1) & x)
So I would recommend to you this:Code: Select all
#define Bitloop(X) for(;X; X = _blsr_u64(X))
That is as efficient as I ever found it. If you have an improvement let me know!Code: Select all
BB pmove = pawns & (occ << 8); BB ppush = pawns & FirstRank & pmove & (occ << 16); BitLoop(pmove) { //*movelist++ = ... //Normally you dont need to go back to integer representation like this from BB (you only loose speed) but i included it here: //int squareFrom = SquareOf(pmove); //int squareTo = squareFrom +8; } BitLoop(ppush) { //*movelist++ = ... }
Its faster to solve all pawns and loop over solution bits instead of looping over all pawns and then over all bits of each pawn.
Later you will have to differentiate between a move and a push because that marks a pawn as Enpassant. If you store both in a single bitboard how do you store that information?Mike Sherwin wrote: ↑Sun Mar 13, 2022 6:16 pm But but but I do not spin the bits into a bulk move list. I store the raw bits into genbb[ply][fs] for later use that still won't make a bulk move list. No move list.
Bob
'Never do now what might not need to be done later.'