hanabi-dealer 0.10.1.0 → 0.10.2.0
raw patch · 5 files changed
+56/−25 lines, 5 filesdep +jsaddledep ~basedep ~jsaddle-warpdep ~misoPVP ok
version bump matches the API change (PVP)
Dependencies added: jsaddle
Dependency ranges changed: base, jsaddle-warp, miso, time, websockets
API changes (from Hackage documentation)
+ Game.Hanabi.Strategies.EndGameSearch: EG :: EndGameSearch
+ Game.Hanabi.Strategies.EndGameSearch: data EndGameSearch
+ Game.Hanabi.Strategies.EndGameSearch: instance GHC.Base.Monad m => Game.Hanabi.Strategy Game.Hanabi.Strategies.EndGameSearch.EndGameSearch m
+ Game.Hanabi.Strategies.EndGameSearch: main :: IO ()
+ Game.Hanabi.Strategies.SimpleStrategy: S :: Simple
+ Game.Hanabi.Strategies.SimpleStrategy: data Simple
+ Game.Hanabi.Strategies.SimpleStrategy: instance GHC.Base.Monad m => Game.Hanabi.Strategy Game.Hanabi.Strategies.SimpleStrategy.Simple m
+ Game.Hanabi.Strategies.SimpleStrategy: main :: IO ()
+ Game.Hanabi.Strategies.StatefulStrategy: SF :: [Annotation] -> Stateful
+ Game.Hanabi.Strategies.StatefulStrategy: instance GHC.Base.Monad m => Game.Hanabi.Strategy Game.Hanabi.Strategies.StatefulStrategy.Stateful m
+ Game.Hanabi.Strategies.StatefulStrategy: lookupOn :: Eq b => (a -> b) -> a -> [a] -> [a]
+ Game.Hanabi.Strategies.StatefulStrategy: main :: IO ()
+ Game.Hanabi.Strategies.StatefulStrategy: newtype Stateful
+ Game.Hanabi.Strategies.Stateless: SL :: Stateless
+ Game.Hanabi.Strategies.Stateless: data Stateless
+ Game.Hanabi.Strategies.Stateless: instance GHC.Base.Monad m => Game.Hanabi.Strategy Game.Hanabi.Strategies.Stateless.Stateless m
+ Game.Hanabi.Strategies.Stateless: lookupOn :: Eq b => (a -> b) -> a -> [a] -> [a]
+ Game.Hanabi.Strategies.Stateless: main :: IO ()
+ Game.Hanabi.Strategies.Stateless: sontakuColorHint :: [PrivateView] -> [Move] -> [PrivateView]
Files
- ChangeLog.md +6/−0
- Game/Hanabi.hs +8/−3
- Game/Hanabi/Client.hs +10/−2
- all.hs +6/−1
- hanabi-dealer.cabal +26/−19
ChangeLog.md view
@@ -1,5 +1,11 @@ # Revision history for hanabi-dealer + ## 0.10.2.0 -- 2020-09-24++ * make the client library buildable with JSaddle + GHC + GUI (though unstable)++ * fix isDoubleDrop to reflect failures+ ## 0.10.1.0 -- 2020-09-08 * slightly improve the GUI
Game/Hanabi.hs view
@@ -386,13 +386,16 @@ chops pub anns = concat $ map reverse $ obviousChopss pub anns isDoubleDrop :: PrivateView -> Result -> [Index] -> Annotation -> Bool-isDoubleDrop pv@PV{publicView=pub} (Discard c@C{..}) [_i] Ann{possibilities=(pc,pn)} = not (any ((==(Just color, Just rank)).marks) myAnns) && -- This pattern captures: the last player discards B1; I have a card which is hinted as B and 1; I don't know where the third B1 is.+isDoubleDrop _pv None _chopset _anns = False+isDoubleDrop _pv (Success _) _chopset _anns = False+isDoubleDrop pv@PV{publicView=pub} lastResult [_i] Ann{possibilities=(pc,pn)} = not (any ((==(Just color, Just rank)).marks) myAnns) && -- This pattern captures: the last player discards B1; I have a card which is hinted as B and 1; I don't know where the third B1 is. -- This can be improved to check whether any card other than the chop is obviously the just-dropped card or not, by looking at the Possibilities. isCritical pub c && color `elem` colorPossibilities pc && rank `elem` rankPossibilities pn && invisibleBagCards pv c > 0 where myAnns = head $ annotations pub+ c@C{..} = revealed lastResult isDoubleDrop _pv _lastresult _chopset _anns = False colors :: PublicInfo -> [Color]@@ -458,6 +461,7 @@ stateToStateHistory (pi:pis) (mv:mvs) st = st : stateToStateHistory pis mvs (rotate (-1) $ recede pi mv st) -- | @'EGS' f p ps@ usually behaves based on @p@, but it conducts the exhaustive search assuming that others behave based on @ps@ when the deck size is @f@ or below @f@.+-- @move pvs mvs (EGS f p ps)@ may cause an error if @p@ can choose an invalid move. data EndGameStrategy p ps = EGS {fromWhen::PublicInfo->Bool, myUsualStrategy::p, otherPlayers::ps} instance (Monad m, Strategy p m, Strategies ps m) => Strategy (EndGameStrategy p ps) m where@@ -469,6 +473,7 @@ return (m,str) -- | 'EndGameMirrorStrategy' assumes that other players think in the same way as itself during endgame.+-- @move pvs mvs (EGMS (EGS f p ps))@ may cause an error if @p@ can choose an invalid move. data EndGameMirrorStrategy p = EGMS (EndGameStrategy p [EndGameMirrorStrategy p]) egms :: (PublicInfo -> Bool) -- ^ from when to start the endgame search -> p -- ^ the default strategy used until endgame@@ -507,7 +512,7 @@ -- | 'tryAMove' tries a 'Move' and then simulate the game to the end, using given 'Strategies'. Running this with empty history, such as @tryAMove [st] [] strs m@ is possible, but that assumes other strategies does not depend on the history. tryAMove :: (Monad m, Strategies ps m) => [State] -> [Move] -> ps -> Move -> m ((EndGame, [State], [Move]),ps)-tryAMove states@(st:_) mvs strs mov = case proceed st mov of Nothing -> fail $ show mov ++ ": invalid move!"+tryAMove states@(st:_) mvs strs mov = case proceed st mov of Nothing -> error $ show mov ++ ": invalid move!" Just st -> let nxt = rotate 1 st in case checkEndGame $ publicState nxt of Nothing -> runSilently (nxt:states) (mov:mvs) strs Just eg -> return ((eg, nxt:states, mov:mvs), strs)@@ -592,7 +597,7 @@ resToMbC r = Just $ revealed r tryAMoveARound :: (Monad m, Strategies ps m) => ([State],ps,Int) -> [Move] -> Move -> m ((Maybe EndGame, [State], [Move]),ps,Int) tryAMoveARound (states@(st:_),strs,n) mvs mov = case proceed st mov of- Nothing -> fail $ show mov ++ ": invalid move!"+ Nothing -> error $ show mov ++ ": invalid move!" Just st -> let nxt = rotate 1 st in case checkEndGame $ publicState nxt of Nothing -> fmap (\(e,p) -> (e,p,n)) $ runARound (\_ _ -> return ()) (nxt:states) (mov:mvs) strs Just eg -> return ((Just eg, nxt:states, mov:mvs), strs, n)
Game/Hanabi/Client.hs view
@@ -31,9 +31,9 @@ import Control.Concurrent +#ifdef ghcjs_HOST_OS import Game.Hanabi.FFI -#ifdef ghcjs_HOST_OS client :: Game.Hanabi.Msg.Options -> IO () client options = clientJSM options #else@@ -41,7 +41,7 @@ {- When building with GHC, 1. miso has to be built with --flags="jsaddle" option;-2. the resulting executable does not work with Firefox or Konqueror---use Chromium. (https://github.com/aveltras/arohi-skeleton/issues/1)+2. the resulting executable does not work with Konqueror---use Firefox. (Cf. https://github.com/aveltras/arohi-skeleton/issues/1) -} # ifdef IOS@@ -87,7 +87,15 @@ model = Model{tboxval = Message "available", players = [S.pack defStr], from = Just 0, rule = defaultRule{numMulticolors=replicate 5 1}, received = [CreateGame], shownHistory = defaultShownHistory, showVerbosity = False, verbosity = verbose, play = True, localStrategy = mvStr, local = False, initialDeck = [], lastMoves = [], preset = False}, update = updateModel options, view = appView strNames $ version options,+#ifdef ghcjs_HOST_OS subs = [ websocketSub wsURI protocols HandleWebSocket, windowBottomSub ViewMore Id ],+#else+# ifdef ALL+ subs = [ websocketSub wsURI protocols HandleWebSocket ],+# else+ subs = [],+# endif+#endif events = defaultEvents, initialAction = Id, -- initialAction = SendMessage $ Message "available", -- Seemingly sending as initialAction does not work, even if connect is executed before send.
all.hs view
@@ -10,6 +10,9 @@ import Game.Hanabi.Strategies.SimpleStrategy hiding (main) import Game.Hanabi.Strategies.StatefulStrategy hiding (main)+import Game.Hanabi.Strategies.Stateless hiding (main)+import Game.Hanabi.Strategies.EndGameSearch hiding (main)+ main :: IO () main = do putStrLn "localhost:8080" -- Seemingly other port than 8080 does not work. let opt = defaultOptions{version="hanabi-dealer quickbuilt server", strategies=strs}@@ -25,6 +28,8 @@ strs :: [(String, IO (DynamicStrategy IO))] strs = [ ("Stupid example strategy", return $ mkDS "Stupid example strategy" $ S),- ("Example strategy with states", return $ mkDS "Example strategy with states" $ SF [])+ ("Example strategy with states", return $ mkDS "Example strategy with states" $ SF []),+ ("Stateless implementation of the strategy with states", return $ mkDS "Stateless implementation of the strategy with states" SL),+ ("Strategy with end game search", return $ mkDS "Strategy with end game search" EG) -- x , ("Sontakki", return $ mkDS "Sontakki" (Sontakki emptyDefault)) ]
hanabi-dealer.cabal view
@@ -10,7 +10,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.10.1.0+version: 0.10.2.0 -- A short (one-line) description of the package. synopsis: Hanabi card game@@ -80,11 +80,11 @@ Description: Quickbuild all-in-one server, using JSaddle. (Package miso must have been built with --flags="jsaddle".) Default: False+Flag examples+ Description: Include example strategies in the library.+ Default: True library- if flag(jsaddle)- buildable: False- else -- Modules exported by the library. exposed-modules: Game.Hanabi @@ -104,8 +104,10 @@ -- Base language which the package is written in. default-language: Haskell2010 - if impl(ghcjs) || flag(server)--- || flag(jsaddle)+ if flag(examples)+ exposed-modules: Game.Hanabi.Strategies.SimpleStrategy, Game.Hanabi.Strategies.StatefulStrategy, Game.Hanabi.Strategies.Stateless, Game.Hanabi.Strategies.EndGameSearch++ if impl(ghcjs) || flag(server) || flag(jsaddle) exposed-modules: Game.Hanabi.VersionInfo other-modules: Game.Hanabi.Msg -- cpp-options: -DCABAL@@ -117,7 +119,7 @@ ghc-options: -O2 -- Not sure if -O2 is worthy, but this should be OK because the server is not built by default. exposed-modules: Game.Hanabi.Backend- build-depends: websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6 && <1.9, text >=1.2, utf8-string+ build-depends: websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6, text >=1.2, utf8-string if flag(TFRANDOM) build-depends: tf-random cpp-options: -DTFRANDOM@@ -128,12 +130,15 @@ if flag(WARP) build-depends: wai-websockets, warp, wai, http-types cpp-options: -DWARP- if impl(ghcjs)--- || flag(jsaddle)+ if impl(ghcjs) || flag(jsaddle) exposed-modules: Game.Hanabi.Client- other-modules: Game.Hanabi.FFI- ghcjs-options: -dedupe -O- build-depends: base >=4.12 && <4.13, jsaddle-warp >=0.9, aeson, miso, time >=1.6, network-uri >=2.6+ if impl(ghcjs)+ build-depends: base >=4.12 && <4.14, aeson, miso, time, network-uri >=2.6+ other-modules: Game.Hanabi.FFI+ ghcjs-options: -dedupe -O+ else+ build-depends: base <4.14, aeson, miso, time, network-uri >=2.6+ build-depends: wai, warp, websockets, jsaddle, jsaddle-warp if flag(official) cpp-options: -DWSURI="ws://133.54.228.39:8720" -- if flag(jsaddle)@@ -141,14 +146,14 @@ executable hanabiq main-is: all.hs- other-modules: Game.Hanabi, Game.Hanabi.Msg, Game.Hanabi.Backend, Game.Hanabi.Client, Game.Hanabi.FFI, Game.Hanabi.Strategies.SimpleStrategy, Game.Hanabi.Strategies.StatefulStrategy+ other-modules: Game.Hanabi, Game.Hanabi.Msg, Game.Hanabi.Backend, Game.Hanabi.Client, Game.Hanabi.Strategies.SimpleStrategy, Game.Hanabi.Strategies.StatefulStrategy, Game.Hanabi.Strategies.Stateless, Game.Hanabi.Strategies.EndGameSearch -- if !flag(all) if !flag(jsaddle) buildable: False else ghc-options: -O0 -rtsopts- cpp-options: -DWSURI="ws://localhost:8080/ws/" -DWARP- build-depends: base >=4.9 && <4.13, containers >=0.5, random >=1.1, jsaddle-warp >=0.9, aeson, miso >=1.4, servant >=0.12, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6 && <1.9, text >=1.2, utf8-string, wai-websockets, warp, wai, http-types, network-uri >=2.6+ cpp-options: -DWSURI="ws://localhost:8080/ws/" -DWARP -DALL+ build-depends: base >=4.9 && <4.14, containers >=0.5, random >=1.1, jsaddle, jsaddle-warp >=0.9, aeson, miso >=1.4, servant >=0.12, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6, text >=1.2, utf8-string, wai-websockets, warp, wai, http-types, network-uri >=2.6 -- I am not sure but seemingly miso fails to build without servant. if flag(TFRANDOM) build-depends: tf-random@@ -164,7 +169,7 @@ ghc-options: -O2 -threaded -Wall -rtsopts -- Not sure if -O2 is worthy, but this should be OK because the server is not built by default. cpp-options: -DCABAL- build-depends: base >=4.8 && <4.14, containers >=0.5, random >=1.1, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6 && <1.9, text >=1.2, utf8-string, hanabi-dealer+ build-depends: base >=4.8 && <4.14, containers >=0.5, random >=1.1, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6, text >=1.2, utf8-string, hanabi-dealer default-language: Haskell2010 if flag(TH) build-depends: template-haskell@@ -182,13 +187,15 @@ executable hanabif main-is: client.hs other-modules: Game.Hanabi.Strategies.SimpleStrategy, Game.Hanabi.Strategies.StatefulStrategy, Game.Hanabi.Strategies.Stateless, Game.Hanabi.Strategies.EndGameSearch- if !impl(ghcjs)--- && !flag(jsaddle)+ if !impl(ghcjs) && !flag(jsaddle) buildable: False else ghcjs-options: -dedupe -O cpp-options: -DCABAL- build-depends: base >=4.12 && <4.13, containers >=0.5, random >=1.1, jsaddle-warp >=0.9, aeson, miso, time >=1.6, hanabi-dealer, network-uri >=2.6+ if !impl(ghcjs)+ build-depends: base >=4.9 && <4.14, containers >=0.5, random >=1.1, jsaddle, jsaddle-warp >=0.9, aeson, miso >=1.4, servant >=0.12, websockets >=0.12 && <0.13, network >=2.6 && <3.2, hashable >=1.3, time >=1.6, text >=1.2, utf8-string, wai-websockets, warp, wai, http-types, network-uri >=2.6+ else+ build-depends: base >=4.12 && <4.14, containers >=0.5, random >=1.1, jsaddle-warp >=0.9, aeson, miso, time >=1.6, hanabi-dealer, network-uri >=2.6 default-language: Haskell2010 if flag(official) cpp-options: -DWSURI="ws://133.54.228.39:8720"