diff --git a/src/robotwar/register.clj b/src/robotwar/register.clj index ae82f7f..30b2883 100644 --- a/src/robotwar/register.clj +++ b/src/robotwar/register.clj @@ -20,73 +20,80 @@ (defn path-to-val [robot-idx reg-name] [:robots robot-idx :registers reg-name :val]) -(defprotocol IRegister - (read-register [this world]) +(defprotocol IReadRegister + "returns the value of a register" + (read-register [this world])) + +(defprotocol IWriteRegister + "returns a world" (write-register [this world data])) -(defrecord StorageRegister [robot-idx reg-name val] - IRegister - (read-register - "returns value stored in register" - [this world] - val) - (write-register - "returns world with value in register altered" - [this world data] - (assoc-in world (path-to-val robot-idx reg-name) data))) +(def default-read-mixin + ; returns :val field of register + {:read-register (fn [this world] + (:val this))}) -(defrecord ReadOnlyRegister [robot-idx field-name] - IRegister - (read-register - "returns the value in a particular robot field" - [this world] - (get-in world (conj (path-to-robot robot-idx) field-name))) - (write-register - "has no effect (returns the world it was given)" - [this world data] - world)) +(def default-write-mixin + ; returns a world with :val field of register altered + {:write-register (fn [this world data] + (assoc-in world + (path-to-val (:robot-idx this) (:reg-name this)) + data))}) -(defn target-register +(def robot-field-read-mixin + ; returns the value of a field in the robot hash-map + {:read-register (fn [this world] + (get-in world (conj path-to-robot (:field-name this))))}) + +(def no-op-write-mixin + ; returns a world with nothing changed + {:write-register (fn [this world data] + world)}) + +(def random-read-mixin + ; returns a random number. maximum value is the :val field of the register + {:read-register (fn [this world] + (rand-int (:val this)))}) + +(defrecord StorageRegister [robot-idx reg-name val]) +(extend StorageRegister + IReadRegister default-read-mixin + IWriteRegister default-write-mixin) + +(defrecord ReadOnlyRegister [robot-idx field-name]) +(extend ReadOnlyRegister + IReadRegister robot-field-read-mixin + IWriteRegister no-op-write-mixin) + +(defrecord RandomRegister [robot-idx reg-name val]) +(extend RandomRegister + IReadRegister random-read-mixin + IWriteRegister default-write-mixin) + +(defn get-target-register "helper function for DataRegister record" [world robot-idx index-reg-name] (let [registers (get-in world (path-to-registers robot-idx))] (registers (reg-names (read-register (registers index-reg-name) world))))) (defrecord DataRegister [robot-idx index-reg-name] - IRegister + IReadRegister (read-register - "returns the number stored in whatever register - is pointed to by the index-reg-name register" + ; returns the number stored in whatever register + ; is pointed to by the index-reg-name register [this world] - (read-register (target-register world robot-idx index-reg-name) world)) + (read-register (get-target-register world robot-idx index-reg-name) world)) + IWriteRegister (write-register - "returns a world with the number in the register pointed to - by the index-reg-name register updated with the data argument to write-register" + ; returns a world with the number in the register pointed to + ; by the index-reg-name register updated with the data argument to write-register [this world data] - (write-register (target-register world robot-idx index-reg-name) world data))) - -; TODO: (defrecord RandomRegister [robot-idx reg-name max-rand]) + (write-register (get-target-register world robot-idx index-reg-name) world data))) ; TODO: (defrecord ShotRegister [robot-idx reg-name]) ; TODO: (defrecord RadarRegister [robot-idx reg-name]) -; ; RANDOM -; (init-register "RANDOM" robot-idx -; (fn [world path-to-val] -; (rand-int (get-in world path-to-val))) -; assoc-in -; 0) -; -; ; X and Y and DAMAGE -; (init-read-only-register "X" robot-idx :pos-x (:pos-x attributes)) -; (init-read-only-register "Y" robot-idx :pos-y (:pos-y attributes)) -; (init-read-only-register "DAMAGE" robot-idx :damage (:damage attributes))]))) -; -; ; TODO: SHOT AND RADAR - - - (defn init-registers "AIM, INDEX, SPEEDX and SPEEDY. AIM and INDEX's specialized behaviors are only when they're used by @@ -104,7 +111,7 @@ {"Y" (->ReadOnlyRegister robot-idx :pos-y)} {"DAMAGE" (->ReadOnlyRegister robot-idx :damage)} {"DATA" (->DataRegister robot-idx "INDEX")} - ; TODO: {"RANDOM" (->RandomRegister robot-idx "RANDOM" 0)} + {"RANDOM" (->RandomRegister robot-idx "RANDOM" 0)} ; TODO: {"SHOT" (->ShotRegister robot-idx "SHOT")} ; TODO: {"RADAR" (->RadarRegister robot-idx "RADAR")} ]))))