board-games-0.3: Three games for inclusion in a web server

Safe HaskellNone
LanguageHaskell2010

Game.Mastermind

Synopsis

Documentation

data Eval Source #

Constructors

Eval Int Int 
Instances
Eq Eval Source # 
Instance details

Defined in Game.Mastermind

Methods

(==) :: Eval -> Eval -> Bool #

(/=) :: Eval -> Eval -> Bool #

Ord Eval Source # 
Instance details

Defined in Game.Mastermind

Methods

compare :: Eval -> Eval -> Ordering #

(<) :: Eval -> Eval -> Bool #

(<=) :: Eval -> Eval -> Bool #

(>) :: Eval -> Eval -> Bool #

(>=) :: Eval -> Eval -> Bool #

max :: Eval -> Eval -> Eval #

min :: Eval -> Eval -> Eval #

Show Eval Source # 
Instance details

Defined in Game.Mastermind

Methods

showsPrec :: Int -> Eval -> ShowS #

show :: Eval -> String #

showList :: [Eval] -> ShowS #

evaluate :: Enum a => [a] -> [a] -> Eval Source #

Given the code and a guess, compute the evaluation.

matching :: (C set, Enum a) => EnumSet a -> [a] -> Eval -> set a Source #

Given a code and an according evaluation, compute the set of possible codes.

The Game.Mastermind game consists of collecting pairs of codes and their evaluations. The searched code is in the intersection of all corresponding code sets.

matchingSimple :: Enum a => EnumSet a -> [a] -> Int -> [[EnumSet a]] Source #

A variant of the game: It is only possible to specify number of symbols at right places.

The results of matching and matchingSimple cannot be compared.

randomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> set a -> State g (Maybe [a]) Source #

mixedRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> set a -> State g (Maybe [a]) Source #

In the beginning we simply choose a random code from the set of possible codes. In the end, when the set becomes small, then we compare different alternatives.

scanningRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> [([a], Eval)] -> set a -> State g (Maybe [a]) Source #

This strategy starts with scanning the alphabet. That is, we test sets of different symbols we did not try so far. The idea is to sort out unused symbols early. This is especially useful when the alphabet is large, i.e. its size is some multiples of the code width.

We stop scanning when we are sure to have seen all characters of the secret code. E.g.:

vicx
alsn   o
mfgt   o
hjqw
edpz   oo
bkru   - we already know, that these cannot be in the secret code

We use the Choice data type for tracking the number of symbols that we can minimally use from the ones we have already tried. The order of applying mergeChoice matters, but I see no easy way to find a good order or to make it robust against re-ordering.

If the user tells us that all symbols in a code are used, then the scanning phase ends immediately. This happens automatically according to our way of processing Choices.

separatingRandomizedAttempt :: (C set, RandomGen g, Enum a) => Int -> EnumSet a -> set a -> State g (Maybe [a]) Source #

In the beginning we choose codes that separate reasonably well, based on heuristics. At the end, when the set becomes small, we do a brute-force search for an optimally separating code.

partitionSizes :: Enum a => EnumSet a -> [a] -> [(Eval, Integer)] Source #

mainSimple :: T Char -> Int -> IO () Source #

mainRandom :: T Char -> Int -> IO () Source #

main :: IO () Source #

propBestSeparatingCode :: (C set, Enum a) => Int -> set a -> T [] [a] -> Bool Source #