{-# LANGUAGE PatternSynonyms #-}
module Game.Chess.Internal.Square where

import           Control.Lens   (Iso', from, iso, view)
import           Data.Bifunctor (Bifunctor (..))
import           Data.Bits      (Bits (testBit))
import           Data.Char      (chr, ord)
import           Data.Coerce    (coerce)
import           Data.Ix        (Ix (..))
import           Data.String    (IsString (fromString))
import           Data.Word
import           GHC.Stack      (HasCallStack)

newtype Rank = Rank Int deriving (Rank -> Rank -> Bool
(Rank -> Rank -> Bool) -> (Rank -> Rank -> Bool) -> Eq Rank
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Rank -> Rank -> Bool
$c/= :: Rank -> Rank -> Bool
== :: Rank -> Rank -> Bool
$c== :: Rank -> Rank -> Bool
Eq, Eq Rank
Eq Rank
-> (Rank -> Rank -> Ordering)
-> (Rank -> Rank -> Bool)
-> (Rank -> Rank -> Bool)
-> (Rank -> Rank -> Bool)
-> (Rank -> Rank -> Bool)
-> (Rank -> Rank -> Rank)
-> (Rank -> Rank -> Rank)
-> Ord Rank
Rank -> Rank -> Bool
Rank -> Rank -> Ordering
Rank -> Rank -> Rank
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Rank -> Rank -> Rank
$cmin :: Rank -> Rank -> Rank
max :: Rank -> Rank -> Rank
$cmax :: Rank -> Rank -> Rank
>= :: Rank -> Rank -> Bool
$c>= :: Rank -> Rank -> Bool
> :: Rank -> Rank -> Bool
$c> :: Rank -> Rank -> Bool
<= :: Rank -> Rank -> Bool
$c<= :: Rank -> Rank -> Bool
< :: Rank -> Rank -> Bool
$c< :: Rank -> Rank -> Bool
compare :: Rank -> Rank -> Ordering
$ccompare :: Rank -> Rank -> Ordering
$cp1Ord :: Eq Rank
Ord)

unRank :: Rank -> Int
unRank :: Rank -> Int
unRank = Rank -> Int
coerce

mkRank :: HasCallStack => Int -> Rank
mkRank :: Int -> Rank
mkRank Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7 = Int -> Rank
Rank Int
n
         | Bool
otherwise        = [Char] -> Rank
forall a. HasCallStack => [Char] -> a
error ([Char] -> Rank) -> [Char] -> Rank
forall a b. (a -> b) -> a -> b
$ [Char]
"mkRank " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n

instance Show Rank where
  showsPrec :: Int -> Rank -> [Char] -> [Char]
showsPrec Int
_ (Rank Int
0) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank1"
  showsPrec Int
_ (Rank Int
1) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank2"
  showsPrec Int
_ (Rank Int
2) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank3"
  showsPrec Int
_ (Rank Int
3) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank4"
  showsPrec Int
_ (Rank Int
4) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank5"
  showsPrec Int
_ (Rank Int
5) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank6"
  showsPrec Int
_ (Rank Int
6) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank7"
  showsPrec Int
_ (Rank Int
7) = [Char] -> [Char] -> [Char]
showString [Char]
"Rank8"
  showsPrec Int
d (Rank Int
n) = Bool -> ([Char] -> [Char]) -> [Char] -> [Char]
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (([Char] -> [Char]) -> [Char] -> [Char])
-> ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$
                         [Char] -> [Char] -> [Char]
showString [Char]
"Rank " ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> [Char] -> [Char]
forall a. Show a => Int -> a -> [Char] -> [Char]
showsPrec Int
11 Int
n

instance Enum Rank where
  toEnum :: Int -> Rank
toEnum Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7 = Int -> Rank
Rank Int
n
           | Bool
otherwise        = [Char] -> Rank
forall a. HasCallStack => [Char] -> a
error ([Char] -> Rank) -> [Char] -> Rank
forall a b. (a -> b) -> a -> b
$ [Char]
"Rank out-of-bound " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n
  fromEnum :: Rank -> Int
fromEnum = Rank -> Int
coerce

instance Bounded Rank where
  minBound :: Rank
minBound = Rank
Rank1
  maxBound :: Rank
maxBound = Rank
Rank8

pattern Rank1, Rank2, Rank3, Rank4, Rank5, Rank6, Rank7, Rank8 :: Rank
pattern $bRank1 :: Rank
$mRank1 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank1 = Rank 0
pattern $bRank2 :: Rank
$mRank2 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank2 = Rank 1
pattern $bRank3 :: Rank
$mRank3 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank3 = Rank 2
pattern $bRank4 :: Rank
$mRank4 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank4 = Rank 3
pattern $bRank5 :: Rank
$mRank5 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank5 = Rank 4
pattern $bRank6 :: Rank
$mRank6 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank6 = Rank 5
pattern $bRank7 :: Rank
$mRank7 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank7 = Rank 6
pattern $bRank8 :: Rank
$mRank8 :: forall r. Rank -> (Void# -> r) -> (Void# -> r) -> r
Rank8 = Rank 7

{-# COMPLETE Rank1, Rank2, Rank3, Rank4, Rank5, Rank6, Rank7, Rank8 :: Rank #-}

newtype File = File Int deriving (File -> File -> Bool
(File -> File -> Bool) -> (File -> File -> Bool) -> Eq File
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: File -> File -> Bool
$c/= :: File -> File -> Bool
== :: File -> File -> Bool
$c== :: File -> File -> Bool
Eq, Eq File
Eq File
-> (File -> File -> Ordering)
-> (File -> File -> Bool)
-> (File -> File -> Bool)
-> (File -> File -> Bool)
-> (File -> File -> Bool)
-> (File -> File -> File)
-> (File -> File -> File)
-> Ord File
File -> File -> Bool
File -> File -> Ordering
File -> File -> File
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: File -> File -> File
$cmin :: File -> File -> File
max :: File -> File -> File
$cmax :: File -> File -> File
>= :: File -> File -> Bool
$c>= :: File -> File -> Bool
> :: File -> File -> Bool
$c> :: File -> File -> Bool
<= :: File -> File -> Bool
$c<= :: File -> File -> Bool
< :: File -> File -> Bool
$c< :: File -> File -> Bool
compare :: File -> File -> Ordering
$ccompare :: File -> File -> Ordering
$cp1Ord :: Eq File
Ord)

unFile :: File -> Int
unFile :: File -> Int
unFile = File -> Int
coerce

mkFile :: HasCallStack => Int -> File
mkFile :: Int -> File
mkFile Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7 = Int -> File
File Int
n
         | Bool
otherwise        = [Char] -> File
forall a. HasCallStack => [Char] -> a
error ([Char] -> File) -> [Char] -> File
forall a b. (a -> b) -> a -> b
$ [Char]
"mkFile " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n

instance Show File where
  showsPrec :: Int -> File -> [Char] -> [Char]
showsPrec Int
_ (File Int
0) = [Char] -> [Char] -> [Char]
showString [Char]
"FileA"
  showsPrec Int
_ (File Int
1) = [Char] -> [Char] -> [Char]
showString [Char]
"FileB"
  showsPrec Int
_ (File Int
2) = [Char] -> [Char] -> [Char]
showString [Char]
"FileC"
  showsPrec Int
_ (File Int
3) = [Char] -> [Char] -> [Char]
showString [Char]
"FileD"
  showsPrec Int
_ (File Int
4) = [Char] -> [Char] -> [Char]
showString [Char]
"FileE"
  showsPrec Int
_ (File Int
5) = [Char] -> [Char] -> [Char]
showString [Char]
"FileF"
  showsPrec Int
_ (File Int
6) = [Char] -> [Char] -> [Char]
showString [Char]
"FileG"
  showsPrec Int
_ (File Int
7) = [Char] -> [Char] -> [Char]
showString [Char]
"FileH"
  showsPrec Int
d (File Int
n) = Bool -> ([Char] -> [Char]) -> [Char] -> [Char]
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (([Char] -> [Char]) -> [Char] -> [Char])
-> ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$
                         [Char] -> [Char] -> [Char]
showString [Char]
"File " ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> [Char] -> [Char]
forall a. Show a => Int -> a -> [Char] -> [Char]
showsPrec Int
11 Int
n

instance Enum File where
  toEnum :: Int -> File
toEnum Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7 = Int -> File
File Int
n
           | Bool
otherwise        = [Char] -> File
forall a. HasCallStack => [Char] -> a
error ([Char] -> File) -> [Char] -> File
forall a b. (a -> b) -> a -> b
$ [Char]
"File out-of-bound " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n
  fromEnum :: File -> Int
fromEnum = File -> Int
coerce

instance Bounded File where
  minBound :: File
minBound = File
FileA
  maxBound :: File
maxBound = File
FileH

pattern FileA, FileB, FileC, FileD, FileE, FileF, FileG, FileH :: File
pattern $bFileA :: File
$mFileA :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileA = File 0
pattern $bFileB :: File
$mFileB :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileB = File 1
pattern $bFileC :: File
$mFileC :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileC = File 2
pattern $bFileD :: File
$mFileD :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileD = File 3
pattern $bFileE :: File
$mFileE :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileE = File 4
pattern $bFileF :: File
$mFileF :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileF = File 5
pattern $bFileG :: File
$mFileG :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileG = File 6
pattern $bFileH :: File
$mFileH :: forall r. File -> (Void# -> r) -> (Void# -> r) -> r
FileH = File 7

{-# COMPLETE FileA, FileB, FileC, FileD, FileE, FileF, FileG, FileH :: File #-}

newtype Square = Sq Int deriving (Square -> Square -> Bool
(Square -> Square -> Bool)
-> (Square -> Square -> Bool) -> Eq Square
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Square -> Square -> Bool
$c/= :: Square -> Square -> Bool
== :: Square -> Square -> Bool
$c== :: Square -> Square -> Bool
Eq, Eq Square
Eq Square
-> (Square -> Square -> Ordering)
-> (Square -> Square -> Bool)
-> (Square -> Square -> Bool)
-> (Square -> Square -> Bool)
-> (Square -> Square -> Bool)
-> (Square -> Square -> Square)
-> (Square -> Square -> Square)
-> Ord Square
Square -> Square -> Bool
Square -> Square -> Ordering
Square -> Square -> Square
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Square -> Square -> Square
$cmin :: Square -> Square -> Square
max :: Square -> Square -> Square
$cmax :: Square -> Square -> Square
>= :: Square -> Square -> Bool
$c>= :: Square -> Square -> Bool
> :: Square -> Square -> Bool
$c> :: Square -> Square -> Bool
<= :: Square -> Square -> Bool
$c<= :: Square -> Square -> Bool
< :: Square -> Square -> Bool
$c< :: Square -> Square -> Bool
compare :: Square -> Square -> Ordering
$ccompare :: Square -> Square -> Ordering
$cp1Ord :: Eq Square
Ord)

instance Ix Square where
  range :: (Square, Square) -> [Square]
range (Sq Int
i, Sq Int
j) = [Int -> Square
Sq Int
k | Int
k <- [Int
i..Int
j]]
  index :: (Square, Square) -> Square -> Int
index (Sq Int
i, Sq Int
j) (Sq Int
k) = (Int, Int) -> Int -> Int
forall a. Ix a => (a, a) -> a -> Int
index (Int
i, Int
j) Int
k
  inRange :: (Square, Square) -> Square -> Bool
inRange (Sq Int
i, Sq Int
j) (Sq Int
k) = (Int, Int) -> Int -> Bool
forall a. Ix a => (a, a) -> a -> Bool
inRange (Int
i, Int
j) Int
k
  rangeSize :: (Square, Square) -> Int
rangeSize (Sq Int
i, Sq Int
j) = Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
i

unSquare :: Square -> Int
unSquare :: Square -> Int
unSquare = Square -> Int
coerce
{-# INLINE unSquare #-}

-- TODO: this check is expensive, maybe only worth in "debug" builds.
mkSq :: HasCallStack => Int -> Square
mkSq :: Int -> Square
mkSq Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
63 = Int -> Square
Sq Int
n
       | Bool
otherwise         = [Char] -> Square
forall a. HasCallStack => [Char] -> a
error ([Char] -> Square) -> [Char] -> Square
forall a b. (a -> b) -> a -> b
$ [Char]
"mkSq " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n

instance Show Square where
  showsPrec :: Int -> Square -> [Char] -> [Char]
showsPrec Int
d (Sq Int
i) | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
63 = [Char] -> [Char] -> [Char]
showString [Char
f', Char
r']
                     | Bool
otherwise         = Bool -> ([Char] -> [Char]) -> [Char] -> [Char]
showParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) (([Char] -> [Char]) -> [Char] -> [Char])
-> ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$
                                           [Char] -> [Char] -> [Char]
showString [Char]
"Sq " ([Char] -> [Char]) -> ([Char] -> [Char]) -> [Char] -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Int -> [Char] -> [Char]
forall a. Show a => Int -> a -> [Char] -> [Char]
showsPrec Int
11 Int
i
      where
        (Int
r, Int
f) = Int
i Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
8
        r' :: Char
r' = Int -> Char
chr (Int
r Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
ord Char
'1')
        f' :: Char
f' = Int -> Char
chr (Int
f Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Char -> Int
ord Char
'A')

instance Enum Square where
  toEnum :: Int -> Square
toEnum Int
n | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
63 = Int -> Square
Sq Int
n
           | Bool
otherwise         = [Char] -> Square
forall a. HasCallStack => [Char] -> a
error ([Char] -> Square) -> [Char] -> Square
forall a b. (a -> b) -> a -> b
$ [Char]
"Sq out-of-bound " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
n
  fromEnum :: Square -> Int
fromEnum = Square -> Int
coerce

instance Bounded Square where
  minBound :: Square
minBound = Square
A1
  maxBound :: Square
maxBound = Square
H8

pattern A1, A2, A3, A4, A5, A6, A7, A8 :: Square
pattern B1, B2, B3, B4, B5, B6, B7, B8 :: Square
pattern C1, C2, C3, C4, C5, C6, C7, C8 :: Square
pattern D1, D2, D3, D4, D5, D6, D7, D8 :: Square
pattern E1, E2, E3, E4, E5, E6, E7, E8 :: Square
pattern F1, F2, F3, F4, F5, F6, F7, F8 :: Square
pattern G1, G2, G3, G4, G5, G6, G7, G8 :: Square
pattern H1, H2, H3, H4, H5, H6, H7, H8 :: Square

pattern $bA1 :: Square
$mA1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A1 = Sq 0
pattern $bB1 :: Square
$mB1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B1 = Sq 1
pattern $bC1 :: Square
$mC1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C1 = Sq 2
pattern $bD1 :: Square
$mD1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D1 = Sq 3
pattern $bE1 :: Square
$mE1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E1 = Sq 4
pattern $bF1 :: Square
$mF1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F1 = Sq 5
pattern $bG1 :: Square
$mG1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G1 = Sq 6
pattern $bH1 :: Square
$mH1 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H1 = Sq 7

pattern $bA2 :: Square
$mA2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A2 = Sq 8
pattern $bB2 :: Square
$mB2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B2 = Sq 9
pattern $bC2 :: Square
$mC2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C2 = Sq 10
pattern $bD2 :: Square
$mD2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D2 = Sq 11
pattern $bE2 :: Square
$mE2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E2 = Sq 12
pattern $bF2 :: Square
$mF2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F2 = Sq 13
pattern $bG2 :: Square
$mG2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G2 = Sq 14
pattern $bH2 :: Square
$mH2 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H2 = Sq 15

pattern $bA3 :: Square
$mA3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A3 = Sq 16
pattern $bB3 :: Square
$mB3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B3 = Sq 17
pattern $bC3 :: Square
$mC3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C3 = Sq 18
pattern $bD3 :: Square
$mD3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D3 = Sq 19
pattern $bE3 :: Square
$mE3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E3 = Sq 20
pattern $bF3 :: Square
$mF3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F3 = Sq 21
pattern $bG3 :: Square
$mG3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G3 = Sq 22
pattern $bH3 :: Square
$mH3 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H3 = Sq 23

pattern $bA4 :: Square
$mA4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A4 = Sq 24
pattern $bB4 :: Square
$mB4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B4 = Sq 25
pattern $bC4 :: Square
$mC4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C4 = Sq 26
pattern $bD4 :: Square
$mD4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D4 = Sq 27
pattern $bE4 :: Square
$mE4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E4 = Sq 28
pattern $bF4 :: Square
$mF4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F4 = Sq 29
pattern $bG4 :: Square
$mG4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G4 = Sq 30
pattern $bH4 :: Square
$mH4 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H4 = Sq 31

pattern $bA5 :: Square
$mA5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A5 = Sq 32
pattern $bB5 :: Square
$mB5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B5 = Sq 33
pattern $bC5 :: Square
$mC5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C5 = Sq 34
pattern $bD5 :: Square
$mD5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D5 = Sq 35
pattern $bE5 :: Square
$mE5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E5 = Sq 36
pattern $bF5 :: Square
$mF5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F5 = Sq 37
pattern $bG5 :: Square
$mG5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G5 = Sq 38
pattern $bH5 :: Square
$mH5 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H5 = Sq 39

pattern $bA6 :: Square
$mA6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A6 = Sq 40
pattern $bB6 :: Square
$mB6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B6 = Sq 41
pattern $bC6 :: Square
$mC6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C6 = Sq 42
pattern $bD6 :: Square
$mD6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D6 = Sq 43
pattern $bE6 :: Square
$mE6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E6 = Sq 44
pattern $bF6 :: Square
$mF6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F6 = Sq 45
pattern $bG6 :: Square
$mG6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G6 = Sq 46
pattern $bH6 :: Square
$mH6 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H6 = Sq 47

pattern $bA7 :: Square
$mA7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A7 = Sq 48
pattern $bB7 :: Square
$mB7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B7 = Sq 49
pattern $bC7 :: Square
$mC7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C7 = Sq 50
pattern $bD7 :: Square
$mD7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D7 = Sq 51
pattern $bE7 :: Square
$mE7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E7 = Sq 52
pattern $bF7 :: Square
$mF7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F7 = Sq 53
pattern $bG7 :: Square
$mG7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G7 = Sq 54
pattern $bH7 :: Square
$mH7 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H7 = Sq 55

pattern $bA8 :: Square
$mA8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
A8 = Sq 56
pattern $bB8 :: Square
$mB8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
B8 = Sq 57
pattern $bC8 :: Square
$mC8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
C8 = Sq 58
pattern $bD8 :: Square
$mD8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
D8 = Sq 59
pattern $bE8 :: Square
$mE8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
E8 = Sq 60
pattern $bF8 :: Square
$mF8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
F8 = Sq 61
pattern $bG8 :: Square
$mG8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
G8 = Sq 62
pattern $bH8 :: Square
$mH8 :: forall r. Square -> (Void# -> r) -> (Void# -> r) -> r
H8 = Sq 63

rank :: Square -> Rank
rank :: Square -> Rank
rank = Int -> Rank
Rank (Int -> Rank) -> (Square -> Int) -> Square -> Rank
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
8) (Int -> Int) -> (Square -> Int) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square -> Int
coerce

file :: Square -> File
file :: Square -> File
file = Int -> File
File (Int -> File) -> (Square -> Int) -> Square -> File
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
8) (Int -> Int) -> (Square -> Int) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square -> Int
coerce

rankFile :: Iso' Square (Rank, File)
rankFile :: p (Rank, File) (f (Rank, File)) -> p Square (f Square)
rankFile = (Square -> (Rank, File))
-> ((Rank, File) -> Square)
-> Iso Square Square (Rank, File) (Rank, File)
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso Square -> (Rank, File)
f (Rank, File) -> Square
t where
  f :: Square -> (Rank, File)
f (Sq Int
i) = (Int -> Rank) -> (Int -> File) -> (Int, Int) -> (Rank, File)
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap Int -> Rank
Rank Int -> File
File ((Int, Int) -> (Rank, File)) -> (Int, Int) -> (Rank, File)
forall a b. (a -> b) -> a -> b
$ Int
i Int -> Int -> (Int, Int)
forall a. Integral a => a -> a -> (a, a)
`divMod` Int
8
  t :: (Rank, File) -> Square
t (Rank Int
r, File Int
f) = Int -> Square
Sq (Int -> Square) -> Int -> Square
forall a b. (a -> b) -> a -> b
$ Int
rInt -> Int -> Int
forall a. Num a => a -> a -> a
*Int
8 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
f

mapRank :: (Rank -> Rank) -> Square -> Square
mapRank :: (Rank -> Rank) -> Square -> Square
mapRank Rank -> Rank
f = Getting Square (Rank, File) Square -> (Rank, File) -> Square
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (AnIso Square Square (Rank, File) (Rank, File)
-> Iso (Rank, File) (Rank, File) Square Square
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso Square Square (Rank, File) (Rank, File)
Iso Square Square (Rank, File) (Rank, File)
rankFile) ((Rank, File) -> Square)
-> (Square -> (Rank, File)) -> Square -> Square
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Rank -> Rank) -> (Rank, File) -> (Rank, File)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Rank -> Rank
f ((Rank, File) -> (Rank, File))
-> (Square -> (Rank, File)) -> Square -> (Rank, File)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting (Rank, File) Square (Rank, File) -> Square -> (Rank, File)
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Rank, File) Square (Rank, File)
Iso Square Square (Rank, File) (Rank, File)
rankFile

mapFile :: (File -> File) -> Square -> Square
mapFile :: (File -> File) -> Square -> Square
mapFile File -> File
f = Getting Square (Rank, File) Square -> (Rank, File) -> Square
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (AnIso Square Square (Rank, File) (Rank, File)
-> Iso (Rank, File) (Rank, File) Square Square
forall s t a b. AnIso s t a b -> Iso b a t s
from AnIso Square Square (Rank, File) (Rank, File)
Iso Square Square (Rank, File) (Rank, File)
rankFile) ((Rank, File) -> Square)
-> (Square -> (Rank, File)) -> Square -> Square
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (File -> File) -> (Rank, File) -> (Rank, File)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second File -> File
f ((Rank, File) -> (Rank, File))
-> (Square -> (Rank, File)) -> Square -> (Rank, File)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting (Rank, File) Square (Rank, File) -> Square -> (Rank, File)
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Rank, File) Square (Rank, File)
Iso Square Square (Rank, File) (Rank, File)
rankFile

fileChar, rankChar :: Square -> Char
fileChar :: Square -> Char
fileChar = Int -> Char
chr (Int -> Char) -> (Square -> Int) -> Square -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Int
ord Char
'a' Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Square -> Int) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. File -> Int
unFile (File -> Int) -> (Square -> File) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square -> File
file
rankChar :: Square -> Char
rankChar = Int -> Char
chr (Int -> Char) -> (Square -> Int) -> Square -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Int
ord Char
'1' Int -> Int -> Int
forall a. Num a => a -> a -> a
+) (Int -> Int) -> (Square -> Int) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rank -> Int
unRank (Rank -> Int) -> (Square -> Rank) -> Square -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square -> Rank
rank

toCoord :: IsString s => Square -> s
toCoord :: Square -> s
toCoord Square
sq = [Char] -> s
forall a. IsString a => [Char] -> a
fromString ([Char] -> s) -> [Char] -> s
forall a b. (a -> b) -> a -> b
$ ((Square -> Char) -> Square -> Char
forall a b. (a -> b) -> a -> b
$ Square
sq) ((Square -> Char) -> Char) -> [Square -> Char] -> [Char]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Square -> Char
fileChar, Square -> Char
rankChar]

isDark :: Square -> Bool
isDark :: Square -> Bool
isDark (Sq Int
i) = (Word64
0xaa55aa55aa55aa55 :: Word64) Word64 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` Int
i

isLight :: Square -> Bool
isLight :: Square -> Bool
isLight = Bool -> Bool
not (Bool -> Bool) -> (Square -> Bool) -> Square -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Square -> Bool
isDark