diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright Dino Morelli 2009
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Dino Morelli nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,21 @@
+All relevant info is in the source file hscurses-fish-ex.hs
+
+-----
+A word about my version numbering scheme:
+
+4-part: major.minor.status.build
+3-part: major.status.build
+
+status:
+   0 alpha
+   1 beta
+   2 release candidate
+   3 release
+
+examples:
+   1.3.0.2         v1.3 alpha build 2
+   1.2.1.0         v1.2 beta build 0
+   4.2.24          v4 release candidate build 24
+   2.10.3.5        v2.10 release build 5 (say they were bug fixes)
+   1.5.2.20090818  Can even use a date for build
+                   v1.5 release candidate 2009-08-18 build
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,10 @@
+#! /usr/bin/env runhaskell
+
+-- Copyright: 2010 Dino Morelli
+-- License: BSD3 (see LICENSE)
+-- Author: Dino Morelli <dino@ui3.info>
+
+import Distribution.Simple
+
+
+main = defaultMain
diff --git a/hscurses-fish-ex.cabal b/hscurses-fish-ex.cabal
new file mode 100644
--- /dev/null
+++ b/hscurses-fish-ex.cabal
@@ -0,0 +1,22 @@
+name:                hscurses-fish-ex
+version:             1.3.0
+cabal-version:       >= 1.2
+build-type:          Simple
+license:             BSD3
+license-file:        LICENSE
+copyright:           2010 Dino Morelli
+author:              Dino Morelli
+maintainer:          Dino Morelli <dino@ui3.info>
+stability:           stable
+homepage:            http://ui3.info/darcs/hscurses-fish-ex/
+synopsis:            hscurses swimming fish example
+description:         Simple curses aquarium written to learn about 
+                     the hscurses library.
+category:            Console, Development, Education, Help,
+                     User Interfaces
+tested-with:         GHC>=6.12.1
+
+executable           hscurses-fish-ex
+   main-is:          hscurses-fish-ex.hs
+   build-depends:    base >= 3 && < 5, hscurses, random, safe, unix
+   ghc-options:      -Wall
diff --git a/hscurses-fish-ex.hs b/hscurses-fish-ex.hs
new file mode 100644
--- /dev/null
+++ b/hscurses-fish-ex.hs
@@ -0,0 +1,200 @@
+#! /usr/bin/env runhaskell
+
+{- Copyright 2010  Dino Morelli <dino@ui3.info>
+   Released under BSD3
+
+   Simple curses aquarium written in Haskell to learn about
+   the hscurses library.
+   Number of fish can be given as an argument, defaults to 20
+
+   This code lives here:
+   http://ui3.info/darcs/hscurses-fish-ex/
+
+   Inspired by this C code:
+   http://alexeyt.freeshell.org/code/aquarium.c
+-}
+
+import Control.Concurrent ( threadDelay )
+import Control.Concurrent.MVar
+   ( MVar, newMVar, putMVar, readMVar, takeMVar )
+import Control.Monad ( liftM, mplus, replicateM )
+import Data.Char ( ord )
+import Data.Maybe ( fromJust )
+import Safe ( headMay, readMay )
+import System.Environment ( getArgs )
+import System.Posix.Signals
+   ( Handler (Catch), installHandler, sigINT, sigTERM )
+import System.Random ( randomRIO )
+import UI.HSCurses.Curses
+   ( Pair (..), attr0, attrSet, endWin, initCurses, initPair, mvAddCh
+   , mvWAddStr, refresh, scrSize, startColor, stdScr, wMove
+   )
+import UI.HSCurses.CursesHelper
+   ( black, blue, cyan, green, magenta, red, white, yellow )
+import UI.HSCurses.Widgets ( getWidth )
+
+
+{- The data needed to track each fish
+-}
+data Fish = Fish
+   Int   -- y
+   Int   -- x
+   Pair  -- color
+   Bool  -- fish is facing right
+
+
+interruptHandler :: MVar Bool -> IO ()
+interruptHandler mvRunStatus = do
+   -- We don't care what it is, we just want to take it from everyone else
+   _ <- takeMVar mvRunStatus
+
+   -- Make note in the state that the user wants to quit
+   putMVar mvRunStatus True
+
+
+worker :: MVar Bool -> [Fish] -> IO ()
+worker mvRunStatus priorSchool = do
+   -- Update fish positions
+   school <- mapM swim priorSchool
+
+   -- Draw the fish
+   mapM_ drawFish school
+   refresh
+   
+   threadDelay 100000
+
+   -- Pull the run state..
+   stopNow <- readMVar mvRunStatus
+
+   -- examine it to figure out what to do next
+   if stopNow == True
+      then return ()
+      else worker mvRunStatus school
+
+
+{- Construct a fish on a random row, facing a random direction
+   Sets the starting column to be just offscreen
+-}
+spawn :: IO Fish
+spawn = do
+   (maxRows, maxCols) <- scrSize
+
+   y <- randomRIO (0, maxRows - 1)
+   right <- randomRIO (True, False)
+   let x = case right of
+         True  -> -1
+         False -> maxCols
+   color <- liftM Pair $ randomRIO (1, 7)
+
+   return $ Fish y x color right
+
+
+{- Returns a copy of a fish moved to a random column onscreen
+   Used for first-time fish initialization
+-}
+randomXPos :: Fish -> IO Fish
+randomXPos (Fish y _ color right) = do
+   maxCols <- liftM getWidth scrSize
+   newX <- randomRIO (0, maxCols - 1)
+   return $ Fish y newX color right
+
+
+{- Move a fish forward. If it's fully offscreen, spawn a random new 
+   fish to replace it.
+-}
+swim :: Fish -> IO Fish
+
+-- Right-facing fish
+swim (Fish y x color right@True) = do
+   let modFish = Fish y (x + 1) color right
+
+   maxCols <- liftM getWidth scrSize
+   if x > (maxCols + 2)
+      then spawn
+      else return modFish
+
+-- Left-facing fish
+swim (Fish y x color right@False) = do
+   let modFish = Fish y (x - 1) color right
+
+   if x < -3
+      then spawn
+      else return modFish
+
+
+{- Draw a fish
+   The reason for this complicated draw-each-char is that mvWAddStr
+   crashes if part of the string is past the bottom right corner of 
+   the window.
+   Not so with calling mvAddCh even with out-of-bounds coords.
+-}
+drawPart :: Int -> (Int, Char) -> IO ()
+drawPart y (x, c) = do
+   mvAddCh y x $ fromIntegral . ord $ c
+
+
+drawFish :: Fish -> IO ()
+
+-- Right-facing fish
+drawFish (Fish y x color True) = do
+   attrSet attr0 color
+   mapM_ (drawPart y) $ zip [(x - 3) .. x] " ><>"
+   wMove stdScr 0 0
+
+-- Left-facing fish
+drawFish (Fish y x color False) = do
+   attrSet attr0 color
+   mapM_ (drawPart y) $ zip [x .. (x + 3)] "<>< "
+   wMove stdScr 0 0
+
+
+{- Clear the screen by drawing spaces with the given color's background
+-}
+paintEntireScr :: Pair -> IO ()
+paintEntireScr color = do
+   (maxRows, maxCols) <- scrSize
+
+   let blanks = replicate (maxCols - 1) ' '
+
+   attrSet attr0 color
+   mapM_ (\y -> mvWAddStr stdScr y 0 blanks) [0 .. (maxRows - 1)]
+   refresh
+
+
+main :: IO ()
+main = do
+   -- Get number of fish from the command-line, or use a default value
+   args <- getArgs
+   let nfish = fromJust $ (return args >>= headMay >>= readMay)
+         `mplus` return 20
+
+   initCurses
+
+   -- Color initialization
+   startColor
+   initPair (Pair 1) green black
+   initPair (Pair 2) red black
+   initPair (Pair 3) yellow black
+   initPair (Pair 4) blue black
+   initPair (Pair 5) magenta black
+   initPair (Pair 6) cyan black
+   initPair (Pair 7) white black
+
+   paintEntireScr $ Pair 7
+
+   -- Randomly generate the first school of fish
+   school <- mapM randomXPos =<< replicateM nfish spawn
+
+   -- Data for communicating between threads
+   mvRunStatus <- newMVar False
+
+   -- A map to install the same handler for multiple signals
+   mapM_ ( \signal -> installHandler signal 
+      (Catch $ interruptHandler mvRunStatus) Nothing ) [sigINT, sigTERM]
+
+   -- This starts the endless work loop
+   worker mvRunStatus school
+
+   paintEntireScr $ Pair 7
+
+   endWin
