@@ -1356,51 +1356,9 @@ def split_index(i: int) -> Tuple[int, int]:
1356
1356
iBMATEt = tb_BMATE | 4
1357
1357
1358
1358
1359
- def removepiece (ys : List [int ], yp : List [int ], j : int ) -> None :
1360
- del ys [j ]
1361
- del yp [j ]
1362
-
1363
1359
def opp (side : int ) -> int :
1364
1360
return 1 if side == 0 else 0
1365
1361
1366
- def adjust_up (dist : int ) -> int :
1367
- udist = dist
1368
- sw = udist & INFOMASK
1369
-
1370
- if sw in [iWMATE , iWMATEt , iBMATE , iBMATEt ]:
1371
- udist += (1 << PLYSHIFT )
1372
-
1373
- return udist
1374
-
1375
- def bestx (side : int , a : int , b : int ) -> int :
1376
- # 0 = selectfirst
1377
- # 1 = selectlowest
1378
- # 2 = selecthighest
1379
- # 3 = selectsecond
1380
- comparison = [
1381
- # draw, wmate, bmate, forbid
1382
- [0 , 3 , 0 , 0 ], # draw
1383
- [0 , 1 , 0 , 0 ], # wmate
1384
- [3 , 3 , 2 , 0 ], # bmate
1385
- [3 , 3 , 3 , 0 ], # forbid
1386
- ]
1387
-
1388
- xorkey = [0 , 3 ]
1389
-
1390
- if a == iFORBID :
1391
- return b
1392
- if b == iFORBID :
1393
- return a
1394
-
1395
- retu = [a , a , b , b ]
1396
-
1397
- if b < a :
1398
- retu [1 ] = b
1399
- retu [2 ] = a
1400
-
1401
- key = comparison [a & 3 ][b & 3 ] ^ xorkey [side ]
1402
- return retu [key ]
1403
-
1404
1362
def unpackdist (d : int ) -> Tuple [int , int ]:
1405
1363
return d >> PLYSHIFT , d & INFOMASK
1406
1364
@@ -1492,12 +1450,11 @@ class Request:
1492
1450
black_piece_types : List [int ]
1493
1451
is_reversed : bool
1494
1452
1495
- def __init__ (self , white_squares : List [int ], white_types : List [chess .PieceType ], black_squares : List [int ], black_types : List [chess .PieceType ], side : int , epsq : int ):
1453
+ def __init__ (self , white_squares : List [int ], white_types : List [chess .PieceType ], black_squares : List [int ], black_types : List [chess .PieceType ], side : int ):
1496
1454
self .white_squares , self .white_types = sortlists (white_squares , white_types )
1497
1455
self .black_squares , self .black_types = sortlists (black_squares , black_types )
1498
1456
self .realside = side
1499
1457
self .side = side
1500
- self .epsq = epsq
1501
1458
1502
1459
1503
1460
@dataclasses .dataclass
@@ -1569,17 +1526,34 @@ def probe_dtm(self, board: chess.Board) -> int:
1569
1526
if board .occupied == board .kings :
1570
1527
return 0
1571
1528
1529
+ # Resolve en passant.
1530
+ dtm = self ._probe_dtm_no_ep (board )
1531
+ for move in board .generate_legal_ep ():
1532
+ try :
1533
+ board .push (move )
1534
+
1535
+ child_dtm = - self ._probe_dtm_no_ep (board )
1536
+ if child_dtm > 0 :
1537
+ child_dtm += 1
1538
+ elif child_dtm < 0 :
1539
+ child_dtm -= 1
1540
+
1541
+ dtm = min (dtm , child_dtm ) if dtm * child_dtm > 0 else max (dtm , child_dtm )
1542
+ finally :
1543
+ board .pop ()
1544
+ return dtm
1545
+
1546
+ def _probe_dtm_no_ep (self , board : chess .Board ) -> int :
1572
1547
# Prepare the tablebase request.
1573
1548
white_squares = list (chess .SquareSet (board .occupied_co [chess .WHITE ]))
1574
1549
white_types = [typing .cast (chess .PieceType , board .piece_type_at (sq )) for sq in white_squares ]
1575
1550
black_squares = list (chess .SquareSet (board .occupied_co [chess .BLACK ]))
1576
1551
black_types = [typing .cast (chess .PieceType , board .piece_type_at (sq )) for sq in black_squares ]
1577
1552
side = 0 if (board .turn == chess .WHITE ) else 1
1578
- epsq = board .ep_square if board .ep_square else NOSQUARE
1579
- req = Request (white_squares , white_types , black_squares , black_types , side , epsq )
1553
+ req = Request (white_squares , white_types , black_squares , black_types , side )
1580
1554
1581
1555
# Probe.
1582
- dtm = self .egtb_get_dtm (req )
1556
+ dtm = self ._tb_probe (req )
1583
1557
ply , res = unpackdist (dtm )
1584
1558
1585
1559
if res == iWMATE :
@@ -1675,10 +1649,7 @@ def _setup_tablebase(self, req: Request) -> BinaryIO:
1675
1649
req .white_piece_types = req .black_types
1676
1650
req .black_piece_squares = [flip_ns (s ) for s in req .white_squares ]
1677
1651
req .black_piece_types = req .white_types
1678
-
1679
1652
req .side = opp (req .side )
1680
- if req .epsq != NOSQUARE :
1681
- req .epsq = flip_ns (req .epsq )
1682
1653
else :
1683
1654
raise MissingTableError (f"no gaviota table available for: { white_letters .upper ()} v{ black_letters .upper ()} " )
1684
1655
@@ -1708,77 +1679,6 @@ def close(self) -> None:
1708
1679
_ , stream = self .streams .popitem ()
1709
1680
stream .close ()
1710
1681
1711
- def egtb_get_dtm (self , req : Request ) -> int :
1712
- dtm = self ._tb_probe (req )
1713
-
1714
- if req .epsq != NOSQUARE :
1715
- capturer_a = 0
1716
- capturer_b = 0
1717
- xed = 0
1718
-
1719
- # Flip for move generation.
1720
- if req .side == 0 :
1721
- xs = list (req .white_piece_squares )
1722
- xp = list (req .white_piece_types )
1723
- ys = list (req .black_piece_squares )
1724
- yp = list (req .black_piece_types )
1725
- else :
1726
- xs = list (req .black_piece_squares )
1727
- xp = list (req .black_piece_types )
1728
- ys = list (req .white_piece_squares )
1729
- yp = list (req .white_piece_types )
1730
-
1731
- # Captured pawn trick: from ep square to captured.
1732
- xed = req .epsq ^ (1 << 3 )
1733
-
1734
- # Find captured index (j).
1735
- try :
1736
- j = ys .index (xed )
1737
- except ValueError :
1738
- j = - 1
1739
-
1740
- # Try first possible ep capture.
1741
- if 0 == (0x88 & (map88 (xed ) + 1 )):
1742
- capturer_a = xed + 1
1743
-
1744
- # Try second possible ep capture.
1745
- if 0 == (0x88 & (map88 (xed ) - 1 )):
1746
- capturer_b = xed - 1
1747
-
1748
- if (j > - 1 ) and (ys [j ] == xed ):
1749
- # Find capturers (i).
1750
- for i in range (len (xs )):
1751
- if xp [i ] == chess .PAWN and (xs [i ] == capturer_a or xs [i ] == capturer_b ):
1752
- epscore = iFORBID
1753
-
1754
- # Copy position.
1755
- xs_after = xs [:]
1756
- ys_after = ys [:]
1757
- xp_after = xp [:]
1758
- yp_after = yp [:]
1759
-
1760
- # Execute capture.
1761
- xs_after [i ] = req .epsq
1762
- removepiece (ys_after , yp_after , j )
1763
-
1764
- # Flip back.
1765
- if req .side == 1 :
1766
- xs_after , ys_after = ys_after , xs_after
1767
- xp_after , yp_after = yp_after , xp_after
1768
-
1769
- # Make subrequest.
1770
- subreq = Request (xs_after , xp_after , ys_after , yp_after , opp (req .side ), NOSQUARE )
1771
- try :
1772
- epscore = self ._tb_probe (subreq )
1773
- epscore = adjust_up (epscore )
1774
-
1775
- # Choose to ep or not.
1776
- dtm = bestx (req .side , epscore , dtm )
1777
- except IndexError :
1778
- break
1779
-
1780
- return dtm
1781
-
1782
1682
def egtb_block_getnumber (self , req : Request , idx : int ) -> int :
1783
1683
maxindex = EGKEY [req .egkey ].maxindex
1784
1684
0 commit comments