ti3-sampler

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2388c2b29a4255582483889b391af42cee4f041a
parent db78854047b4f82f1b5404ce65c4d81acdc7162d
Author: Jared Tobin <jared@jtobin.ca>
Date:   Thu, 16 Aug 2018 10:55:56 -0230

Cabal and stack.

Diffstat:
M.gitignore | 1+
AChangeLog.md | 5+++++
ALICENSE | 30++++++++++++++++++++++++++++++
MREADME.md | 23++++++++++++++++++++---
ASetup.hs | 2++
Asrc/Main.hs | 129+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Astack.yaml | 6++++++
Ati3-sampler.cabal | 22++++++++++++++++++++++
8 files changed, 215 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -2,3 +2,4 @@ ti3sample *swp *.o *.hi +.stack-work diff --git a/ChangeLog.md b/ChangeLog.md @@ -0,0 +1,5 @@ +# Revision history for ti3-sampler + +## 0.1.0 -- 2018-08-16 + +* Initial release. diff --git a/LICENSE b/LICENSE @@ -0,0 +1,30 @@ +Copyright (c) 2018, Jared Tobin + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Jared Tobin nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md @@ -1,18 +1,35 @@ - # 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. +board. I find chocking the board full of domain counters slows the game down a +little too much, but you still want a few of them there for fun. A proportion +of about 0.275 tiles seems to strike a very good balance. + +Supports three, four, five, and six player games. The tile coordinates are +just reported in terms of position on the nth ring of the board. North is one, +and then you just count clockwise from there. + +This takes into account the different board configurations for different +players, and so doesn't sample home systems. Additionally, Mecatol Rex is +always included in the result. + +For the three player game, just interpret the provided coordinates as if all +tiles were present on the board. ## Usage +Just clone the repo, install [Stack](https://www.haskellstack.org/), and run +something like: + ``` -$ stack runghc -- Sampler 4 0.1 +$ stack exec ti3-sampler 4 0.1 Outer 18 Outer 11 Mid 6 Rex ``` +The first argument is the number of players -- the second is the desired tile +proportion. diff --git a/Setup.hs b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/src/Main.hs b/src/Main.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>" + diff --git a/stack.yaml b/stack.yaml @@ -0,0 +1,6 @@ +flags: {} +packages: +- '.' +extra-deps: [] +resolver: lts-12.5 + diff --git a/ti3-sampler.cabal b/ti3-sampler.cabal @@ -0,0 +1,22 @@ +name: ti3-sampler +version: 0.1.0 +synopsis: Sample random locations on a TI3 board. +description: Sample random locations on a TI3 board. +homepage: https://github.com/jtobin/ti3-sampler +license: BSD3 +license-file: LICENSE +author: Jared Tobin +maintainer: jared@jtobin.io +build-type: Simple +extra-source-files: ChangeLog.md, README.md +cabal-version: >=1.10 + +executable ti3-sampler + main-is: Main.hs + hs-source-dirs: src + default-language: Haskell2010 + build-depends: + base >= 4.10 && < 5 + , containers >= 0.5 && < 0.6 + , mwc-random >= 0.13 && < 0.15 + , primitive >= 0.6 && < 0.7