Hi Will,

have a look at this workshop repository, in which we developed a
simple text adventure framework:
https://github.com/learn-postspectacular/resonate-workshop-2014

Hth! K.

On 30 March 2018 at 16:01, Gary Johnson <lambdatro...@gmail.com> wrote:
> Hi Will,
>
> Welcome to the wide world of functional programming, where data flows, and
> functions transmute without destroying their inputs.
>
> As some others in this thread have already suggested, a general approach to
> viewing any problem space from a functional perspective is to imagine your
> problem as a pipeline of data transformations from start to finish. To the
> greatest extent possible, try to represent your data transformations as pure
> functions over immutable arguments rather than holding any global state in a
> var and mutating it at each time step.
>
> In the context of a game program, consider depicting all of your game state
> as a single hierarchical map. Then thread this map through each function and
> return a new derived map as each output result.
>
> ```clojure
> (def world-state {:flags #{}
>                         :location :fancy-room
>                         :inventory #{:sledgehammer :car-keys :lamp}
>                         :rooms {:creepy-corridor {:name "Creepy Corridor"
> :description "Whoa! Spooky..." :items #{:halloween-mask :monkeys-paw
> :troll-doll}}
>                                     :fancy-room {:name "Fancy Room"
> :description "The fanciest!" :items #{:chandelier :toy-poodle
> :looking-glass}}
>                                     ...}})
>
> ```
> Let's imagine this is the initial world state. When your application starts
> up, it enters into the game loop (which would be a nice, friendly recursion,
> of course). In each round of the game loop, you call a sequence of functions
> to get the description of the current room, print it out, ask the user for
> the next command, process that command, and then recurse back to the top of
> the next iteration of the game loop. Although printing to stdout and reading
> from stdin are obviously side effecting functions, you should be able to
> keep your functions for retrieving the room description and processing the
> user's command as pure functions of the current world-state. Just make sure
> that the functions that process a user's command always return a new copy of
> the world-state value. When you want to save the game, just write out the
> world-state to an EDN file. By reading it back in again later, you can
> restore the game to exactly the same state it was in before.
>
> In response to your specific question about having a different room
> description after some event has happened, consider this approach:
>
> ```clojure
> (defn do-important-plot-changing-action [world-state]
>     (-> world-state
>          (update :flags conj :major-plot-point-reached)
>          (assoc-in [:rooms :fancy-room :description] "Gosh! This room isn't
> nearly as fancy anymore!")))
> ```
>
> That is, the function just uses assoc, assoc-in, update, and update-in to
> modify the values in the new map and return it for use in future iterations
> of the game loop. And that's pretty much all there is to it. You just pass
> the changing world state down through the stack rather than mutating it in
> place on the heap. (Ultimately, the world-state data structure is, of
> course, actually stored on the heap, and you are just passing references to
> it through the stack, but I hope you get my meaning here.)
>
> Good luck and happy hacking!
>
> --
> 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.



-- 
Karsten Schmidt
http://postspectacular.com | http://thi.ng | http://toxiclibs.org

On 30 March 2018 at 16:01, Gary Johnson <lambdatro...@gmail.com> wrote:
> Hi Will,
>
> Welcome to the wide world of functional programming, where data flows, and
> functions transmute without destroying their inputs.
>
> As some others in this thread have already suggested, a general approach to
> viewing any problem space from a functional perspective is to imagine your
> problem as a pipeline of data transformations from start to finish. To the
> greatest extent possible, try to represent your data transformations as pure
> functions over immutable arguments rather than holding any global state in a
> var and mutating it at each time step.
>
> In the context of a game program, consider depicting all of your game state
> as a single hierarchical map. Then thread this map through each function and
> return a new derived map as each output result.
>
> ```clojure
> (def world-state {:flags #{}
>                         :location :fancy-room
>                         :inventory #{:sledgehammer :car-keys :lamp}
>                         :rooms {:creepy-corridor {:name "Creepy Corridor"
> :description "Whoa! Spooky..." :items #{:halloween-mask :monkeys-paw
> :troll-doll}}
>                                     :fancy-room {:name "Fancy Room"
> :description "The fanciest!" :items #{:chandelier :toy-poodle
> :looking-glass}}
>                                     ...}})
>
> ```
> Let's imagine this is the initial world state. When your application starts
> up, it enters into the game loop (which would be a nice, friendly recursion,
> of course). In each round of the game loop, you call a sequence of functions
> to get the description of the current room, print it out, ask the user for
> the next command, process that command, and then recurse back to the top of
> the next iteration of the game loop. Although printing to stdout and reading
> from stdin are obviously side effecting functions, you should be able to
> keep your functions for retrieving the room description and processing the
> user's command as pure functions of the current world-state. Just make sure
> that the functions that process a user's command always return a new copy of
> the world-state value. When you want to save the game, just write out the
> world-state to an EDN file. By reading it back in again later, you can
> restore the game to exactly the same state it was in before.
>
> In response to your specific question about having a different room
> description after some event has happened, consider this approach:
>
> ```clojure
> (defn do-important-plot-changing-action [world-state]
>     (-> world-state
>          (update :flags conj :major-plot-point-reached)
>          (assoc-in [:rooms :fancy-room :description] "Gosh! This room isn't
> nearly as fancy anymore!")))
> ```
>
> That is, the function just uses assoc, assoc-in, update, and update-in to
> modify the values in the new map and return it for use in future iterations
> of the game loop. And that's pretty much all there is to it. You just pass
> the changing world state down through the stack rather than mutating it in
> place on the heap. (Ultimately, the world-state data structure is, of
> course, actually stored on the heap, and you are just passing references to
> it through the stack, but I hope you get my meaning here.)
>
> Good luck and happy hacking!
>
> --
> 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.



-- 
Karsten Schmidt
http://thi.ng

-- 
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