content: module Game where
  
  import Board
  import Wins
  import Tree
  
  type Player = Evaluation -> Evaluation -> Evaluation
  type Move = (Board,Evaluation)
  
  
  
  alternate :: Piece -> Player -> Player -> Board -> [Move]
  alternate _ _ _ b | fullBoard b = []
  alternate _ _ _ b | static b == XWin = []
  alternate _ _ _ b | static b == OWin = []
  alternate player f g board = move:alternate opposition g f board'
  	where
  	move@(board',eval) = best f possibles scores
  	scores = map (bestMove opposition g f) possibles
  	possibles = newPositions player board
  	opposition = opposite player
  
  opposite :: Piece -> Piece
  opposite X = O
  opposite O = X
  
  
  best :: Player -> [Board] -> [Evaluation] -> Move
  best f (b:bs) (s:ss) = best' b s bs ss
  	where
  	best' b s [] [] = (b,s)
  	best' b s (b':bs) (s':ss) | s==(f s s') = best' b s bs ss
  				  | otherwise 	    = best' b' s' bs ss
  
  showMove :: Move -> String
  showMove (b,e) = show e ++ "\n" ++ showBoard b
  
  bestMove :: Piece -> Player -> Player -> Board -> Evaluation
  bestMove p f g = (mise f g).cropTree.mapTree static.searchTree p
  
  cropTree :: (Tree Evaluation) -> (Tree Evaluation)
  cropTree (Branch a []) = (Branch a [])
  cropTree (Branch (Score x) l) = Branch (Score x) (map cropTree l)
  cropTree (Branch x l) = Branch x []
  
  searchTree :: Piece -> Board -> (Tree Board)
  searchTree p board = prune 5 (repTree (newPositions p) (newPositions (opposite p)) board)
  
  mise :: Player -> Player -> (Tree Evaluation) -> Evaluation
  mise f g (Branch a []) = a
  mise f g (Branch _ l) = foldr f (g OWin XWin) (map (mise g f) l)
  
  
  max' :: Evaluation -> Evaluation -> Evaluation
  max' XWin _ = XWin
  max' _ XWin = XWin
  max' b OWin = b
  max' OWin b = b
  max' a@(Score x) b@(Score y) 	| x>y = a
  			 	| otherwise = b
  
  min' :: Evaluation -> Evaluation -> Evaluation
  min' OWin _ = OWin
  min' _ OWin = OWin
  min' b XWin = b
  min' XWin b = b
  min' a@(Score x) b@(Score y) 	| x<y = a
  				| otherwise = b
  
  