Pig the dice game/Player: Difference between revisions

Added Haskell solution to Pig_the_dice_game/Player
m (→‎{{header|REXX}}: removed two blank lines above the OUTPUT section.)
(Added Haskell solution to Pig_the_dice_game/Player)
Line 1,388:
player 1 104
player 2 98
</pre>
 
=={{header|Haskell}}==
 
Implemented 4 strategies:
 
- player1 always rolls until he gets 20 or more
- player2 always rolls four times
- player3 rolls three times until she gets more than 60 points, then she rolls until she gets 20 or more
- player4 rolls 3/4 of the time, 1/4 he holds, but if he gets a score more than 75 he goes for the win
 
<lang Haskell>
{-# LANGUAGE ViewPatterns #-}
 
module Main where
 
import System.Random (randomRIO)
import Text.Printf (printf)
 
data PInfo = PInfo { stack :: Int
, score :: Int
, rolls :: Int
, next :: Bool
, won :: Bool
, name :: String
}
 
type Strategy = [PInfo] -> IO ()
 
roll :: [PInfo] -> IO [PInfo]
roll (pinfo:xs) = do
face <- randomRIO (1, 6)
case (face, face + stack pinfo + score pinfo) of
(1,_) -> do
printf "%s rolled 1 - stack is being resetted\n\n" (name pinfo)
return $ pinfo { stack = 0, rolls = 0, next = True } : xs
(_,x) | x >= 100 -> do
printf "%s rolled %i - stack is now %i + score %i => %i - I won!\n" (name pinfo) face (face + stack pinfo) (score pinfo) x
return $ pinfo { won = True } : xs
(_,_) -> do
printf "%s rolled %i - stack is now %i\n" (name pinfo) face (face + (stack pinfo))
return $ pinfo { stack = face + (stack pinfo), rolls = 1 + (rolls pinfo) } : xs
 
hold :: [PInfo] -> IO [PInfo]
hold (pinfo:xs) = do
let score' = stack pinfo + score pinfo
printf "%s holds - score is now %i\n\n" (name pinfo) score'
return $ pinfo { score = score', stack = 0, rolls = 0, next = True } : xs
 
 
logic :: Strategy -> Strategy -> Strategy
logic _ _ ((won -> True) : xs) = return ()
logic _ strat2 (p@(next -> True) : xs) = strat2 $ xs ++ [p { next = False }]
logic strat1 _ (pinfo : xs) = strat1 (pinfo : xs)
 
strat1 :: Strategy
strat1 (pinfo:xs)
| stack pinfo < 20 = roll (pinfo:xs) >>= logic strat1 strat2
| otherwise = hold (pinfo:xs) >>= logic strat1 strat2
 
strat2 :: Strategy
strat2 (pinfo:xs)
| rolls pinfo < 4 = roll (pinfo:xs) >>= logic strat2 strat3
| otherwise = hold (pinfo:xs) >>= logic strat2 strat3
 
strat3 :: Strategy
strat3 (pinfo:xs)
| rolls pinfo < 3 && score pinfo < 60 = roll (pinfo:xs) >>= logic strat3 strat4
| stack pinfo < 20 = roll (pinfo:xs) >>= logic strat3 strat4
| otherwise = hold (pinfo:xs) >>= logic strat3 strat4
 
strat4 :: Strategy
strat4 (pinfo:xs) | score pinfo > 75 = roll (pinfo:xs) >>= logic strat4 strat1
strat4 (pinfo:xs) = do
chance <- randomRIO (0, 4) :: IO Int
case chance of
0 -> hold (pinfo:xs) >>= logic strat4 strat1
_ -> roll (pinfo:xs) >>= logic strat4 strat1
 
main :: IO ()
main = do
let pInfo = PInfo 0 0 0 False False ""
p1 = pInfo { name = "Peter" }
p2 = pInfo { name = "Mia" }
p3 = pInfo { name = "Liz" }
p4 = pInfo { name = "Stephen" }
strat1 [p1, p2, p3, p4]
</lang>
 
Example output:
<pre>
 
Peter rolled 5 - stack is now 5
Peter rolled 5 - stack is now 10
Peter rolled 4 - stack is now 14
Peter rolled 6 - stack is now 20
Peter holds - score is now 20
 
Mia rolled 4 - stack is now 4
Mia rolled 1 - stack is being resetted
 
Liz rolled 4 - stack is now 4
Liz rolled 6 - stack is now 10
Liz rolled 4 - stack is now 14
Liz rolled 3 - stack is now 17
Liz rolled 3 - stack is now 20
Liz holds - score is now 20
 
Stephen rolled 6 - stack is now 6
Stephen rolled 1 - stack is being resetted
 
Peter rolled 3 - stack is now 3
Peter rolled 6 - stack is now 9
 
...
 
Stephen rolled 1 - stack is being resetted
 
Peter rolled 4 - stack is now 4
Peter rolled 2 - stack is now 6
Peter rolled 5 - stack is now 11
Peter rolled 2 - stack is now 13
Peter rolled 5 - stack is now 18
Peter rolled 6 - stack is now 24
Peter holds - score is now 87
 
Mia rolled 5 - stack is now 5
Mia rolled 1 - stack is being resetted
 
Liz rolled 3 - stack is now 3
Liz rolled 1 - stack is being resetted
 
Stephen rolled 6 - stack is now 6
Stephen rolled 2 - stack is now 8
Stephen rolled 5 - stack is now 13
Stephen rolled 4 - stack is now 17
Stephen holds - score is now 43
 
Peter rolled 4 - stack is now 4
Peter rolled 2 - stack is now 6
Peter rolled 5 - stack is now 11
Peter rolled 6 - stack is now 17 + score 87 => 104 - I won!
</pre>
 
To test the distribution by yourself (in parallel):
 
<lang Haskell>
 
-- add this to the top
import Control.Concurrent.ParallelIO.Global (parallel, stopGlobalPool)
import Data.List (sort, group)
 
-- replace "logic _ _ ((won -> True) : xs) = return ()" with
logic _ _ (p@(won -> True) : xs) = return $ name p
 
-- replace strat1 [p1, p2, p3, p4] in main with
let lists = replicate 100000 [p1, p2, p3, p4]
results <- parallel $ map strat1 lists
stopGlobalPool
print $ map length $ group $ sort results
 
-- compile with
-- ghc FILENAME.hs -O2 -threaded -with-rtsopts="-N4" -o dice
 
</lang>
 
Distribution:
 
<pre>
 
Strat1 = 31878 => ~ 32%
Strat2 = 21953 => ~ 22%
Strat3 = 39022 => ~ 39%
Strat4 = 7147 => ~ 7%
 
out of 10 000 tests.
</pre>
 
Anonymous user