Hi Isaac

It sounds to me that your source of pseudo-randomness is an inherent part
of your world state, as without it you're unable to calculate the next
state.

You mention the problem of having to thread your PRNG through your
functions, but I think the problem is broader than that. For instance, you
may decide on a combat engine that takes in a source of randomness and two
creatures as its arguments, only to decide at a later date that you also
want the terrain to affect the battle. Usually we want to restrict what
data a function cares about in order to make its effects more predictable,
but because a game is modelling an analogue of the real world, any part of
the current game state could potentially have an effect upon the outcome.

I must admit I've yet to settle on an entirely satisfactory solution. You'd
prefer to be able to restrain what a function cares about, but you also
don't want to thread an argument through a dozen functions every time you
want the function at the bottom to affect something new.

The most straightforward solution is to thread the game state through your
code as the first argument. It does solve the problem, but feels somewhat
unsatisfactory.

There might be a solution in lenses, zippers, or some similar structure.
Instead of passing through the state bare, we pass through a view upon the
state. How best to do this in Clojure is, I think, still an area of
research.

Alternatively you could think of it in terms of an event stream. You do as
much as you can functionally, then return an event, or action, which
results in a state change. This is similar to the "with gloves" approach
that the IO monad uses.

I apologise for not providing any concrete answers, but this has been
something I've been thinking about as well. You can quite easily narrow the
scope of data a function has access to, but it's very hard to widen it
again.

- James


On 28 October 2014 19:08, Isaac Karth <isaacka...@gmail.com> wrote:

> I've been working on some projects (roguelikes, story-generators) that
> often have a reason to have a random outcome for things like procedurally
> generating a map. Ideally, they would be deterministically psuduorandom, so
> that I can generate the same results from the same seed. The part I'm
> having trouble with is figuring out what method to use to implement this in
> a functional way.
>
> The naive approach that first occurred to me was to pass a PRNG and seed
> value into each function. That would certainly keep the functions
> referentially transparent. But it would also require either rewriting a
> bunch of functions that don't directly use the randomness themselves or
> adding the RNG as part of the map that's already being passed.
>
> Plus, the seed should probably vary (deterministically) between calls to
> the subfunctions. It's not too useful if all the rooms on a map have the
> same type because they all pulled their die roll from the same-nth result
> of the exact same seed. Maybe the seed could be created from the contents
> of the vector or a UUID of a map object or something?
>
> The other suggestion I've run across is to rebind something like
> clojure.data.generators/*rnd* for each high-level procedural generation
> call. I think this requires the generation to be single threaded and
> otherwise deterministic. At the moment I don't feel like I know enough
> about how things work under the hood to say if this a good idea or not.
>
> I've poked around at the bigml.sampling and clojure.data.generators
> libraries, which look useful for dealing with some of this, but I haven't
> come across anything that directly addresses what kind of architecture to
> use for deterministic randomness. This may be my inexperience. I feel like
> I may be a bit too close to the problem, and I can't quite see what the
> idiomatic answer is. Re-read SICP? Implement some kind of monad? Just bite
> the bullet and pass the RNG+seed? Find the secret pure functional library
> everyone is using for repeatable stochastic simulations?
>
> Does anyone have any advice on this? Or prior experience with approaches
> that work? What are some best practices for approaching deterministic
> simulations in an idiomatic, functional way?
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to