annotate clojure/com/aurellem/gb/hxc.clj @ 285:33c546273619

Found the hardcoded pokedex order!! Added/modified a number of functions to take advantage of this new data.
author Dylan Holmes <ocsenave@gmail.com>
date Wed, 28 Mar 2012 05:56:37 -0500
parents 516acb83410f
children eec3e69500d9
rev   line source
rlm@218 1 (ns com.aurellem.gb.hxc
rlm@218 2 (:use (com.aurellem.gb assembly characters gb-driver util
ocsenave@281 3 constants species))
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@259 12
ocsenave@259 13
ocsenave@259 14 (defn low-high
ocsenave@259 15 [low high]
ocsenave@259 16 (+ low (* 256 high)))
ocsenave@259 17
ocsenave@259 18
ocsenave@259 19 (defn format-name
ocsenave@259 20 "Convert the string of alphabetic/space characters into a keyword by
ocsenave@259 21 replacing spaces with hyphens and converting to lowercase."
ocsenave@259 22 [s]
ocsenave@283 23 (if (nil? s) nil
ocsenave@259 24 (keyword (.toLowerCase
ocsenave@259 25 (apply str
ocsenave@283 26 (map #(if (= % \space) "-" %) s))))))
ocsenave@259 27
ocsenave@282 28
ocsenave@282 29 ;; used to decode item prices
ocsenave@282 30
ocsenave@282 31 (defn decode-bcd
ocsenave@282 32 "Take a sequence of binary-coded digits (in written order) and return the number they represent."
ocsenave@282 33 [digits]
ocsenave@282 34 ((fn self [coll]
ocsenave@282 35 (if (empty? coll) 0
ocsenave@282 36 (+ (first coll) (* 100 (self (rest coll))))))
ocsenave@282 37 (map
ocsenave@282 38 #(+ (* 10 (int (/ % 16)))
ocsenave@282 39 (rem % 16))
ocsenave@282 40 (reverse digits))))
ocsenave@282 41
ocsenave@282 42
ocsenave@259 43
ocsenave@259 44
ocsenave@243 45 (def pkmn-types
ocsenave@272 46 [:normal ;;0
ocsenave@272 47 :fighting ;;1
ocsenave@272 48 :flying ;;2
ocsenave@272 49 :poison ;;3
ocsenave@272 50 :ground ;;4
ocsenave@272 51 :rock ;;5
ocsenave@272 52 :bird ;;6
ocsenave@272 53 :bug ;;7
ocsenave@272 54 :ghost ;;8
ocsenave@244 55 :A
ocsenave@244 56 :B
ocsenave@244 57 :C
ocsenave@244 58 :D
ocsenave@244 59 :E
ocsenave@244 60 :F
ocsenave@244 61 :G
ocsenave@244 62 :H
ocsenave@244 63 :I
ocsenave@244 64 :J
ocsenave@244 65 :K
ocsenave@272 66 :fire ;;20 (0x14)
ocsenave@272 67 :water ;;21 (0x15)
ocsenave@272 68 :grass ;;22 (0x16)
ocsenave@272 69 :electric ;;23 (0x17)
ocsenave@272 70 :psychic ;;24 (0x18)
ocsenave@272 71 :ice ;;25 (0x19)
ocsenave@272 72 :dragon ;;26 (0x1A)
ocsenave@244 73 ])
ocsenave@243 74
ocsenave@243 75
ocsenave@246 76 ;; question: when status effects claim to take
ocsenave@246 77 ;; their accuracy from the move accuracy, does
ocsenave@246 78 ;; this mean that the move always "hits" but the
ocsenave@246 79 ;; status effect may not?
ocsenave@246 80
ocsenave@246 81 (def move-effects
ocsenave@246 82 ["normal damage"
ocsenave@246 83 "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
ocsenave@246 84 "0x4C chance of poison"
ocsenave@246 85 "leech half of inflicted damage"
ocsenave@246 86 "0x19 chance of burn"
ocsenave@246 87 "0x19 chance of freeze"
ocsenave@246 88 "0x19 chance of paralyze"
ocsenave@259 89 "user faints; opponent defense halved during attack."
ocsenave@246 90 "leech half of inflicted damage ONLY if sleeping opponent."
ocsenave@246 91 "imitate last attack"
ocsenave@246 92 "user atk +1"
ocsenave@246 93 "user def +1"
ocsenave@246 94 "user spd +1"
ocsenave@246 95 "user spc +1"
ocsenave@246 96 "user acr +1" ;; unused?!
ocsenave@246 97 "user evd +1"
ocsenave@246 98 "get post-battle $ = 2*level*uses"
ocsenave@246 99 "0xFE acr, no matter what."
ocsenave@246 100 "opponent atk -1" ;; acr taken from move acr?
ocsenave@246 101 "opponent def -1" ;;
ocsenave@246 102 "opponent spd -1" ;;
ocsenave@246 103 "opponent spc -1" ;;
ocsenave@246 104 "opponent acr -1";;
ocsenave@246 105 "opponent evd -1"
ocsenave@246 106 "converts user's type to opponent's."
ocsenave@246 107 "(haze)"
ocsenave@246 108 "(bide)"
ocsenave@246 109 "(thrash)"
ocsenave@246 110 "(teleport)"
ocsenave@246 111 "(fury swipes)"
ocsenave@246 112 "attacks 2-5 turns" ;; unused? like rollout?
ocsenave@246 113 "0x19 chance of flinch"
ocsenave@246 114 "opponent sleep for 1-7 turns"
ocsenave@246 115 "0x66 chance of poison"
ocsenave@246 116 "0x4D chance of burn"
ocsenave@246 117 "0x4D chance of freeze"
ocsenave@246 118 "0x4D chance of paralyze"
ocsenave@246 119 "0x4D chance of flinch"
ocsenave@246 120 "one-hit KO"
ocsenave@246 121 "charge one turn, atk next."
ocsenave@246 122 "fixed damage, leaves 1HP." ;; how is dmg determined?
ocsenave@246 123 "fixed damage." ;; cf seismic toss, dragon rage, psywave.
ocsenave@246 124 "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
ocsenave@246 125 "charge one turn, atk next. (can't be hit when charging)"
ocsenave@246 126 "atk hits twice."
ocsenave@246 127 "user takes 1 damage if misses."
ocsenave@246 128 "evade status-lowering effects" ;;caused by you or also your opponent?
ocsenave@246 129 "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
ocsenave@246 130 "atk causes recoil dmg = 1/4 dmg dealt"
ocsenave@246 131 "confuses opponent" ;; acr taken from move acr
ocsenave@246 132 "user atk +2"
ocsenave@246 133 "user def +2"
ocsenave@246 134 "user spd +2"
ocsenave@246 135 "user spc +2"
ocsenave@246 136 "user acr +2" ;; unused!
ocsenave@246 137 "user evd +2" ;; unused!
ocsenave@246 138 "restores up to half of user's max hp." ;; broken: fails if the difference
ocsenave@246 139 ;; b/w max and current hp is one less than a multiple of 256.
ocsenave@246 140 "(transform)"
ocsenave@246 141 "opponent atk -2"
ocsenave@246 142 "opponent def -2"
ocsenave@246 143 "opponent spd -2"
ocsenave@246 144 "opponent spc -2"
ocsenave@246 145 "opponent acr -2"
ocsenave@246 146 "opponent evd -2"
ocsenave@246 147 "doubles user spc when attacked"
ocsenave@246 148 "doubles user def when attacked"
ocsenave@249 149 "just poisons opponent" ;;acr taken from move acr
ocsenave@249 150 "just paralyzes opponent" ;;
ocsenave@246 151 "0x19 chance opponent atk -1"
ocsenave@246 152 "0x19 chance opponent def -1"
ocsenave@246 153 "0x19 chance opponent spd -1"
ocsenave@246 154 "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
ocsenave@246 155 "0x19 chance opponent acr -1"
ocsenave@246 156 "0x19 chance opponent evd -1"
ocsenave@246 157 "???" ;; unused? no effect?
ocsenave@246 158 "???" ;; unused? no effect?
ocsenave@246 159 "0x19 chance opponent confused"
ocsenave@246 160 "atk hits twice. 0x33 chance opponent poisioned."
ocsenave@246 161 "broken. crash the game after attack."
ocsenave@246 162 "(substitute)"
ocsenave@246 163 "unless opponent faints, user must recharge after atk. some
ocsenave@246 164 exceptions apply."
ocsenave@246 165 "(rage)"
ocsenave@246 166 "(mimic)"
ocsenave@246 167 "(metronome)"
ocsenave@246 168 "(leech seed)"
ocsenave@246 169 "does nothing (splash)"
ocsenave@246 170 "(disable)"
ocsenave@246 171 ])
ocsenave@246 172
ocsenave@246 173
ocsenave@249 174 ;; ************** HARDCODED DATA
ocsenave@246 175
ocsenave@249 176 (defn hxc-thunk
ocsenave@259 177 "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
ocsenave@249 178 splits it into a collection by 0x50. If rom is not supplied, uses the
ocsenave@249 179 original rom data."
ocsenave@249 180 [start length]
ocsenave@249 181 (fn self
ocsenave@249 182 ([rom]
ocsenave@249 183 (take-nth 2
ocsenave@249 184 (partition-by #(= % 0x50)
ocsenave@249 185 (take length
ocsenave@249 186 (drop start rom)))))
ocsenave@249 187 ([]
ocsenave@249 188 (self com.aurellem.gb.gb-driver/original-rom))))
ocsenave@246 189
ocsenave@249 190 (def hxc-thunk-words
ocsenave@249 191 "Same as hxc-thunk, except it interprets the rom data as characters,
ocsenave@249 192 returning a collection of strings."
ocsenave@249 193 (comp
ocsenave@249 194 (partial comp (partial map character-codes->str))
ocsenave@249 195 hxc-thunk))
ocsenave@249 196
ocsenave@249 197
ocsenave@249 198 ;; --------------------------------------------------
ocsenave@246 199
ocsenave@246 200 (def hxc-items
ocsenave@249 201 "The hardcoded names of the items in memory. List begins at
ocsenave@249 202 ROM@045B7"
ocsenave@249 203 (hxc-thunk-words 0x45B7 870))
ocsenave@246 204
ocsenave@246 205 (def hxc-types
ocsenave@246 206 "The hardcoded type names in memory. List begins at ROM@27D99,
ocsenave@246 207 shortly before hxc-titles."
ocsenave@249 208 (hxc-thunk-words 0x27D99 102))
ocsenave@246 209
ocsenave@246 210 (def hxc-titles
ocsenave@246 211 "The hardcoded names of the trainer titles in memory. List begins at
ocsenave@246 212 ROM@27E77"
ocsenave@249 213 (hxc-thunk-words 0x27E77 196))
ocsenave@246 214
ocsenave@259 215
ocsenave@285 216 (def hxc-pokedex-text*
ocsenave@259 217 "The hardcoded pokedex entries in memory. List begins at
ocsenave@259 218 ROM@B8000, shortly before move names."
ocsenave@259 219 (hxc-thunk-words 0xB8000 14754))
ocsenave@259 220
ocsenave@285 221 (defn hxc-pokedex-text
ocsenave@285 222 "The hardcoded pokedex entries in memory, presented as an
ocsenave@285 223 associative hash map. List begins at ROM@B8000."
ocsenave@285 224 ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
ocsenave@285 225 ([rom]
ocsenave@285 226 (zipmap
ocsenave@285 227 (hxc-pokedex-names rom)
ocsenave@285 228 (cons nil ;; for missingno.
ocsenave@285 229 (hxc-pokedex-text* rom)))))
ocsenave@259 230
ocsenave@272 231 ;; In red/blue, pokedex stats are in internal order.
ocsenave@272 232 ;; In yellow, pokedex stats are in pokedex order.
ocsenave@259 233
ocsenave@259 234 (defn hxc-pokedex-stats
ocsenave@272 235 "The hardcoded pokedex stats (species height weight) in memory. List
ocsenave@272 236 begins at ROM@40687"
ocsenave@259 237 ;; uses hxc-pokedex-text to count pokemon
ocsenave@259 238 ;; since hxc-pokenames includes several missingno"
ocsenave@259 239 ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
ocsenave@259 240 ([rom]
ocsenave@285 241 (let [poketext (hxc-pokedex-text rom)
ocsenave@259 242 pkmn-count (count poketext)
ocsenave@285 243 pokedex-names (zipmap (range) (hxc-pokedex-names rom))
ocsenave@259 244 ]
ocsenave@259 245 ((fn capture-stats
ocsenave@259 246 [n stats data]
ocsenave@259 247 (if (zero? n) stats
ocsenave@259 248 (let [[species
ocsenave@259 249 [_
ocsenave@259 250 height-ft
ocsenave@259 251 height-in
ocsenave@259 252 weight-1
ocsenave@259 253 weight-2
ocsenave@259 254 _
ocsenave@259 255 dex-ptr-1
ocsenave@259 256 dex-ptr-2
ocsenave@259 257 dex-bank
ocsenave@259 258 _
ocsenave@259 259 & data]]
ocsenave@259 260 (split-with (partial not= 0x50) data)]
ocsenave@259 261 (recur (dec n)
ocsenave@259 262 (assoc stats
ocsenave@285 263 (pokedex-names (- pkmn-count (dec n)))
ocsenave@259 264 {:species
ocsenave@285 265 (format-name (character-codes->str species))
ocsenave@259 266 :height-ft
ocsenave@259 267 height-ft
ocsenave@259 268 :height-in
ocsenave@259 269 height-in
ocsenave@259 270 :weight
ocsenave@259 271 (/ (low-high weight-1 weight-2) 10.)
ocsenave@259 272
ocsenave@259 273 ;; :text
ocsenave@259 274 ;; (character-codes->str
ocsenave@259 275 ;; (take-while
ocsenave@259 276 ;; (partial not= 0x50)
ocsenave@259 277 ;; (drop
ocsenave@259 278 ;; (+ 0xB8000
ocsenave@259 279 ;; -0x4000
ocsenave@259 280 ;; (low-high dex-ptr-1 dex-ptr-2))
ocsenave@259 281 ;; rom)))
ocsenave@259 282 })
ocsenave@259 283
ocsenave@259 284 data)
ocsenave@259 285
ocsenave@259 286
ocsenave@259 287 )))
ocsenave@259 288
ocsenave@259 289 pkmn-count
ocsenave@259 290 {}
ocsenave@259 291 (drop 0x40687 rom))) ))
ocsenave@259 292
ocsenave@259 293
ocsenave@259 294
ocsenave@259 295
ocsenave@259 296
ocsenave@259 297
ocsenave@259 298
ocsenave@246 299 (def hxc-places
ocsenave@246 300 "The hardcoded place names in memory. List begins at
ocsenave@249 301 ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
ocsenave@249 302 (hxc-thunk-words 0x71500 560))
ocsenave@246 303
ocsenave@246 304
ocsenave@249 305 (defn hxc-dialog
ocsenave@249 306 "The hardcoded dialogue in memory, including in-game alerts. Dialog
ocsenave@249 307 seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
ocsenave@249 308 ([rom]
ocsenave@249 309 (map character-codes->str
ocsenave@249 310 (take-nth 2
ocsenave@249 311 (partition-by #(= % 0x57)
ocsenave@249 312 (take 0x0F728
ocsenave@249 313 (drop 0x98000 rom))))))
ocsenave@249 314 ([]
ocsenave@249 315 (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
ocsenave@249 316
ocsenave@246 317
ocsenave@246 318 (def hxc-move-names
ocsenave@246 319 "The hardcoded move names in memory. List begins at ROM@BC000"
ocsenave@249 320 (hxc-thunk-words 0xBC000 1551))
ocsenave@246 321
ocsenave@249 322
ocsenave@249 323 (defn hxc-move-data
ocsenave@246 324 "The hardcoded (basic (move effects)) in memory. List begins at
ocsenave@249 325 0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
ocsenave@249 326 :fx-txt}. The move descriptions are handwritten, not hardcoded."
ocsenave@249 327 ([]
ocsenave@249 328 (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 329 ([rom]
ocsenave@249 330 (let [names (vec (hxc-move-names rom))
ocsenave@249 331 move-count (count names)
ocsenave@281 332 move-size 6
ocsenave@281 333 types pkmn-types ;;; !! hardcoded types
ocsenave@281 334 ]
ocsenave@249 335 (zipmap (map format-name names)
ocsenave@249 336 (map
ocsenave@281 337 (fn [[idx effect power type-id accuracy pp]]
ocsenave@249 338 {:name (names (dec idx))
ocsenave@249 339 :power power
ocsenave@249 340 :accuracy accuracy
ocsenave@249 341 :pp pp
ocsenave@281 342 :type (types type-id)
ocsenave@249 343 :fx-id effect
ocsenave@249 344 :fx-txt (get move-effects effect)
ocsenave@249 345 }
ocsenave@249 346 )
ocsenave@249 347
ocsenave@249 348 (partition move-size
ocsenave@249 349 (take (* move-size move-count)
ocsenave@249 350 (drop 0x38000 rom))))))))
ocsenave@246 351
ocsenave@246 352
ocsenave@246 353
ocsenave@249 354 (defn hxc-move-data*
ocsenave@249 355 "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
ocsenave@249 356 ([]
ocsenave@249 357 (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 358 ([rom]
ocsenave@249 359 (let [names (vec (hxc-move-names rom))
ocsenave@249 360 move-count (count names)
ocsenave@249 361 move-size 6
ocsenave@249 362 format-name (fn [s]
ocsenave@249 363 (keyword (.toLowerCase
ocsenave@249 364 (apply str
ocsenave@249 365 (map #(if (= % \space) "-" %) s)))))
ocsenave@249 366 ]
ocsenave@249 367 (zipmap (map format-name names)
ocsenave@249 368 (map
ocsenave@249 369 (fn [[idx effect power type accuracy pp]]
ocsenave@249 370 {:name (names (dec idx))
ocsenave@249 371 :power power
ocsenave@249 372 :accuracy (hex accuracy)
ocsenave@249 373 :pp pp
ocsenave@249 374 :fx-id (hex effect)
ocsenave@249 375 :fx-txt (get move-effects effect)
ocsenave@249 376 }
ocsenave@249 377 )
ocsenave@249 378
ocsenave@249 379 (partition move-size
ocsenave@249 380 (take (* move-size move-count)
ocsenave@249 381 (drop 0x38000 rom))))))))
ocsenave@243 382
ocsenave@243 383
ocsenave@283 384 (defn hxc-machines
ocsenave@283 385 "The hardcoded moves taught by TMs and HMs. List begins at ROM@0x1232D."
ocsenave@283 386 ([] (hxc-machines
ocsenave@283 387 com.aurellem.gb.gb-driver/original-rom))
ocsenave@283 388 ([rom]
ocsenave@283 389 (let [moves (hxc-move-names rom)]
ocsenave@283 390 (zipmap
ocsenave@283 391 (range)
ocsenave@283 392 (take-while
ocsenave@283 393 (comp not nil?)
ocsenave@283 394 (map (comp
ocsenave@283 395 format-name
ocsenave@283 396 (zipmap
ocsenave@283 397 (range)
ocsenave@283 398 moves)
ocsenave@283 399 dec)
ocsenave@283 400 (take 100
ocsenave@283 401 (drop 0x1232D rom))))))))
ocsenave@283 402
ocsenave@249 403 (defn hxc-pokenames
ocsenave@249 404 "The hardcoded names of the 190 species in memory. List begins at
ocsenave@249 405 ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
ocsenave@285 406 long, these names are stripped of padding. See also, hxc-pokedex-names"
ocsenave@249 407 ([]
ocsenave@249 408 (hxc-pokenames com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 409 ([rom]
ocsenave@249 410 (let [count-species 190
ocsenave@249 411 name-length 10]
ocsenave@249 412 (map character-codes->str
ocsenave@249 413 (partition name-length
ocsenave@249 414 (map #(if (= 0x50 %) 0x00 %)
ocsenave@249 415 (take (* count-species name-length)
ocsenave@249 416 (drop 0xE8000
ocsenave@249 417 rom))))))))
ocsenave@243 418
ocsenave@259 419
ocsenave@259 420
ocsenave@285 421 (defn hxc-pokedex-names
ocsenave@285 422 "The names of the pokemon in hardcoded pokedex order. List begins at
ocsenave@285 423 ROM@410B1. See also, hxc-pokenames."
ocsenave@285 424 ([] (hxc-pokedex-names
ocsenave@285 425 com.aurellem.gb.gb-driver/original-rom))
ocsenave@285 426 ([rom]
ocsenave@285 427 (let [names (hxc-pokenames rom)]
ocsenave@285 428 (#(mapv %
ocsenave@285 429 ((comp range count keys) %))
ocsenave@285 430 (zipmap
ocsenave@285 431 (take (count names)
ocsenave@285 432 (drop 0x410b1 rom))
ocsenave@285 433
ocsenave@285 434 (map format-name names))))))
ocsenave@285 435
ocsenave@285 436
ocsenave@259 437
ocsenave@259 438 (defn internal-id
ocsenave@259 439 ([rom]
ocsenave@259 440 (zipmap
ocsenave@259 441 (map format-name (hxc-pokenames rom))
ocsenave@259 442 (range)))
ocsenave@259 443 ([]
ocsenave@259 444 (internal-id com.aurellem.gb.gb-driver/original-rom)))
ocsenave@285 445
ocsenave@285 446
ocsenave@285 447
ocsenave@259 448
ocsenave@259 449
ocsenave@263 450 ;; nidoran gender change upon levelup
ocsenave@263 451 ;; (->
ocsenave@263 452 ;; @current-state
ocsenave@263 453 ;; rom
ocsenave@263 454 ;; vec
ocsenave@263 455 ;; (rewrite-memory
ocsenave@263 456 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
ocsenave@263 457 ;; [1 1 15])
ocsenave@263 458 ;; (rewrite-memory
ocsenave@263 459 ;; (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
ocsenave@263 460 ;; [1 1 3])
ocsenave@263 461 ;; (write-rom!)
ocsenave@263 462
ocsenave@263 463 ;; )
ocsenave@263 464
ocsenave@259 465
ocsenave@259 466
ocsenave@259 467
ocsenave@249 468 (defn hxc-advantage
ocsenave@249 469 "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 470 the multiplier is 1."
ocsenave@249 471 ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
ocsenave@249 472 ([rom]
ocsenave@249 473 (map
ocsenave@249 474 (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
ocsenave@249 475 (get pkmn-types def (hex def))
ocsenave@249 476 (/ mult 10)])
ocsenave@249 477 (partition 3
ocsenave@249 478 (take-while (partial not= 0xFF)
ocsenave@249 479 (drop 0x3E62D rom))))))
ocsenave@243 480
ocsenave@243 481
ocsenave@281 482
ocsenave@263 483 (defn format-evo
ocsenave@263 484 [coll]
ocsenave@263 485 (let [method (first coll)]
ocsenave@263 486 (cond (empty? coll) []
ocsenave@263 487 (= 0 method) [] ;; just in case
ocsenave@263 488 (= 1 method) ;; level-up evolution
ocsenave@263 489 (conj (format-evo (drop 3 coll))
ocsenave@263 490 {:method :level-up
ocsenave@263 491 :min-level (nth coll 1)
ocsenave@263 492 :into (dec (nth coll 2))})
ocsenave@263 493
ocsenave@263 494 (= 2 method) ;; item evolution
ocsenave@263 495 (conj (format-evo (drop 4 coll))
ocsenave@263 496 {:method :item
ocsenave@263 497 :item (dec (nth coll 1))
ocsenave@263 498 :min-level (nth coll 2)
ocsenave@263 499 :into (dec (nth coll 3))})
ocsenave@243 500
ocsenave@263 501 (= 3 method) ;; trade evolution
ocsenave@263 502 (conj (format-evo (drop 3 coll))
ocsenave@263 503 {:method :trade
ocsenave@263 504 :min-level (nth coll 1) ;; always 1 for trade.
ocsenave@263 505 :into (dec (nth coll 2))}))))
ocsenave@243 506
ocsenave@243 507
ocsenave@263 508 (defn hxc-ptrs-evolve
ocsenave@267 509 "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
ocsenave@263 510 in internal order."
ocsenave@263 511 ([]
ocsenave@263 512 (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
ocsenave@259 513 ([rom]
ocsenave@259 514 (let [names (hxc-pokenames rom)
ocsenave@259 515 pkmn-count (count names)
ocsenave@259 516 ptrs
ocsenave@263 517 (map (fn [[a b]] (low-high a b))
ocsenave@259 518 (partition 2
ocsenave@259 519 (take (* 2 pkmn-count)
ocsenave@263 520 (drop 0x3b1e5 rom))))]
ocsenave@263 521 (map (partial + 0x34000) ptrs)
ocsenave@263 522
ocsenave@263 523 )))
ocsenave@263 524
ocsenave@267 525
ocsenave@267 526 (defn hxc-learnsets
ocsenave@267 527 "Hardcoded map associating pokemon names to lists of pairs [lvl
ocsenave@267 528 move] of abilities they learn as they level up. The data
ocsenave@267 529 exists at ROM@3400, sorted by internal order. Pointers to the data
ocsenave@267 530 exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
ocsenave@267 531 ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
ocsenave@267 532 ([rom]
ocsenave@267 533 (apply assoc
ocsenave@267 534 {}
ocsenave@267 535 (interleave
ocsenave@267 536 (map format-name (hxc-pokenames rom))
ocsenave@267 537 (map (comp
ocsenave@268 538 (partial map
ocsenave@268 539 (fn [[lvl mv]] [lvl (dec mv)]))
ocsenave@267 540 (partial partition 2)
ocsenave@267 541 ;; keep the learnset data
ocsenave@267 542 (partial take-while (comp not zero?))
ocsenave@267 543 ;; skip the evolution data
ocsenave@267 544 rest
ocsenave@267 545 (partial drop-while (comp not zero?)))
ocsenave@267 546 (map #(drop % rom)
ocsenave@267 547 (hxc-ptrs-evolve rom)))))))
ocsenave@267 548
ocsenave@267 549 (defn hxc-learnsets-pretty
ocsenave@267 550 "Live hxc-learnsets except it reports the name of each move --- as
ocsenave@267 551 it appears in rom --- rather than the move index."
ocsenave@267 552 ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@267 553 ([rom]
ocsenave@267 554 (let [moves (vec(map format-name (hxc-move-names)))]
ocsenave@267 555 (into {}
ocsenave@267 556 (map (fn [[pkmn learnset]]
ocsenave@268 557 [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
ocsenave@267 558 learnset)])
ocsenave@267 559 (hxc-learnsets rom))))))
ocsenave@267 560
ocsenave@267 561
ocsenave@267 562
ocsenave@267 563
ocsenave@263 564 (defn hxc-evolution
ocsenave@263 565 "Hardcoded evolution data in memory. The data exists at ROM@34000,
ocsenave@263 566 sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
ocsenave@263 567 ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
ocsenave@263 568 ([rom]
ocsenave@259 569 (apply assoc {}
ocsenave@259 570 (interleave
ocsenave@267 571 (map format-name (hxc-pokenames rom))
ocsenave@259 572 (map
ocsenave@259 573 (comp
ocsenave@259 574 format-evo
ocsenave@263 575 (partial take-while (comp not zero?))
ocsenave@263 576 #(drop % rom))
ocsenave@263 577 (hxc-ptrs-evolve rom)
ocsenave@263 578 )))))
ocsenave@259 579
ocsenave@263 580 (defn hxc-evolution-pretty
ocsenave@263 581 "Like hxc-evolution, except it uses the names of items and pokemon
ocsenave@263 582 --- grabbed from ROM --- rather than their numerical identifiers."
ocsenave@263 583 ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
ocsenave@263 584 ([rom]
ocsenave@263 585 (let
ocsenave@263 586 [poke-names (vec (map format-name (hxc-pokenames rom)))
ocsenave@263 587 item-names (vec (map format-name (hxc-items rom)))
ocsenave@263 588 use-names
ocsenave@263 589 (fn [m]
ocsenave@263 590 (loop [ks (keys m) new-map m]
ocsenave@263 591 (let [k (first ks)]
ocsenave@263 592 (cond (nil? ks) new-map
ocsenave@263 593 (= k :into)
ocsenave@263 594 (recur
ocsenave@263 595 (next ks)
ocsenave@263 596 (assoc new-map
ocsenave@263 597 :into
ocsenave@263 598 (poke-names
ocsenave@263 599 (:into
ocsenave@263 600 new-map))))
ocsenave@263 601 (= k :item)
ocsenave@263 602 (recur
ocsenave@263 603 (next ks)
ocsenave@263 604 (assoc new-map
ocsenave@263 605 :item
ocsenave@263 606 (item-names
ocsenave@263 607 (:item new-map))))
ocsenave@263 608 :else
ocsenave@263 609 (recur
ocsenave@263 610 (next ks)
ocsenave@263 611 new-map)
ocsenave@263 612 ))))]
ocsenave@259 613
ocsenave@263 614 (into {}
ocsenave@263 615 (map (fn [[pkmn evo-coll]]
ocsenave@263 616 [pkmn (map use-names evo-coll)])
ocsenave@263 617 (hxc-evolution rom))))))
ocsenave@263 618
ocsenave@243 619
ocsenave@243 620
ocsenave@243 621
ocsenave@243 622
ocsenave@273 623 (defn hxc-pokemon-base
ocsenave@273 624 ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
ocsenave@273 625 ([rom]
ocsenave@273 626 (let [entry-size 28
ocsenave@273 627 pkmn-count (count (hxc-pokedex-text rom))
ocsenave@285 628 pokemon (rest (hxc-pokedex-names))
ocsenave@273 629 types (apply assoc {}
ocsenave@273 630 (interleave
ocsenave@273 631 (range)
ocsenave@273 632 pkmn-types)) ;;!! softcoded
ocsenave@273 633 moves (apply assoc {}
ocsenave@273 634 (interleave
ocsenave@273 635 (range)
ocsenave@273 636 (map format-name
ocsenave@273 637 (hxc-move-names rom))))
ocsenave@273 638 ]
ocsenave@285 639 (zipmap
ocsenave@285 640 pokemon
ocsenave@285 641 (map
ocsenave@285 642 (fn [[n
ocsenave@285 643 rating-hp
ocsenave@285 644 rating-atk
ocsenave@285 645 rating-def
ocsenave@285 646 rating-speed
ocsenave@285 647 rating-special
ocsenave@285 648 type-1
ocsenave@285 649 type-2
ocsenave@285 650 rarity
ocsenave@285 651 rating-xp
ocsenave@285 652 pic-dimensions ;; tile_width|tile_height (8px/tile)
ocsenave@285 653 ptr-pic-obverse-1
ocsenave@285 654 ptr-pic-obverse-2
ocsenave@285 655 ptr-pic-reverse-1
ocsenave@285 656 ptr-pic-reverse-2
ocsenave@285 657 move-1
ocsenave@285 658 move-2
ocsenave@285 659 move-3
ocsenave@285 660 move-4
ocsenave@285 661 growth-rate
ocsenave@285 662 &
ocsenave@285 663 TMs|HMs]]
ocsenave@285 664 (let
ocsenave@285 665 [base-moves
ocsenave@285 666 (mapv moves
ocsenave@285 667 ((comp
ocsenave@285 668 ;; since the game uses zero as a delimiter,
ocsenave@285 669 ;; it must also increment all move indices by 1.
ocsenave@285 670 ;; heren we decrement to correct this.
ocsenave@285 671 (partial map dec)
ocsenave@285 672 (partial take-while (comp not zero?)))
ocsenave@285 673 [move-1 move-2 move-3 move-4]))
ocsenave@285 674
ocsenave@285 675 types
ocsenave@285 676 (set (list (types type-1)
ocsenave@285 677 (types type-2)))
ocsenave@285 678 TMs|HMs
ocsenave@285 679 (map
ocsenave@285 680 (comp
ocsenave@285 681 (partial map first)
ocsenave@285 682 (partial remove (comp zero? second)))
ocsenave@285 683 (split-at
ocsenave@285 684 50
ocsenave@285 685 (map vector
ocsenave@285 686 (rest(range))
ocsenave@285 687 (reduce concat
ocsenave@285 688 (map
ocsenave@285 689 #(take 8
ocsenave@285 690 (concat (bit-list %)
ocsenave@285 691 (repeat 0)))
ocsenave@285 692
ocsenave@273 693 TMs|HMs)))))
ocsenave@285 694
ocsenave@285 695 TMs (vec (first TMs|HMs))
ocsenave@285 696 HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
ocsenave@285 697
ocsenave@285 698
ocsenave@285 699 ]
ocsenave@285 700
ocsenave@285 701
ocsenave@285 702 {:dex# n
ocsenave@285 703 :base-moves base-moves
ocsenave@285 704 :types types
ocsenave@285 705 :TMs TMs
ocsenave@285 706 :HMs HMs
ocsenave@285 707 :base-hp rating-hp
ocsenave@285 708 :base-atk rating-atk
ocsenave@285 709 :base-def rating-def
ocsenave@285 710 :base-speed rating-speed
ocsenave@285 711 :base-special rating-special
ocsenave@285 712 }))
ocsenave@285 713
ocsenave@285 714 (partition entry-size
ocsenave@285 715 (take (* entry-size pkmn-count)
ocsenave@285 716 (drop 0x383DE
ocsenave@285 717 rom))))))))
ocsenave@285 718
ocsenave@285 719
ocsenave@285 720
ocsenave@282 721 (defn hxc-item-prices
ocsenave@282 722 "The hardcoded list of item prices in memory. List begins at ROM@4495"
ocsenave@282 723 ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
ocsenave@282 724 ([rom]
ocsenave@282 725 (let [items (map format-name (hxc-items rom))
ocsenave@282 726 price-size 3]
ocsenave@282 727 (zipmap items
ocsenave@282 728 (map (comp
ocsenave@282 729 ;; zero-cost items are "priceless"
ocsenave@282 730 #(if (zero? %) :priceless %)
ocsenave@282 731 decode-bcd butlast)
ocsenave@282 732 (partition price-size
ocsenave@282 733 (take (* price-size (count items))
ocsenave@282 734 (drop 0x4495 rom))))))))
ocsenave@273 735
ocsenave@281 736 (defn hxc-shops
ocsenave@281 737 ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
ocsenave@281 738 ([rom]
ocsenave@281 739 (let [items (zipmap (range) (map format-name (hxc-items rom)))
ocsenave@281 740
ocsenave@281 741 ;; temporarily softcode the TM items
ocsenave@281 742 items (into
ocsenave@281 743 items
ocsenave@281 744 (map (juxt identity
ocsenave@281 745 (comp keyword
ocsenave@281 746 (partial str "tm-")
ocsenave@281 747 (partial + 1 -200)
ocsenave@281 748 ))
ocsenave@281 749 (take 200 (drop 200 (range)))))
ocsenave@282 750
ocsenave@281 751 ]
ocsenave@281 752
ocsenave@281 753 ((fn parse-shop [coll [num-items & items-etc]]
ocsenave@282 754 (let [inventory (take-while
ocsenave@282 755 (partial not= 0xFF)
ocsenave@282 756 items-etc)
ocsenave@281 757 [separator & items-etc] (drop num-items (rest items-etc))]
ocsenave@281 758 (if (= separator 0x50)
ocsenave@281 759 (map (partial mapv (comp items dec)) (conj coll inventory))
ocsenave@281 760 (recur (conj coll inventory) items-etc)
ocsenave@281 761 )
ocsenave@281 762 ))
ocsenave@281 763
ocsenave@281 764 '()
ocsenave@282 765 (drop 0x233C rom))
ocsenave@281 766
ocsenave@281 767
ocsenave@281 768 )))
ocsenave@281 769
ocsenave@281 770
ocsenave@273 771
ocsenave@249 772 ;; ********************** MANIPULATION FNS
ocsenave@249 773
ocsenave@249 774
ocsenave@285 775 (defn same-type
ocsenave@285 776 ([pkmn move]
ocsenave@285 777 (same-type?
ocsenave@285 778 com.aurellem.gb.gb-driver/original-rom pkmn move))
ocsenave@285 779 ([rom pkmn move]
ocsenave@285 780 (((comp :types (hxc-pokemon-base rom)) pkmn)
ocsenave@285 781 ((comp :type (hxc-move-data rom)) move))))
ocsenave@285 782
ocsenave@285 783
ocsenave@249 784
ocsenave@249 785
ocsenave@249 786 (defn submap?
ocsenave@249 787 "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false."
ocsenave@249 788 [map-small map-big]
ocsenave@249 789 (cond (empty? map-small) true
ocsenave@249 790 (and
ocsenave@249 791 (contains? map-big (ffirst map-small))
ocsenave@249 792 (= (get map-big (ffirst map-small))
ocsenave@249 793 (second (first map-small))))
ocsenave@249 794 (recur (next map-small) map-big)
ocsenave@249 795
ocsenave@249 796 :else false))
ocsenave@249 797
ocsenave@249 798
ocsenave@249 799 (defn search-map [proto-map maps]
ocsenave@249 800 "Returns all the maps that make the same associations as proto-map."
ocsenave@249 801 (some (partial submap? proto-map) maps))
ocsenave@249 802
rlm@252 803 (defn filter-vals
rlm@252 804 "Returns a map consisting of all the pairs [key val] for
rlm@252 805 which (pred key) returns true."
rlm@252 806 [pred map]
rlm@252 807 (reduce (partial apply assoc) {}
rlm@252 808 (filter (fn [[k v]] (pred v)) map)))
ocsenave@249 809
ocsenave@249 810
ocsenave@249 811 (defn search-moves
rlm@252 812 "Returns a subcollection of all hardcoded moves with the
rlm@252 813 given attributes. Attributes consist of :name :power
rlm@252 814 :accuracy :pp :fx-id
rlm@252 815 (and also :fx-txt, but it contains the same information
rlm@252 816 as :fx-id)"
ocsenave@249 817 ([attribute-map]
rlm@252 818 (search-moves
rlm@252 819 com.aurellem.gb.gb-driver/original-rom attribute-map))
ocsenave@249 820 ([rom attribute-map]
rlm@252 821 (filter-vals (partial submap? attribute-map)
rlm@252 822 (hxc-move-data rom))))
ocsenave@249 823
ocsenave@249 824
ocsenave@249 825
ocsenave@249 826
ocsenave@243 827
ocsenave@283 828 ;; note: 0x2f31 contains the names "TM" "HM"?
ocsenave@283 829
ocsenave@246 830 ;; note for later: credits start at F1290
ocsenave@243 831
ocsenave@243 832
ocsenave@243 833
ocsenave@246 834 (comment
ocsenave@243 835
rlm@218 836 (def hxc-later
rlm@218 837 "Running this code produces, e.g. hardcoded names NPCs give
rlm@218 838 their pokemon. Will sort through it later."
rlm@218 839 (print (character-codes->str(take 10000
rlm@218 840 (drop 0x71597
rlm@218 841 (rom (root)))))))
rlm@218 842
rlm@218 843 (let [dex
rlm@218 844 (partition-by #(= 0x50 %)
rlm@218 845 (take 2540
rlm@218 846 (drop 0x40687
rlm@218 847 (rom (root)))))]
rlm@218 848 (def dex dex)
rlm@218 849 (def hxc-species
rlm@218 850 (map character-codes->str
rlm@218 851 (take-nth 4 dex))))
ocsenave@259 852 )
ocsenave@259 853
ocsenave@259 854
ocsenave@259 855
ocsenave@281 856
ocsenave@281 857
ocsenave@281 858