commit db78854047b4f82f1b5404ce65c4d81acdc7162d
Author: Jared Tobin <jared@jtobin.ca>
Date: Thu, 16 Aug 2018 10:37:57 -0230
Initial commit.
Diffstat:
A | .gitignore | | | 4 | ++++ |
A | README.md | | | 18 | ++++++++++++++++++ |
A | Sampler.hs | | | 129 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 151 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,4 @@
+ti3sample
+*swp
+*.o
+*.hi
diff --git a/README.md b/README.md
@@ -0,0 +1,18 @@
+
+# ti-sampler
+
+Sample random board locations in a TI3 game.
+
+Useful for e.g. setting domain counters only on some limited percentage of the
+board.
+
+## Usage
+
+```
+$ stack runghc -- Sampler 4 0.1
+Outer 18
+Outer 11
+Mid 6
+Rex
+```
+
diff --git a/Sampler.hs b/Sampler.hs
@@ -0,0 +1,129 @@
+{-# OPTIONS_GHC -Wall #-}
+
+import Control.Monad.Primitive
+import qualified Data.Map.Strict as MS
+import System.Random.MWC
+import System.Random.MWC.Distributions (bernoulli)
+import System.Environment
+
+data Players =
+ Three
+ | Four
+ | Five
+ | Six
+
+data Coord =
+ Rex
+ | Inner Int
+ | Mid Int
+ | Outer Int
+ deriving (Show, Eq, Ord)
+
+data Tile =
+ Special
+ | Plain Bool
+ deriving Show
+
+type Board = MS.Map Coord Tile
+
+empty :: Board
+empty = MS.fromList (zip coords (repeat (Plain False))) where
+ coords = mconcat [rex, inner, mid, outer]
+ rex = [Rex]
+ inner = fmap Inner [1..6]
+ mid = fmap Mid [1..12]
+ outer = fmap Outer [1..18]
+
+board :: Players -> Board
+board players = case players of
+ Three -> MS.alter special Rex
+ $ MS.alter special (Outer 4)
+ $ MS.alter special (Outer 5)
+ $ MS.alter special (Outer 6)
+ $ MS.alter special (Outer 9)
+ $ MS.alter special (Outer 10)
+ $ MS.alter special (Outer 11)
+ $ MS.alter special (Outer 15)
+ $ MS.alter special (Outer 16)
+ $ MS.alter special (Outer 17)
+ $ MS.alter special (Outer 1)
+ $ MS.alter special (Outer 7)
+ $ MS.alter special (Outer 13)
+ empty
+
+ Four -> MS.alter special Rex
+ $ MS.alter special (Outer 3)
+ $ MS.alter special (Outer 8)
+ $ MS.alter special (Outer 12)
+ $ MS.alter special (Outer 17)
+ empty
+
+ Five -> MS.alter special Rex
+ $ MS.alter special (Outer 3)
+ $ MS.alter special (Outer 7)
+ $ MS.alter special (Outer 10)
+ $ MS.alter special (Outer 13)
+ $ MS.alter special (Outer 17)
+ empty
+
+ Six -> MS.alter special Rex
+ $ MS.alter special (Outer 1)
+ $ MS.alter special (Outer 4)
+ $ MS.alter special (Outer 7)
+ $ MS.alter special (Outer 10)
+ $ MS.alter special (Outer 13)
+ $ MS.alter special (Outer 16)
+ empty
+ where
+ special :: Maybe Tile -> Maybe Tile
+ special tile = case tile of
+ Just Plain {} -> Just Special
+ _ -> tile
+
+primsample :: Double -> Board -> Gen RealWorld -> IO Board
+primsample prob brd gen = loop gen mempty (MS.toList brd)
+ where
+ loop prng acc tiles = case tiles of
+ [] -> return (MS.fromList acc)
+ (t:ts) -> case t of
+ (c, Plain False) -> do
+ coin <- bernoulli prob prng
+ loop prng ((c, Plain coin):acc) ts
+
+ _ -> loop prng (t:acc) ts
+
+sample :: Players -> Double -> IO Board
+sample players prob = withSystemRandom . asGenIO $
+ primsample prob (board players)
+
+render :: Board -> [Coord]
+render brd = loop mempty (MS.toList brd) where
+ loop acc tiles = case tiles of
+ [] -> acc
+ (t:ts) -> case t of
+ (Rex, _) -> loop (Rex:acc) ts
+ (c, Plain True) -> loop (c:acc) ts
+ _ -> loop acc ts
+
+main :: IO ()
+main = do
+ args <- getArgs
+ case args of
+ (n:p:_) -> do
+ let players = case (read n :: Int) of
+ 3 -> Just Three
+ 4 -> Just Four
+ 5 -> Just Five
+ 6 -> Just Six
+ _ -> Nothing
+
+ prob = read p :: Double
+
+ case players of
+ Nothing -> putStrLn "invalid number of players"
+ Just nps -> do
+ brd <- sample nps prob
+ mapM_ print (render brd)
+
+ _ -> putStrLn "USAGE: ./sample <NPLAYERS> <PROBABILITY>"
+