rlm@162: (ns com.aurellem.gb.moves rlm@162: (:use (com.aurellem.gb gb-driver util constants)) rlm@162: (:import [com.aurellem.gb.gb_driver SaveState])) rlm@162: rlm@162: (def move-code->move-name rlm@162: { rlm@190: 0x00 :end-of-moves rlm@162: 0x01 :pound rlm@162: 0x02 :karate-chop rlm@162: 0x03 :doubleslap rlm@162: 0x04 :comet-punch rlm@162: 0x05 :mega-punch rlm@162: 0x06 :pay-day rlm@162: 0x07 :fire-punch rlm@162: 0x08 :ice-punch rlm@162: 0x09 :thunderpunch rlm@162: 0x0A :scratch rlm@162: 0x0B :vicegrip rlm@162: 0x0C :guillotine rlm@162: 0x0D :razor-wind rlm@162: 0x0E :swords-dance rlm@162: 0x0F :cut rlm@162: 0x10 :gust rlm@162: 0x11 :wing-attack rlm@162: 0x12 :whirlwind rlm@162: 0x13 :fly rlm@162: 0x14 :bind rlm@162: 0x15 :slam rlm@162: 0x16 :vine-whip rlm@162: 0x17 :stomp rlm@162: 0x18 :double-kick rlm@162: 0x19 :mega-kick rlm@162: 0x1A :jump-kick rlm@162: 0x1B :rolling-kick rlm@162: 0x1C :sand-attack rlm@162: 0x1D :headbutt rlm@162: 0x1E :horn-attack rlm@162: 0x1F :fury-attack rlm@162: 0x20 :horn-drill rlm@162: 0x21 :tackle rlm@162: 0x22 :body-slam rlm@162: 0x23 :wrap rlm@162: 0x24 :take-down rlm@162: 0x25 :thrash rlm@162: 0x26 :double-edge rlm@162: 0x27 :tail-whip rlm@162: 0x28 :poison-sting rlm@162: 0x29 :twinneedle rlm@162: 0x2A :pin-missle rlm@162: 0x2B :leer rlm@162: 0x2C :bite rlm@162: 0x2D :growl rlm@162: 0x2E :roar rlm@162: 0x2F :sing rlm@162: 0x30 :supersonic rlm@162: 0x31 :sonicboom rlm@162: 0x32 :disable rlm@162: 0x33 :acid rlm@162: 0x34 :ember rlm@162: 0x35 :flamethrower rlm@162: 0x36 :mist rlm@162: 0x37 :water-gun rlm@162: 0x38 :hydro-pump rlm@162: 0x39 :surf rlm@162: 0x3A :ice-beam rlm@162: 0x3B :blizzard rlm@162: 0x3C :psybeam rlm@162: 0x3D :bubblebeam rlm@162: 0x3E :aurora-beam rlm@162: 0x3F :hyper-beam rlm@162: 0x40 :peck rlm@162: 0x41 :drill-peck rlm@162: 0x42 :submission rlm@162: 0x43 :low-kick rlm@162: 0x44 :counter rlm@162: 0x45 :seismic-toss rlm@162: 0x46 :strength rlm@162: 0x47 :absorb rlm@162: 0x48 :mega-drain rlm@162: 0x49 :leech-seed rlm@162: 0x4A :growth rlm@162: 0x4B :razor-leaf rlm@162: 0x4C :solarbeam rlm@162: 0x4D :poisonpowder rlm@162: 0x4E :stun-spore rlm@162: 0x4F :sleep-powder rlm@162: 0x50 :petal-dance rlm@162: 0x51 :string-shot rlm@162: 0x52 :dragon-rage rlm@162: 0x53 :fire-spin rlm@162: 0x54 :thundershock rlm@162: 0x55 :thunderbolt rlm@162: 0x56 :thunder-wave rlm@162: 0x57 :thunder rlm@162: 0x58 :rock-throw rlm@162: 0x59 :earthquake rlm@162: 0x5A :fissure rlm@162: 0x5B :dig rlm@162: 0x5C :toxic rlm@162: 0x5D :confusion rlm@162: 0x5E :psychic rlm@162: 0x5F :hypnosis rlm@162: 0x60 :meditate rlm@162: 0x61 :agility rlm@162: 0x62 :quick-attack rlm@162: 0x63 :rage rlm@162: 0x64 :teleport rlm@162: 0x65 :night-shade rlm@162: 0x66 :mimic rlm@162: 0x67 :screech rlm@162: 0x68 :double-team rlm@162: 0x69 :recover rlm@162: 0x6A :harden rlm@162: 0x6B :minimize rlm@162: 0x6C :smokescreen rlm@162: 0x6D :confuse-ray rlm@162: 0x6E :withdraw rlm@162: 0x6F :defense-curl rlm@162: 0x70 :barrier rlm@162: 0x71 :light-screen rlm@162: 0x72 :haze rlm@162: 0x73 :reflect rlm@162: 0x74 :focus-energy rlm@162: 0x75 :bide rlm@162: 0x76 :metronome rlm@162: 0x77 :mirror-move rlm@162: 0x78 :selfdestruct rlm@162: 0x79 :egg-bomb rlm@162: 0x7A :lick rlm@162: 0x7B :smog rlm@162: 0x7C :sludge rlm@162: 0x7D :bone-club rlm@162: 0x7E :fire-blast rlm@162: 0x7F :waterfall rlm@162: 0x80 :clamp rlm@162: 0x81 :swift rlm@162: 0x82 :skull-bash rlm@162: 0x83 :spike-cannon rlm@162: 0x84 :constrict rlm@162: 0x85 :amnesia rlm@162: 0x86 :kinesis rlm@162: 0x87 :softboiled rlm@162: 0x88 :hi-jump-kick rlm@162: 0x89 :glare rlm@162: 0x8A :dream-eater rlm@162: 0x8B :poison-gas rlm@162: 0x8C :barrage rlm@162: 0x8D :leech-life rlm@162: 0x8E :lovely-kiss rlm@162: 0x8F :sky-attack rlm@162: 0x90 :transform rlm@162: 0x91 :bubble rlm@162: 0x92 :dizzy-punch rlm@162: 0x93 :spore rlm@162: 0x94 :flash rlm@162: 0x95 :psywave rlm@162: 0x96 :splash rlm@162: 0x97 :acid-armor rlm@162: 0x98 :crabhammer rlm@162: 0x99 :explosion rlm@162: 0x9A :fury-swipes rlm@162: 0x9B :bonemerang rlm@162: 0x9C :rest rlm@162: 0x9D :rock-slide rlm@162: 0x9E :hyper-fang rlm@162: 0x9F :sharpen rlm@162: 0xA0 :conversion rlm@162: 0xA1 :tri-attack rlm@162: 0xA2 :super-fang rlm@162: 0xA3 :slash rlm@162: 0xA4 :substitute rlm@162: 0xA5 :struggle}) rlm@162: rlm@190: (def move-name->move-code rlm@190: (zipmap (vals move-code->move-name) rlm@190: (keys move-code->move-name))) rlm@190: rlm@163: (def moves-codes-pokemon-1 0xD172) rlm@163: rlm@163: (defn moves-codes-start [pokemon-num] rlm@163: (assert (<= 0 pokemon-num 5)) rlm@163: (+ moves-codes-pokemon-1 rlm@163: (* pokemon-num pokemon-record-width))) rlm@163: rlm@190: (defn read-moves rlm@190: ([^SaveState state poke-num] rlm@190: (let [start (moves-codes-start poke-num)] rlm@190: (vec rlm@190: (take-while rlm@191: (partial not= :end-of-moves) rlm@190: (map rlm@190: move-code->move-name rlm@190: (subvec (vec (memory state)) rlm@192: start (+ start 4))))))) rlm@190: ([poke-num] rlm@190: (read-moves @current-state poke-num))) rlm@190: rlm@162: (defn give-moves rlm@162: ([^SaveState state pokemon-num moves] rlm@191: (assert (<= (count moves) 4)) rlm@162: (set-memory-range rlm@162: state rlm@162: (moves-codes-start pokemon-num) rlm@191: (map #(move-name->move-code % %) rlm@191: (concat moves rlm@191: (repeat (- 4 (count moves)) :end-of-moves))))) rlm@162: ([pokemon-num moves] rlm@162: (give-moves @current-state pokemon-num moves)) rlm@162: ([moves] rlm@162: (give-moves 0 moves))) rlm@162: rlm@162: ;; Note regarding PP of moves -- both the current PP and the rlm@162: ;; total PP are stored in the same value. rlm@162: ;; they are bit-packed, with the first 2 bits containing the rlm@162: ;; number of pp-ups that have been applied, and the next rlm@162: ;; six bits containing the current pp of the move. rlm@162: ;; thus, a move can have up to 63 current pp and up to rlm@162: ;; three pp-ups applied. rlm@162: rlm@162: (def pokemon-1-pp-start 0xD187) rlm@162: rlm@162: (defn moves-pp-start [pokemon-num] rlm@162: (assert (<= 0 pokemon-num 5)) rlm@162: (+ pokemon-1-pp-start (* pokemon-num pokemon-record-width))) rlm@162: rlm@162: (defn read-pp rlm@162: ([^SaveState state pokemon-num move-num] rlm@162: (assert (<= 0 move-num 3)) rlm@162: (assert (<= 0 pokemon-num 5)) rlm@162: (let [pp-raw rlm@162: (aget (memory state) rlm@162: (+ (moves-pp-start pokemon-num) rlm@162: move-num)) rlm@162: pp-up rlm@162: (bit-shift-right rlm@162: (bit-and rlm@162: pp-raw rlm@162: (Integer/parseInt "11000000" 2)) 6) rlm@162: current-pp rlm@162: (bit-and rlm@162: pp-raw rlm@162: (Integer/parseInt "00111111" 2))] rlm@192: {:pp-ups pp-up :current-pp current-pp})) rlm@162: ([pokemon-num move-num] rlm@162: (read-pp @current-state pokemon-num move-num))) rlm@162: rlm@162: (defn give-pp rlm@162: ([^SaveState state pokemon-num move-num pp-ups current-pp] rlm@162: (assert (<= 0 move-num 3)) rlm@162: (assert (<= 0 pokemon-num 5)) rlm@162: (assert (<= 0 pp-ups 3)) rlm@162: (assert (<= 0 current-pp 63)) rlm@162: rlm@162: (set-memory rlm@162: state rlm@162: (+ (moves-pp-start pokemon-num) rlm@162: move-num) rlm@162: (+ rlm@162: (bit-shift-left pp-ups 6) rlm@162: (bit-and (Integer/parseInt rlm@162: "00111111" 2) rlm@162: current-pp)))) rlm@162: ([pokemon-num move-num pp-ups current-pp] rlm@163: (give-pp @current-state rlm@162: pokemon-num move-num pp-ups current-pp))) rlm@190: