packages feed

hstzaar-0.7: src/AI/Eval.hs

{-# LANGUAGE BangPatterns #-}
-- Static evaluation functions for board positions
module AI.Eval( eval0, eval1
              ) where

import Board
import AI.Utils (zoneOfControl)
import qualified Data.IntMap as IntMap


-- | Static evaluation of a position for the active player
-- | Level 0: material only
eval0 :: Board -> Int
eval0 b
  | any (==0) counts || (move b==1 && null captures)  = -infinity
  | any (==0) counts'                                 =  infinity
  | otherwise = material
    where
      -- count stacks by piece kind for each player 
      counts = countStacks (active b)
      counts'= countStacks (inactive b)

      -- capture moves for each player
      captures = nextCaptureMoves b
      --captures'= nextCaptureMoves (swapBoard b)    
      
      -- stack heights by piece kinds
      heights = sumHeights (active b)
      heights'= sumHeights (inactive b)

      -- material score 
      material = sum [(mw*h)`div`(c+1) | (c,h)<-zip counts heights] - 
                 sum [(mw*h)`div`(c+1) | (c,h)<-zip counts' heights'] 

      -- scoreing weights coeficients
      mw = 100   -- material 
                


-- | Level 1: material, positional and threats
eval1 :: Board -> Int
eval1 b
  | any (==0) counts || (move b==1 && null captures)  = -infinity
  | any (==0) counts'                                 =  infinity
  | otherwise = material + positional + threats
    where
      -- count stacks by piece kind for each player 
      counts = countStacks (active b)
      counts'= countStacks (inactive b)
      
      -- capture moves for each player
      captures = nextCaptureMoves b
      --captures'= nextCaptureMoves (swapBoard b)    

      -- stack heights by piece kinds
      heights = sumHeights (active b)
      heights'= sumHeights (inactive b)

      -- material score 
      material = sum [(mw*h)`div`(c+1) | (c,h)<-zip counts heights] - 
                 sum [(mw*h)`div`(c+1) | (c,h)<-zip counts' heights'] 

      zoc = zoneOfControl b              -- zone of control for the active player
      zoc_heights = sumHeights zoc       -- piece types in the zone of control

      -- positional score      
      positional = sum [(pw*h)`div`(c+1) | (c,h)<-zip counts' zoc_heights]
          
      -- immediate threats to opponent pieces
      zoc_counts = countStacks zoc
      threats = sum [tw | (x,y)<-zip counts' zoc_counts, x<=min 2 y]
                
      -- scoreing weights coeficients
      mw = 100   -- material 
      pw = 50    -- positional
      tw = 1000  -- threats 
                



-- sum of heights of stacks for each kind
sumHeights :: HalfBoard -> [Int]
sumHeights b = sum 0 0 0 (IntMap.elems b)
  where sum :: Int -> Int -> Int -> [Piece] -> [Int]
        sum !x !y !z ((Tzaar,h):ps)  = sum (x+h) y z ps
        sum !x !y !z ((Tzarra,h):ps) = sum x (y+h) z ps
        sum !x !y !z ((Tott,h):ps)   = sum x y (z+h) ps
        sum !x !y !z []              = [x,y,z]