Compare commits
3
Commits
3f7ebe9718
...
da217b5196
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da217b5196 | ||
|
|
c47e82d2e0 | ||
|
|
56c04ae5df |
@@ -6,3 +6,4 @@
|
|||||||
*.hi
|
*.hi
|
||||||
*.o
|
*.o
|
||||||
*.prof
|
*.prof
|
||||||
|
*.hp
|
||||||
|
|||||||
+33
-28
@@ -4,9 +4,11 @@
|
|||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
module AI.Rulebased (
|
module AI.Rulebased (
|
||||||
mkAIEnv, testds, remove789s, reduce
|
mkAIEnv, testds, simplify
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Control.Parallel.Strategies
|
||||||
|
|
||||||
import Data.Ord
|
import Data.Ord
|
||||||
import Data.Monoid ((<>))
|
import Data.Monoid ((<>))
|
||||||
import Data.List
|
import Data.List
|
||||||
@@ -163,6 +165,7 @@ compareGuess (c1, ops1) (c2, ops2)
|
|||||||
distributions :: Guess -> (Int, Int, Int, Int) -> [Distribution]
|
distributions :: Guess -> (Int, Int, Int, Int) -> [Distribution]
|
||||||
distributions guess nos =
|
distributions guess nos =
|
||||||
helper (sortBy compareGuess $ M.toList guess) nos
|
helper (sortBy compareGuess $ M.toList guess) nos
|
||||||
|
`using` parList rdeepseq
|
||||||
where helper [] _ = []
|
where helper [] _ = []
|
||||||
helper ((c, hs):[]) ns = map fst (distr c hs ns)
|
helper ((c, hs):[]) ns = map fst (distr c hs ns)
|
||||||
helper ((c, hs):gs) ns =
|
helper ((c, hs):gs) ns =
|
||||||
@@ -185,7 +188,9 @@ distributions guess nos =
|
|||||||
in filterMap isOk (f card) hands
|
in filterMap isOk (f card) hands
|
||||||
cardsPerHand = (length guess - 2) `div` 3
|
cardsPerHand = (length guess - 2) `div` 3
|
||||||
|
|
||||||
abstract :: [Card] -> (Int, Int, Int, Int)
|
type Abstract = (Int, Int, Int, Int)
|
||||||
|
|
||||||
|
abstract :: [Card] -> Abstract
|
||||||
abstract cs = foldr f (0, 0, 0, 0) cs
|
abstract cs = foldr f (0, 0, 0, 0) cs
|
||||||
where f c (clubs, spades, hearts, diamonds) =
|
where f c (clubs, spades, hearts, diamonds) =
|
||||||
let v = getID c in
|
let v = getID c in
|
||||||
@@ -195,21 +200,21 @@ abstract cs = foldr f (0, 0, 0, 0) cs
|
|||||||
Spades -> (clubs, spades + 1 + v*100, hearts, diamonds)
|
Spades -> (clubs, spades + 1 + v*100, hearts, diamonds)
|
||||||
Clubs -> (clubs + 1 + v*100, spades, hearts, diamonds)
|
Clubs -> (clubs + 1 + v*100, spades, hearts, diamonds)
|
||||||
|
|
||||||
remove789s :: Hand -> [Distribution] -> [Distribution]
|
remove789s :: Hand
|
||||||
remove789s hand ds = fst $ foldl' f ([], S.empty) ds
|
-> [Distribution]
|
||||||
where f (cleaned, abstracts) d =
|
-> M.Map (Abstract, Abstract) (Distribution, Int)
|
||||||
|
remove789s hand ds = foldl' f M.empty ds
|
||||||
|
where f cleaned d =
|
||||||
let (c1, c2) = reduce hand d
|
let (c1, c2) = reduce hand d
|
||||||
a = (abstract c1, abstract c2) in
|
a = (abstract c1, abstract c2) in
|
||||||
if a `S.member` abstracts then (cleaned, abstracts)
|
M.insertWith (\(oldD, n) _ -> (oldD, n+1)) a (d, 1) cleaned
|
||||||
else (d : cleaned, S.insert a abstracts)
|
reduce Hand1 (_, h2, h3, _) = (h2, h3)
|
||||||
|
reduce Hand2 (h1, _, h3, _) = (h1, h3)
|
||||||
|
reduce Hand3 (h1, h2, _, _) = (h1, h2)
|
||||||
|
|
||||||
reduce :: Hand -> Distribution -> ([Card], [Card])
|
simplify :: Hand -> [Distribution] -> [(Distribution, Int)]
|
||||||
reduce Hand1 (_, h2, h3, _) = (h2, h3)
|
simplify hand ds = M.elems cleaned
|
||||||
reduce Hand2 (h1, _, h3, _) = (h1, h3)
|
where cleaned = remove789s hand ds
|
||||||
reduce Hand3 (h1, h2, _, _) = (h1, h2)
|
|
||||||
|
|
||||||
simplify :: Hand -> [Distribution] -> [Distribution]
|
|
||||||
simplify = remove789s
|
|
||||||
|
|
||||||
onPlayed :: MonadPlayer m => CardS Played -> AI m ()
|
onPlayed :: MonadPlayer m => CardS Played -> AI m ()
|
||||||
onPlayed c = do
|
onPlayed c = do
|
||||||
@@ -244,9 +249,9 @@ chooseStatistic = do
|
|||||||
2 -> 2
|
2 -> 2
|
||||||
3 -> 3
|
3 -> 3
|
||||||
-- simulate only partially
|
-- simulate only partially
|
||||||
4 -> 2
|
4 -> 3
|
||||||
5 -> 1
|
5 -> 2
|
||||||
6 -> 1
|
6 -> 2
|
||||||
7 -> 1
|
7 -> 1
|
||||||
8 -> 1
|
8 -> 1
|
||||||
9 -> 1
|
9 -> 1
|
||||||
@@ -264,16 +269,16 @@ chooseStatistic = do
|
|||||||
0 -> (0, 0, 0, 0)
|
0 -> (0, 0, 0, 0)
|
||||||
1 -> (-1, 0, -1, 0)
|
1 -> (-1, 0, -1, 0)
|
||||||
2 -> (0, 0, -1, 0)
|
2 -> (0, 0, -1, 0)
|
||||||
let dis' = distributions guess ns
|
let realDis = distributions guess ns
|
||||||
disNo' = length dis'
|
realDisNo = length realDis
|
||||||
dis = simplify Hand3 dis'
|
reducedDis = simplify Hand3 realDis
|
||||||
disNo = length dis
|
reducedDisNo = length reducedDis
|
||||||
piless = map (toPiles table) dis
|
piless = map (\(d, n) -> (toPiles table d, n)) reducedDis
|
||||||
limit = if depth == 1 && length table == 2
|
limit = if depth == 1 && length table == 2
|
||||||
then 1
|
then 1
|
||||||
else min 10000 $ disNo `div` 2
|
else min 10000 $ realDisNo `div` 2
|
||||||
liftIO $ putStrLn $ "possible distrs without simp " ++ show disNo'
|
liftIO $ putStrLn $ "possible distrs without simp " ++ show realDisNo
|
||||||
liftIO $ putStrLn $ "possible distrs " ++ show disNo
|
liftIO $ putStrLn $ "possible distrs " ++ show reducedDisNo
|
||||||
vals <- M.toList <$> foldWithLimit limit runOnPiles M.empty piless
|
vals <- M.toList <$> foldWithLimit limit runOnPiles M.empty piless
|
||||||
liftIO $ print vals
|
liftIO $ print vals
|
||||||
return $ fst $ maximumBy (comparing snd) vals
|
return $ fst $ maximumBy (comparing snd) vals
|
||||||
@@ -292,10 +297,10 @@ foldWithLimit limit f start (x:xs) = do
|
|||||||
_ -> return start
|
_ -> return start
|
||||||
|
|
||||||
runOnPiles :: MonadPlayer m
|
runOnPiles :: MonadPlayer m
|
||||||
=> M.Map Card Int -> Piles -> AI m (M.Map Card Int)
|
=> M.Map Card Int -> (Piles, Int) -> AI m (M.Map Card Int)
|
||||||
runOnPiles m ps = do
|
runOnPiles m (ps, n) = do
|
||||||
c <- runWithPiles ps chooseOpen
|
c <- runWithPiles ps chooseOpen
|
||||||
return $ M.insertWith (+) c 1 m
|
return $ M.insertWith (+) c n m
|
||||||
|
|
||||||
chooseOpen :: (MonadState AIEnv m, MonadPlayerOpen m) => m Card
|
chooseOpen :: (MonadState AIEnv m, MonadPlayerOpen m) => m Card
|
||||||
chooseOpen = do
|
chooseOpen = do
|
||||||
|
|||||||
+1
-1
@@ -2,4 +2,4 @@ import AI.Rulebased
|
|||||||
import Pile
|
import Pile
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = print $ length $ remove789s Hand3 testds
|
main = print $ length $ simplify Hand3 testds
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ module Card where
|
|||||||
import Data.List
|
import Data.List
|
||||||
import System.Random (newStdGen)
|
import System.Random (newStdGen)
|
||||||
import Utils
|
import Utils
|
||||||
|
import Control.DeepSeq
|
||||||
|
|
||||||
class Countable a b where
|
class Countable a b where
|
||||||
count :: a -> b
|
count :: a -> b
|
||||||
@@ -57,6 +58,9 @@ instance Countable Card Int where
|
|||||||
instance Countable [Card] Int where
|
instance Countable [Card] Int where
|
||||||
count = sum . map count
|
count = sum . map count
|
||||||
|
|
||||||
|
instance NFData Card where
|
||||||
|
rnf (Card t c) = t `seq` c `seq` ()
|
||||||
|
|
||||||
equals :: Colour -> Maybe Colour -> Bool
|
equals :: Colour -> Maybe Colour -> Bool
|
||||||
equals col (Just x) = col == x
|
equals col (Just x) = col == x
|
||||||
equals col Nothing = True
|
equals col Nothing = True
|
||||||
|
|||||||
@@ -13,7 +13,23 @@ import AI.Human
|
|||||||
import AI.Rulebased
|
import AI.Rulebased
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = putStrLn "Hello World"
|
main = testAI 10
|
||||||
|
|
||||||
|
testAI :: Int -> IO ()
|
||||||
|
testAI n = do
|
||||||
|
let acs = repeat runAI
|
||||||
|
vals <- sequence (take n acs)
|
||||||
|
putStrLn $ "average won points " ++ show (fromIntegral (sum vals) / fromIntegral n)
|
||||||
|
|
||||||
|
runAI :: IO Int
|
||||||
|
runAI = do
|
||||||
|
env <- shuffledEnv
|
||||||
|
let ps = piles env
|
||||||
|
cs = handCards Hand3 ps
|
||||||
|
trs = filter (isTrump Spades) cs
|
||||||
|
if length trs >= 5 && any ((==32) . getID) cs
|
||||||
|
then fst <$> evalStateT (turn Hand1) env
|
||||||
|
else runAI
|
||||||
|
|
||||||
env :: SkatEnv
|
env :: SkatEnv
|
||||||
env = SkatEnv piles Nothing Spades playersExamp
|
env = SkatEnv piles Nothing Spades playersExamp
|
||||||
@@ -50,8 +66,3 @@ env2 = SkatEnv piles Nothing Spades playersExamp
|
|||||||
h3 = map (putAt Hand3) hand3
|
h3 = map (putAt Hand3) hand3
|
||||||
piles = Piles (h1 ++ h2 ++ h3) [] []
|
piles = Piles (h1 ++ h2 ++ h3) [] []
|
||||||
|
|
||||||
testAI :: Int -> IO ()
|
|
||||||
testAI n = do
|
|
||||||
let acs = repeat (shuffledEnv >>= evalStateT (turnGeneric playOpen 10 Hand1) )
|
|
||||||
vals <- sequence (take n acs)
|
|
||||||
putStrLn $ "average won points " ++ show (fromIntegral (sum (map fst vals)) / fromIntegral n)
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ data Team = Team | Single
|
|||||||
|
|
||||||
data CardS p = CardS { getCard :: Card
|
data CardS p = CardS { getCard :: Card
|
||||||
, getPile :: p }
|
, getPile :: p }
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
instance Countable (CardS p) Int where
|
instance Countable (CardS p) Int where
|
||||||
count = count . getCard
|
count = count . getCard
|
||||||
@@ -34,15 +34,15 @@ prev Hand3 = Hand2
|
|||||||
|
|
||||||
data Played = Table Hand
|
data Played = Table Hand
|
||||||
| Won Hand Team
|
| Won Hand Team
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
data SkatP = SkatP
|
data SkatP = SkatP
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
data Piles = Piles { hands :: [CardS Hand]
|
data Piles = Piles { hands :: [CardS Hand]
|
||||||
, played :: [CardS Played]
|
, played :: [CardS Played]
|
||||||
, skat :: [CardS SkatP] }
|
, skat :: [CardS SkatP] }
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
instance Countable Piles (Int, Int) where
|
instance Countable Piles (Int, Int) where
|
||||||
count ps = (sgl, tm)
|
count ps = (sgl, tm)
|
||||||
|
|||||||
Reference in New Issue
Block a user