content: module Board where
  
  import Wins
  
  type Board = [Row] 
  type Row = [Piece]
  data Piece = X | O | Empty deriving Eq
  
  showBoard :: Board -> String
  showBoard [r1,r2,r3] =  showRow r1 ++ "\n------\n" ++
  			showRow r2 ++ "\n------\n" ++
  			showRow r3 ++ "\n\n" 
  
  showRow [p1,p2,p3] = showPiece p1 ++ "|" ++ showPiece p2 ++ "|" ++ showPiece p3
  
  
  showPiece :: Piece -> String
  showPiece X = "X"
  showPiece O = "O"
  showPiece Empty = " "
  
  placePiece :: Piece -> Board -> (Int,Int) -> [Board]
  placePiece p board pos | not (empty pos board) = []
  placePiece p [r1,r2,r3] (1,x) = [[insert p r1 x,r2,r3]]
  placePiece p [r1,r2,r3] (2,x) = [[r1,insert p r2 x,r3]]
  placePiece p [r1,r2,r3] (3,x) = [[r1,r2,insert p r3 x]]
  
  insert :: Piece -> Row -> Int -> Row
  insert p [p1,p2,p3] 1 = [p,p2,p3]
  insert p [p1,p2,p3] 2 = [p1,p,p3]
  insert p [p1,p2,p3] 3 = [p1,p2,p]
  
  empty :: (Int,Int) -> Board -> Bool
  empty (1,x) [r1,r2,r3] = empty' x r1
  empty (2,x) [r1,r2,r3] = empty' x r2
  empty (3,x) [r1,r2,r3] = empty' x r3
  
  empty' :: Int -> Row -> Bool
  empty' 1 [Empty,_,_] = True
  empty' 2 [_,Empty,_] = True
  empty' 3 [_,_,Empty] = True
  empty' _ _ = False
  
  fullBoard b = and (map notEmpty (concat b))
  	where 
  	notEmpty x = not (x==Empty)
  
  --newPositions :: Piece -> Board -> [Board]
  newPositions piece board = concat (map (placePiece piece board) 
  					[(x,y) | x<-[1..3],y <-[1..3]])
  
  initialBoard :: Board
  initialBoard = [[Empty,Empty,Empty], 
  		[Empty,Empty,Empty],
  		[Empty,Empty,Empty]]
  
  data Evaluation = XWin | OWin | Score Int deriving (Show{-was:Text-},Eq)
  
  eval 3 = XWin
  eval (-3) = OWin
  eval x = Score x
  
  static :: Board -> Evaluation
  static board = interpret 0 (map (score board) wins)
  
  interpret :: Int -> [Evaluation] -> Evaluation
  interpret x [] = (Score x)
  interpret x (Score y:l) = interpret (x+y) l
  interpret x (XWin:l) = XWin
  interpret x (OWin:l) = OWin
  
  score :: Board -> Win -> Evaluation
  score board win  = eval (sum (map sum (map2 (map2 scorePiece) board win)))
  
  scorePiece :: Piece -> Int -> Int
  scorePiece X score = score
  scorePiece Empty _ = 0
  scorePiece O score = -score
  
  map2 :: (a -> b -> c) -> [a] -> [b] -> [c]
  map2 f [] x = []
  map2 f x [] = []
  map2 f (x:xs) (y:ys) = f x y:map2 f xs ys
  