Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
Synopsis
- main :: IO ()
- selfplay :: GameSpec -> IO ()
- start :: (RandomGen g, Monad m, Strategies ps m) => GameSpec -> ps -> g -> m (((EndGame, [State], [Move]), ps), g)
- createGame :: RandomGen g => GameSpec -> g -> (State, g)
- run :: (Monad m, Strategies ps m) => [State] -> [Move] -> ps -> m ((EndGame, [State], [Move]), ps)
- prettyEndGame :: (Show a1, Show a2) => (a2, [State], [a1]) -> String
- isMoveValid :: PrivateView -> Move -> Bool
- checkEndGame :: PublicInfo -> Maybe EndGame
- help :: String
- class Strategies ps m
- class Monad m => Strategy p m where
- strategyName :: m p -> m String
- move :: [PrivateView] -> [Move] -> p -> m (Move, p)
- observe :: [PrivateView] -> [Move] -> p -> m ()
- data Verbose p = Verbose {}
- type STDIO = Verbose Blind
- data Blind
- data ViaHandles = VH {}
- data Verbosity = V {
- warnCritical :: Bool
- markUseless :: Bool
- markHints :: Bool
- verbose :: Verbosity
- data GameSpec = GS {
- numPlayers :: Int
- rule :: Rule
- defaultGS :: GameSpec
- data Rule = R {
- numBlackTokens :: Int
- funPlayerHand :: [Int]
- numColors :: Int
- prolong :: Bool
- numMulticolors :: [Int]
- defaultRule :: Rule
- data Move
- type Index = Int
- data State = St {
- publicState :: PublicInfo
- pile :: [Card]
- hands :: [[Card]]
- data PrivateView = PV {
- publicView :: PublicInfo
- handsPV :: [[Card]]
- invisibleBag :: IntMap Int
- data PublicInfo = PI {}
- data EndGame
- data Card = C {}
- data Color
- data Number
- cardToInt :: Card -> Int
- intToCard :: Int -> Card
- readsColorChar :: ReadS Color
- readsNumberChar :: ReadS Number
- isCritical :: PublicInfo -> Card -> Bool
- isUseless :: PublicInfo -> Card -> Bool
- bestPossibleRank :: PublicInfo -> Color -> Number
- what'sUp :: Show a => Verbosity -> [Char] -> [PrivateView] -> [a] -> [Char]
- what'sUp1 :: Show a => Verbosity -> PrivateView -> a -> [Char]
- ithPlayer :: (Eq a, Num a, Show a) => p -> a -> [Char]
Functions for Dealing Games
selfplay :: GameSpec -> IO () Source #
selfplay
starts selfplay with yourself:)
Also,
selfplay defaultGS{numPlayers=n}
(where 1<n<10) starts selfplay with youselves:D
start :: (RandomGen g, Monad m, Strategies ps m) => GameSpec -> ps -> g -> m (((EndGame, [State], [Move]), ps), g) Source #
start
creates and runs a game. This is just the composition of createGame
and run
.
run :: (Monad m, Strategies ps m) => [State] -> [Move] -> ps -> m ((EndGame, [State], [Move]), ps) Source #
prettyEndGame :: (Show a1, Show a2) => (a2, [State], [a1]) -> String Source #
prettyEndGame
can be used to pretty print the final situation.
isMoveValid :: PrivateView -> Move -> Bool Source #
isMoveValid
can be used to check if the candidate Move is compliant to the rule under the current situation. Each player can decide it based on the current PrivateView
(without knowing the full state).
checkEndGame :: PublicInfo -> Maybe EndGame Source #
Datatypes
The Class of Strategies
class Strategies ps m Source #
The Strategies
class defines the list of Strategy
s. If all the strategies have the same type, one can use the list instance.
I (Susumu) guess that in most cases one can use Dynamic
in order to force the same type, but just in case, the tuple instance is also provided. (Also, the tuple instance should be more handy.)
The strategies are used in order, cyclically.
The number of strategies need not be the same as numPlayers
, though the latter should be a divisor of the former.
For normal play, they should be the same.
If only one strategy is provided, that means selfplay, though this is not desired because all the hidden info can be memorized. (In order to avoid such cheating, the same strategy should be repeated.)
If there are twice as many strategies as numPlayers
, the game will be "Pair Hanabi", like "Pair Go" or "Pair Golf" or whatever. (Maybe this is also interesting.)
runARound, broadcast
Instances
(Strategy p m, Monad m) => Strategies [p] m Source # | |
(Strategies p1 m, Strategies p2 m, Monad m) => Strategies (p1, p2) m Source # | |
class Monad m => Strategy p m where Source #
The Strategy
class is exactly the interface that
AI researchers defining their algorithms have to care about.
strategyName :: m p -> m String Source #
strategyName
is just the name of the strategy. The designer of the instance should choose one.
:: [PrivateView] | The history of |
-> [Move] | The history of |
-> p | The strategy's current state. This can be isomorphic to |
-> m (Move, p) |
|
move
is the heart of the strategy. It takes the history of observations and moves, and selects a Move
.
Because the full history is available, your algorithm can be stateless, but still there is the option to design it in the stateful manner.
:: [PrivateView] | The history of |
-> [Move] | The history of |
-> p | The strategy's current state. This can be isomorphic to |
-> m () |
observe
is called during other players' turns. It allows (mainly) human players to think while waiting.
It is arguable whether algorithms running on the same machine may think during other players' turn, especially when the game is timed.
Instances
MonadIO m => Strategy ViaHandles m Source # | |
Defined in Game.Hanabi strategyName :: m ViaHandles -> m String Source # move :: [PrivateView] -> [Move] -> ViaHandles -> m (Move, ViaHandles) Source # observe :: [PrivateView] -> [Move] -> ViaHandles -> m () Source # | |
MonadIO m => Strategy Blind m Source # | |
Defined in Game.Hanabi | |
(Strategy p m, MonadIO m) => Strategy (Verbose p) m Source # | |
Defined in Game.Hanabi |
Verbose makes a player verbose. It is useful to monitor the viewpoint of a specific player.
data ViaHandles Source #
Instances
MonadIO m => Strategy ViaHandles m Source # | |
Defined in Game.Hanabi strategyName :: m ViaHandles -> m String Source # move :: [PrivateView] -> [Move] -> ViaHandles -> m (Move, ViaHandles) Source # observe :: [PrivateView] -> [Move] -> ViaHandles -> m () Source # |
V | |
|
The Game Specification
Rule
is the datatype representing the game variants.
- Minor remark
- When adopting Variant 4, that is, the rule of continuing even after a round after the pile is exhausted, there can be a situation where a player cannot choose any valid move, because she has no card and there is no hint token. This can happen, after one player (who has no critical card) repeats discarding, and other players repeat hinting each other, consuming hint tokens. Seemingly, the rule book does not state what happens in such a case, but I (Susumu) believe the game should end as failure, then, because
- This situation can easily be made, and easily be avoided;
- If deadline is set up, this should cause time out;
- When Variant 4 is adopted, the game must end with either the perfect game or failure.
See also the definition of checkEndGame
.
R | |
|
defaultRule :: Rule Source #
defaultRule
is the normal rule from the rule book of the original card game Hanabi.
The Game State and Interaction History
Drop | drop the card (0-origin) |
Play | play the card (0-origin) |
Hint Int (Either Color Number) | give hint to the ith next player |
State consists of all the information of the current game state, including public info, private info, and the hidden deck.
St | |
|
data PrivateView Source #
PrivateView is the info that is available to the player that has head
.hands
PV | |
|
Instances
Read PrivateView Source # | |
Defined in Game.Hanabi readsPrec :: Int -> ReadS PrivateView # readList :: ReadS [PrivateView] # readPrec :: ReadPrec PrivateView # readListPrec :: ReadPrec [PrivateView] # | |
Show PrivateView Source # | |
Defined in Game.Hanabi showsPrec :: Int -> PrivateView -> ShowS # show :: PrivateView -> String # showList :: [PrivateView] -> ShowS # |
data PublicInfo Source #
PublicInfo is the info that is available to all players.
PI | |
|
Instances
Read PublicInfo Source # | |
Defined in Game.Hanabi readsPrec :: Int -> ReadS PublicInfo # readList :: ReadS [PublicInfo] # readPrec :: ReadPrec PublicInfo # readListPrec :: ReadPrec [PublicInfo] # | |
Show PublicInfo Source # | |
Defined in Game.Hanabi showsPrec :: Int -> PublicInfo -> ShowS # show :: PublicInfo -> String # showList :: [PublicInfo] -> ShowS # |
EndGame
represents the game score, along with the info of how the game ended.
It is not just Int
in order to distinguish Failure
(disaster / no life) from
(not playing any card), though Soso
0
does not look more attractive than Soso
0Failure
.
The Cards
Utilities
Hints
isCritical :: PublicInfo -> Card -> Bool Source #
A critical card is a useful card and the last card that has not been dropped.
Unmarked critical card on the chop should be marked.
isUseless :: PublicInfo -> Card -> Bool Source #
isUseless pi card means either the card is already played or it is above the bestPossibleRank.
bestPossibleRank :: PublicInfo -> Color -> Number Source #
the best achievable rank for each color.