lsund
lsund

Reputation: 744

Artificial time implementation in clojure

I know that it's usually a good idea to keep away from state when programming clojure. However, time seems to me something very stateful.

My goal is to represent time in my game I am writing in clojure. My idea was to run a timer as a seperate process and read its value whenever needed but there doesn't seem to be any natural way of acheiving this in clojure.

How would you implement time in a simple roleplaying game in clojure?

Upvotes: 0

Views: 184

Answers (2)

fl00r
fl00r

Reputation: 83680

Timer is pretty stateless. Actually timer is a point in time in which it started.

I will use clj-time here for simplicity.

(require '[clj-time.core :as t]
         '[clj-time.coerce :as c])

(defn timer
  []
  (let [now-sec #(-> (t/now) c/to-long (/ 1000) int)
        start (now-sec)]
    #(- (now-sec) start)))

(def my-timer (timer))
;; after a second
(my-timer)
;;=> 1
;; and after 2 seconds more
(my-timer)
;;=> 3

Upvotes: 2

WolfeFan
WolfeFan

Reputation: 1447

I've adapted the code from this Java answer into my date-dif function:

(defn date-dif [d1 d2]
  (let [tu java.util.concurrent.TimeUnit/SECONDS
        t1 (. d1 getTime)
        t2 (. d2 getTime)]
    (. tu convert (- t2 t1) java.util.concurrent.TimeUnit/MILLISECONDS)))

(defn start-timer []
  (let [cur-time (new java.util.Date)]
    (fn [] (date-dif cur-time (new java.util.Date)))))

start-timer will create and return a function that, when called, returns the number of seconds since the function was created. To use it, do something like this:

rpg-time.core> (def my-timer (start-timer))
#'rpg-time.core/my-timer
rpg-time.core> (my-timer)
3
rpg-time.core> (my-timer)
5
rpg-time.core> (my-timer)
6

If you want a different unit of time, instead of seconds, replace SECONDS with something more appropriate from here.

There are certainly other options you can consider. This is just the first one I thought of, and it isn't very hard to code or use.

Upvotes: 2

Related Questions