102 lines
3.1 KiB
Clojure
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))))))))
|