Please look at my previous post.dangi12012 wrote: ↑Sun Mar 13, 2022 6:57 pmLater 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.
Also there will have to be promotion - how do you store that too?
Tricky Optimization Question
Moderator: Ras
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
I thought about it and I do appreciate the idea a lot, I really do. However, no matter what the board representation is and what direction the shift is there are two constants and that is occ has the fs bit set and the fs bit has to be zero or the idea won't work.Ras wrote: ↑Sun Mar 13, 2022 4:00 pmYeah, 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.![]()

-
- Posts: 2696
- Joined: Tue Aug 30, 2016 8:19 pm
- Full name: Rasmus Althoff
Re: Tricky Optimization Question
Ah, that's because if you shift up the occ just like that, then the pawn itself appears as fake pawn on the square immediately ahead so that it will erroneously block the single step forward. Actually, I overlooked that catch.Mike Sherwin wrote: ↑Sun Mar 13, 2022 8:26 pmHowever, no matter what the board representation is and what direction the shift is there are two constants and that is occ has the fs bit set and the fs bit has to be zero or the idea won't work.
Rasmus Althoff
https://www.ct800.net
https://www.ct800.net
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
+1Ras wrote: ↑Sun Mar 13, 2022 8:35 pmAh, that's because if you shift up the occ just like that, then the pawn itself appears as fake pawn on the square immediately ahead so that it will erroneously block the single step forward. Actually, I overlooked that catch.Mike Sherwin wrote: ↑Sun Mar 13, 2022 8:26 pmHowever, no matter what the board representation is and what direction the shift is there are two constants and that is occ has the fs bit set and the fs bit has to be zero or the idea won't work.

-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
Oh Nooooo!
It still does not work because of the spurious bits in occ.
But not to worry! I fixed it and optimixed it at the same time
bb = (occ & (0x00100ull << fs)) ? 0 : empty & (0x10100ull << fs);
Let's verify:
00000
false -
10100
00100
true --
00000
10000
false -
00100
10100
true --
00000
Please check or optimix further.
Mike: Well that wasn't all that tricky afterall!
Someone: Then why did it take you almost 3 days?

It still does not work because of the spurious bits in occ.
But not to worry! I fixed it and optimixed it at the same time

bb = (occ & (0x00100ull << fs)) ? 0 : empty & (0x10100ull << fs);
Let's verify:
00000


00100


10000


10100


Please check or optimix further.
Mike: Well that wasn't all that tricky afterall!
Someone: Then why did it take you almost 3 days?
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
I said please!
Oh well, so what.
Anyway, this is the line of code in my engine.
genbb[ply][fs] = (occ & (0x00100ull << fs)) ? 0 : empty & (0x10100ull << fs);
I was able to verify in the debugger that it works perfectly in all possible arrangements of blockers.
So unless anyone can come up with something faster for a single pawn on the second rank this thread looks to be finished.

Oh well, so what.
Anyway, this is the line of code in my engine.
genbb[ply][fs] = (occ & (0x00100ull << fs)) ? 0 : empty & (0x10100ull << fs);
I was able to verify in the debugger that it works perfectly in all possible arrangements of blockers.
So unless anyone can come up with something faster for a single pawn on the second rank this thread looks to be finished.
-
- Posts: 1062
- Joined: Tue Apr 28, 2020 10:03 pm
- Full name: Daniel Infuehr
Re: Tricky Optimization Question
You still have a real conditional in there. So that will not be so fast.Mike Sherwin wrote: ↑Wed Mar 16, 2022 2:21 am So unless anyone can come up with something faster for a single pawn on the second rank this thread looks to be finished.
What do you write into the BB? The pawns that can move - or the attacked squares?
Both can be done unconditionally.
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Daniel Inführ - Software Developer
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
The moves the pawn can make.dangi12012 wrote: ↑Wed Mar 16, 2022 3:28 pmYou still have a real conditional in there. So that will not be so fast.Mike Sherwin wrote: ↑Wed Mar 16, 2022 2:21 am So unless anyone can come up with something faster for a single pawn on the second rank this thread looks to be finished.
What do you write into the BB? The pawns that can move - or the attacked squares?
Both can be done unconditionally.
-
- Posts: 1062
- Joined: Tue Apr 28, 2020 10:03 pm
- Full name: Daniel Infuehr
Re: Tricky Optimization Question
Code: Select all
genbb[ply][fs] = (pawns << 8 & ~occ)
genbb[ply][fs] |= ((genbb[ply][fs] & SecondRank) << 8 & ~occ)
Code: Select all
const auto forward = pawns << 8;
const auto forward2 = forward | ((pawns & ~FirstRank) << 16);
const auto empty = ~occ;
genbb[ply][fs] = (forward & empty) | (forward2 & empty);
But as I said its wasteful to do that for all 8 pawns seperately. The functions above does not care it its 1 pawn or 8 pawns or even more.
If you want to depend the shift on the color so (<< 8 or >> 8) check my signature how that is done without runtime cost.
Worlds-fastest-Bitboard-Chess-Movegenerator
Daniel Inführ - Software Developer
Daniel Inführ - Software Developer
-
- Posts: 965
- Joined: Fri Aug 21, 2020 1:25 am
- Location: Planet Earth, Sol system
- Full name: Michael J Sherwin
Re: Tricky Optimization Question
I took some time off because I was worn out. Today I decided to check the CPW again to see if I missed anything. Well I overlooked the multipawn code that can work on a single pawn.
For a white pawn singlePushs is basically this.
((1ull << fs << 8) & empty);
Which reduces to this.
u64 bb = ((0x0000000000000100 << fs) & empty);
Then adding the check for double move it becomes.
bb = ((0x0000000000000100 << fs) & empty);
bb = bb | ((bb << 8) & empty);
For black.
bb = ((1ull << fs >> 8) & empty);
bb = bb | ((bb >> 8) & empty);
Code: Select all
U64 wSinglePushTargets(U64 wpawns, U64 empty) {
return nortOne(wpawns) & empty;
}
U64 wDblPushTargets(U64 wpawns, U64 empty) {
const U64 rank4 = C64(0x00000000FF000000);
U64 singlePushs = wSinglePushTargets(wpawns, empty);
return nortOne(singlePushs) & empty & rank4;
}
U64 bSinglePushTargets(U64 bpawns, U64 empty) {
return soutOne(bpawns) & empty;
}
U64 bDoublePushTargets(U64 bpawns, U64 empty) {
const U64 rank5 = C64(0x000000FF00000000);
U64 singlePushs = bSinglePushTargets(bpawns, empty);
return soutOne(singlePushs) & empty & rank5;
}
((1ull << fs << 8) & empty);
Which reduces to this.
u64 bb = ((0x0000000000000100 << fs) & empty);
Then adding the check for double move it becomes.
bb = ((0x0000000000000100 << fs) & empty);
bb = bb | ((bb << 8) & empty);
For black.
bb = ((1ull << fs >> 8) & empty);
bb = bb | ((bb >> 8) & empty);