diff --git a/Alice_in_WonderLand_3.ttf b/Alice_in_WonderLand_3.ttf
new file mode 100644
Binary files /dev/null and b/Alice_in_WonderLand_3.ttf differ
diff --git a/Draw.hs b/Draw.hs
new file mode 100644
--- /dev/null
+++ b/Draw.hs
@@ -0,0 +1,135 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+module Draw where
+
+import Control.Monad
+import Control.Monad.Trans
+
+import Graphics.UI.SDL hiding (flip)
+import qualified Graphics.UI.SDL as SDL (flip)
+
+--import Graphics.UI.SDL.Image
+
+import Graphics.UI.SDL.TTF
+
+import Grid
+import GameState hiding (font, screen, grid, winner, stats)
+import GameEnv
+import Surface
+
+textColor :: Color
+textColor = Color 0x00 0xFF 0x00
+
+drawPlayersKey :: AppEnv ()
+drawPlayersKey = do
+    playerPiece <- getPlayerType
+    let aiPiece = swapCell playerPiece
+    
+    font   <- getFont
+    screen <- getScreen
+    
+    liftIO $ do        
+        playerKey <- renderTextSolid font ("Player: " ++ show playerPiece) textColor
+        aiKey     <- renderTextSolid font ("CPU: " ++ show aiPiece) textColor
+        applySurface 10 10 playerKey screen Nothing
+        applySurface 10 (10 + surfaceGetHeight playerKey) aiKey screen Nothing
+
+drawBoard :: AppEnv ()
+drawBoard = do
+
+    Rect x y gw gh <- getGridBounds
+    winIndices     <- snd `liftM` getWinner
+    grid    <- getGrid
+    screen  <- getScreen
+
+    let (w,h) = (gw `div` 3, gh `div` 3)
+    let (halfW, halfH) = (w `div` 4, h `div` 4)
+    
+    let applySurf r c = applySurface' (r * w + x + halfW) (c * h + y + halfH)    
+    -- draw pieces
+    forM_ [(r,c) | r <- [0..2], c <- [0..2]] $ \(r,c) -> do
+        case cellAt grid r c of
+            Nought -> do
+                src <- if (r,c) `elem` winIndices
+                        then getOWinSurf
+                        else getNought
+                applySurf r c src screen Nothing
+            Cross  -> do
+                src <- if (r,c) `elem` winIndices
+                        then getXWinSurf
+                        else getCross                
+                applySurf r c src screen Nothing
+            _      -> return ()
+    
+    -- draw/overlay grid
+    let drawLine' u hh l d = liftIO . drawLine screen u hh l d    
+    drawLine' (x + w, y) gh thickness Vertical gridColor
+    drawLine' (x + w * 2, y) gh thickness Vertical gridColor
+    
+    drawLine' (x, y + h) gw thickness Horizontal gridColor
+    drawLine' (x, y + h * 2) gw thickness Horizontal gridColor
+    
+ where gridColor = Pixel 0xFF00FF
+       thickness = 5
+
+drawEndGame :: AppEnv ()
+drawEndGame = do
+    screen <- getScreen
+    font   <- getFont
+    winner <- fst `liftM` getWinner
+    playerResultStr <- winOrLose winner `liftM` getPlayerType
+    unless (null playerResultStr) $ liftIO $ do
+        textSurface <- renderTextSolid font playerResultStr textColor
+        let x = (screenWidth `div` 2) - (surfaceGetWidth textSurface `div` 2)
+        applySurface x (screenHeight - 35) textSurface screen Nothing
+
+ where winOrLose Noughts Nought = "YOU WON!"
+       winOrLose Crosses Cross  = "YOU WON!"
+       winOrLose Noughts Cross  = "YOU LOST!"
+       winOrLose Crosses Nought = "YOU LOST!"
+       winOrLose Draw _         = "DRAW GAME!"
+       winOrLose _ _            = []
+
+drawScore :: AppEnv ()
+drawScore = do
+    Rect _ ry _ h <- getGridBounds
+    font   <- getFont
+    screen <- getScreen
+    stats  <- getStats                       
+    
+    let y = ry + h + 20
+    liftIO $ do
+        scores <- renderTextSolid font ("Player: " ++ (show $ playerCount stats) ++ " CPU: " ++ (show $ aiCount stats) ++ " Ties: " ++ (show $ tieCount stats)) textColor
+        let x = (screenWidth `div` 2) - (surfaceGetWidth scores `div` 2)
+        applySurface x y scores screen Nothing
+
+render :: AppEnv ()
+render = do
+    screen <- getScreen
+    liftIO $ clear screen 0x00 0x00 0x00
+    drawPlayersKey
+    drawBoard
+    drawScore
+    drawEndGame
+    liftIO $ SDL.flip screen
diff --git a/FontReadMe.txt b/FontReadMe.txt
new file mode 100644
--- /dev/null
+++ b/FontReadMe.txt
@@ -0,0 +1,47 @@
+                                         ENGLISH
+Hello, thanks for downloading the font "Alice in Wonderland" from one of the next sites:
+   - www.por-que-tan-serio.deviantart.com (My DeviantART account)
+   - www.fontspace.com/marcotl (My FontSpace account)
+
+The rules are the following:
+   -Do not use this font for commercial purposes.
+   -Do not claim this font as yours (I beg you xD).
+   -This font is currently under development, so go to my gallery often to make sure
+    you have the latest version.
+   -You can distribute this font as long as you keep this Read-me file with it and intact.
+   -Do not rename this font.
+   -You can edit the font for personal purposes, but please do not distribute edited
+    versions of the font.
+   -You can request for special characters if they're not included in the current version
+    of the font, just let me know and make sure I answered your request.
+   -Feel free to ask whatever you want to know.
+   -PLEASE, SHOW ME YOUR WORK, I'd love to see your creativity and the way my
+    font is being used.
+
+Enjoy this font and have fun!
+-Marco T.L.
+
+______________________________________________________________________________________________
+                                             ESPAÑOL
+Hola, gracias por descargar la fuente "Alice in Wonderland" (Alicia en el País de las
+Maravillas) de alguno de los siguientes sitios:
+   - www.por-que-tan-serio.deviantart.com (Mi cuenta en DeviantART)
+   - www.fontspace.com/marcotl (Mi cuenta en Fontspace)
+
+Las reglas son las siguientes:
+   -No uses la fuente para propósitos comerciales.
+   -No digas que la fuente es tuya (te lo ruego xD).
+   -Esta fuente está bajo desarrollo, así que ve seguido a mi galería para que
+    te asegures de tener la última versión.
+   -Puedes distribuir la fuente mientras mantengas este texto con ella e intacto.
+   -No renombres la fuente.
+   -Puedes editar la fuente para propósitos personales, pero por favor no distribuyas
+    una versión editada de ésta.
+   -Puedes solicitar caracteres especiales si no están incluidos en la versión actual
+    de la fuente, sólo hazmelo saber y asegúrate de que respondí a tu petición.
+   -Siéntete libre para preguntar lo que quieras.
+   -POR FAVOR, MUÉSTRAME TU TRABAJO, me encantaría ver tu creatividad y la manera
+    en la que mi fuente está siendo usada.
+
+¡Disfruta la fuente y diviértete!
+-Marco T.L.
diff --git a/GameEnv.hs b/GameEnv.hs
new file mode 100644
--- /dev/null
+++ b/GameEnv.hs
@@ -0,0 +1,64 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+module GameEnv
+(
+    AppEnv(),
+    runApp,
+    getPTurnCell,
+    modifyPlayerCount,
+    screenWidth,
+    screenHeight,
+    sceenBpp
+) where
+
+import Control.Monad.State
+import Control.Monad.Reader
+
+import Grid
+import GameState
+
+screenWidth, screenHeight, sceenBpp :: Int
+screenWidth  = 640
+screenHeight = 480
+sceenBpp     = 32
+
+type AppState = StateT AppData IO
+newtype AppEnv a = AppEnv { runEnv :: ReaderT AppConfig AppState a }
+    deriving (Monad, MonadIO, MonadReader AppConfig, MonadState AppData)
+
+runApp :: AppConfig -> AppData -> AppEnv a -> IO (a, AppData)
+runApp config state (AppEnv env) = (runStateT . runReaderT env) config state
+
+getPTurnCell :: AppEnv Cell
+getPTurnCell = getTurn >>= mapTurn
+ where mapTurn :: PlayerTurn -> AppEnv TileType
+       mapTurn Player = getPlayerType
+       mapTurn Ai = swapCell `liftM` getPlayerType
+
+modifyPlayerCount :: (Integer -> Integer) -> AppEnv ()
+modifyPlayerCount fn = liftM mapTurn getTurn >>= modifyStats
+ where mapTurn :: PlayerTurn -> Stats -> Stats
+       mapTurn Player = \s@Stats { playerCount=pc } -> s { playerCount=fn pc }
+       mapTurn Ai     = \s@Stats { aiCount=pc } -> s { aiCount=fn pc }
diff --git a/GameState.hs b/GameState.hs
new file mode 100644
--- /dev/null
+++ b/GameState.hs
@@ -0,0 +1,182 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+{-# LANGUAGE FlexibleContexts #-}
+module GameState where
+import System.Random
+
+import Control.Monad.State
+import Control.Monad.Reader
+
+import Graphics.UI.SDL (Surface)
+import Graphics.UI.SDL.Rect
+import Graphics.UI.SDL.TTF (Font)
+
+import Surface hiding (isInside)
+import qualified Surface (isInside)
+
+import Grid
+
+data PlayerTurn = Player | Ai
+    deriving (Eq, Show, Read)
+
+type TileType = Cell
+
+data Stats = Stats {
+    playerCount :: Integer,
+    aiCount     :: Integer,
+    tieCount    :: Integer
+} deriving (Eq, Show)
+
+data AppData = AppData {
+    --gameState   :: GameState,
+    --tiles       :: [Tile],
+    grid     :: Grid,
+    stats    :: Stats,
+    turn     :: PlayerTurn,
+    acRand   :: StdGen,
+    --gameOver :: Bool,
+    winner   :: (Winner, [(Int,Int)])
+}
+
+data AppConfig = AppConfig {
+    screen      :: Surface,
+    font        :: Font,
+    oSurface    :: Surface,
+    xSurface    :: Surface,
+    oWinSurf    :: Surface,
+    xWinSurf    :: Surface,
+    gridBounds  :: Rect,
+    playerStart :: PlayerTurn,
+    playerType  :: TileType
+}
+
+-- Player Cross
+appData :: Int -> PlayerTurn -> AppData
+appData seed t = AppData newGrid (Stats 0 0 0) t (mkStdGen seed) (Nobody,[])
+
+getTurn :: MonadState AppData m => m PlayerTurn
+getTurn = liftM turn get
+
+putTurn :: MonadState AppData m => PlayerTurn -> m ()
+putTurn t = modify $ \s -> s { turn = t }
+
+modifyTurn :: MonadState AppData m => (PlayerTurn -> PlayerTurn) -> m ()
+modifyTurn fn = fn `liftM` getTurn >>= putTurn
+
+modifyTurnM :: MonadState AppData m => (PlayerTurn -> m PlayerTurn) -> m ()
+modifyTurnM act = getTurn >>= act >>= putTurn
+
+getStats :: MonadState AppData m => m Stats
+getStats = liftM stats get
+
+putStats :: MonadState AppData m => Stats -> m ()
+putStats t = modify $ \s -> s { stats = t }
+
+modifyStats :: MonadState AppData m => (Stats -> Stats) -> m ()
+modifyStats fn = fn `liftM` getStats >>= putStats
+
+modifyStatsM :: MonadState AppData m => (Stats -> m Stats) -> m ()
+modifyStatsM act = getStats >>= act >>= putStats
+
+getRGen :: MonadState AppData m => m StdGen
+getRGen = liftM acRand get
+
+putRGen :: MonadState AppData m => StdGen -> m ()
+putRGen t = modify $ \s -> s { acRand = t }
+
+modifyRGen :: MonadState AppData m => (StdGen -> StdGen) -> m ()
+modifyRGen fn = fn `liftM` getRGen >>= putRGen
+
+modifyRGenM :: MonadState AppData m => (StdGen -> m StdGen) -> m ()
+modifyRGenM act = getRGen >>= act >>= putRGen
+
+-- utility function to hide plumbing of random generator types.
+rand :: MonadState AppData m => Int -> Int -> m Int
+rand lo hi = do
+    r <- getRGen
+    let (val, r') = randomR (lo, hi) r
+    putRGen r'
+    return val
+
+getGrid :: MonadState AppData m => m Grid
+getGrid = liftM grid get
+
+putGrid :: MonadState AppData m => Grid -> m ()
+putGrid t = modify $ \s -> s { grid = t }
+
+modifyGrid :: MonadState AppData m => (Grid -> Grid) -> m ()
+modifyGrid fn = fn `liftM` getGrid >>= putGrid
+
+modifyGridM :: MonadState AppData m => (Grid -> m Grid) -> m ()
+modifyGridM act = getGrid >>= act >>= putGrid
+
+isGameOver :: MonadState AppData m => m Bool
+isGameOver = liftM (gameOver . fst . winner) get
+ where gameOver Nobody = False
+       gameOver _      = True
+
+getWinner :: MonadState AppData m => m (Winner, [(Int,Int)])
+getWinner = liftM winner get
+
+putWinner :: MonadState AppData m => (Winner, [(Int,Int)]) -> m ()
+putWinner t = modify $ \s -> s { winner = t }
+
+getScreen :: MonadReader AppConfig m => m Surface
+getScreen = liftM screen ask
+
+getFont :: MonadReader AppConfig m => m Font
+getFont = liftM font ask
+
+getNought :: MonadReader AppConfig m => m Surface
+getNought = liftM oSurface ask
+
+getCross :: MonadReader AppConfig m => m Surface
+getCross = liftM xSurface ask
+
+getXWinSurf :: MonadReader AppConfig m => m Surface
+getXWinSurf = liftM xWinSurf ask
+
+getOWinSurf :: MonadReader AppConfig m => m Surface
+getOWinSurf = liftM oWinSurf ask
+
+getPlayerType :: MonadReader AppConfig m => m TileType
+getPlayerType = liftM playerType ask
+
+getPlayerStart :: MonadReader AppConfig m => m PlayerTurn
+getPlayerStart = liftM playerStart ask
+
+getGridBounds :: MonadReader AppConfig m => m Rect
+getGridBounds = liftM gridBounds ask
+
+inGridBounds :: MonadReader AppConfig m => Int -> Int -> m Bool
+inGridBounds x y = getGridBounds >>= \r -> return $ Surface.isInside r x y
+
+nextTurn :: MonadState AppData m => m ()
+nextTurn = modifyTurn k
+ where k Player = Ai
+       k Ai = Player
+
+toTileType :: MonadReader AppConfig m => PlayerTurn -> m TileType
+toTileType Player = getPlayerType
+toTileType Ai = swapCell `liftM` getPlayerType
diff --git a/Grid.hs b/Grid.hs
new file mode 100644
--- /dev/null
+++ b/Grid.hs
@@ -0,0 +1,109 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+module Grid
+(
+    Cell(..),
+    swapCell,
+    Winner(..),
+    Grid(),
+    newGrid,
+    toArray,
+    cellAt,
+    isEmpty,
+    isComplete,
+    takeTurn,
+    whoWon
+) where
+
+import Data.List
+import Data.Array hiding (indices)
+
+data Cell   = Nought | Cross | Empty
+    deriving Eq
+--    deriving (Eq, Show)
+instance Show Cell where
+    show Nought = "O"
+    show Cross  = "X"
+    show _      = ""
+
+swapCell :: Cell -> Cell
+swapCell Nought = Cross
+swapCell Cross  = Nought
+swapCell Empty = Empty
+
+data Winner = Noughts | Crosses | Draw | Nobody
+    deriving Show
+
+type CellArray = Array (Int,Int) Cell
+newtype Grid = Grid { cells :: CellArray }
+
+rowSize :: Int
+rowSize = 3
+--gridSize = rowSize * rowSize
+
+newGrid :: Grid
+newGrid = Grid $ listArray ((0,0), (rowSize - 1,rowSize - 1)) $ repeat Empty
+
+toArray :: Grid -> CellArray
+toArray (Grid t) = t
+
+cellAt :: Grid -> Int -> Int -> Cell
+cellAt (Grid cs) row col = cs ! (row, col)
+
+isEmpty :: Grid -> Int -> Int -> Bool
+isEmpty g row col =
+    case cellAt g row col of
+        Empty -> True
+        _ -> False
+
+isComplete :: Grid -> Bool
+isComplete g = all (\(r,c) -> not $ isEmpty g r c) [(r,c) | r <- indices, c <- indices]
+ where end     = rowSize - 1
+       indices = [0..end]
+
+takeTurn :: Grid -> Cell -> Int -> Int -> Grid
+takeTurn g Empty _ _ = g
+takeTurn g@(Grid cs) c row col =
+    if isEmpty g row col then
+        Grid $ cs // [((row,col), c)]
+    else g
+
+whoWon :: Grid -> (Winner, [(Int,Int)])
+whoWon g@(Grid cs) =
+    case findWinner Nought of
+        Just x -> (Noughts, x)
+        _ -> case findWinner Cross of
+                Just x -> (Crosses, x)
+                _ -> if isDraw g then (Draw, []) else (Nobody, [])
+ where end         = rowSize - 1
+       indices     = [0..end]
+       rows        = [zip (repeat r) indices | r <- indices]
+       cols        = [zip indices (repeat c) | c <- indices]
+       diagonal    = zip indices indices
+       invDiagonal = zip [end,end-1..0] indices
+       searchSpace = rows ++ cols ++ [diagonal] ++ [invDiagonal]
+       allCells cell = all $ \idx -> cs ! idx == cell 
+       findWinner cell  = find (allCells cell) searchSpace
+       
+       isDraw grid = not $ any (uncurry $ isEmpty grid) [(r,c) | r <- indices, c <- indices]
diff --git a/HTicTacToe.cabal b/HTicTacToe.cabal
new file mode 100644
--- /dev/null
+++ b/HTicTacToe.cabal
@@ -0,0 +1,66 @@
+-- HTicTacToe.cabal auto-generated by cabal init. For additional
+-- options, see
+-- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr.
+-- The name of the package.
+Name:                HTicTacToe
+
+-- The package version. See the Haskell package versioning policy
+-- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for
+-- standards guiding when and how versions should be incremented.
+Version:             0.1
+
+-- A short (one-line) description of the package.
+Synopsis:            A tic-tac-toe game.
+
+-- A longer description of the package.
+Description:         Another tic-tac-toe game in Haskell using the SDL bindings.
+
+-- URL for the project homepage or repository.
+Homepage:            http://github.com/snkkid/HTicTacToe
+
+-- The license under which the package is released.
+License:             MIT
+
+-- The file containing the license text.
+License-file:        LICENSE
+
+-- The package author(s).
+Author:              Korcan Hussein
+
+-- An email address to which users can send suggestions, bug reports,
+-- and patches.
+Maintainer:          korcan_h@hotmail.com
+
+-- A copyright notice.
+-- Copyright:           
+
+Category:            Game,Graphics
+
+Build-type:          Simple
+
+-- Extra files to be distributed with the package, such as examples or
+-- a README.
+-- Extra-source-files:  
+
+-- Constraint on the version of Cabal needed to build this package.
+Cabal-version:       >=1.4
+
+Extra-Source-Files:  README, Surface.hs, Grid.hs, GameState.hs, GameEnv.hs, Draw.hs, HTicTacToe.hs
+
+data-files:          "Alice_in_WonderLand_3.ttf",
+                     "FontReadMe.txt",
+                     "o.png", "x.png", "oWin.png", "xWin.png"
+
+Executable HTicTacToe
+  -- .hs or .lhs file containing the Main module.
+    Main-is:         HTicTacToe.hs
+  
+  -- Packages needed in order to build this package.
+    Build-depends:   base >= 4 && < 5, random, array, mtl, SDL, SDL-image, SDL-ttf
+
+  -- Modules not exported by this package.
+  -- Other-modules:       
+  
+  -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source.
+  -- Build-tools:         
+  --  GHC-Options:     -O2 -Wall
diff --git a/HTicTacToe.hs b/HTicTacToe.hs
new file mode 100644
--- /dev/null
+++ b/HTicTacToe.hs
@@ -0,0 +1,188 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein.
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+module Main where
+
+import Prelude hiding (init)
+
+import System.Environment
+
+import System.Console.GetOpt
+
+--import Data.Word
+import Data.List hiding (init)
+
+import Control.Monad
+import Control.Monad.Trans
+import Control.Exception
+
+import Graphics.UI.SDL hiding (init, quit, flip)
+--import qualified Graphics.UI.SDL as SDL (init, quit, flip)
+
+import Graphics.UI.SDL.TTF hiding (init, quit)
+import qualified Graphics.UI.SDL.TTF as TTFG (init, quit)
+
+import Surface
+import Grid
+import GameState hiding (playerType, screen, font, winner, playerStart)
+import GameEnv
+import Draw
+
+import Paths_HTicTacToe
+
+type ProgramOptions = (PlayerTurn,TileType)
+
+parseArgs :: IO (ProgramOptions, [String])
+parseArgs = do
+    argv <- getArgs
+    case getOpt Permute options argv of
+        (o,n,[]  ) -> return (foldl' (flip id) defaultOptions o, n)
+        (_,_,errs) -> ioError $ userError $ concat errs ++ usageInfo header options
+ where header = "Usage: start player"
+       defaultOptions = (Player, Cross)
+       options :: [OptDescr (ProgramOptions -> ProgramOptions)]
+       options = [Option ['s'] ["start"]  (ReqArg (\str (_,p) -> (pStart str, p)) "PlayerStart") "which players starts \"Player\" or \"Ai\" (default is \"Player\")",
+                  Option ['p'] ["player"]  (ReqArg (\str (s,_) -> (s, pType str)) "PlayerType") "player is \"x\" or \"o\" (default is \"x\")"]
+       --playerStart = Player
+       pType "o" = Nought
+       pType "O" = Nought
+       pType _   = Cross -- default playerType.
+       pStart "Ai" = Ai
+       pStart _ = Player -- default playerStart.
+
+init :: IO (AppConfig, AppData)
+init = do
+    
+    (playerStart, playerType) <- fst `liftM` parseArgs
+    
+    xFileName    <- getDataFileName "x.png"
+    oFileName    <- getDataFileName "o.png"
+    xWinFileName <- getDataFileName "xWin.png"
+    oWinFileName <- getDataFileName "oWin.png"
+    fontFileName <- getDataFileName "Alice_in_WonderLand_3.ttf"
+    
+    screen  <- setVideoMode screenWidth screenHeight sceenBpp [HWSurface, DoubleBuf]
+    setCaption "tic-tac-toe" []
+    enableUnicode True
+    
+    font       <- openFont fontFileName 24
+    xSprite    <- loadImage xFileName colorKey
+    oSprite    <- loadImage oFileName colorKey
+    xWinSprite <- loadImage xWinFileName colorKey
+    oWinSprite <- loadImage oWinFileName colorKey
+    
+    seed    <- fromIntegral `liftM` getTicks
+    
+    let wh = surfaceGetWidth xSprite * 6
+    
+    let gridX = (screenWidth `div` 2) - (wh `div` 2)    
+    return (AppConfig screen font oSprite xSprite oWinSprite xWinSprite (Rect gridX 5 wh wh) playerStart playerType, appData seed playerStart)
+ where colorKey = Just (0, 0, 0)
+
+initGame :: AppEnv ()
+initGame = do
+    putGrid newGrid
+    putWinner (Nobody, [])
+    playerTurn <- getTurn
+    case playerTurn of
+        Ai -> aiPlayGame
+        _  -> return ()
+
+aiPlayGame :: AppEnv ()
+aiPlayGame = do
+    playerTurn <- getTurn
+    case playerTurn of
+        Ai -> randomCell >>= uncurry playGame
+        _  -> return ()
+ where randomCell = do
+        r <- rand 0 2
+        c <- rand 0 2
+        g <- getGrid
+        if isEmpty g r c
+            then return (r,c)
+            else randomCell
+
+playGame :: Int -> Int -> AppEnv ()
+playGame row col = do    
+    g <- getGrid
+    when (isEmpty g row col) $ do 
+        playerCell <- getPTurnCell
+        modifyGrid $ \gr -> takeTurn gr playerCell row col    
+        winner <- whoWon `liftM` getGrid
+        putWinner winner        
+        case fst winner of
+            Draw    -> modifyStats $ \s@Stats{ tieCount=tc } -> s { tieCount=tc + 1 }
+            Nobody  -> nextTurn
+            _       -> modifyPlayerCount (+1)
+        
+        isOver <- isGameOver
+        unless isOver aiPlayGame
+
+handleEvent :: Event -> AppEnv ()
+handleEvent VideoExpose = render
+handleEvent (MouseButtonDown mx my ButtonLeft) = do
+    gridBox@(Rect gx gy w h) <- getGridBounds
+    when (isInside gridBox x y) $ do
+        finished <- isGameOver
+        if finished
+            then do
+                initGame
+                pushEvent_ VideoExpose
+            else do
+                playerTurn <- getTurn
+                case playerTurn of
+                    Player -> do
+                        let (row, col) = ((x - gx) `div` (w `div` 3), (y - gy) `div` (h `div` 3))
+                        playGame row col
+                        pushEvent_ VideoExpose
+                    _ -> return ()
+ where x = fromIntegral mx
+       y = fromIntegral my
+       pushEvent_ = liftIO . pushEvent
+
+handleEvent _ = return ()
+
+loop :: AppEnv ()
+loop = do
+    event <- liftIO waitEvent
+    case event of
+        Quit -> return ()
+        _ -> do
+            handleEvent event
+            loop
+
+main :: IO ()
+main = withInit [InitEverything] $ -- withInit calls quit for us.
+    withTtfInit $ do
+        (config, state) <- init
+        runApp config state $ do
+            aiPlayGame -- if Ai was choosen to start first.
+            render     -- initial render
+            loop
+        return ()
+
+withTtfInit :: IO () -> IO ()
+withTtfInit = bracket_ ttfInit TTFG.quit
+ where ttfInit :: IO ()
+       ttfInit = TTFG.init >>= \success -> when (not success) $ throwIO $ userError "Failed to init ttf\n"
+    
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,31 @@
+HTicTacToe
+==========
+Author: Korcan Hussein
+
+Install
+-------
+
+runhaskell Setup.hs configure --user
+runhaskell Setup.hs build
+runhaskell Setup.hs install
+
+How to Play
+-----------
+
+You are either X or O, select an empty area in the grid you want to pick, get 3 in a row or
+column or across and you win!
+
+Game Options
+------------
+
+Pick Who starts:
+
+HTicTacToe --start=Ai/Player
+
+Pick your type:
+
+HTicTacToe --player=o/x
+
+Both:
+
+HTicTacToe --start=Ai/Player --player=o/x
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Surface.hs b/Surface.hs
new file mode 100644
--- /dev/null
+++ b/Surface.hs
@@ -0,0 +1,90 @@
+{-
+    The MIT License
+    
+    Copyright (c) 2010 Korcan Hussein
+    
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+    
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+    
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+-}
+module Surface where
+
+import Foreign
+
+import Control.Monad
+import Control.Monad.Trans
+
+import Graphics.UI.SDL
+import Graphics.UI.SDL.Image
+
+isInside :: Rect -> Int -> Int -> Bool
+isInside (Rect sx sy w h) x y =  x > sx && x < (sx + w) && y > sy && y < (sy + h)
+
+loadImage :: String -> Maybe (Word8, Word8, Word8) -> IO Surface
+loadImage filename colorKey = load filename >>= displayFormat >>= setColorKey' colorKey
+
+setColorKey' :: Maybe (Word8,Word8,Word8) -> Surface -> IO Surface
+setColorKey' Nothing s = return s
+setColorKey' (Just (r, g, b)) surface = mapRGB' surface r g b >>= setColorKey surface [SrcColorKey] >> return surface
+
+applySurface :: Int -> Int -> Surface -> Surface -> Maybe Rect -> IO ()
+applySurface x y src dst clip = blitSurface src clip dst offset >> return ()
+ where offset = Just Rect { rectX = x, rectY = y, rectW = 0, rectH = 0 }
+
+applySurface' :: MonadIO m => Int -> Int -> Surface -> Surface -> Maybe Rect -> m ()
+applySurface' x y src dst = liftIO . applySurface x y src dst
+
+mapRGB' :: Surface -> Word8 -> Word8 -> Word8 -> IO Pixel
+mapRGB' = mapRGB . surfaceGetPixelFormat
+
+clear :: Surface -> Word8 -> Word8 -> Word8 -> IO ()
+clear surf r g b = do
+    jrect      <- Just `liftM` getClipRect surf
+    clearColor <- mapRGB' surf r g b
+    fillRect surf jrect clearColor
+    return ()
+
+getPixel32 :: Surface -> Int -> Int -> IO Pixel
+getPixel32 s x y = do
+    ps <- surfaceGetPixels s
+    Pixel `liftM` peekElemOff (castPtr ps :: Ptr Word32) offset
+ where offset = y * (fromIntegral $ surfaceGetPitch s `div` 4) + x
+
+setPixel32 :: Surface -> Int -> Int -> Pixel -> IO ()
+setPixel32 s x y (Pixel pixel) = do
+    ps <- surfaceGetPixels s
+    pokeElemOff (castPtr ps :: Ptr Word32) offset pixel
+ where offset = y * (fromIntegral $ surfaceGetPitch s `div` 4) + x
+
+type Point2 = (Int,Int)
+
+data LineDir = Vertical | Horizontal
+
+drawLine :: Surface -> Point2 -> Int -> Int -> LineDir -> Pixel -> IO ()
+drawLine dst (x,y) len thickness Horizontal colour =
+    forM_ [(r,c) | c <- [yStart..yEnd], r <- [x..(x + len)]] $ \(r,c) ->
+        setPixel32 dst r c colour
+ where halfLen = thickness `div` 2
+       yStart  = max (y - halfLen) 0
+       yEnd    = min (yStart + thickness) $  surfaceGetHeight dst
+
+drawLine dst (x,y) len thickness Vertical colour =
+    forM_ [(r,c) | r <- [xStart..xEnd], c <- [y..(y + len)]] $ \(r,c) ->
+        setPixel32 dst r c colour
+ where halfLen = thickness `div` 2
+       xStart  = max (x - halfLen) 0
+       xEnd    = min (xStart + thickness) $ surfaceGetWidth dst
diff --git a/o.png b/o.png
new file mode 100644
Binary files /dev/null and b/o.png differ
diff --git a/oWin.png b/oWin.png
new file mode 100644
Binary files /dev/null and b/oWin.png differ
diff --git a/x.png b/x.png
new file mode 100644
Binary files /dev/null and b/x.png differ
diff --git a/xWin.png b/xWin.png
new file mode 100644
Binary files /dev/null and b/xWin.png differ
