use minmax for rulebased ai

This commit is contained in:
2020-02-29 12:39:04 +01:00
parent 173bd0df2e
commit 5846a22d8a
7 changed files with 93 additions and 62 deletions
+16 -41
View File
@@ -24,6 +24,8 @@ import Skat.Card
import Skat.Utils
import Skat (Skat, modifyp, mkSkatEnv)
import Skat.Operations
import qualified Skat.AI.Minmax as Minmax
import qualified Skat.AI.Stupid as Stupid (Stupid(..))
data AIEnv = AIEnv { getTeam :: Team
, getHand :: Hand
@@ -229,34 +231,12 @@ onPlayed c = do
Nothing -> return ()
choose :: MonadPlayer m => AI m Card
choose = do
handCards <- gets myHand
table <- gets table
case length table of
0 -> if length handCards >= 7
then chooseLead
else chooseStatistic
n -> chooseStatistic
choose = chooseStatistic
chooseStatistic :: MonadPlayer m => AI m Card
chooseStatistic = do
h <- gets getHand
handCards <- gets myHand
let depth = case length handCards of
0 -> 0
1 -> 1
-- simulate whole game
2 -> 2
3 -> 3
-- simulate only partially
4 -> 3
5 -> 3
6 -> 2
7 -> 1
8 -> 1
9 -> 1
10 -> 1
modify $ setDepth depth
guess__ <- gets guess
self <- get
maySkat <- showSkat self
@@ -274,9 +254,7 @@ chooseStatistic = do
reducedDis = simplify Hand3 realDis
reducedDisNo = length reducedDis
piless = map (\(d, n) -> (toPiles table d, n)) reducedDis
limit = if depth == 1 && length table == 2
then 1
else min 10000 $ realDisNo `div` 2
limit = min 10000 $ realDisNo `div` 2
liftIO $ putStrLn $ "players hand" ++ show handCards
liftIO $ putStrLn $ "possible distrs without simp " ++ show realDisNo
liftIO $ putStrLn $ "possible distrs " ++ show reducedDisNo
@@ -310,29 +288,26 @@ chooseOpen = do
let myCards = handCards hand piles
liftIO $ putStrLn $ show hand ++ " chooses from " ++ show myCards
possible <- filterM (P.isAllowed myCards) myCards
case length myCards of
case length possible of
0 -> do
liftIO $ print hand
liftIO $ print piles
error "no cards left to choose from"
1 -> return $ head myCards
1 -> return $ head possible
_ -> chooseSimulating
chooseSimulating :: (MonadState AIEnv m, MonadPlayerOpen m)
=> m Card
chooseSimulating = do
piles <- showPiles
hand <- gets getHand
let myCards = handCards hand piles
possible <- filterM (P.isAllowed myCards) myCards
case possible of
[card] -> return card
cs -> do
results <- mapM simulate cs
let both = zip results cs
best = maximumBy (comparing fst) both
liftIO $ putStrLn $ "results " ++ show both
return $ snd best
turnCol <- turnColour
trumpCol <- trumpColour
myHand <- gets getHand
let ps = Players (PL $ Stupid.Stupid Team Hand1)
(PL $ Stupid.Stupid Team Hand2)
(PL $ Stupid.Stupid Single Hand3)
env = mkSkatEnv piles turnCol trumpCol ps myHand
liftIO $ evalStateT (Minmax.choose :: Skat Card) env
simulate :: (MonadState AIEnv m, MonadPlayerOpen m)
=> Card -> m Int
@@ -351,11 +326,11 @@ simulate card = do
(PL $ mkAIEnv Team Hand1 newDepth)
(PL $ mkAIEnv Team Hand2 newDepth)
(PL $ mkAIEnv Single Hand3 newDepth)
env = mkSkatEnv piles turnCol trumpCol ps
env = mkSkatEnv piles turnCol trumpCol ps (next myHand)
-- simulate the game after playing the given card
(sgl, tm) <- liftIO $ evalStateT (do
modifyp $ playCard card
turnGeneric playOpen depth (next myHand)) env
turnGeneric playOpen depth) env
let v = if myTeam == Single then (sgl, tm) else (tm, sgl)
-- put the value into context for when not the whole game is
-- simulated