From a32058babd5a1ad1e3a00c9145d340564ea7393d Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Tue, 5 Mar 2013 23:14:20 -0500 Subject: [PATCH] Initial commit with working gamestate + indexing. --- .gitignore | 8 +++++ README | 13 +++++++++ project.clj | 3 ++ src/hottub/gs.clj | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 .gitignore create mode 100644 README create mode 100644 project.clj create mode 100644 src/hottub/gs.clj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..114e85a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/pom.xml +*jar +/lib +/classes +/native +/.lein-failures +/checkouts +/.lein-deps-sum diff --git a/README b/README new file mode 100644 index 0000000..dd2a275 --- /dev/null +++ b/README @@ -0,0 +1,13 @@ +# hottub + +FIXME: write description + +## Usage + +FIXME: write + +## License + +Copyright (C) 2013 FIXME + +Distributed under the Eclipse Public License, the same as Clojure. diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..5cf403d --- /dev/null +++ b/project.clj @@ -0,0 +1,3 @@ +(defproject hottub "1.0.0-SNAPSHOT" + :description "Hot Tub Time Machine Game Engine" + :dependencies [[org.clojure/clojure "1.5.0"]]) \ No newline at end of file diff --git a/src/hottub/gs.clj b/src/hottub/gs.clj new file mode 100644 index 0000000..2abd84c --- /dev/null +++ b/src/hottub/gs.clj @@ -0,0 +1,74 @@ +(ns hottub.gs) + +(defmulti update-index (fn [indextype indexold id entityold entitynew] indextype)) +(defmulti query-index (fn [indextype index query] indextype)) + + +(def gs-empty {:entities {} :indices {} :id-lim 0}) + +(def ^:dynamic *gamestate* (ref gs-empty)) +(defn gen-id [] + (let [id (:id-lim @*gamestate*)] + (ref-set *gamestate* (assoc @*gamestate* :id-lim (+ id 1))) + id)) + +(defmacro with-gs [gs & body] + `(binding [*gamestate* (ref ~gs)] (dosync ~@body))) + +(defn get-gs [] @*gamestate*) + +(defn entity [id] (get-in @*gamestate* [:entities id])) + +(defn- update-indices [id entityold entitynew] + (ref-set *gamestate* + (loop [gs @*gamestate* indextypes (keys (:indices gs))] + (if (seq indextypes) + (let [indextype (first indextypes) + indexold (get-in gs [:indices indextype]) + indexnew (update-index indextype indexold id entityold entitynew) + gsnew (assoc-in gs [:indices indextype] indexnew)] + (recur gsnew (next indextypes))) + gs)))) + +(defn add-index [indextype] + (ref-set *gamestate* + (loop [index {} ids (keys (:entities @*gamestate*))] + (if (seq ids) + (let [id (first ids) + indexnew (update-index indextype index id nil (entity id))] + (recur indexnew (next ids))) + (assoc-in @*gamestate* [:indices indextype] index))))) + +(defn remove-id-from-index [index id key] + (if-let [idsbefore (get index key)] + (let [idsafter (disj idsbefore id)] + (if (empty? idsafter) + (dissoc index key) + (assoc index key idsafter))) + index)) + +(defn add-id-to-index [index id key] + (if-let [idsbefore (get index key)] + (assoc index key (conj idsbefore id)) + (if key + (assoc index key #{id}) + index))) + +(defn set-entity [id value] + (update-indices id (entity id) value) + (let [gsnew + (if (= value nil) + (assoc @*gamestate* :entities (dissoc (get @*gamestate* :entities) id)) + (assoc-in @*gamestate* [:entities id] value))] + (ref-set *gamestate* gsnew))) + +(defn q [indextype query] + (query-index indextype (get-in @*gamestate* [:indices indextype]) query)) + +(defmethod update-index :name [indextype indexold id entityold entitynew] + (-> indexold + (remove-id-from-index id (get entityold :name)) + (add-id-to-index id (get entitynew :name)))) + +(defmethod query-index :name [indextype index query] (or (get index query) #{})) +