Updating castling rights

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Jan Brouwer
Posts: 201
Joined: Thu Mar 22, 2007 7:12 pm
Location: Netherlands

Updating castling rights

Post by Jan Brouwer »

My program updates castling rights (4 bits) using masks which are part of the piece encoding:

Code: Select all

state &= board[move.from] & board[move.to] & MASK;
However this requires two types of rook encodings per color, which I don't like and want to remove.

An alternative is to use a lookup table indexed by square:

Code: Select all

state &= table[move.from] & table[move.to]
(I think this works, I haven't tried it.)
The disadvantage of this approach is the additional lookup table, of which only 6 entries are really used.

So can anyone think of yet another approach for simple, branchless castling rights update?
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: Updating castling rights

Post by Zach Wegner »

Sure. Here's one I came up with a while back. I call it "Spanish Castle Magic". :) I originally used a lookup table with it, but you can go without one if you redefine your castling rights (using 6 bits rather than 4). Unfortunately the castling rights become asymmetric doing this:

WKR=1
WK=16
WQR=2
BKR=8
BK=4
BQR=32

with the 1 bit indicating if white's king-side rook has moved, etc.

Code: Select all

#define CASTLE_MASK (0x9100000000000091)
#define CASTLE_MAGIC (0x0410000000000021)

#define CAN_CASTLE_W_KS(c) ((c) & 0x22)
#define CAN_CASTLE_W_QS(c) ((c) & 0x12)
#define CAN_CASTLE_B_KS(c) ((c) & 0x0C)
#define CAN_CASTLE_B_QS(c) ((c) & 0x05)

...

mask = (bb_from | bb_to) & CASTLE_MASK;
castle_rights &= mask * CASTLE_MAGIC >> 58;
Michael Sherwin
Posts: 3196
Joined: Fri May 26, 2006 3:00 am
Location: WY, USA
Full name: Michael Sherwin

Re: Updating castling rights

Post by Michael Sherwin »

In my opinion, castling rights do not need to be updated in (un)make.

In the move generator:

Code: Select all

if&#40;ply <= whiteCastleStopPly&#41; &#123;
  whiteCastleStopPly = INFINITY;
  if&#40;ply <= whiteShortStopPly&#41; &#123;
    whiteShortStopPly = INFINITY;
    if&#40;board&#91;E1&#93; == WHITE_KING&#41; &#123;
      if&#40;board&#91;H1&#93; == WHITE_KING_ROOK&#41; &#123;

        ... rest of castling short test here ...

      &#125; else &#123;
        if&#40;board&#91;H1&#93; == BlackPiece&#40;H1&#41;) &#123;
          whiteShortStopPly = ply - 1;
          if&#40;ply > whiteLongStopPly&#41; whiteCastleStopPly = ply - 1;
        &#125; else &#123;
          whiteShortStopPly = ply - 2;
          if&#40;ply > whiteLongStopPly&#41; whiteCastleStopPly = ply - 2;
        &#125;
      &#125;
    &#125; else &#123;
      whiteCastleStopPly = ply - 2;
      if&#40;ply > whiteLongStopPly&#41; whiteCastleStopPly = ply - 2;
    &#125;
  &#125; 
  if&#40;ply <= whiteLongStopPly &#123; ... &#125;
&#125;
    
I hope that I did not flub this up as I just did it from reinventing it in my head.

The nice thing about it is, once castling is no longer possible there is just one check for it and no updating in (un)make.
If you are on a sidewalk and the covid goes beep beep
Just step aside or you might have a bit of heat
Covid covid runs through the town all day
Can the people ever change their ways
Sherwin the covid's after you
Sherwin if it catches you you're through
Jan Brouwer
Posts: 201
Joined: Thu Mar 22, 2007 7:12 pm
Location: Netherlands

Re: Updating castling rights

Post by Jan Brouwer »

Nice, I hadn't expected to see two new approaches!
Michael, your approach of effectively replacing a stack of 4 bits with 4 numbers has a certain elegance to it, I'll look into it.

Meanwhile, thinking a bit more about this, I found a bug in my present code:
Jan Brouwer wrote:

Code: Select all

state &= board&#91;move.from&#93; & board&#91;move.to&#93; & MASK;
However this requires two types of rook encodings per color, ...
I actually need a 3rd rook encoding for promoted rooks, which doesn't modify the castling rights!

So, could anyone confirm that the following perft counts are now correct?

Code: Select all

position fen 4k3/8/8/8/8/8/R7/R3K2R w KQ - 0 1
perft 3
4893
position fen 4k3/8/8/8/8/8/R7/R3K2R w Q - 0 1
perft 3
4729
position fen 4k3/8/8/8/8/8/R7/R3K2R w K - 0 1
perft 3
4686
position fen 4k3/8/8/8/8/8/R7/R3K2R w - - 0 1
perft 3
4522
They are about a promoted rook move incorrectly modifying castling state:

[d]4k3/8/8/8/8/8/R7/R3K2R w KQ - 0 1
tvrzsky
Posts: 128
Joined: Sat Sep 23, 2006 7:10 pm
Location: Prague

Re: Updating castling rights

Post by tvrzsky »

My engine is here in agreement with yours.

Code: Select all

4k3/8/8/8/8/8/R7/R3K2R w KQ - 0 1
 _______________________________
|   |///|   |///|   |///|   |///|
|   |   |   |   |&#40;k&#41;|   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
| R |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
| R |   |   |   | K |   |   | R |
|___|___|___|___|___|___|___|___|


 Ply&#58; 0   Bily na tahu   Pocet figur&#58; 4 1   Material&#58; 1560  Figmat&#58; 1560/0

Ke1,Ra1,Ra2,Rh1,
ke8,
perft3
-------------------------------------------------------------------------------
perft&#40;3&#41;               SubtreePerft        InnerNodes
-------------------------------------------------------------------------------
01/32    O-O-O                  114                 4       0.00s    270.69kN/s
02/32      O-O                   96                 4       0.01s    108.28kN/s
03/32   Ra1-b1                  195                 6       0.02s    336.03kN/s
04/32   Ra1-c1                  195                 6       0.02s    249.87kN/s
05/32   Ra1-d1                  114                 4       0.03s    249.87kN/s
06/32  Ra2-a8+                  114                 4       0.04s    232.02kN/s
07/32  Ra2-e2+                  152                 5       0.05s    261.96kN/s
08/32   Ra2-a3                  165                 6       0.05s    314.36kN/s
09/32   Ra2-a4                  170                 6       0.06s    324.83kN/s
10/32   Ra2-a5                  175                 6       0.07s    314.36kN/s
11/32   Ra2-a6                  180                 6       0.08s    304.53kN/s
12/32   Ra2-a7                   74                 3       0.08s    168.02kN/s
13/32   Ra2-b2                  200                 6       0.09s    286.62kN/s
14/32   Ra2-c2                  200                 6       0.10s    314.36kN/s
15/32   Ra2-d2                  117                 4       0.11s    224.02kN/s
16/32   Ra2-f2                  117                 4       0.12s    216.56kN/s
17/32   Ra2-g2                  200                 6       0.12s    304.53kN/s
18/32   Ra2-h2                  160                 6       0.13s    314.36kN/s
19/32  Rh1-h8+                  108                 4       0.14s    196.87kN/s
20/32   Rh1-f1                   90                 4       0.15s    224.02kN/s
21/32   Rh1-g1                  155                 6       0.15s    314.36kN/s
22/32   Rh1-h2                  170                 6       0.16s    348.04kN/s
23/32   Rh1-h3                  180                 6       0.17s    324.83kN/s
24/32   Rh1-h4                  180                 6       0.18s    314.36kN/s
25/32   Rh1-h5                  180                 6       0.18s    314.36kN/s
26/32   Rh1-h6                  180                 6       0.19s    314.36kN/s
27/32   Rh1-h7                   72                 3       0.20s    108.28kN/s
28/32   Ke1-d1                  150                 6       0.21s    336.03kN/s
29/32   Ke1-d2                  175                 6       0.21s    348.04kN/s
30/32   Ke1-e2                  180                 6       0.22s    324.83kN/s
31/32   Ke1-f1                  150                 6       0.23s    348.04kN/s
32/32   Ke1-f2                  185                 6       0.24s    374.81kN/s
-------------------------------------------------------------------------------
total&#58;                        4,893               169       0.24s      0.70kN/s
-------------------------------------------------------------------------------
perft&#40;3&#41; = 4,893

Cil SharperPath nenalezen! &#40;cesta&#58; d&#58;\work\chessprog\Engines\Sharper.exe&#41;

a
4k3/8/8/8/8/8/R7/R3K2R w Q - 0 1
 _______________________________
|   |///|   |///|   |///|   |///|
|   |   |   |   |&#40;k&#41;|   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
| R |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
| R |   |   |   | K |   |   | R |
|___|___|___|___|___|___|___|___|


 Ply&#58; 0   Bily na tahu   Pocet figur&#58; 4 1   Material&#58; 1560  Figmat&#58; 1560/0

Ke1,Ra1,Ra2,Rh1,
ke8,
perft3
-------------------------------------------------------------------------------
perft&#40;3&#41;               SubtreePerft        InnerNodes
-------------------------------------------------------------------------------
01/31    O-O-O                  114                 4       0.00s    259.87kN/s
02/31   Ra1-b1                  190                 6       0.01s    324.83kN/s
03/31   Ra1-c1                  190                 6       0.02s    304.53kN/s
04/31   Ra1-d1                  111                 4       0.02s    240.62kN/s
05/31  Ra2-a8+                  111                 4       0.03s    209.57kN/s
06/31  Ra2-e2+                  148                 5       0.04s    116.01kN/s
07/31   Ra2-a3                  160                 6       0.05s    295.30kN/s
08/31   Ra2-a4                  165                 6       0.05s    237.68kN/s
09/31   Ra2-a5                  170                 6       0.06s    243.63kN/s
10/31   Ra2-a6                  175                 6       0.07s    324.83kN/s
11/31   Ra2-a7                   72                 3       0.07s    174.02kN/s
12/31   Ra2-b2                  195                 6       0.08s    314.36kN/s
13/31   Ra2-c2                  195                 6       0.09s    270.69kN/s
14/31   Ra2-d2                  114                 4       0.10s    240.62kN/s
15/31   Ra2-f2                  114                 4       0.10s    224.02kN/s
16/31   Ra2-g2                  195                 6       0.11s    314.36kN/s
17/31   Ra2-h2                  155                 6       0.12s    304.53kN/s
18/31  Rh1-h8+                  108                 4       0.13s    180.46kN/s
19/31   Rh1-f1                   90                 4       0.13s    240.62kN/s
20/31   Rh1-g1                  155                 6       0.14s    348.04kN/s
21/31   Rh1-h2                  170                 6       0.15s    278.43kN/s
22/31   Rh1-h3                  180                 6       0.16s    226.63kN/s
23/31   Rh1-h4                  180                 6       0.16s    270.69kN/s
24/31   Rh1-h5                  180                 6       0.17s    270.69kN/s
25/31   Rh1-h6                  180                 6       0.17s    256.45kN/s
26/31   Rh1-h7                   72                 3       0.18s    128.22kN/s
27/31   Ke1-d1                  150                 6       0.19s    226.63kN/s
28/31   Ke1-d2                  175                 6       0.19s    207.34kN/s
29/31   Ke1-e2                  180                 6       0.20s    211.85kN/s
30/31   Ke1-f1                  150                 6       0.21s    256.45kN/s
31/31   Ke1-f2                  185                 6       0.22s    278.43kN/s
-------------------------------------------------------------------------------
total&#58;                        4,729               165       0.22s      0.74kN/s
-------------------------------------------------------------------------------
perft&#40;3&#41; = 4,729

Cil SharperPath nenalezen! &#40;cesta&#58; d&#58;\work\chessprog\Engines\Sharper.exe&#41;

a
4k3/8/8/8/8/8/R7/R3K2R w K - 0 1
 _______________________________
|   |///|   |///|   |///|   |///|
|   |   |   |   |&#40;k&#41;|   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
| R |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
| R |   |   |   | K |   |   | R |
|___|___|___|___|___|___|___|___|


 Ply&#58; 0   Bily na tahu   Pocet figur&#58; 4 1   Material&#58; 1560  Figmat&#58; 1560/0

Ke1,Ra1,Ra2,Rh1,
ke8,
perft3
-------------------------------------------------------------------------------
perft&#40;3&#41;               SubtreePerft        InnerNodes
-------------------------------------------------------------------------------
01/31      O-O                   96                 4       0.00s    166.58kN/s
02/31   Ra1-b1                  195                 6       0.01s    324.83kN/s
03/31   Ra1-c1                  195                 6       0.02s    314.36kN/s
04/31   Ra1-d1                  114                 4       0.02s    240.62kN/s
05/31  Ra2-a8+                  111                 4       0.03s    240.62kN/s
06/31  Ra2-e2+                  148                 5       0.04s    312.34kN/s
07/31   Ra2-a3                  160                 6       0.05s    336.03kN/s
08/31   Ra2-a4                  165                 6       0.05s    141.23kN/s
09/31   Ra2-a5                  170                 6       0.06s    348.04kN/s
10/31   Ra2-a6                  175                 6       0.07s    348.04kN/s
11/31   Ra2-a7                   72                 3       0.08s    174.02kN/s
12/31   Ra2-b2                  195                 6       0.08s    324.83kN/s
13/31   Ra2-c2                  195                 6       0.09s    314.36kN/s
14/31   Ra2-d2                  114                 4       0.10s    240.62kN/s
15/31   Ra2-f2                  114                 4       0.11s    203.02kN/s
16/31   Ra2-g2                  195                 6       0.11s    336.03kN/s
17/31   Ra2-h2                  155                 6       0.12s    336.03kN/s
18/31  Rh1-h8+                  105                 4       0.13s    259.87kN/s
19/31   Rh1-f1                   87                 4       0.13s    259.87kN/s
20/31   Rh1-g1                  150                 6       0.14s    360.93kN/s
21/31   Rh1-h2                  165                 6       0.15s    216.56kN/s
22/31   Rh1-h3                  175                 6       0.16s    304.53kN/s
23/31   Rh1-h4                  175                 6       0.16s    348.04kN/s
24/31   Rh1-h5                  175                 6       0.17s    360.93kN/s
25/31   Rh1-h6                  175                 6       0.18s    336.03kN/s
26/31   Rh1-h7                   70                 3       0.19s    203.02kN/s
27/31   Ke1-d1                  150                 6       0.19s    374.81kN/s
28/31   Ke1-d2                  175                 6       0.20s    360.93kN/s
29/31   Ke1-e2                  180                 6       0.21s    348.04kN/s
30/31   Ke1-f1                  150                 6       0.21s    374.81kN/s
31/31   Ke1-f2                  185                 6       0.22s    360.93kN/s
-------------------------------------------------------------------------------
total&#58;                        4,686               165       0.23s      0.73kN/s
-------------------------------------------------------------------------------
perft&#40;3&#41; = 4,686

Cil SharperPath nenalezen! &#40;cesta&#58; d&#58;\work\chessprog\Engines\Sharper.exe&#41;

a
4k3/8/8/8/8/8/R7/R3K2R w - - 0 1
 _______________________________
|   |///|   |///|   |///|   |///|
|   |   |   |   |&#40;k&#41;|   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
|   |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|   |///|   |///|   |///|   |///|
| R |   |   |   |   |   |   |   |
|___|___|___|___|___|___|___|___|
|///|   |///|   |///|   |///|   |
| R |   |   |   | K |   |   | R |
|___|___|___|___|___|___|___|___|


 Ply&#58; 0   Bily na tahu   Pocet figur&#58; 4 1   Material&#58; 1560  Figmat&#58; 1560/0

Ke1,Ra1,Ra2,Rh1,
ke8,
perft3
-------------------------------------------------------------------------------
perft&#40;3&#41;               SubtreePerft        InnerNodes
-------------------------------------------------------------------------------
01/30   Ra1-b1                  190                 6       0.00s    389.80kN/s
02/30   Ra1-c1                  190                 6       0.01s    324.83kN/s
03/30   Ra1-d1                  111                 4       0.02s    249.87kN/s
04/30  Ra2-a8+                  108                 4       0.02s    249.87kN/s
05/30  Ra2-e2+                  144                 5       0.03s    290.03kN/s
06/30   Ra2-a3                  155                 6       0.04s    203.02kN/s
07/30   Ra2-a4                  160                 6       0.04s    374.81kN/s
08/30   Ra2-a5                  165                 6       0.05s    324.83kN/s
09/30   Ra2-a6                  170                 6       0.06s    304.53kN/s
10/30   Ra2-a7                   70                 3       0.06s    187.40kN/s
11/30   Ra2-b2                  190                 6       0.07s    336.03kN/s
12/30   Ra2-c2                  190                 6       0.08s    304.53kN/s
13/30   Ra2-d2                  111                 4       0.09s    240.62kN/s
14/30   Ra2-f2                  111                 4       0.09s    232.02kN/s
15/30   Ra2-g2                  190                 6       0.10s    324.83kN/s
16/30   Ra2-h2                  150                 6       0.11s    360.93kN/s
17/30  Rh1-h8+                  105                 4       0.11s    240.62kN/s
18/30   Rh1-f1                   87                 4       0.12s    224.02kN/s
19/30   Rh1-g1                  150                 6       0.13s    360.93kN/s
20/30   Rh1-h2                  165                 6       0.14s    348.04kN/s
21/30   Rh1-h3                  175                 6       0.14s    360.93kN/s
22/30   Rh1-h4                  175                 6       0.15s    374.81kN/s
23/30   Rh1-h5                  175                 6       0.16s    336.03kN/s
24/30   Rh1-h6                  175                 6       0.16s    389.80kN/s
25/30   Rh1-h7                   70                 3       0.17s    221.48kN/s
26/30   Ke1-d1                  150                 6       0.18s    336.03kN/s
27/30   Ke1-d2                  175                 6       0.18s    314.36kN/s
28/30   Ke1-e2                  180                 6       0.19s    123.35kN/s
29/30   Ke1-f1                  150                 6       0.20s    360.93kN/s
30/30   Ke1-f2                  185                 6       0.21s    324.83kN/s
-------------------------------------------------------------------------------
total&#58;                        4,522               161       0.21s      0.76kN/s
-------------------------------------------------------------------------------
perft&#40;3&#41; = 4,522

Cil SharperPath nenalezen! &#40;cesta&#58; d&#58;\work\chessprog\Engines\Sharper.exe&#41;

wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: Updating castling rights

Post by wgarvin »

Jan Brouwer wrote:I actually need a 3rd rook encoding for promoted rooks, which doesn't modify the castling rights!
I don't understand this part. There's no way to gain castling rights by moving a piece -- all you can do is lose them. Any time you move a piece FROM the square initially occupied by the rook, you can mask off the appropriate right (if this is anything other than the first move by that rook, then the right will already be gone). Similarly, any time you move a piece TO the square initially occupied by the rook, you can mask off the appropriate right too. Either its an enemy piece capturing that rook, or the rook has already moved at least once so the right is already gone.

I don't see how promotions can change this at all. If you make a capture+promotion move with an enemy pawn, you still want to remove the castling rights from the TO square just like with any other move. The type of the moving piece is irrelevant, for anything other than a castling move you can just mask off the rights for the FROM and TO squares.

[Edit: oops, I understand now. You have a bit in your piece encoding which says "I'm a rook that can castle QS" or similar. ...Why do this at all? Just to handle one special move during move generation? Seems like overkill.]
Jan Brouwer
Posts: 201
Joined: Thu Mar 22, 2007 7:12 pm
Location: Netherlands

Re: Updating castling rights

Post by Jan Brouwer »

tvrzsky wrote:My engine is here in agreement with yours.
Thanks, another bug squashed!
Jan Brouwer
Posts: 201
Joined: Thu Mar 22, 2007 7:12 pm
Location: Netherlands

Re: Updating castling rights

Post by Jan Brouwer »

wgarvin wrote: [Edit: oops, I understand now. You have a bit in your piece encoding which says "I'm a rook that can castle QS" or similar. ...Why do this at all? Just to handle one special move during move generation? Seems like overkill.]
Yes, the piece encodings contain a 4 bit mask which disables castling rights, like so:

Code: Select all

 * WK   &#58; b .... .... .... .... .... ...1 1=1= .1-1
 * BK   &#58; b .... .... .... .... .... ..1. =1=1 .1-1
 * WQ   &#58; b .... .... .... .... ...1 .1.. 1111 .1--
 * BQ   &#58; b .... .... .... .... ..1. 1... 1111 .1--
 * WR   &#58; b .... .... .... .... .... .1.. 1111 .-11  &#40;white promoted R&#41;
 * WRA  &#58; b .... .... .... .... .... .1.. 111= .-11  &#40;white queen side R&#41;
 * WRH  &#58; b .... .... .... .... .... .1.. 1=11 .-11  &#40;white king side R&#41;
 * BR   &#58; b .... .... .... .... .... 1... 1111 .-11  &#40;black promoted R&#41;
 * BRA  &#58; b .... .... .... .... .... 1... 11=1 .-11  &#40;black queen side R&#41;
 * BRH  &#58; b .... .... .... .... .... 1... =111 .-11  &#40;black king side R&#41;
 * WB   &#58; b .... .... .... .... ...1 .... 1111 .-1-
 * BB   &#58; b .... .... .... .... ..1. .... 1111 .-1-
 * WN   &#58; b .... .... .... .... .1.. .... 1111 .--1
 * BN   &#58; b .... .... .... .... 1... .... 1111 .--1
 * WP   &#58; b .... .... .... ...1 .... .... 1111 .---
 * BP   &#58; b .... .... .... ..1. .... .... 1111 .---
This allows easy update of castling state when executing a move:

Code: Select all

state &= board&#91;move.from&#93; & board&#91;move.to&#93; & 0xf0;
("state" has the castling bits conveniently located in bits 4..7.)
Note that this also handles losing castling rights by having your rook captured.
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: Updating castling rights

Post by wgarvin »

You could also just use a single bit to mean "this piece still has its initial castling right". Then do the same masking trick. Its not any more complicated in move generation because you still have to check the king and both rooks to make sure they have the right.

OTOH, you could forget about storing this bit in your piece encoding, and just keep 4 bits in your board representation for the 4 castling cases that are still allowed. Then you need to have a table with a 4-bit mask per board square, then in makemove do something like:

Code: Select all

    board.castlingRights &= castlingRightsPerSquare&#91;fromSq&#93; & castlingRightsPerSquare&#91;toSq&#93;;
Or if you like bitboards in your engine, you could just keep a bitboard of "pieces that don't have their initial castling right" and when making a move, just set the FROM and TO bits in this bitboard. If you do that, you won't even need a table. And you'd have to calculate the bitboards (1<<FROM) and (1<<TO) for other reasons anyway. When generating moves, just AND the bitboard with the proper mask for each castling move and if the result is non-zero, don't generate that move.
User avatar
Zach Wegner
Posts: 1922
Joined: Thu Mar 09, 2006 12:51 am
Location: Earth

Re: Updating castling rights

Post by Zach Wegner »

wgarvin wrote:Or if you like bitboards in your engine, you could just keep a bitboard of "pieces that don't have their initial castling right" and when making a move, just set the FROM and TO bits in this bitboard. If you do that, you won't even need a table. And you'd have to calculate the bitboards (1<<FROM) and (1<<TO) for other reasons anyway. When generating moves, just AND the bitboard with the proper mask for each castling move and if the result is non-zero, don't generate that move.
Not a bad idea. Funny I didn't think of that when doing my magic stuff. Saves the magic multiply/shift for having a bigger castle rights state holder (8 vs 1 byte, if that matters). One other advantage of your idea is that it becomes symmetrical:

Code: Select all

#define CAN_CASTLE_KS&#40;s,c&#41;       (&#40;c&#41;>>&#40;s&#41;*56 & 0x90&#41;
for white=0, black=1.