Hacker News new | ask | show | jobs
by yiransheng 3197 days ago
In FP world, there's a somewhat advanced solution to this, Free Monad DSL/Interpreter pattern. I first found out about it in this talk: [https://www.youtube.com/watch?v=fU8eKoakd6o](https://www.you.... There's an example of a pure functional game ai DSL in it.

The gist of the idea is you would write _pure_ functions like this with an imperative style (example in Haskell)

    bullet = do
      player <- getEntityByID playerID
      applyDamage 20 player
This will require some syntactic sugar (do notation in Haskell, for comprehension in Scala) to make it look procedure / imperative. However, the whole expression remains pure, and does not read or write to global state, it's just a data structure capable of expressing steps of mutations (and/or side effects).

A separate part of the system (interpreter) will actually collect all such data structures and apply actual updates to global states in one place and in a principled way.

Some additional benefits includes easily implementing different interpreters (eg. for unit testing), adding "middlewares" to support things like logging and type safety on mutations.

I have no idea whether game programmers uses this pattern or not. However, it's very common in games to add a scripting language (LUA is a popular one) to express things like unit AI, dialog trees on top the underlying engine; which seems rather similar architecturally: adding a layer of indirection, use a expressive (just enough) DSL to encode the logic for mutations with only limited exposure to underlying global states.

A better resource that explores this idea can be found here: http://gameprogrammingpatterns.com/bytecode.html