hfiar-1.2.0: src/HFiaR/AI.hs
module HFiaR.AI (aiDropIn) where
import HFiaR
-- | Drop a tile in a column choosen by the Artificial Inteligence
aiDropIn :: Monad m => HFiaRT m (Either HFiaRError ())
aiDropIn =
do {
r <- result;
case r of {
Left GameNotEnded ->
do {
Right p <- player;
b <- board;
dropIn $ bestColumnFor p b
};
Left err ->
return $ Left err;
Right _ ->
return $ Left GameEnded
}
}
bestColumnFor :: Player -> [[Tile]] -> Int
bestColumnFor p b =
case columnWhereWins p b of
Nothing ->
case columnWhereLoses p b of
Nothing ->
case length (b !! 3) of
7 -> length $ takeWhile (\c -> length c == 7) b
_ -> 3
Just cwl -> cwl
Just cww -> cww
columnWhereWins :: Player -> [[Tile]] -> Maybe Int
columnWhereWins Pl{tiles=tile} b =
case (length $ takeWhile (not . wins tile b) [0..6]) of
7 -> Nothing
x -> Just x
columnWhereLoses :: Player -> [[Tile]] -> Maybe Int
columnWhereLoses Pl{tiles=tile} b =
let otherTile = case tile of {Green -> Red; Red -> Green}
in case (length $ takeWhile (not . wins otherTile b) [0..6]) of
7 -> Nothing
x -> Just x
wins :: Tile -> [[Tile]] -> Int -> Bool
wins t b c =
let newBoard = (take c b) ++ ((t : (b !! c)) : drop (c+1) b)
col = newBoard !! c
getRow r = map (cell r)
getDiagUpRight c r xss = map (\i -> cell (i+r-c) (xss !! i)) [0..6]
getDiagUpLeft c r xss = map (\i -> cell (r+c-i) (xss !! i)) [0..6]
cell c xs = if (c >= 0 && c < length xs)
then Just $ (reverse xs) !! c
else Nothing
fourIn [] = False
fourIn (Nothing:xs) = fourIn xs
fourIn (Just p :xs) = ([Just p, Just p, Just p] == take 3 xs) || fourIn xs
in ([t,t,t,t] == take 4 col) ||
fourIn (getRow (length col - 1) newBoard) ||
fourIn (getDiagUpRight c (length col - 1) newBoard) ||
fourIn (getDiagUpLeft c (length col - 1) newBoard)
testGame :: [[Tile]]
testGame = justEval $ aiDropIn >> aiDropIn >>
aiDropIn >> aiDropIn >>
aiDropIn >> aiDropIn >>
aiDropIn >> aiDropIn >> board