mirror of
https://github.com/richardharrington/robotwar.git
synced 2024-07-15 16:29:35 +00:00
even more gruesome refactoring
This commit is contained in:
parent
9112c82dc6
commit
134d5ac439
@ -10,21 +10,28 @@
|
|||||||
(-> op read-string eval)))
|
(-> op read-string eval)))
|
||||||
op-commands)))
|
op-commands)))
|
||||||
|
|
||||||
(defn init-register [reg-name read write data]
|
(defn init-register [reg-name read-func write-func data]
|
||||||
{reg-name {:read read
|
"the read function should take a world and return a value.
|
||||||
:write write
|
the write function should take a world and a value and return
|
||||||
:data data}})
|
a new world."
|
||||||
|
{reg-name {:read read-func
|
||||||
|
:write write-func
|
||||||
|
:val data}})
|
||||||
|
|
||||||
(defn default-read [data world]
|
(defn read-register
|
||||||
data)
|
"wrapper for the read function in each register. takes a register
|
||||||
|
and also takes world state, because
|
||||||
|
some of those functions may need access to the world state.
|
||||||
|
returns a numeric value."
|
||||||
|
[{read :read} world]
|
||||||
|
(read world))
|
||||||
|
|
||||||
(defn default-write [robot data]
|
(defn write-register
|
||||||
(assoc-in robot [:brain :registers reg-name] data))
|
"wrapper for the write function in each register.
|
||||||
|
takes a register, a robot, a world, and the data to write.
|
||||||
(def default-data 0)
|
returns a full world."
|
||||||
|
[{write :write} world data]
|
||||||
(defn default-register [reg-name]
|
(write world data))
|
||||||
(init-register reg-name default-read default-write default-data))
|
|
||||||
|
|
||||||
(defn init-brain
|
(defn init-brain
|
||||||
"initialize the brain (meaning all the internal state variables that go along
|
"initialize the brain (meaning all the internal state variables that go along
|
||||||
@ -38,22 +45,6 @@
|
|||||||
:program program
|
:program program
|
||||||
:registers (into {} (concat (map default-register reg-names) registers))})
|
:registers (into {} (concat (map default-register reg-names) registers))})
|
||||||
|
|
||||||
(defn read-register
|
|
||||||
"wrapper for the read function in each register. takes a register
|
|
||||||
and also takes world state, because
|
|
||||||
some of those functions may need access to the world state.
|
|
||||||
returns a numeric value."
|
|
||||||
[{:keys [read data] :as register} world]
|
|
||||||
(read data world))
|
|
||||||
|
|
||||||
(defn write-register
|
|
||||||
"wrapper for the write function in each register.
|
|
||||||
takes a robot, a register, and the data to write.
|
|
||||||
returns a full robot (brain and external properties as well).
|
|
||||||
TODO: implement extra flag to indicate if we've fired a shot."
|
|
||||||
[robot {write :write :as register} data]
|
|
||||||
(write robot data))
|
|
||||||
|
|
||||||
(defn resolve-arg [{arg-val :val arg-type :type} registers labels world]
|
(defn resolve-arg [{arg-val :val arg-type :type} registers labels world]
|
||||||
"resolves an instruction argument to a numeric value
|
"resolves an instruction argument to a numeric value
|
||||||
(either an arithmetic or logical comparison operand, or an instruction pointer)."
|
(either an arithmetic or logical comparison operand, or an instruction pointer)."
|
||||||
@ -63,38 +54,38 @@
|
|||||||
:register (read-register (registers arg-val) world)
|
:register (read-register (registers arg-val) world)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(defn tick-brain
|
(defn step-brain
|
||||||
"takes a full robot. Only the internal state (the brain) will be
|
"takes a robot index and a world. Returns a world.
|
||||||
different when we pass it back, for all of the operations except 'TO',
|
|
||||||
which may alter the external state of the robot as well. (And for the time
|
|
||||||
being, shots fired will be indicated with a flag in the robot.)
|
|
||||||
|
|
||||||
Also takes a 'world' parameter, which may contain information that some of the
|
Read functions may or may not need anything except the brain.
|
||||||
registers' read functions may need. Will not be passed out in the return value.
|
|
||||||
|
|
||||||
TODO: Figure out a way to have this function not know about the external robot stuff,
|
Only the brain (the internal state of the robot)
|
||||||
|
will be different when we pass it back, for all of the operations
|
||||||
|
except 'TO', which may also alter the external state of the robot, or the wider world.
|
||||||
|
|
||||||
|
TODO: Figure out a way to have this function not know about the external stuff,
|
||||||
like that the name of the field leading to the brain is :brain."
|
like that the name of the field leading to the brain is :brain."
|
||||||
|
|
||||||
[robot world]
|
[robot-idx world]
|
||||||
(let [brain (:brain robot)
|
(let [{brain :brain :as robot} ((:robots world) robot-idx)
|
||||||
{:keys [acc instr-ptr call-stack registers program]} brain
|
{:keys [acc instr-ptr call-stack registers program]} brain
|
||||||
[{command :val} arg] ((:instrs program) instr-ptr)
|
[{command :val} arg] ((:instrs program) instr-ptr)
|
||||||
resolve #(resolve-arg % registers (:labels program) world)
|
resolve #(resolve-arg % registers (:labels program) world)
|
||||||
return-robot #(assoc robot :brain (into brain %))]
|
into-world-brain #(assoc-in world [:robots robot-idx :brain] (into brain %))]
|
||||||
(case command
|
(case command
|
||||||
"GOTO" (return-robot {:instr-ptr (resolve arg)})
|
"GOTO" (into-world-brain {:instr-ptr (resolve arg)})
|
||||||
"GOSUB" (return-robot {:instr-ptr (resolve arg)
|
"GOSUB" (into-world-brain {:instr-ptr (resolve arg)
|
||||||
:call-stack (conj call-stack (inc instr-ptr))})
|
:call-stack (conj call-stack (inc instr-ptr))})
|
||||||
"ENDSUB" (return-robot {:instr-ptr (peek call-stack)
|
"ENDSUB" (into-world-brain {:instr-ptr (peek call-stack)
|
||||||
:call-stack (pop call-stack)})
|
:call-stack (pop call-stack)})
|
||||||
("IF", ",") (return-robot {:instr-ptr (inc instr-ptr)
|
("IF", ",") (into-world-brain {:instr-ptr (inc instr-ptr)
|
||||||
:acc (resolve arg)})
|
:acc (resolve arg)})
|
||||||
("+" "-" "*" "/") (return-robot {:instr-ptr (inc instr-ptr)
|
("+" "-" "*" "/") (into-world-brain {:instr-ptr (inc instr-ptr)
|
||||||
:acc ((op-map command) acc (resolve arg))})
|
:acc ((op-map command) acc (resolve arg))})
|
||||||
("=" ">" "<" "#") (if ((op-map command) acc (resolve arg))
|
("=" ">" "<" "#") (if ((op-map command) acc (resolve arg))
|
||||||
(return-robot {:instr-ptr (inc instr-ptr)})
|
(into-world-brain {:instr-ptr (inc instr-ptr)})
|
||||||
(return-robot {:instr-ptr (+ instr-ptr 2)}))
|
(into-world-brain {:instr-ptr (+ instr-ptr 2)}))
|
||||||
"TO" (write-register (return-robot {:instr-ptr (inc instr-ptr)})
|
"TO" (write-register (into-world-brain {:instr-ptr (inc instr-ptr)})
|
||||||
(registers (:val arg))
|
(registers (:val arg))
|
||||||
acc))))
|
acc))))
|
||||||
|
|
||||||
|
@ -20,6 +20,62 @@
|
|||||||
; A BIT CLEARER. THE NAMES CAN BE SHORTENED QUITE A BIT,
|
; A BIT CLEARER. THE NAMES CAN BE SHORTENED QUITE A BIT,
|
||||||
; WHEN LOADED INTO THE MODULES.
|
; WHEN LOADED INTO THE MODULES.
|
||||||
|
|
||||||
|
(defn make-default-read [register]
|
||||||
|
"takes a register and returns the default version of its :read function,
|
||||||
|
which ignores the `world` parameter and just returns
|
||||||
|
the :val field from the register."
|
||||||
|
(fn [_]
|
||||||
|
(:val register)))
|
||||||
|
|
||||||
|
(defn make-default-write [robot-idx reg-name]
|
||||||
|
"takes a robot-idx and a reg-name to locate a register, and
|
||||||
|
returns the default version of that register's :write function,
|
||||||
|
which takes a world parameter and a data value and returns the
|
||||||
|
world with the data value assoc'd into it."
|
||||||
|
(fn [world data]
|
||||||
|
(assoc-in world [:robots robot-idx :registers reg-name :val] data)))
|
||||||
|
|
||||||
|
(def default-data 0)
|
||||||
|
|
||||||
|
(defn default-register [robot-idx reg-name]
|
||||||
|
(init-register
|
||||||
|
reg-name
|
||||||
|
|
||||||
|
|
||||||
|
(defn init-robot
|
||||||
|
[program x y]
|
||||||
|
{:pos-x x
|
||||||
|
:pos-y y
|
||||||
|
:veloc-x 0
|
||||||
|
:veloc-y 0
|
||||||
|
:accel-x 0
|
||||||
|
:accel-y 0
|
||||||
|
:damage 100
|
||||||
|
:
|
||||||
|
[let [special-registers
|
||||||
|
[init-register "X" default-
|
||||||
|
|
||||||
|
(defn init-world
|
||||||
|
"initialize all the variables for a robot world"
|
||||||
|
[width height programs]
|
||||||
|
{:width width
|
||||||
|
:height height
|
||||||
|
:shells []
|
||||||
|
:robots (vec (map-indexed (fn [idx program]
|
||||||
|
{:brain (init-brain
|
||||||
|
program
|
||||||
|
reg-names
|
||||||
|
{(init-register "X"
|
||||||
|
default-read
|
||||||
|
default-write
|
||||||
|
(rand-int width))
|
||||||
|
(init-register "Y"
|
||||||
|
default-read
|
||||||
|
default-write
|
||||||
|
(rand-int height))})
|
||||||
|
:icon (str idx)})
|
||||||
|
programs))})
|
||||||
|
|
||||||
(defn tick-robot
|
(defn tick-robot
|
||||||
[robot world]
|
[robot world]
|
||||||
(let [ticked (tick-brain robot world)]
|
(let [ticked (tick-brain robot world)]
|
||||||
|
Loading…
Reference in New Issue
Block a user