diff --git a/Tic-Tac-Toe.cabal b/Tic-Tac-Toe.cabal
--- a/Tic-Tac-Toe.cabal
+++ b/Tic-Tac-Toe.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                Tic-Tac-Toe
-version:             0.1.0.1
+version:             0.1.0.2
 synopsis:            Tic Tac Toe in your command line!
 description:         Bored, tired, or just need a break? Play a quick game of tic tac toe against your computer in the command line!
 homepage:            https://github.com/2016rshah/Tic-Tac-Toe
@@ -19,9 +19,13 @@
 cabal-version:       >=1.10
 
 executable Tic-Tac-Toe
-  main-is:             Main.hs
-  -- other-modules:       
-  -- other-extensions:    
+  main-is: Main.hs
+  -- Modules exported by the library.
+  -- exposed-modules:     
+  
+  -- Modules included in this library but not exported.
+  other-modules:       TicTacToe
+
   build-depends:       base >= 2 && < 5
                      , safe -any
   hs-source-dirs:      src
diff --git a/src/TicTacToe.hs b/src/TicTacToe.hs
new file mode 100644
--- /dev/null
+++ b/src/TicTacToe.hs
@@ -0,0 +1,120 @@
+module TicTacToe where
+
+{-# LANGUAGE FlexibleInstances #-}
+
+
+import Data.Either
+import Safe
+import Data.Maybe
+import Data.List
+
+-- |Slots in the board can either be filled with Naughts or Crosses
+data Symbol = X | O 
+	deriving (Show, Eq)
+
+-- |Empty slots are referred to by their location on the board
+type Piece = Either Int Symbol
+
+-- |A set of three pieces is used to represent rows, columns, and diagonals
+type Three = [Piece] -- how do I constrain this to a length of three?
+
+-- |The game board is made up of three rows of three pieces each. 
+data Board = Board Three Three Three
+	deriving (Eq)
+
+--Thank you to http://projects.haskell.org/operational/examples/TicTacToe.hs.html for the show function
+instance Show Board where
+	show board =
+	      unlines . surround "+---+---+---+"
+	    . map (concat . surround "|". map showSquare)
+	    $ (rows board)
+	    where
+	    surround x xs = [x] ++ intersperse x xs ++ [x]
+	    showSquare = either (\n -> " " ++ show n ++ " ") (\n -> " " ++ show n ++ " ")
+
+-- |Convenience function for constructing an empty board
+emptyBoard :: Board
+emptyBoard = Board [Left 1, Left 2, Left 3] [Left 4, Left 5, Left 6] [Left 7, Left 8, Left 9]
+
+-- |Given either a row, column, or diagonal, it checks whether it is entirely filled with naughts or crosses
+full :: Three -> Bool
+full ts@[a,b,c] = noLefts && allEqual
+	where 
+		noLefts = foldl (\acc curr -> acc && (isRight curr)) True ts 
+		allEqual = a == b && b == c
+
+-- |Given a game board, check whether the game is over because someone won
+won :: Board -> Bool
+won b = foldl (\acc curr -> acc || (full curr)) False ((rows b) ++ (cols b) ++ (diags b))
+
+-- |Given a game board, check whether the game is over due to a draw
+draw :: Board -> Bool
+draw b = length (possibleMoves b) == 0
+
+-- |Message to display to the user about the results of the game
+winner :: Board -> String
+winner b = if length winnerType > 0 then head winnerType else "It was a draw!"
+	where 
+		allConfigs = ((rows b) ++ (cols b) ++ (diags b))
+		winnerType = [if a == (Right X) then "The computer wins!" else "You win!" | curr@[a,b,c] <- allConfigs, full curr]
+
+-- |Extract rows from game board
+rows :: Board -> [Three]
+rows (Board x y z) = [x, y, z]
+
+-- |Extract columns from game board
+cols :: Board -> [Three]
+cols (Board [a, b, c] [d, e, f] [g, h, i]) = [[a, d, g], [b, e, h], [c, f, i]]
+
+-- |Extract diagonals from game board
+diags :: Board -> [Three]
+diags (Board [a, _, c] [_, e, _] [g, _, i]) = [[a, e, i], [c, e, g]]
+
+-- |List of places where a piece can be placed
+possibleMoves :: Board -> [Piece]
+possibleMoves board = filter isLeft (boardToList board)
+
+-- |Helper function to convert a board into a list of values
+boardToList :: Board -> [Piece]
+boardToList (Board x y z) = x ++ y ++ z
+
+-- |Helper function to convert a list of values into a board
+listToBoard :: [Piece] -> Board
+listToBoard [a,b,c,d,e,f,g,h,i] = Board [a,b,c] [d,e,f] [g,h,i]
+
+-- |Function to update the game board with a new value at a specified point
+findAndReplace :: Board -> Piece -> Piece -> Board
+findAndReplace b p1 p2 = listToBoard [if x==p1 then p2 else x | x <- bl]
+	where bl = boardToList b
+
+-- |Check if X's can immediately win, and if so, do it
+winningXMove :: Board -> Maybe Board
+winningXMove b = headMay [findAndReplace b p (Right X) | p <- (possibleMoves b), won (findAndReplace b p (Right X))]
+
+-- |Check if O's can immediately win, and if so, block it
+blockOWin :: Board -> Maybe Board
+blockOWin b = headMay [findAndReplace b p (Right X) | p <- (possibleMoves b), won (findAndReplace b p (Right O))]
+
+-- |Check whether a board has been forked
+isFork :: Board -> Bool
+isFork b = 2 == length [findAndReplace b p (Right X) | p <- (possibleMoves b), won (findAndReplace b p (Right X))]
+
+-- |Check if X's can make a fork, and if so, do it
+forkX :: Board -> Maybe Board
+forkX b = headMay [findAndReplace b p (Right X) | p <- (possibleMoves b), isFork (findAndReplace b p (Right X))]
+
+-- |Check if O's can make a fork, and if so, block it
+blockOFork :: Board -> Maybe Board
+blockOFork b = headMay [findAndReplace b p (Right X) | p <- (possibleMoves b), isFork (findAndReplace b p (Right O))]
+
+-- |Decision tree for AI that will go down the list to make its move
+makeXMove :: Board -> Board
+makeXMove board@(Board x@[a, b, c] y@[d, e, f] z@[g, h, i])
+	| isJust (winningXMove board) 	= fromJust (winningXMove board)
+	| isJust (blockOWin board) 		= fromJust (blockOWin board)
+	| isJust (forkX board) 			= fromJust (forkX board)
+	| isJust (blockOFork board) 	= fromJust (blockOFork board)
+	| elem e (possibleMoves board)	= findAndReplace board e (Right X)
+	| otherwise 					= if length (possibleMoves board) > 0 
+		then findAndReplace board (head (possibleMoves board)) (Right X)
+		else board --This should not happen
