Mercurial > vba-clojure
view clojure/com/aurellem/exp/pokemon.clj @ 513:3dbb863eb801
accuracy of displayed image is much improved, but there the palettes are still messed up.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 22 Jun 2012 18:58:47 -0500 |
parents | d5dddf33543c |
children |
line wrap: on
line source
1 (ns com.aurellem.exp.pokemon2 "Here I find out how pokemon are stored in memory."3 (:use (com.aurellem.gb gb-driver items assembly util4 constants5 characters species moves))6 (:import java.io.File)7 (:import [com.aurellem.gb.gb_driver SaveState]))10 (def pidgeot-lvl-36 (mid-game))13 (def pidgeot-lvl-37 (read-state "pidgeot-lvl-37"))16 (def pidgeot-lvl-38 (read-state "pidgeot-lvl-38"))19 (def pidgeot-lvl-39 (read-state "pidgeot-lvl-39"))22 (def pidgeot-lvl-40 (read-state "pidgeot-lvl-40"))25 (defn level-analysis []26 (apply common-differences27 (map (comp vec memory)28 [pidgeot-lvl-3629 pidgeot-lvl-3730 pidgeot-lvl-3831 pidgeot-lvl-3932 pidgeot-lvl-40])))34 ;; inconclusive -- implies that level is calculated from35 ;; some other values.38 (def name-pidgeotto (read-state "name-pidgeotto"))39 (def named-A (read-state "named-A"))40 (def named-B (read-state "named-B"))41 (def named-C (read-state "named-C"))42 (def named-D (read-state "named-D"))43 (def named-E (read-state "named-E"))44 (def named-F (read-state "named-F"))46 (defn name-analysis []47 (apply common-differences48 (map (comp vec memory)49 [named-A50 named-B51 named-C52 named-D53 named-E54 named-F])))56 ;; resluted in 3 separate locations that could57 ;; possibly hold the first letter of the pokemon's name59 0xCF4A60 0xD2EB61 0xCEED63 ;; try changing each of them66 (defn test-cf4a []67 (continue!68 (set-memory named-A 0xCF4A (character->character-code "Z"))))69 ;; result -- pidgeotto named "A"71 (defn test-d2eb []72 (continue!73 (set-memory named-A 0xD2EB (character->character-code "Z"))))74 ;; result -- pidgeotto named "Z"76 (defn test-ceed []77 (continue!78 (set-memory named-A 0xCEED (character->character-code "Z"))))79 ;; result -- pidgeotto named "A"81 (def sixth-pokemon-name-start 0xD2EB)84 (defn set-sixth-pokemon-name-first-character85 ([state character]86 (set-memory state sixth-pokemon-name-start87 (character->character-code character)))88 ([character]89 (set-sixth-pokemon-name-first-character @current-state90 character)))93 ;;(def end-of-name-marker 0x50)94 ;;(def max-name-length 10)95 ;;(def name-width 11)97 ;; (defn read-name [codes]98 ;; (character-codes->str99 ;; (take-while100 ;; (partial not= end-of-name-marker) codes)))103 (defn sixth-pokemon-name [^SaveState state]104 (read-name105 (subvec (vec (memory state))106 sixth-pokemon-name-start107 (+ (inc max-name-length)108 sixth-pokemon-name-start))))110 (defn rename-sixth-pokemon111 ([^SaveState state new-name]112 (assert (< (count new-name) max-name-length))113 (set-memory-range state sixth-pokemon-name-start114 (concat (str->character-codes new-name)115 [end-of-name-marker])))116 ([new-name]117 (rename-sixth-pokemon @current-state new-name)))120 (defn examine-name-memory []121 (print-text122 named-A123 (- sixth-pokemon-name-start 100)124 (+ sixth-pokemon-name-start 100)))126 ;; results:127 ;; 0xD287: end-of-name-sentinel128 ;; 0xD288: R129 ;; 0xD289: L130 ;; 0xD28A: M131 ;; 0xD28B: end-of-pokemon-name-sentinel132 ;; 0xD28C: end-of-name-sentinel133 ;; 0xD28D: end-of-name-sentinel134 ;; 0xD28E: end-of-name-sentinel135 ;; 0xD28F: end-of-name-sentinel136 ;; 0xD290: end-of-name-sentinel137 ;; 0xD291: end-of-name-sentinel138 ;; 0xD292: end-of-name-sentinel139 ;; 0xD293: R140 ;; 0xD294: L141 ;; 0xD295: M142 ;; 0xD296: end-of-pokemon-name-sentinel143 ;; 0xD297: end-of-name-sentinel144 ;; 0xD298: end-of-name-sentinel145 ;; 0xD299: end-of-name-sentinel146 ;; 0xD29A: end-of-name-sentinel147 ;; 0xD29B: end-of-name-sentinel148 ;; 0xD29C: end-of-name-sentinel149 ;; 0xD29D: end-of-name-sentinel150 ;; 0xD29E: R151 ;; 0xD29F: L152 ;; 0xD2A0: M153 ;; 0xD2A1: end-of-pokemon-name-sentinel154 ;; 0xD2A2: end-of-name-sentinel155 ;; 0xD2A3: end-of-name-sentinel156 ;; 0xD2A4: end-of-name-sentinel157 ;; 0xD2A5: end-of-name-sentinel158 ;; 0xD2A6: end-of-name-sentinel159 ;; 0xD2A7: end-of-name-sentinel160 ;; 0xD2A8: end-of-name-sentinel161 ;; 0xD2A9: R162 ;; 0xD2AA: L163 ;; 0xD2AB: M164 ;; 0xD2AC: end-of-pokemon-name-sentinel165 ;; 0xD2AD: end-of-name-sentinel166 ;; 0xD2AE: end-of-name-sentinel167 ;; 0xD2AF: end-of-name-sentinel168 ;; 0xD2B0: end-of-name-sentinel169 ;; 0xD2B1: end-of-name-sentinel170 ;; 0xD2B2: end-of-name-sentinel171 ;; 0xD2B3: end-of-name-sentinel172 ;; 0xD2B4: P173 ;; 0xD2B5: I174 ;; 0xD2B6: D175 ;; 0xD2B7: G176 ;; 0xD2B8: E177 ;; 0xD2B9: O178 ;; 0xD2BA: T179 ;; 0xD2BB: end-of-pokemon-name-sentinel180 ;; 0xD2BC: end-of-pokemon-name-sentinel181 ;; 0xD2BD: end-of-pokemon-name-sentinel182 ;; 0xD2BE: end-of-pokemon-name-sentinel183 ;; 0xD2BF: P184 ;; 0xD2C0: I185 ;; 0xD2C1: K186 ;; 0xD2C2: A187 ;; 0xD2C3: C188 ;; 0xD2C4: H189 ;; 0xD2C5: U190 ;; 0xD2C6: end-of-pokemon-name-sentinel191 ;; 0xD2C7: end-of-pokemon-name-sentinel192 ;; 0xD2C8: end-of-pokemon-name-sentinel193 ;; 0xD2C9: end-of-pokemon-name-sentinel194 ;; 0xD2CA: C195 ;; 0xD2CB: H196 ;; 0xD2CC: A197 ;; 0xD2CD: R198 ;; 0xD2CE: I199 ;; 0xD2CF: Z200 ;; 0xD2D0: A201 ;; 0xD2D1: R202 ;; 0xD2D2: D203 ;; 0xD2D3: end-of-pokemon-name-sentinel204 ;; 0xD2D4: end-of-pokemon-name-sentinel205 ;; 0xD2D5: V206 ;; 0xD2D6: E207 ;; 0xD2D7: N208 ;; 0xD2D8: U209 ;; 0xD2D9: S210 ;; 0xD2DA: A211 ;; 0xD2DB: U212 ;; 0xD2DC: R213 ;; 0xD2DD: end-of-pokemon-name-sentinel214 ;; 0xD2DE: end-of-pokemon-name-sentinel215 ;; 0xD2DF: end-of-pokemon-name-sentinel216 ;; 0xD2E0: P217 ;; 0xD2E1: R218 ;; 0xD2E2: I219 ;; 0xD2E3: M220 ;; 0xD2E4: E221 ;; 0xD2E5: A222 ;; 0xD2E6: P223 ;; 0xD2E7: E224 ;; 0xD2E8: end-of-pokemon-name-sentinel225 ;; 0xD2E9: end-of-pokemon-name-sentinel226 ;; 0xD2EA: end-of-pokemon-name-sentinel227 ;; 0xD2EB: A228 ;; 0xD2EC: end-of-pokemon-name-sentinel229 ;; 0xD2ED: S230 ;; 0xD2EE: T231 ;; 0xD2EF: E232 ;; 0xD2F0: R233 ;; 0xD2F1:234 ;; 0xD2F2: B235 ;; 0xD2F3: A236 ;; 0xD2F4: L237 ;; 0xD2F5: L238 ;; 0xD2F6:239 ;; 0xD2F7: A240 ;; 0xD2F8:241 ;; 0xD2F9:242 ;; 0xD2FA: end-of-name-sentinel243 ;; 0xD2FB: end-of-name-sentinel244 ;; 0xD2FC: A245 ;; 0xD2FD:246 ;; 0xD2FE: end-of-name-sentinel247 ;; 0xD2FF: end-of-name-sentinel248 ;; 0xD300: end-of-name-sentinel249 ;; 0xD301: end-of-name-sentinel250 ;; 0xD302: end-of-name-sentinel251 ;; 0xD303: end-of-name-sentinel252 ;; 0xD304: end-of-name-sentinel253 ;; 0xD305: end-of-name-sentinel254 ;; 0xD306: end-of-name-sentinel255 ;; 0xD307: end-of-name-sentinel256 ;; 0xD308: end-of-name-sentinel257 ;; 0xD309:258 ;; 0xD30A: w259 ;; 0xD30B:260 ;; 0xD30C: V261 ;; 0xD30D:262 ;; 0xD30E:263 ;; 0xD30F: K264 ;; 0xD310:265 ;; 0xD311:266 ;; 0xD312:267 ;; 0xD313: A268 ;; 0xD314:269 ;; 0xD315:270 ;; 0xD316:271 ;; 0xD317: i272 ;; 0xD318:273 ;; 0xD319:274 ;; 0xD31A: end-of-name-sentinel275 ;; 0xD31B: end-of-name-sentinel276 ;; 0xD31C:277 ;; 0xD31D:278 ;; 0xD31E:279 ;; 0xD31F:280 ;; 0xD320:281 ;; 0xD321:282 ;; 0xD322:283 ;; 0xD323:284 ;; 0xD324:285 ;; 0xD325:286 ;; 0xD326:287 ;; 0xD327:288 ;; 0xD328:289 ;; 0xD329:290 ;; 0xD32A:291 ;; 0xD32B:292 ;; 0xD32C:293 ;; 0xD32D:294 ;; 0xD32E:295 ;; 0xD32F:296 ;; 0xD330:297 ;; 0xD331: 9298 ;; 0xD332: end-of-name-sentinel299 ;; 0xD333: 9300 ;; 0xD334:301 ;; 0xD335: 9302 ;; 0xD336:303 ;; 0xD337: 9304 ;; 0xD338: end-of-name-sentinel305 ;; 0xD339: end-of-name-sentinel306 ;; 0xD33A: end-of-name-sentinel307 ;; 0xD33B: end-of-name-sentinel308 ;; 0xD33C: end-of-name-sentinel309 ;; 0xD33D: end-of-name-sentinel310 ;; 0xD33E: end-of-name-sentinel311 ;; 0xD33F: end-of-name-sentinel312 ;; 0xD340: end-of-name-sentinel313 ;; 0xD341: end-of-name-sentinel314 ;; 0xD342: end-of-name-sentinel315 ;; 0xD343: end-of-name-sentinel316 ;; 0xD344: end-of-name-sentinel317 ;; 0xD345: end-of-name-sentinel318 ;; 0xD346:319 ;; 0xD347:320 ;; 0xD348:321 ;; 0xD349: G322 ;; 0xD34A: A323 ;; 0xD34B: R324 ;; 0xD34C: Y325 ;; 0xD34D: end-of-pokemon-name-sentinel326 ;; 0xD34E: J329 ;; from this, it looks like the pokemon names are stored all330 ;; together in one location that begins at 0xD2B4 and331 ;; extends until 0xD2F5, with each name taking up 11 bytes.332 ;;333 ;; rival's name again clearly starts at 0xD349.336 (def pokemon-names-start 0xD2B4)339 ;; determine whether "number of pokemon in party"340 ;; might be kept in RAM and if so, where?342 (def six-pokemon (read-state "6-pokemon"))343 (def five-pokemon (read-state "5-pokemon"))344 (def four-pokemon (read-state "4-pokemon"))345 (def three-pokemon (read-state "3-pokemon"))346 (def two-pokemon (read-state "2-pokemon"))347 (def one-pokemon (read-state "1-pokemon"))350 (defn analyze-num-pokemon []351 (apply common-differences352 (map (comp vec memory)353 [one-pokemon354 two-pokemon355 three-pokemon356 four-pokemon357 five-pokemon358 six-pokemon])))360 ;; ;; results361 ;; ([53602 (1 2 3 4 5 6)]362 ;; [65314 (105 61 93 60 92 34)]363 ;; [55875 (34 36 43 52 7 0)]364 ;; [55876 (18 0 33 52 54 30)]365 ;; [49158 (197 194 77 117 174 134)]366 ;; [49160 (29 26 57 239 15 243)]367 ;; [49736 (74 93 34 89 91 59)]368 ;; [49162 (165 162 182 179 197 109)]369 ;; [49227 (187 105 204 5 90 238)]370 ;; [53067 (128 136 132 145 135 11)]371 ;; [53068 (147 131 141 136 128 7)]372 ;; [53069 (136 134 148 140 145 2)]373 ;; [49904 (2 11 10 3 27 12)]374 ;; [49172 (100 109 213 195 68 104)]375 ;; [65492 (11 103 128 160 19 56)]376 ;; [49173 (80 77 72 75 76 67)]377 ;; [49334 (8 10 11 5 3 1)]378 ;; [49335 (49 10 11 19 17 15)]379 ;; [49336 (8 10 11 5 3 1)]380 ;; [49720 (106 14 118 0 38 11)]381 ;; [65304 (32 88 19 114 106 33)]382 ;; [53561 (59 229 48 17 155 103)]383 ;; [55935 (6 5 4 3 2 1)])386 ;; two canidates : 0xD162 or 0xDA7F387 ;; they seem to always sum to 6...389 ;; try to set both of them when having only one pokemon.391 (defn change-party-number [^SaveState state new-num]392 (set-memory state 0xD162 new-num))394 ;; (continue! (change-party-number one-pokemon 3))395 ;; result -- can scroll down beyone first pokemon, finding396 ;; glitched pokemon in places where there were previously no397 ;; pokemon.400 (defn change-party-number* [^SaveState state new-num]401 (set-memory state 0xDA7F new-num))404 ;; (continue! (change-party-number* one-pokemon 3))405 ;; cannot widthdraw any pokemon from box 1 past the third406 ;; pokemon.408 (def party-number-address 0xD162)410 (defn party-number411 ([^SaveState state]412 (aget (memory state) party-number-address))413 ([] (party-number @current-state)))415 (def pokemon-in-box-1-address 0xDA7F)417 (defn party-names418 ([^SaveState state]419 (let [raw-names420 (subvec (vec (memory state))421 pokemon-names-start422 (+ pokemon-names-start423 (* name-width 6)))]424 (map425 read-name426 (take427 (party-number state)428 (partition name-width429 raw-names)))))430 ([] (party-names @current-state)))433 (defn rename-pokemon434 ([^SaveState state n new-name]435 (assert (<= 0 n (dec (party-number state))))436 (assert (<= (count new-name) max-name-length))437 (set-memory-range438 state439 (+ (* n name-width) pokemon-names-start)440 (concat (str->character-codes new-name) [end-of-name-marker])))441 ([n new-name]442 (rename-pokemon @current-state n new-name)))444 ;; on further analysis, it appears that the original445 ;; trainer info for each pokemon is also stored together,446 ;; starting at 0xD272 and continuing to 0xD2B3, with447 ;; 11 bytes reserved for each OT name.449 (def OT-start 0xD272)451 (defn original-trainers452 ([^SaveState state]453 (let [raw-names454 (subvec (vec (memory state))455 OT-start456 (+ OT-start457 (* name-width 6)))]458 (map read-name459 (take (party-number state)460 (partition name-width raw-names)))))461 ([] (original-trainers @current-state)))463 (defn set-original-trainer464 "Set the OT name for a pokemon.465 Note that a pokemon is still considered 'yours' if466 the OT ID is the same as your own."467 ([^SaveState state n new-name]468 (assert (<= 0 n (dec (party-number state))))469 (assert (<= (count new-name) max-name-length))470 (set-memory-range471 state472 (+ (* n name-width) OT-start)473 (concat (str->character-codes new-name) [end-of-name-marker])))474 ([n new-name]475 (set-original-trainer @current-state n new-name)))477 ;; PIKACHU stops following if you set it's OT to another name478 ;; and then back to you own.479 ;; But not if you set it to your own name, obviously.484 ;; OT ID Numbers.485 ;; My own id is 05195. A quick search of memory between486 ;; 0xD162 and 0xD31B revealed the pattern 0x144B exactly487 ;; six times.489 ;; the locations were:491 (def OT-ID-addresses [0xD176 0xD1A2 0xD1CE 0xD1FA 0xD228 0xD252])494 (defn set-pokemon-id495 ([^SaveState state n new-id]496 (assert (<= 0 n (dec (party-number state))))497 (assert (<= 0 new-id 0xFFFF))498 (set-memory-range499 state500 (OT-ID-addresses n)501 [(bit-shift-right (bit-and new-id 0xFF00) 8)502 (bit-and new-id 0xFF)503 ]))504 ([n new-id]505 (set-pokemon-id @current-state n new-id)))508 (defn get-pokemon-1-info509 ([state]510 (subvec (vec (memory state))511 0xD162 0xD197))512 ([] (get-pokemon-1-info @current-state)))514 (def baseline (File. "/home/r/baseline-poke"))519 (import java.io.File)521 (defn set-baseline [state]522 (clojure.java.io/copy523 (with-out-str (print-listing state 0xD162 0xD197))524 baseline))526 (defn compare-pokemon527 ([state]528 (let [target (File. "/home/r/temp-poke")]529 (clojure.java.io/copy530 (with-out-str (print-listing state 0xD162 0xD197))531 target)532 (println (:out533 (clojure.java.shell/sh "diff"534 (.getCanonicalPath baseline)535 (.getCanonicalPath target))))))536 ([] (compare-pokemon @current-state)))539 (defn crazy-pid []540 (read-state "crazy-pidgeot"))542 (def unknown "[[[UNKNOWN]]]")544 (def unknown "")546 (def pokemon-1-info547 {0xD16A "Color Map" ;; 0548 0xD16B "Current-HP (h)" ;; 1549 0xD16C "Current-HP (l)" ;; 2550 0XD16D unknown ;; 3551 0xD16E unknown ;; 4552 0xD16F unknown ;; 5553 0xD170 unknown ;; 6554 0xD171 unknown ;; 7555 0xD172 "Move 1 ID" ;; 8556 0xD173 "Move 2 ID" ;; 9557 0xD174 "Move 3 ID" ;; 10558 0xD175 "Move 4 ID" ;; 11559 0xD176 "OT-ID (h)" ;; 12560 0xD177 "OT-ID (l)" ;; 13561 0xD178 "Exp. Points (h)" ;; 14562 0xD179 "Exp. Points (m)" ;; 15563 0xD17A "Exp. Points (l)" ;; 16564 0xD17B "HP Exp. (h)" ;; 17565 0xD17C "HP Exp. (l)" ;; 18566 0xD17D "Attack Exp. (h)" ;; 19567 0xD17E "Attack Exp. (l)" ;; 20568 0xD17F "Defense Exp. (h)" ;; 21569 0xD180 "Defense Exp. (l)" ;; 22570 0xD181 "Speed Exp. (h)" ;; 23571 0xD182 "Speed Exp. (l)" ;; 24572 0xD183 "Special Exp. (h)" ;; 25573 0xD184 "Special Exp. (l)" ;; 26574 0xD185 "DV Atk/Def" ;; 27575 0xD186 "DV Speed/Spc" ;; 28576 0xD187 "PP Move 1" ;; 29577 0xD188 "PP Move 2" ;; 30578 0xD189 "PP Move 3" ;; 31579 0xD18A "PP Move 4" ;; 32580 0xD18B "Current Level" ;; 33581 0xD18C "HP Total (h)" ;; 34582 0xD18D "HP Total (l)" ;; 35583 0xD18E "Attack (h)" ;; 36584 0xD18F "Attack (l)" ;; 37585 0xD190 "Defense (h)" ;; 38586 0xD191 "Defense (l)" ;; 39587 0xD192 "Speed (h)" ;; 40588 0xD193 "Speed (l)" ;; 41589 0xD194 "Special (h)" ;; 42590 0xD195 "Special (l)" ;; 43591 })593 (defn pokemon-data594 ([^SaveState state pokemon-num]595 (assert (<= 0 pokemon-num 5))596 (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)]597 (subvec (vec (memory state)) base598 (+ base pokemon-record-width))))599 ([pokemon-num] (pokemon-data @current-state pokemon-num)))601 (defn set-pokemon-data602 ([^SaveState state pokemon-num new-data]603 (assert (<= 0 pokemon-num 5))604 (let [base (+ (* pokemon-num pokemon-record-width) 0xD16A)]605 (set-memory-range state base new-data)))606 ([pokemon-num new-data]607 (set-pokemon-data @current-state pokemon-num new-data)))609 (defn print-pokemon-data610 ([^SaveState state pokemon-num]611 (assert (<= 0 pokemon-num 5))612 (let [poke-data (pokemon-data state pokemon-num)613 backbone (sort (keys pokemon-1-info))]614 (println "Pokemon " pokemon-num " -- "615 (nth (party-names state)616 pokemon-num) \newline)618 (println " Desc. | Hex | Dec | Binary |")619 (println "-------------------+------+-----+----------+")620 (dorun621 (map622 (comp println623 (fn [desc data]624 (format "%-16s | 0x%02X | %3d | %s |"625 desc data data626 (let [s (Integer/toBinaryString data)]627 (apply628 str629 (concat (repeat (- 8 (count s)) "0" )630 s)))633 )))635 (map pokemon-1-info backbone)636 poke-data))))637 ([pokemon-num]638 (print-pokemon-data @current-state pokemon-num)))645 (defn pika-lvl-100-DV-0 []646 (read-state "at-pc-lv-100-pikachu"))648 ;; Performed following experiment:649 ;; Raised Pikachu to Lvl 100 with rare-candies,650 ;; then put it at the head of the party and651 ;; set 0xD185 and 0xD186 to zero.653 ;; then, for each pattern, deposited pikachu into654 ;; Box 1 and immediately widthdrew it and observed the655 ;; stats.658 ;; Pikachu L:100 Base Stats with DVs = 0659 ;; HP : 187660 ;; Attack : 123661 ;; Defense : 73662 ;; Speed : 194663 ;; Special : 112665 ;; 0xD185:667 ;; 00000001668 ;; Defense => 75 (+2)669 ;; HP => 195 (+8)671 ;; 00000010672 ;; Defense => 77 (+4)674 ;; 00000100675 ;; Defense => 81 (+8)677 ;; 00001000678 ;; Defense => 89 (+16)680 ;; 00010000681 ;; HP => 203 (+16)682 ;; Attack => 125 (+2)684 ;; 00100000685 ;; Attack => 127 (+4)687 ;; 01000000688 ;; Attack -> 131 (+8)690 ;; 10000000691 ;; Attack -> 139 (+16)693 ;; 0xD186695 ;; 00000001696 ;; HP => 189 (+2)697 ;; Special => (+2)699 ;; 00000010700 ;; Special => 116 (+4)702 ;; 00000100703 ;; Special => 120 (+8)705 ;; 00001000706 ;; Special => 128 (+16)708 ;; 00010000709 ;; HP => 191 (+4)710 ;; Speed => 196 (+2)712 ;; 00100000713 ;; Speed => 198 (+4)715 ;; 01000000716 ;; Speed => 202 (+8)718 ;; 10000000719 ;; Speed => 210 (+16)722 ;; investigating status effects724 ;; status of pokemon 1 appears to be725 ;; 0xD16E727 ;; with pidgeot728 ;; 00000000 -- normal729 ;; 00000001 -- sleep (wake-immediately)730 ;; 00000010 -- sleep731 ;; 00000100 -- sleep732 ;; 00001000 -- poisoned733 ;; 00010000 -- burned734 ;; 00100000 -- frozen735 ;; 01000000 -- paralyzed736 ;; 10000000 -- ball is dark, but no status738 ;; with pikachu739 ;; 00000000 -- normal740 ;; 00000001 -- sleep (1 turn wasted) \741 ;; 00000010 -- sleep (2 turns wasted) |-- additive742 ;; 00000100 -- sleep (3 turns wasted) /743 ;; 00001000 -- poisoned744 ;; 00010000 -- burned745 ;; 00100000 -- frozen746 ;; 01000000 -- paralyzed747 ;; 10000000 -- ball is dark, but no status