annotate clojure/com/aurellem/exp/pokemon.clj @ 169:4857f59f63a6

added functions to read and set DV values for pokemon.
author Robert McIntyre <rlm@mit.edu>
date Wed, 21 Mar 2012 01:37:10 -0500
parents 04dfda91db9c
children 63ec3db6f6d1
rev   line source
rlm@145 1 (ns com.aurellem.exp.pokemon
rlm@145 2 "Here I find out how pokemon are stored in memory."
rlm@145 3 (:use (com.aurellem.gb gb-driver items assembly util
rlm@166 4 constants
rlm@166 5 characters species moves))
rlm@161 6 (:import java.io.File)
rlm@145 7 (:import [com.aurellem.gb.gb_driver SaveState]))
rlm@145 8
rlm@145 9
rlm@145 10 (def pidgeot-lvl-36 (mid-game))
rlm@145 11
rlm@145 12
rlm@145 13 (def pidgeot-lvl-37 (read-state "pidgeot-lvl-37"))
rlm@145 14
rlm@145 15
rlm@145 16 (def pidgeot-lvl-38 (read-state "pidgeot-lvl-38"))
rlm@145 17
rlm@145 18
rlm@145 19 (def pidgeot-lvl-39 (read-state "pidgeot-lvl-39"))
rlm@145 20
rlm@145 21
rlm@145 22 (def pidgeot-lvl-40 (read-state "pidgeot-lvl-40"))
rlm@145 23
rlm@145 24
rlm@145 25 (defn level-analysis []
rlm@145 26 (apply common-differences
rlm@145 27 (map (comp vec memory)
rlm@145 28 [pidgeot-lvl-36
rlm@145 29 pidgeot-lvl-37
rlm@145 30 pidgeot-lvl-38
rlm@145 31 pidgeot-lvl-39
rlm@145 32 pidgeot-lvl-40])))
rlm@145 33
rlm@145 34 ;; inconclusive -- implies that level is calculated from
rlm@145 35 ;; some other values.
rlm@145 36
rlm@145 37
rlm@145 38 (def name-pidgeotto (read-state "name-pidgeotto"))
rlm@145 39 (def named-A (read-state "named-A"))
rlm@145 40 (def named-B (read-state "named-B"))
rlm@145 41 (def named-C (read-state "named-C"))
rlm@145 42 (def named-D (read-state "named-D"))
rlm@145 43 (def named-E (read-state "named-E"))
rlm@145 44 (def named-F (read-state "named-F"))
rlm@145 45
rlm@145 46 (defn name-analysis []
rlm@145 47 (apply common-differences
rlm@145 48 (map (comp vec memory)
rlm@145 49 [named-A
rlm@145 50 named-B
rlm@145 51 named-C
rlm@145 52 named-D
rlm@145 53 named-E
rlm@145 54 named-F])))
rlm@145 55
rlm@145 56 ;; resluted in 3 separate locations that could
rlm@145 57 ;; possibly hold the first letter of the pokemon's name
rlm@145 58
rlm@145 59 0xCF4A
rlm@145 60 0xD2EB
rlm@145 61 0xCEED
rlm@145 62
rlm@145 63 ;; try changing each of them
rlm@145 64
rlm@145 65
rlm@145 66 (defn test-cf4a []
rlm@145 67 (continue!
rlm@145 68 (set-memory named-A 0xCF4A (character->character-code "Z"))))
rlm@145 69 ;; result -- pidgeotto named "A"
rlm@145 70
rlm@145 71 (defn test-d2eb []
rlm@145 72 (continue!
rlm@145 73 (set-memory named-A 0xD2EB (character->character-code "Z"))))
rlm@145 74 ;; result -- pidgeotto named "Z"
rlm@145 75
rlm@145 76 (defn test-ceed []
rlm@145 77 (continue!
rlm@145 78 (set-memory named-A 0xCEED (character->character-code "Z"))))
rlm@145 79 ;; result -- pidgeotto named "A"
rlm@145 80
rlm@145 81 (def sixth-pokemon-name-start 0xD2EB)
rlm@145 82
rlm@145 83
rlm@145 84 (defn set-sixth-pokemon-name-first-character
rlm@145 85 ([state character]
rlm@145 86 (set-memory state sixth-pokemon-name-start
rlm@145 87 (character->character-code character)))
rlm@145 88 ([character]
rlm@145 89 (set-sixth-pokemon-name-first-character @current-state
rlm@145 90 character)))
rlm@145 91
rlm@145 92
rlm@146 93 (def end-of-name-marker 0x50)
rlm@147 94 (def max-name-length 10)
rlm@147 95 (def name-width 11)
rlm@147 96
rlm@148 97 (defn read-name [codes]
rlm@147 98 (character-codes->str
rlm@147 99 (take-while
rlm@147 100 (partial not= end-of-name-marker) codes)))
rlm@147 101
rlm@145 102
rlm@146 103 (defn sixth-pokemon-name [^SaveState state]
rlm@148 104 (read-name
rlm@146 105 (subvec (vec (memory state))
rlm@146 106 sixth-pokemon-name-start
rlm@146 107 (+ (inc max-name-length)
rlm@147 108 sixth-pokemon-name-start))))
rlm@145 109
rlm@147 110 (defn rename-sixth-pokemon
rlm@147 111 ([^SaveState state new-name]
rlm@147 112 (assert (< (count new-name) max-name-length))
rlm@147 113 (set-memory-range state sixth-pokemon-name-start
rlm@147 114 (concat (str->character-codes new-name)
rlm@147 115 [end-of-name-marker])))
rlm@147 116 ([new-name]
rlm@147 117 (rename-sixth-pokemon @current-state new-name)))
rlm@147 118
rlm@147 119 (defn print-text
rlm@147 120 ([^SaveState state begin end]
rlm@147 121 (dorun
rlm@147 122 (map (fn [character-code line]
rlm@147 123 (println
rlm@147 124 (format "0x%04X: " line)
rlm@149 125 (str (character-code->character character-code))))
rlm@147 126 (subvec (vec (memory state)) begin end)
rlm@147 127 (range begin end)))
rlm@147 128 state)
rlm@147 129 ([begin end]
rlm@147 130 (print-text @current-state begin end)))
rlm@147 131
rlm@147 132 (defn examine-name-memory []
rlm@147 133 (print-text
rlm@147 134 named-A
rlm@147 135 (- sixth-pokemon-name-start 100)
rlm@147 136 (+ sixth-pokemon-name-start 100)))
rlm@147 137
rlm@147 138 ;; results:
rlm@147 139 ;; 0xD287: end-of-name-sentinel
rlm@147 140 ;; 0xD288: R
rlm@147 141 ;; 0xD289: L
rlm@147 142 ;; 0xD28A: M
rlm@147 143 ;; 0xD28B: end-of-pokemon-name-sentinel
rlm@147 144 ;; 0xD28C: end-of-name-sentinel
rlm@147 145 ;; 0xD28D: end-of-name-sentinel
rlm@147 146 ;; 0xD28E: end-of-name-sentinel
rlm@147 147 ;; 0xD28F: end-of-name-sentinel
rlm@147 148 ;; 0xD290: end-of-name-sentinel
rlm@147 149 ;; 0xD291: end-of-name-sentinel
rlm@147 150 ;; 0xD292: end-of-name-sentinel
rlm@147 151 ;; 0xD293: R
rlm@147 152 ;; 0xD294: L
rlm@147 153 ;; 0xD295: M
rlm@147 154 ;; 0xD296: end-of-pokemon-name-sentinel
rlm@147 155 ;; 0xD297: end-of-name-sentinel
rlm@147 156 ;; 0xD298: end-of-name-sentinel
rlm@147 157 ;; 0xD299: end-of-name-sentinel
rlm@147 158 ;; 0xD29A: end-of-name-sentinel
rlm@147 159 ;; 0xD29B: end-of-name-sentinel
rlm@147 160 ;; 0xD29C: end-of-name-sentinel
rlm@147 161 ;; 0xD29D: end-of-name-sentinel
rlm@147 162 ;; 0xD29E: R
rlm@147 163 ;; 0xD29F: L
rlm@147 164 ;; 0xD2A0: M
rlm@147 165 ;; 0xD2A1: end-of-pokemon-name-sentinel
rlm@147 166 ;; 0xD2A2: end-of-name-sentinel
rlm@147 167 ;; 0xD2A3: end-of-name-sentinel
rlm@147 168 ;; 0xD2A4: end-of-name-sentinel
rlm@147 169 ;; 0xD2A5: end-of-name-sentinel
rlm@147 170 ;; 0xD2A6: end-of-name-sentinel
rlm@147 171 ;; 0xD2A7: end-of-name-sentinel
rlm@147 172 ;; 0xD2A8: end-of-name-sentinel
rlm@147 173 ;; 0xD2A9: R
rlm@147 174 ;; 0xD2AA: L
rlm@147 175 ;; 0xD2AB: M
rlm@147 176 ;; 0xD2AC: end-of-pokemon-name-sentinel
rlm@147 177 ;; 0xD2AD: end-of-name-sentinel
rlm@147 178 ;; 0xD2AE: end-of-name-sentinel
rlm@147 179 ;; 0xD2AF: end-of-name-sentinel
rlm@147 180 ;; 0xD2B0: end-of-name-sentinel
rlm@147 181 ;; 0xD2B1: end-of-name-sentinel
rlm@147 182 ;; 0xD2B2: end-of-name-sentinel
rlm@147 183 ;; 0xD2B3: end-of-name-sentinel
rlm@147 184 ;; 0xD2B4: P
rlm@147 185 ;; 0xD2B5: I
rlm@147 186 ;; 0xD2B6: D
rlm@147 187 ;; 0xD2B7: G
rlm@147 188 ;; 0xD2B8: E
rlm@147 189 ;; 0xD2B9: O
rlm@147 190 ;; 0xD2BA: T
rlm@147 191 ;; 0xD2BB: end-of-pokemon-name-sentinel
rlm@147 192 ;; 0xD2BC: end-of-pokemon-name-sentinel
rlm@147 193 ;; 0xD2BD: end-of-pokemon-name-sentinel
rlm@147 194 ;; 0xD2BE: end-of-pokemon-name-sentinel
rlm@147 195 ;; 0xD2BF: P
rlm@147 196 ;; 0xD2C0: I
rlm@147 197 ;; 0xD2C1: K
rlm@147 198 ;; 0xD2C2: A
rlm@147 199 ;; 0xD2C3: C
rlm@147 200 ;; 0xD2C4: H
rlm@147 201 ;; 0xD2C5: U
rlm@147 202 ;; 0xD2C6: end-of-pokemon-name-sentinel
rlm@147 203 ;; 0xD2C7: end-of-pokemon-name-sentinel
rlm@147 204 ;; 0xD2C8: end-of-pokemon-name-sentinel
rlm@147 205 ;; 0xD2C9: end-of-pokemon-name-sentinel
rlm@147 206 ;; 0xD2CA: C
rlm@147 207 ;; 0xD2CB: H
rlm@147 208 ;; 0xD2CC: A
rlm@147 209 ;; 0xD2CD: R
rlm@147 210 ;; 0xD2CE: I
rlm@147 211 ;; 0xD2CF: Z
rlm@147 212 ;; 0xD2D0: A
rlm@147 213 ;; 0xD2D1: R
rlm@147 214 ;; 0xD2D2: D
rlm@147 215 ;; 0xD2D3: end-of-pokemon-name-sentinel
rlm@147 216 ;; 0xD2D4: end-of-pokemon-name-sentinel
rlm@147 217 ;; 0xD2D5: V
rlm@147 218 ;; 0xD2D6: E
rlm@147 219 ;; 0xD2D7: N
rlm@147 220 ;; 0xD2D8: U
rlm@147 221 ;; 0xD2D9: S
rlm@147 222 ;; 0xD2DA: A
rlm@147 223 ;; 0xD2DB: U
rlm@147 224 ;; 0xD2DC: R
rlm@147 225 ;; 0xD2DD: end-of-pokemon-name-sentinel
rlm@147 226 ;; 0xD2DE: end-of-pokemon-name-sentinel
rlm@147 227 ;; 0xD2DF: end-of-pokemon-name-sentinel
rlm@147 228 ;; 0xD2E0: P
rlm@147 229 ;; 0xD2E1: R
rlm@147 230 ;; 0xD2E2: I
rlm@147 231 ;; 0xD2E3: M
rlm@147 232 ;; 0xD2E4: E
rlm@147 233 ;; 0xD2E5: A
rlm@147 234 ;; 0xD2E6: P
rlm@147 235 ;; 0xD2E7: E
rlm@147 236 ;; 0xD2E8: end-of-pokemon-name-sentinel
rlm@147 237 ;; 0xD2E9: end-of-pokemon-name-sentinel
rlm@147 238 ;; 0xD2EA: end-of-pokemon-name-sentinel
rlm@147 239 ;; 0xD2EB: A
rlm@147 240 ;; 0xD2EC: end-of-pokemon-name-sentinel
rlm@147 241 ;; 0xD2ED: S
rlm@147 242 ;; 0xD2EE: T
rlm@147 243 ;; 0xD2EF: E
rlm@147 244 ;; 0xD2F0: R
rlm@147 245 ;; 0xD2F1:
rlm@147 246 ;; 0xD2F2: B
rlm@147 247 ;; 0xD2F3: A
rlm@147 248 ;; 0xD2F4: L
rlm@147 249 ;; 0xD2F5: L
rlm@147 250 ;; 0xD2F6:
rlm@147 251 ;; 0xD2F7: A
rlm@147 252 ;; 0xD2F8:
rlm@147 253 ;; 0xD2F9:
rlm@147 254 ;; 0xD2FA: end-of-name-sentinel
rlm@147 255 ;; 0xD2FB: end-of-name-sentinel
rlm@147 256 ;; 0xD2FC: A
rlm@147 257 ;; 0xD2FD:
rlm@147 258 ;; 0xD2FE: end-of-name-sentinel
rlm@147 259 ;; 0xD2FF: end-of-name-sentinel
rlm@147 260 ;; 0xD300: end-of-name-sentinel
rlm@147 261 ;; 0xD301: end-of-name-sentinel
rlm@147 262 ;; 0xD302: end-of-name-sentinel
rlm@147 263 ;; 0xD303: end-of-name-sentinel
rlm@147 264 ;; 0xD304: end-of-name-sentinel
rlm@147 265 ;; 0xD305: end-of-name-sentinel
rlm@147 266 ;; 0xD306: end-of-name-sentinel
rlm@147 267 ;; 0xD307: end-of-name-sentinel
rlm@147 268 ;; 0xD308: end-of-name-sentinel
rlm@147 269 ;; 0xD309:
rlm@147 270 ;; 0xD30A: w
rlm@147 271 ;; 0xD30B:
rlm@147 272 ;; 0xD30C: V
rlm@147 273 ;; 0xD30D:
rlm@147 274 ;; 0xD30E:
rlm@147 275 ;; 0xD30F: K
rlm@147 276 ;; 0xD310:
rlm@147 277 ;; 0xD311:
rlm@147 278 ;; 0xD312:
rlm@147 279 ;; 0xD313: A
rlm@147 280 ;; 0xD314:
rlm@147 281 ;; 0xD315:
rlm@147 282 ;; 0xD316:
rlm@147 283 ;; 0xD317: i
rlm@147 284 ;; 0xD318:
rlm@147 285 ;; 0xD319:
rlm@147 286 ;; 0xD31A: end-of-name-sentinel
rlm@147 287 ;; 0xD31B: end-of-name-sentinel
rlm@147 288 ;; 0xD31C:
rlm@147 289 ;; 0xD31D:
rlm@147 290 ;; 0xD31E:
rlm@147 291 ;; 0xD31F:
rlm@147 292 ;; 0xD320:
rlm@147 293 ;; 0xD321:
rlm@147 294 ;; 0xD322:
rlm@147 295 ;; 0xD323:
rlm@147 296 ;; 0xD324:
rlm@147 297 ;; 0xD325:
rlm@147 298 ;; 0xD326:
rlm@147 299 ;; 0xD327:
rlm@147 300 ;; 0xD328:
rlm@147 301 ;; 0xD329:
rlm@147 302 ;; 0xD32A:
rlm@147 303 ;; 0xD32B:
rlm@147 304 ;; 0xD32C:
rlm@147 305 ;; 0xD32D:
rlm@147 306 ;; 0xD32E:
rlm@147 307 ;; 0xD32F:
rlm@147 308 ;; 0xD330:
rlm@147 309 ;; 0xD331: 9
rlm@147 310 ;; 0xD332: end-of-name-sentinel
rlm@147 311 ;; 0xD333: 9
rlm@147 312 ;; 0xD334:
rlm@147 313 ;; 0xD335: 9
rlm@147 314 ;; 0xD336:
rlm@147 315 ;; 0xD337: 9
rlm@147 316 ;; 0xD338: end-of-name-sentinel
rlm@147 317 ;; 0xD339: end-of-name-sentinel
rlm@147 318 ;; 0xD33A: end-of-name-sentinel
rlm@147 319 ;; 0xD33B: end-of-name-sentinel
rlm@147 320 ;; 0xD33C: end-of-name-sentinel
rlm@147 321 ;; 0xD33D: end-of-name-sentinel
rlm@147 322 ;; 0xD33E: end-of-name-sentinel
rlm@147 323 ;; 0xD33F: end-of-name-sentinel
rlm@147 324 ;; 0xD340: end-of-name-sentinel
rlm@147 325 ;; 0xD341: end-of-name-sentinel
rlm@147 326 ;; 0xD342: end-of-name-sentinel
rlm@147 327 ;; 0xD343: end-of-name-sentinel
rlm@147 328 ;; 0xD344: end-of-name-sentinel
rlm@147 329 ;; 0xD345: end-of-name-sentinel
rlm@147 330 ;; 0xD346:
rlm@147 331 ;; 0xD347:
rlm@147 332 ;; 0xD348:
rlm@147 333 ;; 0xD349: G
rlm@147 334 ;; 0xD34A: A
rlm@147 335 ;; 0xD34B: R
rlm@147 336 ;; 0xD34C: Y
rlm@147 337 ;; 0xD34D: end-of-pokemon-name-sentinel
rlm@147 338 ;; 0xD34E: J
rlm@147 339
rlm@147 340
rlm@147 341 ;; from this, it looks like the pokemon names are stored all
rlm@147 342 ;; together in one location that begins at 0xD2B4 and
rlm@147 343 ;; extends until 0xD2F5, with each name taking up 11 bytes.
rlm@147 344 ;;
rlm@147 345 ;; rival's name again clearly starts at 0xD349.
rlm@147 346
rlm@147 347
rlm@147 348 (def pokemon-names-start 0xD2B4)
rlm@147 349
rlm@147 350
rlm@147 351 ;; determine whether "number of pokemon in party"
rlm@147 352 ;; might be kept in RAM and if so, where?
rlm@147 353
rlm@147 354 (def six-pokemon (read-state "6-pokemon"))
rlm@147 355 (def five-pokemon (read-state "5-pokemon"))
rlm@147 356 (def four-pokemon (read-state "4-pokemon"))
rlm@147 357 (def three-pokemon (read-state "3-pokemon"))
rlm@147 358 (def two-pokemon (read-state "2-pokemon"))
rlm@147 359 (def one-pokemon (read-state "1-pokemon"))
rlm@147 360
rlm@147 361
rlm@147 362 (defn analyze-num-pokemon []
rlm@147 363 (apply common-differences
rlm@147 364 (map (comp vec memory)
rlm@147 365 [one-pokemon
rlm@147 366 two-pokemon
rlm@147 367 three-pokemon
rlm@147 368 four-pokemon
rlm@147 369 five-pokemon
rlm@147 370 six-pokemon])))
rlm@147 371
rlm@147 372 ;; ;; results
rlm@147 373 ;; ([53602 (1 2 3 4 5 6)]
rlm@147 374 ;; [65314 (105 61 93 60 92 34)]
rlm@147 375 ;; [55875 (34 36 43 52 7 0)]
rlm@147 376 ;; [55876 (18 0 33 52 54 30)]
rlm@147 377 ;; [49158 (197 194 77 117 174 134)]
rlm@147 378 ;; [49160 (29 26 57 239 15 243)]
rlm@147 379 ;; [49736 (74 93 34 89 91 59)]
rlm@147 380 ;; [49162 (165 162 182 179 197 109)]
rlm@147 381 ;; [49227 (187 105 204 5 90 238)]
rlm@147 382 ;; [53067 (128 136 132 145 135 11)]
rlm@147 383 ;; [53068 (147 131 141 136 128 7)]
rlm@147 384 ;; [53069 (136 134 148 140 145 2)]
rlm@147 385 ;; [49904 (2 11 10 3 27 12)]
rlm@147 386 ;; [49172 (100 109 213 195 68 104)]
rlm@147 387 ;; [65492 (11 103 128 160 19 56)]
rlm@147 388 ;; [49173 (80 77 72 75 76 67)]
rlm@147 389 ;; [49334 (8 10 11 5 3 1)]
rlm@147 390 ;; [49335 (49 10 11 19 17 15)]
rlm@147 391 ;; [49336 (8 10 11 5 3 1)]
rlm@147 392 ;; [49720 (106 14 118 0 38 11)]
rlm@147 393 ;; [65304 (32 88 19 114 106 33)]
rlm@147 394 ;; [53561 (59 229 48 17 155 103)]
rlm@147 395 ;; [55935 (6 5 4 3 2 1)])
rlm@147 396
rlm@147 397
rlm@147 398 ;; two canidates : 0xD162 or 0xDA7F
rlm@147 399 ;; they seem to always sum to 6...
rlm@147 400
rlm@147 401 ;; try to set both of them when having only one pokemon.
rlm@147 402
rlm@147 403 (defn change-party-number [^SaveState state new-num]
rlm@147 404 (set-memory state 0xD162 new-num))
rlm@147 405
rlm@147 406 ;; (continue! (change-party-number one-pokemon 3))
rlm@147 407 ;; result -- can scroll down beyone first pokemon, finding
rlm@147 408 ;; glitched pokemon in places where there were previously no
rlm@147 409 ;; pokemon.
rlm@147 410
rlm@147 411
rlm@147 412 (defn change-party-number* [^SaveState state new-num]
rlm@147 413 (set-memory state 0xDA7F new-num))
rlm@147 414
rlm@147 415
rlm@147 416 ;; (continue! (change-party-number* one-pokemon 3))
rlm@147 417 ;; cannot widthdraw any pokemon from box 1 past the third
rlm@147 418 ;; pokemon.
rlm@147 419
rlm@147 420 (def party-number-address 0xD162)
rlm@147 421
rlm@147 422 (defn party-number
rlm@147 423 ([^SaveState state]
rlm@147 424 (aget (memory state) party-number-address))
rlm@147 425 ([] (party-number @current-state)))
rlm@147 426
rlm@147 427 (def pokemon-in-box-1-address 0xDA7F)
rlm@147 428
rlm@147 429 (defn party-names
rlm@147 430 ([^SaveState state]
rlm@147 431 (let [raw-names
rlm@147 432 (subvec (vec (memory state))
rlm@147 433 pokemon-names-start
rlm@147 434 (+ pokemon-names-start
rlm@148 435 (* name-width 6)))]
rlm@147 436 (map
rlm@148 437 read-name
rlm@147 438 (take
rlm@147 439 (party-number state)
rlm@147 440 (partition name-width
rlm@147 441 raw-names)))))
rlm@147 442 ([] (party-names @current-state)))
rlm@147 443
rlm@148 444
rlm@148 445 (defn rename-pokemon
rlm@148 446 ([^SaveState state n new-name]
rlm@148 447 (assert (<= 0 n (dec (party-number state))))
rlm@148 448 (assert (<= (count new-name) max-name-length))
rlm@148 449 (set-memory-range
rlm@148 450 state
rlm@148 451 (+ (* n name-width) pokemon-names-start)
rlm@148 452 (concat (str->character-codes new-name) [end-of-name-marker])))
rlm@148 453 ([n new-name]
rlm@148 454 (rename-pokemon @current-state n new-name)))
rlm@148 455
rlm@148 456 ;; on further analysis, it appears that the original
rlm@148 457 ;; trainer info for each pokemon is also stored together,
rlm@148 458 ;; starting at 0xD272 and continuing to 0xD2B3, with
rlm@148 459 ;; 11 bytes reserved for each OT name.
rlm@148 460
rlm@148 461 (def OT-start 0xD272)
rlm@148 462
rlm@148 463 (defn original-trainers
rlm@148 464 ([^SaveState state]
rlm@148 465 (let [raw-names
rlm@148 466 (subvec (vec (memory state))
rlm@148 467 OT-start
rlm@148 468 (+ OT-start
rlm@148 469 (* name-width 6)))]
rlm@148 470 (map read-name
rlm@148 471 (take (party-number state)
rlm@148 472 (partition name-width raw-names)))))
rlm@148 473 ([] (original-trainers @current-state)))
rlm@148 474
rlm@148 475 (defn set-original-trainer
rlm@148 476 "Set the OT name for a pokemon.
rlm@148 477 Note that a pokemon is still considered 'yours' if
rlm@148 478 the OT ID is the same as your own."
rlm@148 479 ([^SaveState state n new-name]
rlm@148 480 (assert (<= 0 n (dec (party-number state))))
rlm@148 481 (assert (<= (count new-name) max-name-length))
rlm@148 482 (set-memory-range
rlm@148 483 state
rlm@148 484 (+ (* n name-width) OT-start)
rlm@148 485 (concat (str->character-codes new-name) [end-of-name-marker])))
rlm@148 486 ([n new-name]
rlm@148 487 (set-original-trainer @current-state n new-name)))
rlm@148 488
rlm@148 489 ;; PIKACHU stops following if you set it's OT to another name
rlm@148 490 ;; and then back to you own.
rlm@148 491 ;; But not if you set it to your own name, obviously.
rlm@149 492
rlm@149 493
rlm@150 494
rlm@150 495
rlm@150 496 ;; OT ID Numbers.
rlm@152 497 ;; My own id is 05195. A quick search of memory between
rlm@150 498 ;; 0xD162 and 0xD31B revealed the pattern 0x144B exactly
rlm@150 499 ;; six times.
rlm@150 500
rlm@150 501 ;; the locations were:
rlm@150 502
rlm@150 503 (def OT-ID-addresses [0xD176 0xD1A2 0xD1CE 0xD1FA 0xD228 0xD252])
rlm@150 504
rlm@150 505
rlm@150 506 (defn set-pokemon-id
rlm@150 507 ([^SaveState state n new-id]
rlm@150 508 (assert (<= 0 n (dec (party-number state))))
rlm@150 509 (assert (<= 0 new-id 0xFFFF))
rlm@150 510 (set-memory-range
rlm@150 511 state
rlm@150 512 (OT-ID-addresses n)
rlm@151 513 [(bit-shift-right (bit-and new-id 0xFF00) 8)
rlm@151 514 (bit-and new-id 0xFF)
rlm@151 515 ]))
rlm@150 516 ([n new-id]
rlm@151 517 (set-pokemon-id @current-state n new-id)))
rlm@152 518
rlm@152 519
rlm@152 520
rlm@160 521
rlm@160 522
rlm@160 523 (defn get-pokemon-1-info
rlm@160 524 ([state]
rlm@160 525 (subvec (vec (memory state))
rlm@160 526 0xD162 0xD197))
rlm@160 527 ([] (get-pokemon-1-info @current-state)))
rlm@160 528
rlm@160 529 (def baseline (File. "/home/r/baseline-poke"))
rlm@160 530
rlm@160 531
rlm@160 532
rlm@160 533
rlm@160 534 (import java.io.File)
rlm@160 535
rlm@160 536 (defn set-baseline [state]
rlm@160 537 (clojure.java.io/copy
rlm@160 538 (with-out-str (print-listing state 0xD162 0xD197))
rlm@160 539 baseline))
rlm@160 540
rlm@160 541 (defn compare-pokemon
rlm@160 542 ([state]
rlm@160 543 (let [target (File. "/home/r/temp-poke")]
rlm@160 544 (clojure.java.io/copy
rlm@160 545 (with-out-str (print-listing state 0xD162 0xD197))
rlm@160 546 target)
rlm@160 547 (println (:out
rlm@160 548 (clojure.java.shell/sh "diff"
rlm@160 549 (.getCanonicalPath baseline)
rlm@160 550 (.getCanonicalPath target))))))
rlm@161 551 ([] (compare-pokemon @current-state)))
rlm@160 552
rlm@160 553
rlm@160 554 (defn crazy-pid []
rlm@160 555 (read-state "crazy-pidgeot"))
rlm@166 556
rlm@168 557 (def unknown "[[[UNKNOWN]]]")
rlm@168 558
rlm@166 559 (def unknown "")
rlm@166 560
rlm@166 561 (def pokemon-1-info
rlm@166 562 {0xD16A "Color Map" ;; 0
rlm@166 563 0xD16B "Current-HP (h)" ;; 1
rlm@166 564 0xD16C "Current-HP (l)" ;; 2
rlm@166 565 0XD16D unknown ;; 3
rlm@166 566 0xD16E unknown ;; 4
rlm@166 567 0xD16F unknown ;; 5
rlm@166 568 0xD170 unknown ;; 6
rlm@166 569 0xD171 unknown ;; 7
rlm@166 570 0xD172 "Move 1 ID" ;; 8
rlm@166 571 0xD173 "Move 2 ID" ;; 9
rlm@166 572 0xD174 "Move 3 ID" ;; 10
rlm@166 573 0xD175 "Move 4 ID" ;; 11
rlm@166 574 0xD176 "OT-ID (h)" ;; 12
rlm@166 575 0xD177 "OT-ID (l)" ;; 13
rlm@166 576 0xD178 "Exp. Points (h)" ;; 14
rlm@166 577 0xD179 "Exp. Points (m)" ;; 15
rlm@166 578 0xD17A "Exp. Points (l)" ;; 16
rlm@168 579 0xD17B "HP Exp. (h)" ;; 17
rlm@168 580 0xD17C "HP Exp. (l)" ;; 18
rlm@168 581 0xD17D "Attack Exp. (h)" ;; 19
rlm@168 582 0xD17E "Attack Exp. (l)" ;; 20
rlm@168 583 0xD17F "Defense Exp. (h)" ;; 21
rlm@168 584 0xD180 "Defense Exp. (l)" ;; 22
rlm@168 585 0xD181 "Speed Exp. (h)" ;; 23
rlm@168 586 0xD182 "Speed Exp. (l)" ;; 24
rlm@168 587 0xD183 "Special Exp. (h)" ;; 25
rlm@168 588 0xD184 "Special Exp. (l)" ;; 26
rlm@166 589 0xD185 unknown ;; 27
rlm@166 590 0xD186 unknown ;; 28
rlm@166 591 0xD187 "PP Move 1" ;; 29
rlm@166 592 0xD188 "PP Move 2" ;; 30
rlm@166 593 0xD189 "PP Move 3" ;; 31
rlm@166 594 0xD18A "PP Move 4" ;; 32
rlm@166 595 0xD18B "Current Level" ;; 33
rlm@166 596 0xD18C "HP Total (h)" ;; 34
rlm@166 597 0xD18D "HP Total (l)" ;; 35
rlm@166 598 0xD18E "Attack (h)" ;; 36
rlm@166 599 0xD18F "Attack (l)" ;; 37
rlm@166 600 0xD190 "Defense (h)" ;; 38
rlm@166 601 0xD191 "Defense (l)" ;; 39
rlm@166 602 0xD192 "Speed (h)" ;; 40
rlm@166 603 0xD193 "Speed (l)" ;; 41
rlm@166 604 0xD194 "Special (h)" ;; 42
rlm@168 605 0xD195 "Special (l)" ;; 43
rlm@166 606 })
rlm@166 607
rlm@166 608 (defn pokemon-data
rlm@166 609 ([^SaveState state pokemon-num]
rlm@166 610 (assert (<= 0 pokemon-num 5))
rlm@166 611 (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)]
rlm@166 612 (subvec (vec (memory state)) base
rlm@166 613 (+ base pokemon-record-width))))
rlm@166 614 ([pokemon-num] (pokemon-data @current-state pokemon-num)))
rlm@166 615
rlm@166 616 (defn set-pokemon-data
rlm@166 617 ([^SaveState state pokemon-num new-data]
rlm@166 618 (assert (<= 0 pokemon-num 5))
rlm@166 619 (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)]
rlm@166 620 (set-memory-range state base new-data)))
rlm@166 621 ([pokemon-num new-data]
rlm@166 622 (set-pokemon-data @current-state pokemon-num new-data)))
rlm@166 623
rlm@167 624 (defn print-pokemon-data
rlm@167 625 ([^SaveState state pokemon-num]
rlm@167 626 (assert (<= 0 pokemon-num 5))
rlm@167 627 (let [poke-data (pokemon-data state pokemon-num)
rlm@167 628 backbone (sort (keys pokemon-1-info))]
rlm@168 629 (println "Pokemon " pokemon-num " -- "
rlm@168 630 (nth (party-names state)
rlm@168 631 pokemon-num) \newline)
rlm@168 632
rlm@168 633 (println " Desc. | Hex | Dec | Binary |")
rlm@168 634 (println "-------------------+------+-----+----------+")
rlm@167 635 (dorun
rlm@167 636 (map
rlm@167 637 (comp println
rlm@167 638 (fn [desc data]
rlm@168 639 (format "%-16s | 0x%02X | %3d | %s |"
rlm@168 640 desc data data
rlm@168 641 (let [s (Integer/toBinaryString data)]
rlm@168 642 (apply
rlm@168 643 str
rlm@168 644 (concat (repeat (- 8 (count s)) "0" )
rlm@168 645 s)))
rlm@168 646
rlm@168 647
rlm@168 648 )))
rlm@167 649
rlm@167 650 (map pokemon-1-info backbone)
rlm@167 651 poke-data))))
rlm@167 652 ([pokemon-num]
rlm@167 653 (print-pokemon-data @current-state pokemon-num)))
rlm@167 654
rlm@166 655
rlm@166 656
rlm@167 657 (defn pre-battle [] (read-state "prepare-for-battle"))
rlm@167 658
rlm@168 659
rlm@169 660 (defn pika-lvl-100-DV-0 []
rlm@169 661 (read-state "at-pc-lv-100-pikachu"))
rlm@168 662
rlm@169 663 ;; Performed following experiment:
rlm@169 664 ;; Raised Pikachu to Lvl 100 with rare-candies,
rlm@169 665 ;; then put it at the head of the party and
rlm@169 666 ;; set 0xD185 and 0xD186 to zero.
rlm@168 667
rlm@169 668 ;; then, for each pattern, deposited pikachu into
rlm@169 669 ;; Box 1 and immediately widthdrew it and observed the
rlm@169 670 ;; stats.
rlm@168 671
rlm@169 672
rlm@169 673 ;; Pikachu L:100 Base Stats with DVs = 0
rlm@169 674 ;; HP : 187
rlm@169 675 ;; Attack : 123
rlm@169 676 ;; Defense : 73
rlm@169 677 ;; Speed : 194
rlm@169 678 ;; Special : 112
rlm@169 679
rlm@169 680 ;; 0xD185:
rlm@169 681
rlm@169 682 ;; 00000001
rlm@169 683 ;; Defense => 75 (+2)
rlm@169 684 ;; HP => 195 (+8)
rlm@169 685
rlm@169 686 ;; 00000010
rlm@169 687 ;; Defense => 77 (+4)
rlm@169 688
rlm@169 689 ;; 00000100
rlm@169 690 ;; Defense => 81 (+8)
rlm@169 691
rlm@169 692 ;; 00001000
rlm@169 693 ;; Defense => 89 (+16)
rlm@169 694
rlm@169 695 ;; 00010000
rlm@169 696 ;; HP => 203 (+16)
rlm@169 697 ;; Attack => 125 (+2)
rlm@169 698
rlm@169 699 ;; 00100000
rlm@169 700 ;; Attack => 127 (+4)
rlm@169 701
rlm@169 702 ;; 01000000
rlm@169 703 ;; Attack -> 131 (+8)
rlm@169 704
rlm@169 705 ;; 10000000
rlm@169 706 ;; Attack -> 139 (+16)
rlm@169 707
rlm@169 708 ;; 0xD186
rlm@169 709
rlm@169 710 ;; 00000001
rlm@169 711 ;; HP => 189 (+2)
rlm@169 712 ;; Special => (+2)
rlm@169 713
rlm@169 714 ;; 00000010
rlm@169 715 ;; Special => 116 (+4)
rlm@169 716
rlm@169 717 ;; 00000100
rlm@169 718 ;; Special => 120 (+8)
rlm@169 719
rlm@169 720 ;; 00001000
rlm@169 721 ;; Special => 128 (+16)
rlm@169 722
rlm@169 723 ;; 00010000
rlm@169 724 ;; HP => 191 (+4)
rlm@169 725 ;; Speed => 196 (+2)
rlm@169 726
rlm@169 727 ;; 00100000
rlm@169 728 ;; Speed => 198 (+4)
rlm@169 729
rlm@169 730 ;; 01000000
rlm@169 731 ;; Speed => 202 (+8)
rlm@169 732
rlm@169 733 ;; 10000000
rlm@169 734 ;; Speed => 210 (+16)
rlm@169 735
rlm@169 736 (def pokemon-1-DV-start 0xD185)
rlm@169 737
rlm@169 738 (defn pokemon-DV-start-point [poke-num]
rlm@169 739 (+ (* poke-num pokemon-record-width)
rlm@169 740 pokemon-1-DV-start))
rlm@169 741
rlm@169 742 (def reverse-4-bit
rlm@169 743 {0 0
rlm@169 744 1 8
rlm@169 745 2 4
rlm@169 746 3 12
rlm@169 747 5 10
rlm@169 748 6 6
rlm@169 749 7 14
rlm@169 750 9 9
rlm@169 751 15 15
rlm@169 752 13 11
rlm@169 753
rlm@169 754 8 1
rlm@169 755 4 2
rlm@169 756 12 3
rlm@169 757 10 5
rlm@169 758 11 13
rlm@169 759 14 7 })
rlm@169 760
rlm@169 761 (defn read-DV
rlm@169 762 ([^SaveState state poke-num]
rlm@169 763 (assert (<= 0 poke-num 5))
rlm@169 764 (let [[raw-DV-1
rlm@169 765 raw-DV-2]
rlm@169 766 (subvec (vec (memory state))
rlm@169 767 (pokemon-DV-start-point poke-num)
rlm@169 768 (+ 2 (pokemon-DV-start-point poke-num)))
rlm@169 769 defense-DV (bit-and raw-DV-1 0x0F)
rlm@169 770 attack-DV (bit-shift-right
rlm@169 771 (bit-and raw-DV-1 0xF0)
rlm@169 772 4)
rlm@169 773 special-DV (bit-and raw-DV-2 0x0F)
rlm@169 774 speed-DV (bit-shift-right
rlm@169 775 (bit-and raw-DV-2 0xF0)
rlm@169 776 4)
rlm@169 777 HP-DV
rlm@169 778 (+
rlm@169 779 (if (bit-test special-DV 0) 1 0)
rlm@169 780 (if (bit-test speed-DV 0) 2 0)
rlm@169 781 (if (bit-test defense-DV 0) 4 0)
rlm@169 782 (if (bit-test attack-DV 0) 8 0))]
rlm@169 783 {:attack attack-DV
rlm@169 784 :defense defense-DV
rlm@169 785 :speed speed-DV
rlm@169 786 :special special-DV
rlm@169 787 :hp HP-DV}))
rlm@169 788 ([poke-num]
rlm@169 789 (read-DV @current-state poke-num)))
rlm@169 790
rlm@169 791
rlm@169 792 (defn give-DV
rlm@169 793 ([^SaveState state poke-num dv-values]
rlm@169 794
rlm@169 795 (assert (<= 0 poke-num 5))
rlm@169 796 (map #(assert (<= 0 % 15)) (vals dv-values))
rlm@169 797 (let [raw-dv-1*
rlm@169 798 (+ (:defense dv-values)
rlm@169 799 (bit-shift-left (:attack dv-values) 4))
rlm@169 800 raw-dv-2*
rlm@169 801 (+ (:special dv-values)
rlm@169 802 (bit-shift-left (:speed dv-values) 4))
rlm@169 803 hp-dv (:hp dv-values)
rlm@169 804 hp-masks-1
rlm@169 805 [[0 (bit-test hp-dv 2)]
rlm@169 806 [4 (bit-test hp-dv 3)]]
rlm@169 807 hp-masks-2
rlm@169 808 [[0 (bit-test hp-dv 0)]
rlm@169 809 [4 (bit-test hp-dv 1)]]
rlm@169 810 set-hp-bits
rlm@169 811 (fn [init [index hp?]]
rlm@169 812 (if hp?
rlm@169 813 (bit-set init index)
rlm@169 814 (bit-clear init index)))
rlm@169 815
rlm@169 816 raw-dv-1 (reduce set-hp-bits raw-dv-1*
rlm@169 817 hp-masks-1)
rlm@169 818
rlm@169 819 raw-dv-2 (reduce set-hp-bits raw-dv-2*
rlm@169 820 hp-masks-2)
rlm@169 821
rlm@169 822 dv-start (pokemon-DV-start-point poke-num)]
rlm@169 823
rlm@169 824 (if (or (not= raw-dv-1* raw-dv-1)
rlm@169 825 (not= raw-dv-2* raw-dv-2))
rlm@169 826 (println "Warning: inconsistent DV-values."
rlm@169 827 "Using HP settings."))
rlm@169 828
rlm@169 829 (set-memory
rlm@169 830 (set-memory state dv-start raw-dv-1)
rlm@169 831 (inc dv-start) raw-dv-2)))
rlm@169 832 ([poke-num dv-values]
rlm@169 833 (give-DV @current-state poke-num dv-values)))
rlm@169 834
rlm@169 835 (def good-DVs
rlm@169 836 {:attack 15
rlm@169 837 :defense 15
rlm@169 838 :speed 15
rlm@169 839 :special 15
rlm@169 840 :hp 15})
rlm@169 841
rlm@169 842 (def bad-DVs
rlm@169 843 {:attack 0
rlm@169 844 :defense 0
rlm@169 845 :speed 0
rlm@169 846 :special 0
rlm@169 847 :hp 0})
rlm@169 848
rlm@169 849