Skip to content

Commit e905117

Browse files
Merge pull request #10 from startnow2024/main
2 parents 4fd714f + 6556cc9 commit e905117

1 file changed

Lines changed: 75 additions & 1 deletion

File tree

cchess/__init__.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Iterable, Union, SupportsInt, Iterator, Callable, List, Tuple, Dict, Optional
1+
from typing import Iterable, Union, SupportsInt, Iterator, Callable, List, Tuple, Dict, TypeVar,Optional
22
import copy
33
import dataclasses
44
import enum
@@ -306,6 +306,30 @@ def square_mirror(square: Square) -> Square:
306306
BB_START_OCCUPIED = 0x3fe00415540000aaa0801ff
307307

308308

309+
def flip_vertical(bb: BitBoard) -> BitBoard:
310+
# https://www.chessprogramming.org/Flipping_Mirroring_and_Rotating#FlipVertically
311+
K1 = 0x1FF00003FE00FF80001FF
312+
K2 = 0xFF8000000007FC0000
313+
bb = ((bb >> 9) & K1) | ((bb & K1) << 9) | (bb & K2)
314+
K3 = 0x7FFFE0000003FFFF
315+
bb = (bb >> 9*3) & K3 | (bb & K3) << 9*3 | (bb & K2)
316+
317+
K4 = 0x1FFFFFFFFFFF
318+
bb= (bb >> 9*5) & K4 | (bb & K4) << 9*5
319+
320+
return bb
321+
322+
def flip_horizontal(bb: BitBoard) -> BitBoard:
323+
# https://www.chessprogramming.org/Flipping_Mirroring_and_Rotating#MirrorHorizontally
324+
FH1 = 0x14AA552A954AA552A954AA5
325+
FH2 = 0x2010080402010080402010
326+
FH3 = 0xC6633198CC6633198CC663
327+
FH4 = 0x1E0F0783C1E0F0783C1E0F
328+
bb = ((bb >> 1) & FH1) | ((bb & FH1) << 1) | (bb & FH2)
329+
bb = ((bb >> 2) & FH3) | ((bb & FH3) << 2) | (bb & FH2)
330+
bb = ((bb >> 5) & FH4) | ((bb & FH4) << 5)
331+
return bb
332+
309333
def _sliding_attacks(square: Square, occupied: BitBoard, deltas: Iterable[int]):
310334
attacks = BB_EMPTY
311335

@@ -617,6 +641,7 @@ def null(cls):
617641
def __hash__(self):
618642
return hash((self.from_square, self.to_square))
619643

644+
BaseBoardT = TypeVar("BaseBoardT", bound="BaseBoard")
620645

621646
class BaseBoard:
622647
def __init__(self, board_fen: Optional[str] = STARTING_BOARD_FEN):
@@ -907,6 +932,55 @@ def attacks_mask(self, square: Square) -> BitBoard:
907932
return _cannon_attacks(square, self.occupied)
908933
return 0
909934

935+
936+
def apply_transform(self, f: Callable[[BitBoard], BitBoard]) -> None:
937+
self.pawns = f(self.pawns)
938+
self.knights = f(self.knights)
939+
self.bishops = f(self.bishops)
940+
self.rooks = f(self.rooks)
941+
self.advisors = f(self.advisors)
942+
self.kings = f(self.kings)
943+
self.cannons = f(self.cannons)
944+
945+
self.occupied_co[RED] = f(self.occupied_co[RED])
946+
self.occupied_co[BLACK] = f(self.occupied_co[BLACK])
947+
self.occupied = f(self.occupied)
948+
949+
950+
def transform(self: BaseBoardT, f: Callable[[BitBoard], BitBoard]) -> BaseBoardT:
951+
"""
952+
Returns a transformed copy of the board (without move stack)
953+
by applying a bitboard transformation function.
954+
955+
Available transformations include :func:`chess.flip_vertical()`,
956+
:func:`chess.flip_horizontal()`, :func:`chess.flip_vertical()`,
957+
958+
959+
Alternatively, :func:`~chess.BaseBoard.apply_transform()` can be used
960+
to apply the transformation on the board.
961+
"""
962+
board = self.copy()
963+
board.apply_transform(f)
964+
return board
965+
966+
def apply_mirror(self: BaseBoardT) -> None:
967+
self.apply_transform(flip_vertical)
968+
self.occupied_co[RED], self.occupied_co[BLACK] = self.occupied_co[BLACK], self.occupied_co[RED]
969+
970+
def mirror(self: BaseBoardT) -> BaseBoardT:
971+
"""
972+
Returns a mirrored copy of the board (without move stack).
973+
974+
The board is mirrored vertically and piece colors are swapped, so that
975+
the position is equivalent modulo color.
976+
977+
Alternatively, :func:`~chess.BaseBoard.apply_mirror()` can be used
978+
to mirror the board.
979+
"""
980+
board = self.copy()
981+
board.apply_mirror()
982+
return board
983+
910984
def attacks(self, square: Square):
911985
"""
912986
Gets the set of attacked squares from the given square.

0 commit comments

Comments
 (0)