Untitled
unknown
plain_text
a year ago
5.0 kB
13
Indexable
{-| Função para arredondar as posições para obter a posição geral
Como sabemos, na matriz toda posição em que o x pertence a [0,1] e o y pertence a [0,1] é a posição (0,0) da matriz, essa função acha essa posição "geral" da matriz.
-}
arredondarPosicao :: Posicao -> (Int, Int)
arredondarPosicao (x, y) = (floor x,floor y)
-- | Função que encontra o caminho mais curto entre as duas posições (semelhante a função da Tarefa 1)
encontrarCaminho :: Posicao -> Posicao -> Mapa -> Maybe [Posicao]
encontrarCaminho posinicial posfinal mapa = encontrarCaminhoAux [[posinicial]] []
where
encontrarCaminhoAux :: [[Posicao]] -> [Posicao] -> Maybe [Posicao]
encontrarCaminhoAux [] _ = Nothing
encontrarCaminhoAux (caminho:fila) visitados
| arredondarPosicao atual == arredondarPosicao posfinal = Just caminho -- ^ verificar se tá na mesma posição geral do quadrado da posição final
| atual `elem` visitados = encontrarCaminhoAux fila visitados
| otherwise =
let visitados' = atual : visitados
adjacentes = filter (`notElem` visitados') (posAdjacentes atual mapa) -- ^ pos adjacentes são de terra
novosCaminhos = [caminho ++ [adj] | adj <- adjacentes] -- ^ lista de caminhos (cada caminho é uma lista de posições)
in (encontrarCaminhoAux (fila ++ novosCaminhos) visitados')
where atual = last caminho -- ^ a pos final de um caminho é a que interessa para comparar
-- | Função auxiliar que retorna as posições válidas para o inimigo se mover (nunca voltar para trás).
getPosicoesValidas :: Posicao -> Direcao -> Mapa -> [(Posicao,Direcao)]
getPosicoesValidas (x,y) dir mapa =
case dir of
Norte -> filter (\((x,y),_) -> validaPosicaoTerra (x,y) mapa) [((x,y-0.501),Norte),((x+0.501,y),Este),((x-0.501,y),Oeste)]
Sul -> filter (\((x,y),_) -> validaPosicaoTerra (x,y) mapa) [((x,y+0.501),Sul),((x+0.501,y),Este),((x-0.501,y),Oeste)]
Este -> filter (\((x,y),_) -> validaPosicaoTerra (x,y) mapa) [((x+0.501,y),Este),((x,y-0.501),Norte),((x,y+0.501),Sul)]
Oeste -> filter (\((x,y),_) -> validaPosicaoTerra (x,y) mapa) [((x-0.501,y),Oeste),((x,y-0.501),Norte),((x,y+0.501),Sul)]
{-| Função auxiliar que escolhe a direção que o inimigo deve seguir para chegar a base quando há mais de uma direção possível.
A primeira lista é a lista das tuplas de posições e direções válidas para o inimigo se mover.
A segunda lista é a lista de posições do caminho que o inimigo deve seguir.
-}
escolheDirecao :: [(Posicao,Direcao)] -> [Posicao] -> Maybe Direcao
escolheDirecao [] _ = Nothing
escolheDirecao _ [] = Nothing
escolheDirecao ((pos,d):rl) caminho
| elem (posicaoArredondada pos) caminho = Just d
| otherwise = escolheDirecao rl caminho
where posicaoArredondada :: Posicao -> Posicao
posicaoArredondada (x,y) = (fromIntegral (floor x),fromIntegral (floor y))
-- | Função auxiliar que verifica se uma dada posição pertence ao caminho que o inimigo deve seguir.
pertenceCaminho :: Posicao -> [Posicao] -> Bool
pertenceCaminho _ [] = False
pertenceCaminho (x,y) caminho = elem (x',y') caminho
where (x',y') = (fromIntegral (floor x),fromIntegral (floor y)) -- ^ arredonda para pegar a posição "toda" (a da matriz)
-- | Função que move o inimigo de acordo com a sua direção e velocidade.
moveInimigo :: Tempo -> Inimigo -> Posicao -> Mapa -> (Direcao,Posicao)
moveInimigo t Inimigo {posicaoInimigo = (x,y), direcaoInimigo = direcao, velocidadeInimigo = velocidade, projeteisInimigo = lprojeteis} posbase mapa
= if any (\proj -> tipoProjetil proj == Gelo) lprojeteis
then (direcao,(x,y))
else
let caminho = map (\(x,y) -> (fromIntegral (floor x),fromIntegral(floor y))) (fromJust(encontrarCaminho (x,y) (posbase) mapa)) -- ^ passa o caminho para as posições "gerais"
posicoesvalidas = getPosicoesValidas (x,y) direcao mapa
in case direcao of
Norte -> if pertenceCaminho (x,y-0.501) caminho
then (direcao,(x,y-(velocidade*t)))
else trace ("Posicao direcao atual:" ++ show (direcao,(x,y)) ++ "Escolhendo direção: " ++ show (posicoesvalidas, caminho)) $ (fromJust (escolheDirecao posicoesvalidas caminho), (x,y)) -- ^ tomada de decisão (mais de uma direção possível e a direção Norte não leva a base)
Sul -> if pertenceCaminho (x,(y+0.501)) caminho
then (direcao,(x,y+(velocidade*t)))
else (fromJust (escolheDirecao posicoesvalidas caminho), (x,y))
Este -> if pertenceCaminho (x+0.501,y) caminho
then (direcao,(x+(velocidade*t),y))
else (fromJust (escolheDirecao posicoesvalidas caminho), (x,y))
Oeste -> if pertenceCaminho (x-0.501,y) caminho
then (direcao,(x-(velocidade*t),y))
else (fromJust (escolheDirecao posicoesvalidas caminho), (x,y))
Editor is loading...
Leave a Comment