106 lines
3.3 KiB
Clojure
106 lines
3.3 KiB
Clojure
(ns advent.action-test2
|
|
(:require [clojure.core.async :refer [put! <! <!! >! chan go thread 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)))
|
|
|
|
(defmacro get-script [& forms]
|
|
`(fn [action-channel#] (thread ~@forms (put! action-channel# :end))))
|
|
|
|
(defn run-script [state action-channel]
|
|
(let [random-loc (+ 3 (rand-int 10))]
|
|
(get-script
|
|
(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."))))))
|
|
|
|
(defn test-run []
|
|
(let [state {:x 0 :y 0 :time 0 :items #{} :current-action nil}
|
|
action-channel (chan)
|
|
script (run-script state action-channel)
|
|
]
|
|
(script 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))))))))
|