now only stores last world in each round when building simulation

also did significant refactoring, including changing
variable names from 'round' to 'combined-world' before
going through the simulation-pass, and 'sim-world' afterwards.

Soon, we'll make the worlds coming out of 'sim-world' a lot less
verbose.
This commit is contained in:
Richard Harrington 2013-08-16 23:26:34 -04:00
parent 9ab14a7653
commit a1df709c4f
5 changed files with 52 additions and 68 deletions

View File

@ -5,16 +5,13 @@
(:require [clj-time.core :as time]
[clj-time.periodic :as periodic]))
(defn build-simulation-rounds [worlds fast-forward]
(let [round-duration (/ *GAME-SECONDS-PER-TICK* fast-forward)
num-robots (count (:robots (nth worlds 0)))
rounds (partition num-robots worlds)]
;(println round-duration num-robots (nth rounds 0))
(map-indexed (fn [idx worlds]
{:worlds worlds
(defn build-sim-worlds [combined-worlds fast-forward]
(let [tick-duration (/ *GAME-SECONDS-PER-TICK* fast-forward)]
(map-indexed (fn [idx combined-world]
{:sim-world combined-world
:idx idx
:timestamp (int (* idx round-duration 1000))})
rounds)))
:timestamp (int (* idx tick-duration 1000))})
combined-worlds)))
(defn near-point [[pos-x pos-y] [x y]]
(and (= (int pos-x) x)
@ -41,43 +38,42 @@
"\n"
header-footer)))
(defn display-robots-info [world]
(doseq [robot-idx (range (count (:robots world)))]
(defn display-robots-info [sim-world idx fps]
(doseq [robot-idx (range (count (:robots sim-world)))]
(println (apply format
"%d: x %.1f, y %.1f, v-x %.1f, v-y %.1f, desired-v-x %.1f, desired-v-y %.1f"
(map #(get-in world [:robots robot-idx %])
[:idx :pos-x :pos-y :v-x :v-y :desired-v-x :desired-v-y])))))
(map #(get-in sim-world [:robots robot-idx %])
[:idx :pos-x :pos-y :v-x :v-y :desired-v-x :desired-v-y]))))
(println (format "Animation frame rate: %.1f frames per second", fps))
(println "Round number:" idx)
(println (format "Seconds elapsed in the game-world: %.1f", (* idx *GAME-SECONDS-PER-TICK*)))
(println))
(defn animate
"takes a simulation and animates it."
[initial-simulation-rounds print-width print-height fps]
[initial-sim-worlds print-width print-height fps]
(let [frame-period (time/millis (* (/ 1 fps) 1000))
starting-instant (time/now)]
(loop [[{:keys [worlds idx]} :as rounds] initial-simulation-rounds
(loop [[{:keys [sim-world idx]} :as sim-worlds] initial-sim-worlds
frame-start starting-instant]
(doseq [world worlds]
(println (arena-text-grid world print-width print-height))
(display-robots-info world)
(println (format "Animation frame rate: %.1f frames per second", fps))
(println "Round number:" idx)
(println (format "Seconds elapsed in the game-world: %.1f", (* idx *GAME-SECONDS-PER-TICK*)))
(println))
(let [desired-next-frame-start (time/plus frame-start frame-period)
(println (arena-text-grid sim-world print-width print-height))
(display-robots-info sim-world idx fps)
(let [desired-next-frame-calc-start (time/plus frame-start frame-period)
this-instant (time/now)
next-frame-start (if (time/after? this-instant desired-next-frame-start)
this-instant
(do
(Thread/sleep (time/in-msecs (time/interval
this-instant
desired-next-frame-start)))
desired-next-frame-start))
next-frame-calc-start (if (time/after? this-instant desired-next-frame-calc-start)
this-instant
(do
(-> (time/interval
this-instant
desired-next-frame-calc-start)
(time/in-msecs)
(Thread/sleep))
desired-next-frame-calc-start))
animation-timestamp (time/in-msecs (time/interval
starting-instant
next-frame-start))]
(recur (drop-while (fn [round]
(< (:timestamp round) animation-timestamp))
rounds)
next-frame-start)))))
next-frame-calc-start))]
(recur (drop-while #(< (:timestamp %) animation-timestamp)
sim-worlds)
next-frame-calc-start)))))

