module Evaluation.Parameters where

import           AppPrelude
import           Data.List.Split           (chunksOf)
import           Evaluation.ScoreBreakdown
import           Models.Piece
import           Models.Score
import           Utils.Board

import qualified Data.Vector.Storable      as Vector


-- Material scores
pawnScore :: Score
pawnScore :: Score
pawnScore = Score
100

bishopScore :: Score
bishopScore :: Score
bishopScore = Score
340

knightScore :: Score
knightScore :: Score
knightScore = Score
340

rookScore :: (?phase :: Phase) => Score
rookScore :: (?phase::Score) => Score
rookScore = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
500 Score
550

queenScore :: (?phase :: Phase) => Score
queenScore :: (?phase::Score) => Score
queenScore = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
1000 Score
1050


-- Bonuses
castlingRightsBonus :: Score
castlingRightsBonus :: Score
castlingRightsBonus = Score
20

bishopPairBonus :: (?phase :: Phase) => Score
bishopPairBonus :: (?phase::Score) => Score
bishopPairBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
25 Score
100

knightOutpostBonus :: (?phase :: Phase) => Score
knightOutpostBonus :: (?phase::Score) => Score
knightOutpostBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
50 Score
0

rookOnSemiOpenFileBonus :: (?phase :: Phase) => Score
rookOnSemiOpenFileBonus :: (?phase::Score) => Score
rookOnSemiOpenFileBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
10 Score
0

pawnShield1RankBonus :: (?phase :: Phase) => Score
pawnShield1RankBonus :: (?phase::Score) => Score
pawnShield1RankBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
10 Score
0

pawnShield2RankBonus :: (?phase :: Phase) => Score
pawnShield2RankBonus :: (?phase::Score) => Score
pawnShield2RankBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
5 Score
0

unstoppablePawnBonus :: Score
unstoppablePawnBonus :: Score
unstoppablePawnBonus = Score
700

kingEscortedPassedPawnBonus :: (?phase :: Phase) => Score
kingEscortedPassedPawnBonus :: (?phase::Score) => Score
kingEscortedPassedPawnBonus = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (ScorePair -> Score) -> ScorePair -> Score
forall a b. (a -> b) -> a -> b
$ Score -> Score -> ScorePair
ScorePair Score
0 Score
20

passedPawnTable :: Vector ScorePair
passedPawnTable :: Vector ScorePair
passedPawnTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(Score
0, Score
0), (Score
0, Score
5), (Score
5, Score
20), (Score
20, Score
50),
   (Score
30, Score
100), (Score
40, Score
150), (Score
50, Score
200)]

freePassedPawnTable :: Vector ScorePair
freePassedPawnTable :: Vector ScorePair
freePassedPawnTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(Score
0, Score
0), (Score
0, Score
10), (Score
5, Score
35), (Score
20, Score
80),
   (Score
30, Score
150), (Score
40, Score
230), (Score
50, Score
350)]


knightMobilityTable :: Vector ScorePair
knightMobilityTable :: Vector ScorePair
knightMobilityTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(-Score
15, -Score
30), (-Score
5, -Score
10), (-Score
1, -Score
2), (Score
2, Score
4), (Score
5, Score
10),
   (Score
8, Score
16), (Score
11, Score
21), (Score
13, Score
26), (Score
15, Score
30)]

bishopMobilityTable :: Vector ScorePair
bishopMobilityTable :: Vector ScorePair
bishopMobilityTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(-Score
25, -Score
75), (-Score
11, -Score
33), (-Score
6, -Score
18), (-Score
1, -Score
3),
   (Score
3, Score
9), (Score
6, Score
18), (Score
9, Score
27), (Score
12, Score
36), (Score
14, Score
42),
   (Score
17, Score
51), (Score
19, Score
57), (Score
21, Score
63), (Score
23, Score
69), (Score
25, Score
75)]

