You can try using the in-memory version of Datomic.

Besides keeping track of the state at every point, it can help with
the reasoning about what should happen next for each state change.


On Sun, Apr 15, 2012 at 11:25 PM, Nicolas Buduroi <nbudu...@gmail.com> wrote:
> I'm working on a turn-based game and I'm looking for a good way to manage
> states. In the game each turn is composed of multiple phases. I started by
> using atoms for the phases field (this is a sequence of functions) in a
> record and realized that it wouldn't be ideal to keep track of states in the
> case where I'd need to keep a snapshot of every phases. Here's the original
> code I had:
>
> (defrecord Game [phases]
>   (next-phase [this]
>     (stop-timer)
>     (swap! phases #(conj (vec (rest %)) (first %)))
>     (log :info "change phase to %s" (key (first @phases)))
>     (start-phase this))
>
> I then started to think that this would be a good opportunity to use a state
> monad. I've tried to reimplement the above code using the algo.monads
> library but the result was less than satisfactory (probably due to my own
> shortcoming), here's the monadic version:
>
> (defrecord Game [phases]
>
>   (next-phase [this]
>     (->
>      ((domonad state-m
>         [_ (fn [s] (stop-timer) [s s])
>          _ (update-state
>             (fn [s]
>               (update-in s [:phases]
>                          #(conj (vec (rest %)) (first %)))))
>          _ (fn [s]
>              (log :info "change phase to %s" (key (first (:phases s)))) [s
> s])]
>         nil)
>       state)
>      second
>      start-phase))
>
> As my code probably doesn't need the full power of the state monad, I tried
> to write a lighter-weight version using the following macro:
>
> (defmacro >> [& state-and-forms]
>   (reduce #(list (if ('#{fn fn*} (first %2))
>                    %2
>                    `(fn [s#] ~%2 s#)) %)
>           state-and-forms))
>
> Which let me write:
>
>   (next-phase [state]
>     (>> state
>      (stop-timer)
>      (fn [s] (update-in s [:phases] #(conj (vec (rest %)) (first %))))
>      #(do (log :info "change phase to %s" (key (first (:phases %)))) %)
>      #(start-phase %)))
>
> With some more helper macro this version looks promising. In the end I
> wonder if there's some Clojure feature I'm overlooking or if I should
> rethink the whole solution? Is there a better way to accomplish this?
>
>
> --
> 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 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

Reply via email to