diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -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
diff --git a/Game/Hanabi.hs b/Game/Hanabi.hs
--- a/Game/Hanabi.hs
+++ b/Game/Hanabi.hs
@@ -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)
diff --git a/Game/Hanabi/Client.hs b/Game/Hanabi/Client.hs
--- a/Game/Hanabi/Client.hs
+++ b/Game/Hanabi/Client.hs
@@ -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.
diff --git a/all.hs b/all.hs
--- a/all.hs
+++ b/all.hs
@@ -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))
   ]
diff --git a/hanabi-dealer.cabal b/hanabi-dealer.cabal
--- a/hanabi-dealer.cabal
+++ b/hanabi-dealer.cabal
@@ -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"
