AwesomeUnicorn
AwesomeUnicorn

Reputation: 33

Changing variables inside a recursive function

I'm trying to make a game in Haskell. Right now, I'm working on enemy collision: that is, if an enemy collides with the player, the score gets reset to 0 and the enemy dies. However, I just can't quite work out how.

I've already considered a do block but that's not right (I don't want to return IO). I can't find anything to point me in the right direction, leaving me to wonder if it's even possible...

The (kind of ugly) piece of code I have is this:

newEnemies = updateEnemies enemies
    updateEnemies :: [Point] -> [Point]
    updateEnemies [] = []
    updateEnemies (x:xs) | hitPlayer (nextLocation x) = -- TODO: Reset multipliers
                                                        updateEnemies xs
                         | otherwise = nextLocation x : updateEnemies xs
        where
        hitPlayer :: Point -> Bool
        hitPlayer (x, y) | abs (fst newPosition - x) < 10 && abs (snd newPosition - y) < 10
                            = True
                         | otherwise = False
        nextLocation loc = (loc + ((dirToPlayer loc) * (100, 100) * (timeStep, timeStep)))
        dirToPlayer loc = normalizeV (playerPosition - loc)

Can one of you point me in the right direction, or am I just too used to imperative languages?

Thanks!

Upvotes: 0

Views: 81

Answers (1)

jwodder
jwodder

Reputation: 57590

All updateEnemies is really doing is applying nextLocation to each element of the input list and then discarding the ones that hitPlayer. The main body can thus be reduced to:

updateEnemies xs = filter (not . hitPlayer) $ map nextLocation xs

or, if you prefer something more points-free:

updateEnemies = filter (not . hitPlayer) . map nextLocation

In addition, defining hitPlayer by using a guard to decide whether to return True or False is just wrong; the equivalent mistake in other languages would be writing if (condition) return true; else return false;. Just return the result of the test directly!

hitPlayer (x, y) = abs (fst newPosition - x) < 10 && abs (snd newPosition - y) < 10

Upvotes: 1

Related Questions