Files
gitea-docker/desktop/src-common/advent/action_test2.clj
2014-09-15 12:50:35 -07:00

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))))))))