rookMobilityTable :: Vector ScorePair
rookMobilityTable :: Vector ScorePair
rookMobilityTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(-Score
10, -Score
50), (-Score
4, -Score
20), (-Score
2, -Score
10), (Score
0, Score
0), (Score
1, Score
5),
   (Score
2, Score
10), (Score
3, Score
15), (Score
4, Score
20), (Score
5, Score
25), (Score
6, Score
30),
   (Score
7, Score
34), (Score
8, Score
38), (Score
9, Score
42), (Score
10, Score
46), (Score
10, Score
50)]

queenMobilityTable :: Vector ScorePair
queenMobilityTable :: Vector ScorePair
queenMobilityTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ ((Score, Score) -> ScorePair) -> [(Score, Score)] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map ((Score -> Score -> ScorePair) -> (Score, Score) -> ScorePair
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Score -> Score -> ScorePair
ScorePair)
  [(-Score
10, -Score
50), (-Score
6, -Score
30), (-Score
5, -Score
22), (-Score
4, -Score
16), (-Score
2, -Score
10),
   (-Score
1, -Score
5), (Score
0, -Score
1), (Score
1, Score
3), (Score
1, Score
7), (Score
2, Score
11), (Score
2, Score
14),
   (Score
3, Score
17), (Score
3, Score
20), (Score
4, Score
23), (Score
4, Score
26), (Score
5, Score
28), (Score
5, Score
30),
   (Score
6, Score
32), (Score
6, Score
34), (Score
7, Score
36), (Score
7, Score
38), (Score
8, Score
40), (Score
8, Score
42),
   (Score
9, Score
44), (Score
9, Score
46), (Score
10, Score
48), (Score
10, Score
49), (Score
10, Score
50)]



-- Penalties
threatByMinorPenalty :: Score
threatByMinorPenalty :: Score
threatByMinorPenalty = Score
20

threatByRookPenalty :: Score
threatByRookPenalty :: Score
threatByRookPenalty = Score
40

threatByQueenPenalty :: Score
threatByQueenPenalty :: Score
threatByQueenPenalty = Score
80

isolatedPawnPenalty :: Score
isolatedPawnPenalty :: Score
isolatedPawnPenalty = Score
25

doubledPawnPenalty :: Score
doubledPawnPenalty :: Score
doubledPawnPenalty = Score
20

minorPieceThreat :: Score
minorPieceThreat :: Score
minorPieceThreat = Score
20

rookThreat :: Score
rookThreat :: Score
rookThreat = Score
30

queenThreat :: Score
queenThreat :: Score
queenThreat = Score
40

pieceTradesPenalty :: Score
pieceTradesPenalty :: Score
pieceTradesPenalty = Score
15

pawnTradesPenalty :: Score
pawnTradesPenalty :: Score
pawnTradesPenalty = Score
30


kingThreatPiecesTable :: Vector Score
kingThreatPiecesTable :: Vector Score
kingThreatPiecesTable = [Score] -> Vector Score
forall a. Storable a => [a] -> Vector a
Vector.fromList
  [Score
0, Score
0, Score
0, Score
50, Score
75, Score
88, Score
94, Score
97, Score
99, Score
100,
   Score
100, Score
100, Score
100, Score
100, Score
100, Score
100, Score
100]


