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.