{-# LANGUAGE LambdaCase #-} module Internal.Karel where import Internal.Types import Internal.World data Karel = Karel { karelPosition :: Vector, karelDirection :: Direction, karelBeepers :: Int, karelWorld :: World } deriving (Show, Eq) stepVector :: Direction -> Vector stepVector = \case North -> (0, 1) East -> (1, 0) South -> (0, -1) West -> (-1, 0) leftTurn :: Direction -> Direction leftTurn = \case North -> West West -> South South -> East East -> North changeBeepers :: Int -> Karel -> Karel changeBeepers db robot | checkedCount <= 0 = error ("There are no beepers to " ++ msg) | otherwise = robot { karelBeepers = inBag + db, karelWorld = setBeepersAt position (atPosition - db) world } where (position, world) = (karelPosition robot, karelWorld robot) inBag = karelBeepers robot atPosition = getBeepersAt position world (checkedCount, msg) = if db == 1 then (atPosition, "pick up") else (inBag, "put down") defaultKarel :: World -> Karel defaultKarel world = Karel { karelPosition = (1, 1), karelDirection = East, karelBeepers = 0, karelWorld = world } initialPosition :: Vector -> Karel -> Karel initialPosition pos robot | not $ positionWithinWorld (karelWorld robot) pos = error "Invalid position" | otherwise = robot { karelPosition = pos } initialDirection :: Direction -> Karel -> Karel initialDirection dir robot = robot { karelDirection = dir } initialBeepersInBag :: Int -> Karel -> Karel initialBeepersInBag beepers robot | beepers < 0 = error "Invalid count of beepers" | otherwise = robot { karelBeepers = beepers }