blackKingSquareTable :: Vector ScorePair
blackKingSquareTable :: Vector ScorePair
blackKingSquareTable = [ScorePair] -> Vector ScorePair
forall a. Storable a => [a] -> Vector a
Vector.fromList ([ScorePair] -> Vector ScorePair)
-> [ScorePair] -> Vector ScorePair
forall a b. (a -> b) -> a -> b
$ (Score -> ScorePair) -> [Score] -> [ScorePair]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (Score -> Score -> ScorePair
`ScorePair` Score
0)
  [-Score
30,-Score
40,-Score
40,-Score
50,-Score
50,-Score
40,-Score
40,-Score
30,
   -Score
30,-Score
40,-Score
40,-Score
50,-Score
50,-Score
40,-Score
40,-Score
30,
   -Score
30,-Score
40,-Score
40,-Score
50,-Score
50,-Score
40,-Score
40,-Score
30,
   -Score
30,-Score
40,-Score
40,-Score
50,-Score
50,-Score
40,-Score
40,-Score
30,
   -Score
20,-Score
30,-Score
30,-Score
40,-Score
40,-Score
30,-Score
30,-Score
20,
   -Score
10,-Score
20,-Score
20,-Score
30,-Score
30,-Score
20,-Score
20,-Score
10,
     Score
10, Score
10, Score
0, -Score
10, -Score
10, Score
0,  Score
10, Score
10,
    Score
30, Score
30, Score
30,  Score
0,  Score
0, Score
0, Score
30, Score
30]

whiteKingSquareTable :: Vector ScorePair
whiteKingSquareTable :: Vector ScorePair
whiteKingSquareTable = Vector ScorePair -> Vector ScorePair
forall a. Storable a => Vector a -> Vector a
reverseSquareTable Vector ScorePair
blackKingSquareTable

infixl 9 !!%
(!!%) :: (?phase::Phase) => Vector ScorePair -> Int -> Score
!!% :: (?phase::Score) => Vector ScorePair -> Square -> Score
(!!%) Vector ScorePair
table Square
idx = (?phase::Score) => ScorePair -> Score
ScorePair -> Score
taperScore (Vector ScorePair
table Vector ScorePair -> Square -> ScorePair
forall a. Storable a => Vector a -> Square -> a
!! Square
idx)


taperScore :: (?phase :: Phase) => ScorePair -> Score
taperScore :: (?phase::Score) => ScorePair -> Score
taperScore (ScorePair Score
mgScore Score
egScore) =
  (?phase::Score
Score
?phase Score -> Score -> Score
forall a. Num a => a -> a -> a
* Score
mgScore Score -> Score -> Score
forall a. Num a => a -> a -> a
+ (Score
totalPhase Score -> Score -> Score
forall a. Num a => a -> a -> a
- ?phase::Score
Score
?phase) Score -> Score -> Score
forall a. Num a => a -> a -> a
* Score
egScore) Score -> Score -> Score
forall a. Integral a => a -> a -> a
/ Score
totalPhase


getSquareTableIndex :: Board -> Color -> Square
getSquareTableIndex :: Board -> Color -> Square
getSquareTableIndex Board
board Color
color =
  Board -> Square
lsb Board
board Square -> Square -> Square
forall a. Num a => a -> a -> a
+ Square
64 Square -> Square -> Square
forall a. Num a => a -> a -> a
* Color -> Square
forall a b. (Integral a, Num b) => a -> b
fromIntegral Color
color


reverseSquareTable :: Storable a => Vector a -> Vector a
reverseSquareTable :: forall a. Storable a => Vector a -> Vector a
reverseSquareTable =
  [a] -> Vector a
[Element (Vector a)] -> Vector a
forall seq. IsSequence seq => [Element seq] -> seq
fromList ([a] -> Vector a) -> (Vector a -> [a]) -> Vector a -> Vector a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [[a]] -> [a]
[[a]] -> Element [[a]]
forall mono.
(MonoFoldable mono, Monoid (Element mono)) =>
mono -> Element mono
fold ([[a]] -> [a]) -> (Vector a -> [[a]]) -> Vector a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [[a]] -> [[a]]
forall seq. SemiSequence seq => seq -> seq
reverse ([[a]] -> [[a]]) -> (Vector a -> [[a]]) -> Vector a -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Square -> [a] -> [[a]]
forall e. Square -> [e] -> [[e]]
chunksOf Square
8 ([a] -> [[a]]) -> (Vector a -> [a]) -> Vector a -> [[a]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Vector a -> [a]
Vector a -> [Element (Vector a)]
forall mono. MonoFoldable mono => mono -> [Element mono]
toList