{-# LANGUAGE BangPatterns #-} -- -- Static evaluation functions for board positions -- module AI.Eval (simple_val, full_val) where import Board import AI.Gametree -- simple static board valuation (material score only) simple_val :: Valuation Board simple_val b = if null (nextMoves b) then lost else material b -- better static board valuation (material and positional scores) full_val :: Valuation Board full_val b = if null (nextMoves b) then lost else material b + positional b -- score for a losing position -- this should be strictly greater than minBound to avoid "boundary" issues lost :: Int lost = minBound`div`2 -- | Material score -- * multiply sum of heights by counts -- * height weights for kinds with lowest counts material :: Board -> Int {-# INLINE material #-} material b = (sum [(30-n)*h | (n,h)<-zip counts heights] - sum [(30-n)*h | (n,h)<-zip counts' heights']) where -- stacks counts by piece kinds for each player counts = activeCounts b counts'= inactiveCounts b -- sum of heights by piece kinds heights = activeHeights b heights'= inactiveHeights b -- | Positional score -- for each kind, count opponent's pieces in each player's zone of control positional :: Board -> Int {-# INLINE positional #-} positional b = (sum [pw*m`div`n | (n,m)<-zip counts' zoc_counts] - sum [pw*m`div`n | (n,m)<-zip counts zoc_counts']) where counts = activeCounts b counts'= inactiveCounts b -- zone of control of each player zoc = zoneOfControl (active b) (pieces b) zoc'= zoneOfControl (inactive b) (pieces b) -- count pieces in each zone of control zoc_counts= countStacks (inactive b) zoc zoc_counts'= countStacks (active b) zoc' pw = 100