Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a game built with purely functional programming, how could one player do damage (alter state) of another player? [closed]

I know very little about functional programming other than the idea of pure functions. In John Carmack's 2013 Quakecon talk he mentioned one of the questions often asked about functional programming as related to games: how do you fire a gun and do damage to another player if you don't have access to state? (paraphrased) In mentioned something about an event system, which I didn't quite understand, since it seems to me an event system would still need state?

How would one accomplish this in a purely functional language?

like image 611
talloaktrees Avatar asked Aug 03 '13 10:08

talloaktrees


People also ask

Is functional programming used in games?

Games are commonly programmed in imperative languages. Functional languages have been known to have benefits but have rarely been used to program games.

How do you maintain state in functional programming?

In pure functional programming, state is manipulated by functions that take some state and return the next state. Sequencing through states is then achieved by passing the state through a sequence of pure functions. Even global mutable state can be modeled this way.

Is functional programming suitable for game development?

There are a lot of advantages to functional programming in terms of concurrency, using persistent data-structures makes it cheaper (as well as much simpler in terms of code) to maintain old copies of game state which is very important if your game is going to feature a multi-player component.

How is data stored in functional programming?

In functional programming, data cannot be stored in objects and it can only be transformed by creating functions. In object-oriented programming, data is stored in objects. The object-oriented programming is widely used by the programmers and successful also.


1 Answers

To repeat one of my favorite quotes

... takes in the state of the world and returns a new world, thus remaining pure.

This was talking about Clean, a cousin of Haskell but it's still related. The gist of it is, you're right, you need some kind of state, but it doesn't have to be mutable. Consider

myFun :: StateOfTheWorld -> a -> (StateOfTheWorld, b)

so we don't modify the state, we just produce a new one. This is referentially transparent, since given the same state of the world and the same action, you'll get the same thing back.

For you you might have something like

 killPlayer :: Game -> Event -> Game
 killPlayer g (Kill x) = g { isDead = x : isDead g }

which is just using functional updates for records. This is a bit klunky, so we might do something like

 killPlayer :: Game -> Event -> Action
 killPlayer (PlayerDamaged x amount) = if playerHealth g x <= amount
                                       then KillPlayer x
                                       else ReduceHealth x amount

So we just return the differences, not the full game state.

This works, but is ugly. So we prettify this with do notation and Control.Monad.State. This sounds scary but it's exactly what we were doing above, just with a bit more syntactic abstraction. In fact, this is what IO is on GHC as well. I don't know if you've learned about Monads, but the State monad is often the motivating example.

Finally to get back to games, many of the gameframeworks I've seen are like this: piles of things listening to events and then suggesting some small incremental change to the game state and returning the different, finally the framework itself makes the appropriate openGL calls or whatever to implement those changes.

like image 185
Daniel Gratzer Avatar answered Oct 10 '22 02:10

Daniel Gratzer