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@197: 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: rlm@197: rlm@197: (def move-name->move-pp rlm@197: { rlm@197: :absorb 20 rlm@197: :acid 30 rlm@197: :acid-armor 40 ;; WTF happens with 3 PP-UPs??! rlm@197: :agility 30 rlm@197: :amnesia 20 rlm@197: :aurora-beam 20 rlm@197: :barrage 20 rlm@197: :barrier 30 rlm@197: :bide 10 rlm@197: :bind 20 rlm@197: :bite 25 rlm@197: :blizzard 5 rlm@197: :body-slam 15 rlm@197: :bone-club 20 rlm@197: :bonemerang 10 rlm@197: :bubble 30 rlm@197: :bubblebeam 20 rlm@197: :clamp 10 rlm@197: :comet-punch 15 rlm@197: :confuse-ray 10 rlm@197: :confusion 25 rlm@197: :constrict 35 rlm@197: :conversion 30 rlm@197: :counter 20 rlm@197: :crabhammer 10 rlm@197: :cut 30 rlm@197: :defense-curl 40 rlm@197: :dig 10 rlm@197: :disable 20 rlm@197: :dizzy-punch 10 rlm@197: :double-edge 15 rlm@197: :double-kick 30 rlm@197: :double-team 10 rlm@197: :doubleslap 15 rlm@197: :dragon-rage 10 rlm@197: :dream-eater 15 rlm@197: :drill-peck 20 rlm@197: :earthquake 10 rlm@197: :egg-bomb 10 rlm@197: :ember 25 rlm@197: :explosion 5 rlm@197: :fire-blast 5 rlm@197: :fire-punch 15 rlm@197: :fire-spin 15 rlm@197: :fissure 5 rlm@197: :flamethrower 15 rlm@197: :flash 20 rlm@197: :fly 15 rlm@197: :focus-energy 30 rlm@197: :fury-attack 20 rlm@197: :fury-swipes 15 rlm@197: :glare 30 rlm@197: :growl 40 rlm@197: :growth 40 rlm@197: :guillotine 5 rlm@197: :gust 35 rlm@197: :harden 30 rlm@198: :haze 30 rlm@198: :headbutt 15 rlm@198: :hi-jump-kick 20 rlm@198: :horn-attack 25 rlm@198: :horn-drill 5 rlm@198: :hydro-pump 5 rlm@198: :hyper-beam 5 rlm@198: :hyper-fang 15 rlm@198: :hypnosis 20 rlm@198: :ice-beam 10 rlm@198: :ice-punch 15 rlm@198: :jump-kick 25 rlm@198: :karate-chop 25 rlm@198: :kinesis 15 rlm@198: :leech-life 15 rlm@198: :leech-seed 10 rlm@198: :leer 30 rlm@198: :lick 30 rlm@198: :light-screen 30 rlm@198: :lovely-kiss 10 rlm@198: :low-kick 20 rlm@198: :meditate 40 rlm@198: :mega-drain 10 rlm@198: :mega-kick 5 rlm@198: :mega-punch 20 rlm@198: :metronome 10 rlm@198: :mimic 10 rlm@198: :minimize 20 rlm@198: :mirror-move 20 rlm@198: :mist 30 rlm@198: :night-shade 15 rlm@198: :pay-day 20 rlm@198: :peck 35 rlm@198: :petal-dance 20 rlm@198: :pin-missle 20 rlm@198: :poison-gas 40 rlm@198: :poison-sting 35 rlm@198: :poisonpowder 35 rlm@198: :pound 35 rlm@198: :psybeam 20 rlm@198: :psychic 10 rlm@198: :psywave 15 rlm@198: :quick-attack 30 rlm@198: :rage 20 rlm@198: :razor-leaf 25 rlm@198: :razor-wind 10 rlm@198: :recover 20 rlm@198: :reflect 20 rlm@198: :rest 10 rlm@198: :roar 20 rlm@198: :rock-slide 10 rlm@198: :rock-throw 15 rlm@198: :rolling-kick 15 rlm@198: :sand-attack 15 rlm@198: :scratch 30 rlm@198: :screech 40 rlm@198: :seismic-toss 20 rlm@198: :selfdestruct 5 rlm@198: :sharpen 30 rlm@198: :sing 15 rlm@198: :skull-bash 15 rlm@198: :sky-attack 5 rlm@198: :slam 20 rlm@198: :slash 20 rlm@198: :sleep-powder 15 rlm@198: :sludge 20 rlm@198: :smog 20 rlm@198: :smokescreen 20 rlm@198: :softboiled 10 rlm@198: :solarbeam 10 rlm@198: :sonicboom 20 rlm@198: :spike-cannon 15 rlm@198: :splash 40 rlm@198: :spore 15 rlm@198: :stomp 20 rlm@198: :strength 15 rlm@198: :string-shot 40 rlm@198: :struggle 1 rlm@198: :stun-spore 30 rlm@198: :submission 25 rlm@198: :substitute 10 rlm@198: :super-fang 10 rlm@198: :supersonic 20 rlm@198: :surf 15 rlm@198: :swift 20 rlm@198: :swords-dance 30 rlm@198: :tackle 35 rlm@198: :tail-whip 30 rlm@198: :take-down 20 rlm@198: :teleport 20 rlm@198: :thrash 20 rlm@198: :thunder 10 rlm@198: :thunder-wave 20 rlm@198: :thunderbolt 15 rlm@198: :thunderpunch 15 rlm@198: :thundershock 30 rlm@198: :toxic 10 rlm@198: :transform 10 rlm@198: :tri-attack 10 rlm@198: :twinneedle 20 rlm@198: :vicegrip 30 rlm@198: :vine-whip 10 rlm@198: :water-gun 25 rlm@198: :waterfall 15 rlm@198: :whirlwind 20 rlm@198: :wing-attack 35 rlm@198: :withdraw 40 rlm@198: :wrap 20}) rlm@198: rlm@198: (defn max-pp [name pp-ups] rlm@198: (int (* (+ 1 (* (/ 1 5) pp-ups)) rlm@198: (move-name->move-pp name))))