annotate clojure/com/aurellem/gb/hxc.clj @ 258:2a46422902be

script: got pikachu.
author Robert McIntyre <rlm@mit.edu>
date Mon, 26 Mar 2012 18:01:39 -0500
parents 2b6bd03feb4f
children b2f9a0cb13e3
rev   line source
rlm@218 1 (ns com.aurellem.gb.hxc
rlm@218 2 (:use (com.aurellem.gb assembly characters gb-driver util
rlm@218 3 constants))
rlm@218 4 (:use (com.aurellem.world practice))
rlm@218 5 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@218 6
rlm@218 7
ocsenave@243 8
ocsenave@249 9
ocsenave@249 10 ; ************* HANDWRITTEN CONSTANTS
ocsenave@249 11
ocsenave@243 12 (def pkmn-types
ocsenave@244 13 [:normal
ocsenave@244 14 :fighting
ocsenave@244 15 :flying
ocsenave@244 16 :poison
ocsenave@244 17 :ground
ocsenave@244 18 :rock
ocsenave@245 19 :bird
ocsenave@244 20 :bug
ocsenave@244 21 :ghost
ocsenave@244 22 :A
ocsenave@244 23 :B
ocsenave@244 24 :C
ocsenave@244 25 :D
ocsenave@244 26 :E
ocsenave@244 27 :F
ocsenave@244 28 :G
ocsenave@244 29 :H
ocsenave@244 30 :I
ocsenave@244 31 :J
ocsenave@244 32 :K
ocsenave@244 33 :fire
ocsenave@244 34 :water
ocsenave@244 35 :grass
ocsenave@244 36 :electric
ocsenave@244 37 :psychic
ocsenave@244 38 :ice
ocsenave@244 39 :dragon
ocsenave@244 40 ])
ocsenave@243 41
ocsenave@243 42
ocsenave@246 43 ;; question: when status effects claim to take
ocsenave@246 44 ;; their accuracy from the move accuracy, does
ocsenave@246 45 ;; this mean that the move always "hits" but the
ocsenave@246 46 ;; status effect may not?
ocsenave@246 47
ocsenave@246 48 (def move-effects
ocsenave@246 49 ["normal damage"
ocsenave@246 50 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@246 51 "0x4C chance of poison"
ocsenave@246 52 "leech half of inflicted damage"
ocsenave@246 53 "0x19 chance of burn"
ocsenave@246 54 "0x19 chance of freeze"
ocsenave@246 55 "0x19 chance of paralyze"
ocsenave@246 56 "user faints; opponent defense halved."
ocsenave@246 57 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@246 58 "imitate last attack"
ocsenave@246 59 "user atk +1"
ocsenave@246 60 "user def +1"
ocsenave@246 61 "user spd +1"
ocsenave@246 62 "user spc +1"
ocsenave@246 63 "user acr +1" ;; unused?!
ocsenave@246 64 "user evd +1"
ocsenave@246 65 "get post-battle $ = 2*level*uses"
ocsenave@246 66 "0xFE acr, no matter what."
ocsenave@246 67 "opponent atk -1" ;; acr taken from move acr?
ocsenave@246 68 "opponent def -1" ;;
ocsenave@246 69 "opponent spd -1" ;;
ocsenave@246 70 "opponent spc -1" ;;
ocsenave@246 71 "opponent acr -1";;
ocsenave@246 72 "opponent evd -1"
ocsenave@246 73 "converts user's type to opponent's."
ocsenave@246 74 "(haze)"
ocsenave@246 75 "(bide)"
ocsenave@246 76 "(thrash)"
ocsenave@246 77 "(teleport)"
ocsenave@246 78 "(fury swipes)"
ocsenave@246 79 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@246 80 "0x19 chance of flinch"
ocsenave@246 81 "opponent sleep for 1-7 turns"
ocsenave@246 82 "0x66 chance of poison"
ocsenave@246 83 "0x4D chance of burn"
ocsenave@246 84 "0x4D chance of freeze"
ocsenave@246 85 "0x4D chance of paralyze"
ocsenave@246 86 "0x4D chance of flinch"
ocsenave@246 87 "one-hit KO"
ocsenave@246 88 "charge one turn, atk next."
ocsenave@246 89 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@246 90 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@246 91 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@246 92 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@246 93 "atk hits twice."
ocsenave@246 94 "user takes 1 damage if misses."
ocsenave@246 95 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@246 96 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@246 97 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@246 98 "confuses opponent" ;; acr taken from move acr
ocsenave@246 99 "user atk +2"
ocsenave@246 100 "user def +2"
ocsenave@246 101 "user spd +2"
ocsenave@246 102 "user spc +2"
ocsenave@246 103 "user acr +2" ;; unused!
ocsenave@246 104 "user evd +2" ;; unused!
ocsenave@246 105 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@246 106 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@246 107 "(transform)"
ocsenave@246 108 "opponent atk -2"
ocsenave@246 109 "opponent def -2"
ocsenave@246 110 "opponent spd -2"
ocsenave@246 111 "opponent spc -2"
ocsenave@246 112 "opponent acr -2"
ocsenave@246 113 "opponent evd -2"
ocsenave@246 114 "doubles user spc when attacked"
ocsenave@246 115 "doubles user def when attacked"
ocsenave@249 116 "just poisons opponent" ;;acr taken from move acr
ocsenave@249 117 "just paralyzes opponent" ;;
ocsenave@246 118 "0x19 chance opponent atk -1"
ocsenave@246 119 "0x19 chance opponent def -1"
ocsenave@246 120 "0x19 chance opponent spd -1"
ocsenave@246 121 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@246 122 "0x19 chance opponent acr -1"
ocsenave@246 123 "0x19 chance opponent evd -1"
ocsenave@246 124 "???" ;; unused? no effect?
ocsenave@246 125 "???" ;; unused? no effect?
ocsenave@246 126 "0x19 chance opponent confused"
ocsenave@246 127 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@246 128 "broken. crash the game after attack."
ocsenave@246 129 "(substitute)"
ocsenave@246 130 "unless opponent faints, user must recharge after atk. some
ocsenave@246 131 exceptions apply."
ocsenave@246 132 "(rage)"
ocsenave@246 133 "(mimic)"
ocsenave@246 134 "(metronome)"
ocsenave@246 135 "(leech seed)"
ocsenave@246 136 "does nothing (splash)"
ocsenave@246 137 "(disable)"
ocsenave@246 138 ])
ocsenave@246 139
ocsenave@246 140
ocsenave@249 141 ;; ************** HARDCODED DATA
ocsenave@246 142
ocsenave@249 143 (defn hxc-thunk
ocsenave@249 144 "Creates a thunk (unary fn) that grabs data in a certain region of rom and
ocsenave@249 145 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@249 146 original rom data."
ocsenave@249 147 [start length]
ocsenave@249 148 (fn self
ocsenave@249 149 ([rom]
ocsenave@249 150 (take-nth 2
ocsenave@249 151 (partition-by #(= % 0x50)
ocsenave@249 152 (take length
ocsenave@249 153 (drop start rom)))))
ocsenave@249 154 ([]
ocsenave@249 155 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@246 156
ocsenave@249 157 (def hxc-thunk-words
ocsenave@249 158 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@249 159 returning a collection of strings."
ocsenave@249 160 (comp
ocsenave@249 161 (partial comp (partial map character-codes->str))
ocsenave@249 162 hxc-thunk))
ocsenave@249 163
ocsenave@249 164
ocsenave@249 165 ;; --------------------------------------------------
ocsenave@246 166
ocsenave@246 167 (def hxc-items
ocsenave@249 168 "The hardcoded names of the items in memory. List begins at
ocsenave@249 169 ROM@045B7"
ocsenave@249 170 (hxc-thunk-words 0x45B7 870))
ocsenave@246 171
ocsenave@246 172 (def hxc-types
ocsenave@246 173 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@246 174 shortly before hxc-titles."
ocsenave@249 175 (hxc-thunk-words 0x27D99 102))
ocsenave@246 176
ocsenave@246 177 (def hxc-titles
ocsenave@246 178 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@246 179 ROM@27E77"
ocsenave@249 180 (hxc-thunk-words 0x27E77 196))
ocsenave@246 181
ocsenave@246 182 (def hxc-places
ocsenave@246 183 "The hardcoded place names in memory. List begins at
ocsenave@249 184 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
ocsenave@249 185 (hxc-thunk-words 0x71500 560))
ocsenave@246 186
ocsenave@246 187
ocsenave@249 188 (defn hxc-dialog
ocsenave@249 189 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@249 190 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@249 191 ([rom]
ocsenave@249 192 (map character-codes->str
ocsenave@249 193 (take-nth 2
ocsenave@249 194 (partition-by #(= % 0x57)
ocsenave@249 195 (take 0x0F728
ocsenave@249 196 (drop 0x98000 rom))))))
ocsenave@249 197 ([]
ocsenave@249 198 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@249 199
ocsenave@246 200
ocsenave@246 201 (def hxc-pokedex
ocsenave@246 202 "The hardcoded pokedex entries in memory. List begins at
ocsenave@246 203 ROM@B8000, shortly before move names."
ocsenave@249 204 (hxc-thunk-words 0xB8000 14754))
ocsenave@249 205
ocsenave@246 206 (def hxc-move-names
ocsenave@246 207 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@249 208 (hxc-thunk-words 0xBC000 1551))
ocsenave@246 209
ocsenave@249 210
ocsenave@249 211 (defn hxc-move-data
ocsenave@246 212 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@249 213 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@249 214 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@249 215 ([]
ocsenave@249 216 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 217 ([rom]
ocsenave@249 218 (let [names (vec (hxc-move-names rom))
ocsenave@249 219 move-count (count names)
ocsenave@249 220 move-size 6
ocsenave@249 221 format-name (fn [s]
ocsenave@246 222 (keyword (.toLowerCase
ocsenave@249 223 (apply str
ocsenave@249 224 (map #(if (= % \space) "-" %) s)))))]
ocsenave@249 225 (zipmap (map format-name names)
ocsenave@249 226 (map
ocsenave@249 227 (fn [[idx effect power type accuracy pp]]
ocsenave@249 228 {:name (names (dec idx))
ocsenave@249 229 :power power
ocsenave@249 230 :accuracy accuracy
ocsenave@249 231 :pp pp
ocsenave@249 232 :fx-id effect
ocsenave@249 233 :fx-txt (get move-effects effect)
ocsenave@249 234 }
ocsenave@249 235 )
ocsenave@249 236
ocsenave@249 237 (partition move-size
ocsenave@249 238 (take (* move-size move-count)
ocsenave@249 239 (drop 0x38000 rom))))))))
ocsenave@246 240
ocsenave@246 241
ocsenave@246 242
ocsenave@249 243 (defn hxc-move-data*
ocsenave@249 244 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@249 245 ([]
ocsenave@249 246 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 247 ([rom]
ocsenave@249 248 (let [names (vec (hxc-move-names rom))
ocsenave@249 249 move-count (count names)
ocsenave@249 250 move-size 6
ocsenave@249 251 format-name (fn [s]
ocsenave@249 252 (keyword (.toLowerCase
ocsenave@249 253 (apply str
ocsenave@249 254 (map #(if (= % \space) "-" %) s)))))
ocsenave@249 255 ]
ocsenave@249 256 (zipmap (map format-name names)
ocsenave@249 257 (map
ocsenave@249 258 (fn [[idx effect power type accuracy pp]]
ocsenave@249 259 {:name (names (dec idx))
ocsenave@249 260 :power power
ocsenave@249 261 :accuracy (hex accuracy)
ocsenave@249 262 :pp pp
ocsenave@249 263 :fx-id (hex effect)
ocsenave@249 264 :fx-txt (get move-effects effect)
ocsenave@249 265 }
ocsenave@249 266 )
ocsenave@249 267
ocsenave@249 268 (partition move-size
ocsenave@249 269 (take (* move-size move-count)
ocsenave@249 270 (drop 0x38000 rom))))))))
ocsenave@243 271
ocsenave@243 272
ocsenave@243 273
ocsenave@249 274 (defn hxc-pokenames
ocsenave@249 275 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@249 276 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@249 277 long, these names are stripped of padding."
ocsenave@249 278 ([]
ocsenave@249 279 (hxc-pokenames com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 280 ([rom]
ocsenave@249 281 (let [count-species 190
ocsenave@249 282 name-length 10]
ocsenave@249 283 (map character-codes->str
ocsenave@249 284 (partition name-length
ocsenave@249 285 (map #(if (= 0x50 %) 0x00 %)
ocsenave@249 286 (take (* count-species name-length)
ocsenave@249 287 (drop 0xE8000
ocsenave@249 288 rom))))))))
ocsenave@243 289
ocsenave@249 290 (defn hxc-advantage
ocsenave@249 291 "The hardcoded type advantages in memory, returned as tuples of atk-type def-type multiplier. By default (i.e. if not listed here),
ocsenave@249 292 the multiplier is 1."
ocsenave@249 293 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 294 ([rom]
ocsenave@249 295 (map
ocsenave@249 296 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@249 297 (get pkmn-types def (hex def))
ocsenave@249 298 (/ mult 10)])
ocsenave@249 299 (partition 3
ocsenave@249 300 (take-while (partial not= 0xFF)
ocsenave@249 301 (drop 0x3E62D rom))))))
ocsenave@243 302
ocsenave@243 303
ocsenave@243 304
ocsenave@243 305
ocsenave@243 306
ocsenave@243 307
ocsenave@243 308
ocsenave@243 309
ocsenave@243 310
ocsenave@243 311
ocsenave@249 312 ;; ********************** MANIPULATION FNS
ocsenave@249 313
ocsenave@249 314
ocsenave@249 315
ocsenave@249 316
ocsenave@249 317 (defn submap?
ocsenave@249 318 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@249 319 [map-small map-big]
ocsenave@249 320 (cond (empty? map-small) true
ocsenave@249 321 (and
ocsenave@249 322 (contains? map-big (ffirst map-small))
ocsenave@249 323 (= (get map-big (ffirst map-small))
ocsenave@249 324 (second (first map-small))))
ocsenave@249 325 (recur (next map-small) map-big)
ocsenave@249 326
ocsenave@249 327 :else false))
ocsenave@249 328
ocsenave@249 329
ocsenave@249 330 (defn search-map [proto-map maps]
ocsenave@249 331 "Returns all the maps that make the same associations as proto-map."
ocsenave@249 332 (some (partial submap? proto-map) maps))
ocsenave@249 333
rlm@252 334 (defn filter-vals
rlm@252 335 "Returns a map consisting of all the pairs [key val] for
rlm@252 336 which (pred key) returns true."
rlm@252 337 [pred map]
rlm@252 338 (reduce (partial apply assoc) {}
rlm@252 339 (filter (fn [[k v]] (pred v)) map)))
ocsenave@249 340
ocsenave@249 341
ocsenave@249 342 (defn search-moves
rlm@252 343 "Returns a subcollection of all hardcoded moves with the
rlm@252 344 given attributes. Attributes consist of :name :power
rlm@252 345 :accuracy :pp :fx-id
rlm@252 346 (and also :fx-txt, but it contains the same information
rlm@252 347 as :fx-id)"
ocsenave@249 348 ([attribute-map]
rlm@252 349 (search-moves
rlm@252 350 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@249 351 ([rom attribute-map]
rlm@252 352 (filter-vals (partial submap? attribute-map)
rlm@252 353 (hxc-move-data rom))))
ocsenave@249 354
ocsenave@249 355
ocsenave@249 356
ocsenave@249 357
ocsenave@249 358
ocsenave@249 359
ocsenave@249 360
ocsenave@249 361
ocsenave@249 362
ocsenave@249 363
ocsenave@243 364
ocsenave@246 365 ;; note for later: credits start at F1290
ocsenave@243 366
ocsenave@243 367
ocsenave@243 368
ocsenave@246 369 (comment
ocsenave@243 370
rlm@218 371 (def hxc-later
rlm@218 372 "Running this code produces, e.g. hardcoded names NPCs give
rlm@218 373 their pokemon. Will sort through it later."
rlm@218 374 (print (character-codes->str(take 10000
rlm@218 375 (drop 0x71597
rlm@218 376 (rom (root)))))))
rlm@218 377
rlm@218 378 (let [dex
rlm@218 379 (partition-by #(= 0x50 %)
rlm@218 380 (take 2540
rlm@218 381 (drop 0x40687
rlm@218 382 (rom (root)))))]
rlm@218 383 (def dex dex)
rlm@218 384 (def hxc-species
rlm@218 385 (map character-codes->str
rlm@218 386 (take-nth 4 dex))))
ocsenave@246 387 )