Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import qualified Data.Matrix as M
- import qualified Data.Map as Mp
- import Data.List
- import Debug.Trace
- main = do
- content <- readFile "input9"
- let ls = lines content
- let mx = parseInput ls
- loop mx 0
- return ()
- loop mx i = do
- print $ show i
- let isGoElves = (length $ (findTargets mx (E 0 0 1))) == 0
- let isGoGoblins = (length $ (findTargets mx (G 0 0 1))) == 0
- let isGameOver = isGoElves || isGoGoblins
- let hp = sum $ map (\a -> getHp a) $ M.toList mx
- if isGameOver then print ("GameOver " ++ (show hp) ++ " * (" ++ (show (i-1)) ++ " or " ++ (show i) ++ ")") else return ()
- printMatrix mx
- --x <- getLine
- --cls
- let x = ""
- if not isGameOver && x == "" then loop (moveAll mx) (i+1) else return()
- printMatrix mx = do
- let ls = map (\l -> concat $ map show l) $ M.toLists mx
- mapM_ putStrLn ls
- return ()
- cls = putStr "\ESC[2J"
- data T = E Int Int Int | G Int Int Int | C Int Int | W Int Int
- instance Show T where
- show (E _ _ hp) = "\ESC[32m" ++ (if hp > 100 then "E" else "e") ++ "\ESC[m"
- show (G _ _ hp) = "\ESC[31m" ++ (if hp > 100 then "G" else "g") ++ "\ESC[m"
- show (C _ _) = "."
- show (W _ _) = "#"
- toT row col '.' = C row col
- toT row col '#' = W row col
- toT row col 'G' = G row col 200
- toT row col 'E' = E row col 200
- isW (W _ _) = True
- isW _ = False
- isE (E _ _ _) = True
- isE _ = False
- isG (G _ _ _) = True
- isG _ = False
- isWeg t = isW t || isE t || isG t
- getXY (E x y _) = (x, y)
- getXY (G x y _) = (x, y)
- setXY (E x y hp) newX newY = (E newX newY hp)
- setXY (G x y hp) newX newY = (G newX newY hp)
- getHp (E x y hp) = hp
- getHp (G x y hp) = hp
- getHp _ = 0
- setHp (E x y hp) newHp = (E x y newHp)
- setHp (G x y hp) newHp = (G x y newHp)
- getXYHp (E x y hp) = (x, y, hp)
- getXYHp (G x y hp) = (x, y, hp)
- parseInput ls = M.matrix (M.nrows a) (M.ncols a) (\(i, j) -> toT i j $ M.getElem i j a)
- where a = M.fromLists ls
- neighbours mx i j = [(x,y)| (x,y) <- [(i-1,j),(i+1,j),(i,j-1),(i,j+1)], let n = (at x y mx), not (isW n || isE n || isG n)]
- allNeigh mx i j = [(x,y)| (x,y) <- [(i-1,j),(i+1,j),(i,j-1),(i,j+1)], x > 0, y > 0, x < M.nrows mx, y < M.ncols mx]
- at i j m = if (i < 1) || (j < 1) || (i >= M.nrows m) || (j >= M.ncols m) then W i j else M.getElem i j m
- flood mx x y = flood' mx x y 0 $ M.zero 1 1
- flood'::M.Matrix T->Int->Int->Int->M.Matrix Int->M.Matrix Int
- flood' mx x y n dx | n == 0 = flood' mx x y 1 $ M.matrix nrows ncols (\(i, j) -> init i j)
- | newDx == dx = dx
- | otherwise = flood' mx x y (n+1) $ newDx
- where ncols = M.ncols mx
- nrows = M.nrows mx
- init i j = if (i, j) == (x, y) then 0 else (if isWeg (at i j mx) then -1 else 1024)
- f i j = if (any (\(_x, _y) -> (M.getElem _x _y dx) == (n-1)) (allNeigh mx i j)) then min n (M.getElem i j dx) else (M.getElem i j dx)
- newDx = M.matrix nrows ncols (\(i, j) -> f i j)
- findTargets mx t = filter (opponent t) $ M.toList mx
- opponent t = if isE t then isG else isE
- accquireTargets::M.Matrix T->T->[(Int,Int,Int)]
- accquireTargets mx t = targets
- where targets =
- filter (\(_, _, d) -> d < 1024) $
- sortOn (\(_, _, d) -> d) $
- sortOn (\(x, _, _) -> x) $
- sortOn (\(_, y, _) -> y) $
- map (\(x, y) -> (x, y, M.getElem x y edsgar)) $
- concat $
- map (\(x, y) -> neighbours mx x y) $
- map getXY $
- findTargets mx t
- (tx, ty) = getXY t
- edsgar = flood mx tx ty
- moveAndAttack::M.Matrix T->T->M.Matrix T
- moveAndAttack mx t | False && trace ("moveAndAttack " ++ (show t) ++ (show $ getXY t) ++ " " ++ (show noNeedToMove)) False = undefined
- | targets == [] = attack mx t
- | noNeedToMove = attack mx t
- | otherwise = attack (M.setElem newC (x, y) $ M.setElem newT (newX, newY) mx) newT
- where targets = accquireTargets mx t
- target = head targets
- (tx, ty, _) = target
- (x, y) = getXY t
- edsgar = flood mx tx ty
- moves =
- sortOn (\(_, _, d) -> d) $
- sortOn (\(x, _, _) -> x) $
- sortOn (\(_, y, _) -> y) $
- map (\(x,y) -> (x, y, M.getElem x y edsgar)) $
- neighbours mx x y
- (newX, newY, _) = head moves
- newT = setXY t newX newY
- newC = C x y
- noNeedToMove = any (\(i, j) -> opponent t (M.getElem i j mx)) $ allNeigh mx x y
- attack mx t | targets == [] = mx
- | otherwise = M.setElem newTarget' (tx, ty) mx
- where targets =
- sortOn (\(_, _, hp) -> hp) $
- sortOn (\(x, _, _) -> x) $
- sortOn (\(_, y, _) -> y) $
- map (\a-> getXYHp a) $
- filter (opponent t) $
- map (\(_x, _y) -> M.getElem _x _y mx) $ allNeigh mx x y
- (x, y) = getXY t
- (tx, ty, hp) = head targets
- target = M.getElem tx ty mx
- newTarget = setHp target (hp - 3)
- newTarget' = if (hp - 3) <= 0 then C tx ty else newTarget
- moveAll mx = moveAll' mx positions
- where positions = map getXY $ filter (\a-> isE a || isG a) $ M.toList mx
- moveAll' mx [] = mx
- moveAll' mx ((x,y):ps) = moveAll' newMx ps
- where newMx = if (isE t || isG t) then moveAndAttack mx t else mx
- t = M.getElem x y mx
- -- 227480 -- to low
- -- 230065 -- to high
Add Comment
Please, Sign In to add comment