View File

@ -15,12 +15,12 @@
(defn world []
(world/init-world 256.0 256.0 (progs)))
(defn worlds []
(iterate world/tick-world (world)))
(defn simulation-rounds []
(animate/build-simulation-rounds (worlds) 25))
(defn combined-worlds []
(world/build-combined-worlds (world)))
(defn sim-worlds []
(animate/build-sim-worlds (combined-worlds) 25))
(defn make-it-so []
(animate/animate (simulation-rounds) 25 25 20.0))
(animate/animate (sim-worlds) 25 25 20.0))
(def rr register/read-register)
(def wr register/write-register)

View File

@ -11,7 +11,7 @@
(GET "/" [] "Hello World, Welcome to Robotwar.")
(GET "/json-test" [] (response/response {:foo 6 :bar 8}))
(GET "/programs" [] (response/response test-programs/programs))
(GET "/simulations" [] (response/response (take 1 (core/simulation-rounds))))
(GET "/simulations" [] (response/response (take 1 (core/sim-worlds))))
(route/resources "/")
(route/not-found "Not Found"))

View File

@ -18,25 +18,13 @@
:pos-y (rand height)
:aim 0.0
:damage 100.0}))
programs))
:robot-idx 0})
programs))})
(defn tick-world
"TODO: fill this out quite a bit. Dealing with shells, for instance.
We might want to change this to a system where we count by whole rounds
(where each robot gets to go) rather than just a stream of worlds, one for
each robot. Because otherwise, do we step the shells after every
single robot has their turn?"
[{:keys [robots robot-idx] :as world}]
(assoc (robot/step-robot (robots robot-idx) world)
:robot-idx
(mod (inc robot-idx) (count robots))))
(defn tick-combined-world
[starting-world]
(reduce (fn [{robots :robots :as world} robot-idx]
(robot/step-robot (robots robot-idx) world))
starting-world
(range (count (:robots starting-world)))))
(defn get-world
"convenience function for identifying a world in a sequence of worlds
by its round idx (where one round means all the robots have stepped)
and its robot idx."
[round-idx robot-idx worlds]
(let [num-robots (count (:robots (nth worlds 0)))
world-idx (+ (* round-idx num-robots) robot-idx)]
(nth worlds world-idx)))
(def build-combined-worlds (partial iterate tick-combined-world))

View File

@ -9,24 +9,24 @@
(def initial-world
(world/init-world 256.0 256.0 [(:multi-use test-programs/programs)]))
(def worlds (iterate world/tick-world initial-world))
(def combined-worlds (world/build-combined-worlds initial-world))
(deftest branching-test
(testing "comparison statement should cause jump in instr-ptr"
(is (= (get-in (world/get-world 4 0 worlds)
(is (= (get-in (nth combined-worlds 4)
[:robots 0 :brain :instr-ptr])
5))))
(deftest arithmetic-test
(testing "addition"
(is (= (get-in (world/get-world 7 0 worlds)
(is (= (get-in (nth combined-worlds 7)
[:robots 0 :brain :acc])
1))))
(deftest gosub-test
(testing "gosub should move instr-ptr and add the return-ptr to the call stack"
(is (let [{:keys [instr-ptr call-stack]}
(get-in (world/get-world 5 0 worlds)
(get-in (nth combined-worlds 5)
[:robots 0 :brain])]
(= [instr-ptr call-stack]
[9 [6]])))))
@ -34,13 +34,13 @@
(deftest endsub-test
(testing "endsub pops instr-ptr off call stack and goes there"
(is (let [{:keys [instr-ptr call-stack]}
(get-in (world/get-world 9 0 worlds)
(get-in (nth combined-worlds 9)
[:robots 0 :brain])]
(= [instr-ptr call-stack]
[6 []])))))
(deftest push-test
(testing "pushing number to register"
(is (= (get-in (world/get-world 8 0 worlds)
(is (= (get-in (nth combined-worlds 8)
[:robots 0 :brain :registers "A" :val])
1))))