packages feed

hstzaar-0.9.2: src/AI.hs

--
-- Library of AI players
--
module AI where

import Board
import System.Random
import Data.Map(Map)
import qualified Data.Map as Map
import Data.Maybe(catMaybes)
import AI.Gametree
import AI.Minimax
import AI.Eval 


-- | instance the gametree class for TZAAR 
instance Gametree Board where
  children b = [applyMove m b | m<-nextMoves b]
  is_terminal b = null (nextMoves b)

-- | An AI play strategy 
-- takes a  board and pseudo-random generator 
-- yields evaluation, next move and new random generator
type Playing = Board -> StdGen -> (Int, Move, StdGen)

-- | An AI player.
data AI = AI
  { name :: String          -- ^ Unique name
  , description :: String   -- ^ Brief description of AI.
  , playing     :: Playing  -- ^ The play strategy.
  }




aiLevels :: [AI]
aiLevels = catMaybes [lookupAI label aiPlayers | label<-list]
  where list = ["nscout_simple_1", 
                "nscout_simple_3",
                "nscout_full_1", 
                "nscout_full_3", 
                "nscout_full_6", 
                "pscout_full_3", 
                "pscout_full_6"]


lookupAI :: String -> [AI] -> Maybe AI
lookupAI label ai_list 
  = case [ai | ai<-ai_list, name ai==label] of  
    [] -> Nothing
    (ai : _) -> Just ai


aiPlayers :: [AI]
aiPlayers = do (txt0,txt1,strat) <- list
               (val,txt2) <- zip [simple_val, full_val] ["simple", "full"]
               ply <- [1..9]
               let label = txt0 ++ "_" ++ txt2 ++ "_" ++ show ply
               let desc = txt1 ++ " " ++ txt2 ++ " valuation, ply " ++ show ply
               return AI { name = label
                         , description  = desc
                         , playing = play (strat val ply)
                         }
   where list = [ ("nmax", "Negamax", negamax_alpha_beta),
                  ("nscout", "Negascout", negascout),                 
                  ("pscout", "Parallel negascout", jamboree)
                ]
         
play strat b rndgen 
    | m `elem` nextMoves b = (score, m, rndgen)
    | otherwise = error "panic: AI gave invalid move!"
      where vpos = strat b
            score = value vpos
            -- next move in principal variation
            m = (reverse $ moves $ unvalued vpos) !! move b