Files
gitea-docker/desktop/src-common/advent/action_test2.clj
2014-09-12 23:51:27 -07:00

102 lines
3.1 KiB
Clojure

(ns advent.action-test2
(:require [clojure.core.async :refer [put! <! <!! >! chan go take! alts!!]]))
(defprotocol IAction
(begin [this state])
(done? [this state])
(continue [this state])
(terminate [this state]))
(defmacro do-actions [name & forms]
`(vector ~@(for [form forms]
`(fn [~name]
~form))))
(defn talk [action-channel who text]
(let [c (chan)]
(put! action-channel
(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))
(terminate [this state]
(put! c state)
state)))
c))
(defn give-item [action-channel item]
(let [c (chan)]
(put! action-channel
(reify
IAction
(begin [this state]
(println "Receiving item:" item)
(update-in state [:items] #(conj % item)))
(continue [this state]
state)
(done? [this state]
true)
(terminate [this state]
(put! c state)
state)))
c))
(defn walk-to [action-channel who & targets ]
(let [c (chan)]
(doseq [[target-x target-y] targets]
(put! action-channel
(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)))
(terminate [this state]
(put! c state)
state))))
c))
(defn run-script [state action-channel]
(let [random-loc (+ 3 (rand-int 10))]
(go
(if (= 1 (rand-int 2))
(<! (give-item action-channel :gold))
(<! (give-item action-channel :candy)))
(let [state (<! (walk-to action-channel :ego [3 3] [random-loc random-loc] ))]
(if ((:items state) :gold)
(<! (talk action-channel :ego "I have enough money to buy something"))
(<! (talk action-channel :ego "I'm broke."))))
(>! action-channel :end))))
(defn test-run []
(let [state {:x 0 :y 0 :time 0 :items #{} :current-action nil}
action-channel (chan)
actions (run-script state action-channel)]
(loop [state state
current-action nil
started? false]
(if (= :end current-action)
nil
(if current-action
(let [state (if started? state (begin current-action state))
state (continue current-action state)]
(if (done? current-action state)
(recur (terminate current-action state) nil false)
(recur state current-action true)))
(let [[current-action _] (alts!! [action-channel] :default nil)]
(do (Thread/sleep 50)
(recur state current-action false))))))))