(ns advent.action-test) (defprotocol IAction (begin [this state]) (done? [this state]) (continue [this state])) (defmacro do-actions [name & forms] `(vector ~@(for [form forms] `(fn [~name] ~form)))) (defn walk-to [who & targets ] (for [[target-x target-y] targets] (fn [state] (reify IAction (begin [this state] (println "Starting Walking") state) (continue [this {:keys [x y] :as state}] (println "Continue Walking from" x y) (Thread/sleep 500) (assoc state :x (inc x) :y (inc y))) (done? [this {:keys [x y]} ] (and (= x target-x) (= y target-y))))))) (defn talk [who text] (reify IAction (begin [this state] (println "Speaking:" text) (assoc state :time 0)) (continue [this state] (Thread/sleep 200) (assoc state :time (inc (:time state)))) (done? [this {:keys [time]}] (< 3 time)))) (defn give-item [item] (reify IAction (begin [this state] (println "Receiving item:" item) (update-in state [:items] #(conj % item))) (continue [this state] state) (done? [this state] true))) (defn walk-to [who & targets ] (for [[target-x target-y] targets] (fn [state] (reify IAction (begin [this state] (println "Starting Walking to" target-x target-y) state) (continue [this {:keys [x y] :as state}] (println "Continue Walking from" x y) (Thread/sleep 500) (assoc state :x (inc x) :y (inc y))) (done? [this {:keys [x y]} ] (and (>= x target-x) (>= y target-y))))))) (defn get-script [] (let [random-loc (+ 3 (rand-int 10))] (do-actions state (if (= 1 (rand-int 2)) (give-item :gold) (give-item :candy)) (walk-to :ego [3 3] [random-loc random-loc] ) (if ((:items state) :gold) (talk :ego "I have enough money to buy something") (talk :ego "I'm broke."))))) (defn test-run [] (let [state {:x 0 :y 0 :time 0 :items #{}} actions (get-script)] (loop [actions actions state state started? false] (when (seq actions) (let [step ((first actions) state)] (if (sequential? step) (recur (concat step (rest actions)) state false) (let [state (if started? state (begin step state)) state (continue step state)] (if (done? step state) (recur (rest actions) state false) (recur actions state true)))))))))