Reputation: 676
I'm trying my hand at a text adventure in clojure.
This is where I am struggling:
(ns records)
(defrecord Room [fdesc sdesc ldesc exit seen])
(defrecord Item [name location adjective fdesc ldesc sdesc flags action ])
(def bedroom (Room. "A lot of text."
nil
"some text"
'(( "west" hallway wearing-clothes? wear-clothes-f))
false))
(def hallway (Room. "description of room."
nil
"short desc of room."
'(("east" bedroom) ("west" frontdoor))
false))
(def location (ref bedroom))
(defn in?
"Check if sequence contains item."
[item lst]
(some #(= item %) lst))
(defn next-location
"return the location for a entered direction"
[direction ]
(second (first (filter #(in? direction %) (:exit @location)))))
(defn set-new-location
"set location parameter to new location."
[loc]
(dosync (ref-set location loc)))
My problem is with updating the var location.
If I enter (set-new-location hallway)
it works correctly. Location is set to the new room and I can access its fields. However, what I need to do is read the next possible exit from the exit field of a room, but when I enter (set-new-direction (next-exit "west"))
location says hallway, but it doesn't point to the variable "hallway".
In CL I'd use (symbol-value hallway). How can I do this in Clojure?
EDIT: I really want to use var-per-location because I have sketched out roughly 30 locations, at 20 lines each, making it too unwieldy to put in one map.
Upvotes: 1
Views: 633
Reputation: 84331
You can use @(resolve sym)
as a symbol-value
workalike; what it actually does is look up the Var named by the symbol sym
in the current namespace (might be a Var brought in with use
/ require :refer
) and extract its value. See ns-resolve
if you want to control the namespace the Var is looked up in.
You could also not use Var-per-location, but rather store your locations in a map somewhere:
(def locations {:hallway ... :bedroom ...})
(You could also put this map in a Ref for convenience of adding new locations at runtime.)
Upvotes: 3