hanabi-dealer-0.15.1.1: Game/Hanabi/Strategies.hs
{-# LANGUAGE FlexibleContexts, CPP #-}
module Game.Hanabi.Strategies(module Game.Hanabi.Strategies,
module Game.Hanabi.Strategies.SimpleStrategy,
module Game.Hanabi.Strategies.StatefulStrategy,
module Game.Hanabi.Strategies.Stateless,
module Game.Hanabi.Strategies.EndGameSearch,
module Game.Hanabi.Strategies.MCSearch,
#ifdef MHLMC
module Game.Hanabi.Strategies.AdaptiveLMC,
module Game.Hanabi.Strategies.AppendDSL
#endif
) where
import Game.Hanabi.Strategies.SimpleStrategy hiding (main)
import Game.Hanabi.Strategies.StatefulStrategy hiding (main, lookupOn)
import Game.Hanabi.Strategies.Stateless hiding (main)
import Game.Hanabi.Strategies.EndGameSearch hiding (main)
import Game.Hanabi.Strategies.MCSearch(mcs)
import qualified Game.Hanabi.Strategies.LazyMC as LMC
#ifdef MHLMC
import Game.Hanabi.Strategies.AdaptiveLMC
import Game.Hanabi.Strategies.AppendDSL
#endif
import System.Random
import Data.Typeable
import Game.Hanabi(pileNum, DynamicStrategy, mkDS, Strategy(..)) -- (Replay(..))
-- DynamicStrategyにする前にpreloadしないと、DynamicStrategyのinitializeが使われる。
type Constrs = Bool -> IO (IO (DynamicStrategy IO))
mkStr :: (String, String -> DynamicStrategy IO) -> (String, Maybe Constrs)
mkStr (xs, f) = (xs, Just $ preload (return $ f xs) return)
mkStrIO :: (String, String -> IO (DynamicStrategy IO)) -> (String, Maybe Constrs)
mkStrIO (xs, f) = (xs, Just $ preload (f xs) return)
mksd :: (Strategy t IO, Typeable t) => t -> String -> DynamicStrategy IO
mksd = flip mkDS
mksdIO :: (Strategy t IO, Typeable t) => IO t -> String -> IO (DynamicStrategy IO)
mksdIO iop s = fmap (mkDS s) iop
preload :: Strategy p m =>
m p -- ^ constructor that should be executed only once that can take time,
-- such as reading parameters from a file or maybe self-contained training
-> (p -> m p) -- ^ constructor that require different behaviour at every game,
-- such as setting RNG or creating network socket
-> Bool -- ^ if True, initialize lazily, i.e., does not stop computation until the initialization finishes
-> m (m p)
preload oneShot beforeTheGame lz = do p <- oneShot
p' <- initialize lz p
return (beforeTheGame p')
-- | 'predefinedStrategies' is the list of strategies included in this library, with some recommended parameters.
-- This value is subject to change in future versions, and adding strategies to this list is considered as extension rather than modification.
predefinedStrategies :: [(String, Maybe Constrs)]
predefinedStrategies = map mkStr [
("Stupid example strategy", mksd $ S False),
-- ("Example strategy with states", mksd $ sfs (S False)),
("Stateless implementation of the strategy with states", mksd $ SL $ S False),
("Strategy with states with aggressive positional drop", mksd $ sf),
("Strategy with end game search", mksd $ EG $ SL (S False)),
-- ("Strategy with end game search with aggressive positional drop", mksd $ EG $ sf),
-- ("Strategy with Monte Carlo search assuming Stateless with aggressive positional drop (light)", mksd $ lightmc),
("Strategy with Monte Carlo search assuming Stateless with aggressive positional drop", mksd $ mc),
("Lazy Monte Carlo search specialized to Stateful with aggressive positional drop", mksd $ lmc $ sf)
-- , ("Lazy Monte Carlo search specialized to Stateless with aggressive positional drop", mksd $ lmc $ sl)
]
#ifdef MHLMC
++ [mkStrIO ("Adaptive Lazy Monte Carlo without incremental learning",
mksdIO $ mkAdaptiveLMC (PADSL (PALMC 0 AverageScore FromTheBeginning 800 False) 1 (ProgsPerDepth 20000)) instinct $ mkStdGen 54321012345)]
#else
++ [("Adaptive Lazy Monte Carlo without incremental learning", Nothing)]
#endif
lightmc = mcs (\pub -> pileNum pub < 8) 3000 (mkStdGen 1234567890) (SL $ S True) (SL $ S True) $ repeat $ SL $ S True
mc = mcs (\pub -> pileNum pub < 18) 6000 (mkStdGen 1234567890) (SL $ S True) (SL $ S True) $ repeat $ SL $ S True
lmc sf = LMC.lmcs LMC.AvoidZero 400 100 (mkStdGen 1234567890) sf sf [repeat sf]
sl = SL $ S True
sf = sfs $ S True