mirror of
https://github.com/richardharrington/robotwar.git
synced 2024-08-20 02:29:35 +00:00
living on hope
This commit is contained in:
parent
08dcf38214
commit
4a8f83ad95
@ -13,23 +13,53 @@
|
|||||||
(-> op read-string eval)))
|
(-> op read-string eval)))
|
||||||
op-commands)))
|
op-commands)))
|
||||||
|
|
||||||
|
(defn init-internal-state
|
||||||
|
"initialize all the internal state variables that go along
|
||||||
|
with the robot program when it's running.
|
||||||
|
(Optionally, also pass in a hash-map of register names and values,
|
||||||
|
which will override the defaults)."
|
||||||
|
[program reg-names & [registers]]
|
||||||
|
{:registers (into {} (concat
|
||||||
|
(for [reg-name reg-names]
|
||||||
|
; default values for :read, :write and :data. (TODO: move these into a higher-level module)
|
||||||
|
; NOTE: the default version of the :read function does not need the world-state parameter.
|
||||||
|
[reg-name {:read (fn [data _] data)
|
||||||
|
:write (fn [robot data]
|
||||||
|
(assoc-in robot [:internal-state :registers reg-name] data))
|
||||||
|
:data 0}])
|
||||||
|
registers))
|
||||||
|
:program program
|
||||||
|
:acc 0
|
||||||
|
:instr-ptr 0
|
||||||
|
:call-stack []})
|
||||||
|
|
||||||
|
(defn read-register
|
||||||
|
"returns a numeric value"
|
||||||
|
[{:keys [read data] :as register} world]
|
||||||
|
(read data world))
|
||||||
|
|
||||||
|
(defn write-register
|
||||||
|
"returns a full robot state, including its external state and its internal brain state.
|
||||||
|
TODO: implement extra flag to indicate if we've fired a shot."
|
||||||
|
[robot {write :write :as register} data]
|
||||||
|
(write robot data))
|
||||||
|
|
||||||
(defn resolve-register [registers reg]
|
(defn resolve-register [registers reg]
|
||||||
(case reg
|
(case reg
|
||||||
"RANDOM" (rand-int (registers reg))
|
"RANDOM" (rand-int (registers reg))
|
||||||
"DATA" (registers (reg-names (registers "INDEX")))
|
"DATA" (registers (reg-names (registers "INDEX")))
|
||||||
(registers reg)))
|
(registers reg)))
|
||||||
|
|
||||||
(defn resolve-arg [{arg-val :val arg-type :type} registers labels]
|
(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).
|
||||||
|
If it's reading from a register, uses that register's :read function."
|
||||||
(case arg-type
|
(case arg-type
|
||||||
:label (labels arg-val)
|
:label (labels arg-val)
|
||||||
:number arg-val
|
:number arg-val
|
||||||
:register (resolve-register registers arg-val)
|
:register (read-register (registers arg-val) world)
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(def registers-with-effect-on-world #{"SHOT" "RADAR" "SPEEDX" "SPEEDY"})
|
|
||||||
|
|
||||||
(defn tick-robot
|
(defn tick-robot
|
||||||
"takes as input a data structure representing all that the robot's brain
|
"takes as input a data structure representing all that the robot's brain
|
||||||
needs to know about the world:
|
needs to know about the world:
|
||||||
@ -47,36 +77,26 @@
|
|||||||
plus an optional :action field, to notify the world if the SHOT, SPEEDX, SPEEDY or RADAR
|
plus an optional :action field, to notify the world if the SHOT, SPEEDX, SPEEDY or RADAR
|
||||||
registers have been pushed to."
|
registers have been pushed to."
|
||||||
|
|
||||||
[{:keys [acc instr-ptr call-stack registers program] :as state}]
|
[robot world]
|
||||||
(let [[{command :val} {unresolved-arg-val :val :as arg}] ((program :instrs) instr-ptr)
|
(let [internal-state (:internal-state robot)
|
||||||
resolve #(resolve-arg % registers (program :labels))]
|
{:keys [acc instr-ptr call-stack registers program]} internal-state
|
||||||
|
[{command :val} {unresolved-arg-val :val :as arg}] ((program :instrs) instr-ptr)
|
||||||
|
resolve #(resolve-arg % registers (program :labels) world)
|
||||||
|
return-robot #(assoc robot :internal-state (into internal-state %))]
|
||||||
(case command
|
(case command
|
||||||
"GOTO" (into state {:instr-ptr (resolve arg)})
|
"GOTO" (return-robot {:instr-ptr (resolve arg)})
|
||||||
"GOSUB" (into state {:instr-ptr (resolve arg)
|
"GOSUB" (return-robot {:instr-ptr (resolve arg)
|
||||||
:call-stack (conj call-stack (inc instr-ptr))})
|
:call-stack (conj call-stack (inc instr-ptr))})
|
||||||
"ENDSUB" (into state {:instr-ptr (peek call-stack)
|
"ENDSUB" (return-robot {:instr-ptr (peek call-stack)
|
||||||
:call-stack (pop call-stack)})
|
:call-stack (pop call-stack)})
|
||||||
("IF", ",") (into state {:instr-ptr (inc instr-ptr)
|
("IF", ",") (return-robot {:instr-ptr (inc instr-ptr)
|
||||||
:acc (resolve arg)})
|
:acc (resolve arg)})
|
||||||
("+" "-" "*" "/") (into state {:instr-ptr (inc instr-ptr)
|
("+" "-" "*" "/") (return-robot {: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))
|
||||||
(into state {:instr-ptr (inc instr-ptr)})
|
(return-robot {:instr-ptr (inc instr-ptr)})
|
||||||
(into state {:instr-ptr (+ instr-ptr 2)}))
|
(return-robot {:instr-ptr (+ instr-ptr 2)}))
|
||||||
"TO" (let [return-state (into state {:instr-ptr (inc instr-ptr)
|
"TO" (write-register (return-robot {:instr-ptr (inc instr-ptr)})
|
||||||
:registers (into registers {unresolved-arg-val acc})})]
|
(registers unresolved-arg-val)
|
||||||
(if (registers-with-effect-on-world unresolved-arg-val)
|
acc))))
|
||||||
(conj return-state {:action unresolved-arg-val})
|
|
||||||
return-state)))))
|
|
||||||
|
|
||||||
(defn init-robot-state
|
|
||||||
"initialize all the state variables that go along
|
|
||||||
with the robot program when it's running.
|
|
||||||
(Optionally, pass in a hash-map of register names and values)."
|
|
||||||
[program reg-names & [registers]]
|
|
||||||
{:program program
|
|
||||||
:acc 0
|
|
||||||
:instr-ptr 0
|
|
||||||
:registers (into (zipmap reg-names (repeat 0))
|
|
||||||
registers)
|
|
||||||
:call-stack []})
|
|
||||||
|
Loading…
Reference in New Issue
Block a user