packages feed

intricacy 0.5.5 → 0.5.7

raw patch · 14 files changed

+206/−86 lines, 14 filesdep ~network-fancy

Dependency ranges changed: network-fancy

Files

CursesUIMInstance.hs view
@@ -14,6 +14,7 @@ import qualified UI.HSCurses.Curses as Curses import qualified UI.HSCurses.CursesHelper as CursesH import Control.Concurrent.STM+import Control.Concurrent import Control.Applicative import Data.Char (ord) import Data.Monoid@@ -366,7 +367,12 @@      toggleColourMode = modify $ \s -> s {monochrome = not $ monochrome s} -    getDrawImpatience = return $ \_ -> return ()+    impatience ticks = do+	when (ticks>20) $ say "Waiting for server (^C to abort)..."+	unblock <- unblockInput+	liftIO $ forkIO $ threadDelay 50000 >> unblock+	cmds <- getInput IMImpatience+	return $ CmdQuit `elem` cmds      getInput mode = do 	let userResizeCode = 1337  -- XXX: chosen not to conflict with HSCurses codes
InputMode.hs view
@@ -10,5 +10,5 @@  module InputMode where -data InputMode = IMEdit | IMPlay | IMReplay | IMMeta | IMTextInput+data InputMode = IMEdit | IMPlay | IMReplay | IMMeta | IMTextInput | IMImpatience     deriving (Eq, Ord, Show, Read)
Interact.hs view
@@ -511,9 +511,10 @@ 		Just $ WrenchPush dir 	    | otherwise = Just $ HookPush dir 	torque whs dir-	    | whs == WHSHook || (whs == WHSSelected && not wsel)=+	    {- | whs == WHSHook || (whs == WHSSelected && not wsel)= 		Just $ HookTorque dir-	    | otherwise = Nothing+	    | otherwise = Nothing -}+	    = Just $ HookTorque dir 	(wsel', pm) = 	    case cmd of 		CmdTile (WrenchTile _) -> (True, Nothing)
InteractUtil.hs view
@@ -173,7 +173,7 @@ 		Nothing -> waitConfirm 	ansOfCmd (CmdInputChar 'y') = Just True 	ansOfCmd (CmdInputChar 'Y') = Just True-	ansOfCmd CmdRedraw = Nothing+	ansOfCmd CmdRedraw = Just False 	ansOfCmd CmdRefresh = Nothing 	ansOfCmd CmdUnselect = Nothing 	ansOfCmd _ = Just False@@ -229,7 +229,6 @@ 		    Right $ (name++[':',lockIndexChar idx], Nothing) 		applyCmd x (CmdInputCodename name) = 		    Right $ (name, Nothing)-		applyCmd x CmdRedraw = Right x 		applyCmd x CmdRefresh = Right x 		applyCmd x CmdUnselect = Right x 		applyCmd _ _ = Left False
KeyBindings.hs view
@@ -186,11 +186,16 @@     , ('<', CmdPrevPage)     ] ++ miscGlobal +impatienceBindings = lowerToo $+    [ ('Q', CmdQuit)+    , (ctrl 'C', CmdQuit) ]+ bindings :: InputMode -> KeyBindings bindings IMEdit = editBindings bindings IMPlay = playBindings bindings IMMeta = metaBindings bindings IMReplay = replayBindings+bindings IMImpatience = impatienceBindings bindings _ = []  findBindings :: KeyBindings -> Command -> [Char]
MainBoth.hs view
@@ -8,6 +8,10 @@ -- You should have received a copy of the GNU General Public License -- along with this program.  If not, see http://www.gnu.org/licenses/. +{-# OPTIONS_GHC -cpp #-}+#ifdef APPLE+{-# LANGUAGE ForeignFunctionInterface #-}+#endif module Main where  import Init@@ -16,6 +20,13 @@ import qualified CursesUI (UIM) import CursesUIMInstance () import MainState++#ifdef APPLE+foreign export ccall hs_MAIN :: IO ()++hs_MAIN :: IO ()+hs_MAIN = main+#endif  main = main'     (Just (doUI::SDLUI.UIM MainState -> IO (Maybe MainState)))
MainSDL.hs view
@@ -8,12 +8,23 @@ -- You should have received a copy of the GNU General Public License -- along with this program.  If not, see http://www.gnu.org/licenses/. +{-# OPTIONS_GHC -cpp #-}+#ifdef APPLE+{-# LANGUAGE ForeignFunctionInterface #-}+#endif module Main where  import Init import qualified SDLUI import SDLUIMInstance () import MainState++#ifdef APPLE+foreign export ccall hs_MAIN :: IO ()++hs_MAIN :: IO ()+hs_MAIN = main+#endif  main = main'     (Just (doUI::SDLUI.UIM MainState -> IO (Maybe MainState)))
MainState.hs view
@@ -62,7 +62,7 @@     unblockInput :: m (IO ())     setUIBinding :: InputMode -> Command -> Char -> m ()     getUIBinding :: InputMode -> Command -> m String-    getDrawImpatience :: m ( Int -> IO () )+    impatience :: Int -> m Bool     toggleColourMode :: m ()     warpPointer :: HexPos -> m ()     getUIMousePos :: m (Maybe HexPos)@@ -296,7 +296,7 @@     modify $ \ms -> ms { listOffset = 0 }     mourNameSelected >>? getRandomNames     lift $ modify $ \ms -> ms {retiredLocks = Nothing}-    lift.lift $ drawMessage ""+    --lift.lift $ drawMessage ""     where 	getRandomNames = do 	    rnamestvar <- gets randomCodenames@@ -337,7 +337,8 @@     auth <- gets curAuth     cOnly <- gets cacheOnly     if cOnly then return $ ServerError "Can't contact server in cache-only mode"-	else lift $ withImpatience $ liftIO $ makeRequest saddr $ ClientRequest protocolVersion auth act+	else (fromMaybe (ServerError "Request aborted") <$>) $+	    lift $ withImpatience $ makeRequest saddr $ ClientRequest protocolVersion auth act  curServerActionAsyncThenInvalidate :: UIMonad uiM => Protocol.Action -> Maybe Codenames -> MainStateT uiM () curServerActionAsyncThenInvalidate act names = do@@ -384,30 +385,32 @@ getFreshRecBlocking rec = do     tvar <- getRecordCachedFromCur False rec     cOnly <- gets cacheOnly-    fetched <- lift $ withImpatience $ liftIO $ atomically $ do+    mfetched <- lift $ withImpatience $ atomically $ do 	fetched@(FetchedRecord fresh _ _) <- readTVar tvar 	check $ fresh || cOnly 	return fetched-    case fetchError fetched of-	Nothing -> return $ fetchedRC fetched-	Just err -> lift (drawError err) >> return Nothing+    case mfetched of+	Nothing -> lift (drawError "Request aborted") >> return Nothing+	Just fetched ->+	    case fetchError fetched of+		Nothing -> return $ fetchedRC fetched+		Just err -> lift (drawError err) >> return Nothing --- |draw indication that we're waiting for the server while we do so-withImpatience :: UIMonad uiM => uiM a -> uiM a+-- |indicate waiting for server, and allow cancellation+withImpatience :: UIMonad uiM => IO a -> uiM (Maybe a) withImpatience m = do-    drawImpatience <- getDrawImpatience-    finishedTV <- liftIO $ atomically $ newTVar False+    finishedTV <- liftIO $ atomically $ newTVar Nothing+    id <- liftIO $ forkIO $ m >>= atomically . writeTVar finishedTV . Just     let waitImpatiently ticks = do-	    wakeTV <- atomically $ newTVar False-	    forkIO $ threadDelay (10^6) >> atomically (writeTVar wakeTV True)-	    finished <- atomically $ do-		wake <- readTVar wakeTV-		finished <- readTVar finishedTV-		check $ wake || finished-		return finished-	    when (not finished) $ drawImpatience (ticks+1) >> waitImpatiently (ticks+1)-    liftIO $ forkIO $ waitImpatiently 0-    m <* (liftIO $ atomically $ writeTVar finishedTV True)+	finished <- liftIO $ atomically $ readTVar finishedTV+	if isJust finished+	    then return finished+	    else do+		abort <- impatience ticks+		if abort+		    then liftIO $ killThread id >> return Nothing+		    else waitImpatiently $ ticks+1+    waitImpatiently 0   getRelScore :: (UIMonad uiM) => Codename -> MainStateT uiM (Maybe Int)@@ -451,22 +454,22 @@ metagameHelpText =     [ "By ruthlessly guarded secret arrangement, the Council's agents can pick any lock in the city."     , "The Guild produces the necessary locks - apparently secure, but with fatal hidden flaws."-    , "The ritual game known as \"Intricacy\" is played to determine the best designs."-    , "Players attempt to design locks which can be picked only by one who knows the secret,"-    , "and try to discover the secret flaws in the designs of their colleagues."+    , "A ritual game is played to determine the best designs."+    , "To play the game well, you must build locks which can be picked only by one who knows the secret,"+    , "and you must discover the secret flaws in the locks designed by your colleagues."     , ""     , "You may put forward up to three prototype locks. They will guard the secrets you discover."-    , "If you pick a colleague's lock, the rules require that a note be written describing your solution."-    , "The composition and deciphering of notes is an art in itself, whose details do not concern us here,"-    , "but a note proves that the author found a solution, while revealing as little detail as possible."+    , "If you pick a colleague's lock, the rules require that you have a note written on your solution."+    , "A note proves that a solution was found, while revealing no more of its details than necessary."+    , "Composing notes is a tricky and ritual-bound art of its own, performed by independent experts."     , "To declare your success, you must secure your note behind a lock of your own."     , "If you are able to unlock a lock, you automatically read all the notes it secures."-    , "If you read three notes on a lock, you will piece together the clues and work out how to solve it."+    , "If you read three notes on a lock, you will piece together the secrets of unlocking that lock."     , ""-    , "Players are judged relative to each of their peers. There are no absolute rankings."-    , "You win a point of esteem against another player for one of their locks if either:"-    , "you have declared a note on the lock and the lock's owner has not read that note,"-    , "or if you have read three notes on the lock."+    , "The game judges players relative to each of their peers. There are no absolute rankings."+    , "You win a point of esteem against another player for each of their locks for which either:"+    , "you have declared a note on the lock which the lock's owner has not read,"+    , "or you have read three notes on the lock."     , "Relative esteem ranges from +3 (best) to -3 (worst), and is calculated as"     , "the number of their locks which win you a point minus the number of your locks which win them one."     , "If the secrets to one of your locks become widely disseminated, you may wish to replace it."
NEWS view
@@ -1,5 +1,11 @@ This is an abbreviated summary; see the git log for gory details. +0.5.7:+    Allow cancellation of server requests if the server doesn't respond.+    Minor UI tweaks.+0.5.6:+    Support OS X (thanks Kevin Eaves).+    Rework setting dimensions. 0.5.5:     Save solutions-in-progress of locks and tutorial.     Indicate when there's a pending request.
SDLUI.hs view
@@ -23,6 +23,7 @@ import Control.Monad.State import Control.Monad.Trans.Maybe import Control.Monad.Trans.Reader+import Control.Arrow import Data.Word import Data.Array import Data.List@@ -173,7 +174,7 @@ 	    markGroup = ([Button (tl+^hw) CmdMark [("set",hu+^neg hw),("mark",hu+^neg hv)] 		, Button (tl+^hw+^hv) CmdJumpMark [("jump",hu+^neg hw),("mark",hu+^neg hv)] 		, Button (tl+^hw+^2*^hv) CmdReset [("jump",hu+^neg hw),("start",hu+^neg hv)]],(0,1))-	    global = if mode == IMTextInput then [] else+	    global = if mode `elem` [IMTextInput,IMImpatience] then [] else 		[ singleButton br CmdQuit 0 [("quit",hu+^neg hw)] 		, singleButton (tr +^ 3*^hv +^ 3*^hu) CmdHelp 3 [("help",hu+^neg hw)] ] 	    whsBGs :: Maybe WrHoSel -> InputMode -> [ ButtonGroup ]@@ -291,33 +292,33 @@ helpOfSelectable (SelLockUnset False _) = Just     "An empty lock slot." helpOfSelectable (SelUndeclared _) = Just-    "Declare yourself privy to a lock's secrets by securing a note on it behind a lock of your own."+    "Declare yourself able to unlock a lock by securing a note on it behind a lock of your own." helpOfSelectable (SelRandom _) = Just     "Random set of guild members. Colours show relative esteem, bright red (-3) to bright green (+3)." helpOfSelectable (SelScoreLock (Just name) Nothing _) = Just $-    "Your lock, the secrets of which "++name++" is not privy to."+    "Your lock, which "++name++" can not unlock." helpOfSelectable (SelScoreLock (Just name) (Just AccessedPrivyRead) _) = Just $-    "Your lock, the secrets of which "++name++" has read three notes on: -1 to relative esteem."+    "Your lock, on which "++name++" has read three notes: -1 to relative esteem." helpOfSelectable (SelScoreLock (Just name) (Just (AccessedPrivySolved False)) _) = Just $     "Your lock, on which "++name++" has declared a note which you have not read: -1 to relative esteem." helpOfSelectable (SelScoreLock (Just name) (Just (AccessedPrivySolved True)) _) = Just $-    "Your lock, on which "++name++" has declared a note which you have read."+    "Your lock, on which "++name++" has declared a note which you have, however, read." helpOfSelectable (SelScoreLock (Just name) (Just AccessedPub) _) = Just $     "Your lock, the secrets of which have been publically revealed: -1 to relative esteem." helpOfSelectable (SelScoreLock (Just name) (Just AccessedEmpty) _) = Just $-    "Your empty lock slot; "++name++" is privy to the secrets of all your locks: -1 to relative esteem."+    "Your empty lock slot; "++name++" can unlock all your locks: -1 to relative esteem." helpOfSelectable (SelScoreLock Nothing Nothing (ActiveLock name _)) = Just $-    name++"'s lock, the secrets of which you are not privy to."+    name++"'s lock, which you can not unlock." helpOfSelectable (SelScoreLock Nothing (Just AccessedPrivyRead) (ActiveLock name _)) = Just $-    name++"'s lock, the secrets of which you have read three notes on: +1 to relative esteem."+    name++"'s lock, on which you have read three notes: +1 to relative esteem." helpOfSelectable (SelScoreLock Nothing (Just (AccessedPrivySolved False)) (ActiveLock name _)) = Just $     name++"'s lock, on which you have declared a note which "++name++" has not read: +1 to relative esteem." helpOfSelectable (SelScoreLock Nothing (Just (AccessedPrivySolved True)) (ActiveLock name _)) = Just $-    name++"'s lock, on which you have declared a note which "++name++" has read."+    name++"'s lock, on which you have declared a note which "++name++" has, however, read." helpOfSelectable (SelScoreLock Nothing (Just AccessedPub) (ActiveLock name _)) = Just $     name++"'s lock, the secrets of which have been publically revealed: +1 to relative esteem." helpOfSelectable (SelScoreLock Nothing (Just AccessedEmpty) (ActiveLock name _)) = Just $-    name++"'s empty lock slot; you are privy to the secrets of all "++name++"'s locks: +1 to relative esteem."+    name++"'s empty lock slot; you can unlock all "++name++"'s locks: +1 to relative esteem." helpOfSelectable (SelReadNote note) = Just $     "You have read "++noteAuthor note++"'s note on this lock." helpOfSelectable SelReadNoteSlot = Just $@@ -329,7 +330,7 @@ 	" has secured their note on this lock behind their lock " ++ [lockIndexChar idx] ++ "."     Nothing -> noteAuthor note ++ "'s note on this lock is public knowledge." helpOfSelectable (SelAccessed name) = Just $-    name ++ " did not pick this lock, but by reading three notes became privy its secrets."+    name ++ " did not pick this lock, but learnt how to unlock it by reading three notes on it." helpOfSelectable (SelPublicLock) = Just     "Notes behind retired or public locks are public; locks with three public notes are public." helpOfSelectable (SelAccessedInfo meth) = Just $ case meth of@@ -343,7 +344,7 @@ helpOfSelectable SelLockPath = Just $     "Select a lock by its name. The names you give your locks are not revealed to others." helpOfSelectable SelPrivyHeader = Just $-    "Fellow guild members privy to this lock's secrets, hence able to read its secured notes."+    "Fellow guild members able to unlock this lock, hence able to read its secured notes." helpOfSelectable SelNotesHeader = Just $     "Secured notes. Notes are obfuscated sketches of method, proving success but revealing little." helpOfSelectable SelToolWrench = Just $ "The wrench, one of your lockpicking tools. Click and drag to move."@@ -714,14 +715,29 @@ 	]     where enumerate = zip [0..] +initMisc :: IO ()+initMisc = void $ enableUnicode True >> enableKeyRepeat 250 30 >> setCaption "intricacy" "intricacy"+ initVideo :: Int -> Int -> UIM () initVideo w h = do+    liftIO $ (((w,h)==(0,0) &&) . (InitVideo `elem`) <$> wasInit [InitVideo]) >>?+	-- reset video so that passing (0,0) to setVideoMode sets to+	-- current screen res rather than current window size+	(quitSubSystem [InitVideo] >> initSubSystem [InitVideo] >> initMisc)+     fs <- fullscreen <$> gets uiOptions-    liftIO $ setVideoMode w h 0 [if fs then Fullscreen else Resizable]+    liftIO $ do+	(w',h') <- if (fs || (w,h)/=(0,0)) then return (w,h) else do+	    -- use smaller dimensions than the screen's, to work around a bug+	    -- seen on mac, whereby a resizable window created with+	    -- (w,h)=(0,0), or even with the (w,h) given by getDimensions+	    -- after creating such a window, is reported to be larger than it+	    -- is.+	    (w',h') <- getDimensions+	    return $ (4*w'`div`5,4*h'`div`5)+	setVideoMode w' h' 0 $ if fs then [Fullscreen] else [Resizable] -    -- see what size we actually got:-    vinfo <- liftIO $ getVideoInfo-    let [w',h'] = map ($vinfo) [videoInfoWidth,videoInfoHeight]+    (w',h') <- liftIO getDimensions      modify $ \ds -> ds { scrWidth = w' }     modify $ \ds -> ds { scrHeight = h' }@@ -750,6 +766,10 @@ 	putStr text 	writeFile "error.log" text +    where+	getDimensions = (videoInfoWidth &&& videoInfoHeight) <$> getVideoInfo++ initAudio :: UIM () #ifdef SOUND initAudio = do@@ -783,6 +803,14 @@ #else initAudio = return () #endif++pollEvents = do+    e <- pollEvent+    case e of+	NoEvent -> return []+	_ -> do+	    es <- pollEvents+	    return $ e:es  drawMsgLine = void.runMaybeT $ do     (col,str) <- msum
SDLUIMInstance.hs view
@@ -270,18 +270,21 @@     getUIBinding mode cmd = ($cmd) <$> getBindingStr mode      initUI = liftM isJust (runMaybeT $ do-	catchIOErrorMT $ SDL.init [InitVideo]+	catchIOErrorMT $ SDL.init+#ifdef SOUND+            [InitVideo,InitAudio]+#else+            [InitVideo]+#endif 	catchIOErrorMT TTF.init 	lift $ do 	    readUIConfigFile 	    initVideo 0 0-	    liftIO $ setCaption "intricacy" "intricacy"+	    liftIO $ initMisc 	    w <- gets scrWidth 	    h <- gets scrHeight 	    liftIO $ warpMouse (fi $ w`div`2) (fi $ h`div`2) 	    renderToMain $ erase-	    liftIO $ enableUnicode True-	    liftIO $ enableKeyRepeat 250 30 	    initAudio 	    readBindings 	)@@ -297,15 +300,22 @@     suspend = return ()     redraw = return () -    getDrawImpatience = do-	curState <- get-	let pos = serverWaitPos-	return $ \ticks -> void $ flip runStateT curState $ do-	    when (ticks>2) $ renderToMain $ do-		mapM (drawAtRel (FilledHexGlyph $ bright black)) [ pos +^ i*^hu | i <- [0..3] ]-		withFont (dispFontSmall curState) $-		    renderStrColAtLeft errorCol ("waiting..."++replicate (ticks`mod`3) '.') $ pos-	    refresh+    impatience ticks = do+	liftIO $ threadDelay 50000+	if (ticks>20) then do+		let pos = serverWaitPos+		smallFont <- gets dispFontSmall+		renderToMain $ do+		    mapM (drawAtRel (FilledHexGlyph $ bright black)) [ pos +^ i*^hu | i <- [0..3] ]+		    withFont smallFont $+			renderStrColAtLeft errorCol ("waiting..."++replicate ((ticks`div`5)`mod`3) '.') $ pos+		clearButtons+		registerButton (pos +^ neg hv) CmdQuit 0 [("abort",hu+^neg hw)]+		drawButtons IMImpatience+		refresh+		cmds <- getInput IMImpatience+		return $ CmdQuit `elem` cmds+	    else return False      warpPointer pos = do 	(scrCentre, size) <- getGeom@@ -481,7 +491,7 @@ 	    processEvent (VideoResize w h) = do 		initVideo w h 		return [ CmdRedraw ]-	    processEvent VideoExpose = return [ CmdRedraw ]+	    processEvent VideoExpose = return [ CmdRefresh ] 	    processEvent Quit = return [ CmdForceQuit ]  	    processEvent _ = return []@@ -640,14 +650,6 @@     es' <- pollEvents     return $ es++es' -pollEvents = do-    e <- pollEvent-    case e of-	NoEvent -> return []-	_ -> do-	    es <- pollEvents-	    return $ e:es- updateHoverStr :: InputMode -> UIM () updateHoverStr mode = do     p@(mPos,isCentral) <- gets mousePos@@ -790,7 +792,7 @@      size <- snd <$> lift getGeom     lift $ do-	renderToMain $ displaceRender (SVec size 0) $ renderStrColAt (brightish white) "PRIVY" $ accessedByPos +^ hv+	renderToMain $ displaceRender (SVec size 0) $ renderStrColAt (brightish white) "UNLOCKED BY" $ accessedByPos +^ hv 	registerSelectable (accessedByPos +^ hv) 0 SelPrivyHeader 	registerSelectable (accessedByPos +^ hv +^ hu) 0 SelPrivyHeader     if public lockinfo@@ -833,7 +835,7 @@ 				renderToMain (drawAtRel (HollowGlyph $ dim green) pos)))      lift $ do-	renderToMain $ displaceRender (SVec size 0) $ renderStrColAt (brightish white) "NOTES" $ notesPos +^ hv+	renderToMain $ displaceRender (SVec size 0) $ renderStrColAt (brightish white) "SECURING" $ notesPos +^ hv 	registerSelectable (notesPos +^ hv) 0 SelNotesHeader 	registerSelectable (notesPos +^ hv +^ hu) 0 SelNotesHeader     if null $ notesSecured lockinfo
+ c_main.c view
@@ -0,0 +1,46 @@+/* Workaround for SDL on OS X, based on the corresponding file in TimePiece-0.0.5+ *   http://hackage.haskell.org/package/TimePiece ,+ * placed in the public domin by by Audrey Tang <audreyt@audreyt.org>. */+#include <stdio.h>+#include "HsFFI.h"++#ifdef __APPLE__+#include <objc/objc.h>+#include <objc/objc-runtime.h>+#endif++#include <SDL.h>++#ifdef __GLASGOW_HASKELL__+#include "Main_stub.h"+extern void __stginit_Main ( void );+#endif++#ifdef main+int SDL_main(int argc, char *argv[])+#else+int main(int argc, char *argv[])+#endif+{+    int i;++#ifdef __APPLE__+    void * pool =+      objc_msgSend(objc_lookUpClass("NSAutoreleasePool"), sel_getUid("alloc"));+    objc_msgSend(pool, sel_getUid("init"));+#endif++    hs_init(&argc, &argv);+#ifdef __GLASGOW_HASKELL__+    hs_add_root(__stginit_Main);+#endif++    hs_MAIN();++    hs_exit();++#ifdef __APPLE__+    objc_msgSend(pool, sel_getUid("release"));+#endif+    return 0;+}
intricacy.cabal view
@@ -1,5 +1,5 @@ name:                intricacy-version:             0.5.5+version:             0.5.7 synopsis:            A game of competitive puzzle-design homepage:            http://mbays.freeshell.org/intricacy license:             GPL-3@@ -69,9 +69,14 @@               if flag(Sound)                   Extra-Libraries: SDL_mixer               ghc-options: -optl-mwindows-      if os(darwin)-          -- I'm told OSX doesn't like static builds-          ghc-options: -dynamic+          if os(darwin)+              -- network-fancy-0.2.1+ causes a ___xpg_strerror_r link error+              build-depends: network-fancy < 0.2.1+              -- workaround for SDL on OS X, borrowed from TimePiece-0.0.5+              cpp-options: -DAPPLE+              ghc-options: -no-hs-main+              include-dirs: /usr/include/SDL /usr/local/include/SDL+              c-sources: c_main.c   else       Buildable: False   if flag(Curses)@@ -110,9 +115,6 @@         , cryptohash >= 0.8         , random >= 1.0, pipes >= 4         , feed >= 0.3.1, xml >= 1.2.6-      if os(darwin)-          -- I'm told OSX doesn't like static builds-          ghc-options: -dynamic   else     Buildable: False   main-is:  Server.hs
tutorial/5-springs.lock view
@@ -6,7 +6,7 @@    "                       # "   "    "   & &   % % %         # # " "    "     ]   " S S %           # "   -"       ]   " # # # #   #     # "  +"       ]   " # # #     #     # "    "       ]   " ] # #   # #   7 "      "       ] # " ] #   # #   7 "      " "     # # # " " # # S S % "