-- CPSC 312 - 2023 - Games in Haskell
module CountGame where


data State = State InternalState [Action]  -- internal_state available_actions
         deriving (Ord, Eq, Show)

data Result = EndOfGame Double State    -- end of game: value, starting state
            | ContinueGame State        -- continue with new state
         deriving (Eq, Show)

type Game = Action -> State -> Result

type Player = State -> Action

----- CountGame

type Action = Int            -- a move for a player is just an integer

type InternalState = Int           -- the state of the game is just an integer

countGame :: Int -> [Action] -> Game
-- countGame breakValue actions   returns a Game
countGame breakValue possibleActions  move (State st _)
    | newsum >= breakValue = EndOfGame (-1) (State 0  possibleActions)
    | otherwise = ContinueGame (State newsum possibleActions)
    where newsum = move+st

-- Some games:
-- countGame 20 [1,2,3,5,7]
-- countGame 100 [1..9]
-- countGame 500 [7,14,28,63]




-- A simple Player
simple_count_player :: Int -> [Action] -> Player
simple_count_player breakValue possibleActions (State st _ ) 
    | elem (breakValue-1-st) possibleActions =  (breakValue-1-st)
    | otherwise =  foldr max 0 possibleActions


-- In Play:
-- cg = countGame 20 [1,2,3,5,7]
-- play cg (State 0 [1,2,3,5,7]) (simple_count_player 20 [1,2,3,5,7]) (0,0,0)


createCountGame :: Int -> [Action] -> (Game ,State)
-- Given breakValue possibleActions returns game and initial state
createCountGame breakValue possibleActions = (countGame breakValue possibleActions, State 0 possibleActions)


-- with minimax try
-- minimax (countGame 20 [1,2,3,5,7]) (State 0 [1,2,3,5,7])
-- then try 21, 25, 30