diff org/rom.org @ 347:ff65ee0944fe

more progess: now rom.org tangles into hxc.clj; i'll be subdividing the code blocks as I write more.
author Dylan Holmes <ocsenave@gmail.com>
date Sun, 08 Apr 2012 06:13:39 -0500
parents 5639312a393f
children 497ca041f5af
line wrap: on
line diff
     1.1 --- a/org/rom.org	Sun Apr 08 01:28:39 2012 -0500
     1.2 +++ b/org/rom.org	Sun Apr 08 06:13:39 2012 -0500
     1.3 @@ -10,7 +10,9 @@
     1.4  # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
     1.5  # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html
     1.6  # pokedollar: U+20B1
     1.7 -* Mapping the ROM
     1.8 +* Introduction
     1.9 +
    1.10 +** Mapping the ROM
    1.11  
    1.12  | ROM address (hex) | Description     | Format          | Example         |
    1.13  |-------------------+-----------------+-----------------+-----------------|
    1.14 @@ -22,18 +24,24 @@
    1.15  | 05EDB.            | Which Pok\eacute{}mon to show during Prof. Oak's introduction. | A single byte, the Pok\eacute{}mon's internal id. | In Pok\eacute{}mon Yellow, it shows Pikachu during the introduction; Pikachu's internal id is 0x54. |
    1.16  | 06698-            | ? Background music. |                 |                 |
    1.17  | 0822E-082F?       | Pointers to background music, part I. |                 |                 |
    1.18 -| 0CB95-            | Pointers to lists of wild pokemon to encounter in each region. These lists begin at 04D89, see above. | Each pointer is a low-byte, high-byte pair. | The first entry is 0x89 0x4D, corresponding to the address 0x4D89, the location of the first list of wild Pok\eacute{}mon (see above). |
    1.19 +| 0CB95-            | Pointers to lists of wild pokemon to encounter in each region. These lists begin at 04D89, see above. | Each pointer is a low-byte, high-byte pair. | The first entry is 0x89 0x4D, corresponding to the address 0x4D89, the location of the first list of wild Pok\eacute{}mon (see 04D89, above). |
    1.20 +|-------------------+-----------------+-----------------+-----------------|
    1.21 +| 0DADB.            | Amount of HP restored by Hyper Potion. | The HP consists of a single byte. TODO: Discover what the surrounding data does, and find the data for the amount of HP restored by other items: Fresh Water (50HP), Soda (60HP), Lemonade(80HP). | 200             |
    1.22 +| 0DAE0.            | Amount of HP restored by Super Potion. | "               | 50              |
    1.23 +| 0DAE3.            | Amount of HP restored by Potion. | "               | 20              |
    1.24 +|-------------------+-----------------+-----------------+-----------------|
    1.25  | 0DD4D-DD72        | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# |
    1.26  | 1195C-1196A       | The two terms for being able/unable to learn a TM/HM. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE#  |
    1.27  | 119C0-119CE       | The two terms for being able/unable to evolve using the current stone. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE#  |
    1.28  | 1232D-12364       | Which moves are taught by the TMs and HMs | A list of 55 move ids (50 TMs, plus 5 HMs). First, the move that will be taught by TM01; second, the move that will be taught by TM02; and so on. The last five entries are the moves taught by HMs 1-5. (See also, BC000 below) | The first few entries are (5 13 14 18 ...) corresponding to Mega Punch (TM01), Razor Wind (TM02), Swords Dance (TM03), Whirlwind (TM04), ... |
    1.29  | 27D99-27DFF       | Names of the Pok\eacute{}mon types. | Variable-length type names (strings of character codes). Names are separated by a single 0x80 character. | NORMAL#FIGHTING#... |
    1.30 -| 27E77-            | Trainer title names. |                 | YOUNGSTER#BUG CATCHER#LASS#... |
    1.31 -| 34000-            | Evolution and learnset data. |                 |                 |
    1.32 -| 38000-            | The basic properties and effects of moves. | Fixed-length (6 byte) continguous descriptions (no separating character): move-index, move-effect, power, move-type, accuracy, pp. | The entry for Pound, the first attack in the list, is (1 0 40 0 255 35). See below for more explanation. |
    1.33 +| 27E77-            | Trainer title names. | Variable-length names separated by 0x80. | YOUNGSTER#BUG CATCHER#LASS#... |
    1.34 +| 34000-            |                 |                 |                 |
    1.35 +| 38000-383DE       | The basic properties and effects of moves. (165 moves total) | Fixed-length (6 byte) continguous descriptions (no separating character): move-index, move-effect, power, move-type, accuracy, pp. | The entry for Pound, the first attack in the list, is (1 0 40 0 255 35). See below for more explanation. |
    1.36  | 383DE-            | Species data for the Pokemon, listed in Pokedex order: Pokedex number; base moves; types; learnable TMs and HMs; base HP, attack, defense, speed, special; sprite data. |                 |                 |
    1.37  | 39462-            | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. |                 |
    1.38  | 3B1E5-            | Pointers to evolution/learnset data. |                 |                 |
    1.39 +| 3B361-            | Evolution and learnset data. [fn::Evolution data consists of how to make Pok\eacute{}mon evolve, and what they evolve into. Learnset data consists of the moves that Pok\eacute{}mon learn as they level up.] | Variable-length evolution information (see below), followed by a list of level/move-id learnset pairs. |                 |
    1.40  | 40687-            | Species data from the Pok\eacute{}dex: species name, height, weight, etc. | Fixed-length sequences of bytes. See below for specifics. |                 |
    1.41  | 410B1-            | A conversion table between internal order and Pokedex order. |                 |                 |
    1.42  | 5DE10-5DE30       | Abbreviations for status ailments. | Fixed-length strings, probably[fn::Here's something strange: all of the status messages start with 0x7F and end with 0x4F \mdash{}except PAR, which ends with 0x50.]. The last entry is QUIT##. | [0x7F] *SLP* [0x4E][0x7F] *PSN* [0x4E][0x7F] *PAR* [0x50][0x7F]... |
    1.43 @@ -41,13 +49,1156 @@
    1.44  | 7C249-7C2??       | Pointers to background music, pt II. |                 |                 |
    1.45  | 98000-            | Dialogue        |                 |                 |
    1.46  | B8000-            | The text of each Pokemon's Pok\eacute{}dex entry. |                 |                 |
    1.47 -| BC000-            | Move names.     |                 |                 |
    1.48 +| BC000-BC60E       | Move names.     | Variable-length move names, separated by 0x80. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... |
    1.49  | E8000-E876C       | Names of the \ldquo{}190\rdquo{} species of Pok\eacute{}mon in memory. | Fixed length (10-letter) Pok\eacute{}mon names. Any extra space is padded with the character 0x80. The names are in \ldquo{}internal order\rdquo{}. | RHYDON####KANGASKHANNIDORAN♂#... |
    1.50  |                   |                 |                 |                 |
    1.51  |                   |                 |                 |                 |
    1.52  
    1.53 +
    1.54 +
    1.55 +
    1.56 +** COMMENT Getting linguistic data: names, words, etc.
    1.57 +
    1.58 +Some of the simplest data 
    1.59 +
    1.60 +
    1.61 +One of the simplest data structures in the Pok\eacute{} ROM is an
    1.62 +unbroken list of strings that either (a) all have a specific length,
    1.63 +or (b) are all separated by the same character.
    1.64 +
    1.65 +Because lots of good data has this format, we'll start by writing a
    1.66 +template function to extract it:
    1.67 +
    1.68 +#+name: hxc-thunks
    1.69 +#+begin_src clojure :results silent
    1.70 +(defn hxc-thunk
    1.71 +  "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
    1.72 +splits it into a collection by 0x50. If rom is not supplied, uses the
    1.73 +  original rom data."
    1.74 +  [start length]
    1.75 +  (fn self
    1.76 +    ([rom]
    1.77 +       (take-nth 2
    1.78 +                 (partition-by #(= % 0x50)
    1.79 +                               (take length
    1.80 +                                     (drop start rom)))))
    1.81 +    ([]
    1.82 +      (self com.aurellem.gb.gb-driver/original-rom))))
    1.83 +
    1.84 +(def hxc-thunk-words
    1.85 +  "Same as hxc-thunk, except it interprets the rom data as characters,
    1.86 +  returning a collection of strings."
    1.87 +  (comp
    1.88 +   (partial comp (partial map character-codes->str))
    1.89 +   hxc-thunk))
    1.90 +
    1.91 +#+end_src
    1.92 +
    1.93 +* Pok\eacute{}mon
    1.94 +** Names of each species
    1.95 +The names of the Pok\eacute{}mon species are stored in
    1.96 +ROM@E8000. This name list is interesting, for a number of reasons:
    1.97 +- The names are stored in [[ ][internal order]] rather than in the familiar
    1.98 +  Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or
    1.99 +  programmed in the Pok\eacute{}mon; it's used throughout the game.
   1.100 +- There is enough space allocated for 190 Pok\eacute{}mon. As I
   1.101 +  understand it, there were originally going to be 190 Pok\eacute{}mon
   1.102 +  in Generation I, but the creators decided to defer some to
   1.103 +  Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon
   1.104 +  have the same aesthetic feel.
   1.105 +- The list is pockmarked with random gaps, due to the strange internal
   1.106 +  ordering
   1.107 +  and 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the
   1.108 +  placeholder name,  =MISSINGNO.= (\ldquo{}Missing number\rdquo{}).
   1.109 +
   1.110 +Each name is exactly ten letters long (Whenever a name is too short, the extra
   1.111 +space is padded with the character 0x50). 
   1.112 +
   1.113 +
   1.114 +
   1.115 +#+name: pokenames
   1.116 +#+begin_src clojure
   1.117 +
   1.118 +(defn hxc-pokenames-raw
   1.119 +  "The hardcoded names of the 190 species in memory. List begins at
   1.120 +ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
   1.121 +  long, these names are stripped of padding. See also, hxc-pokedex-names"
   1.122 +  ([]
   1.123 +     (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
   1.124 +  ([rom]
   1.125 +     (let [count-species 190
   1.126 +           name-length 10]
   1.127 +       (map character-codes->str
   1.128 +            (partition name-length
   1.129 +                       (map #(if (= 0x50 %) 0x00 %)
   1.130 +                            (take (* count-species name-length)
   1.131 +                                  (drop 0xE8000
   1.132 +                                        rom))))))))
   1.133 +(def hxc-pokenames
   1.134 +  (comp
   1.135 +   (partial map format-name)
   1.136 +   hxc-pokenames-raw))
   1.137 +
   1.138 +
   1.139 +
   1.140 +
   1.141 +(defn hxc-pokedex-names
   1.142 +  "The names of the pokemon in hardcoded pokedex order. List begins at
   1.143 +ROM@410B1. See also, hxc-pokenames."
   1.144 +  ([] (hxc-pokedex-names
   1.145 +       com.aurellem.gb.gb-driver/original-rom))
   1.146 +  ([rom]
   1.147 +     (let [names (hxc-pokenames rom)]
   1.148 +       (#(mapv %
   1.149 +               ((comp range count keys) %))
   1.150 +        (zipmap
   1.151 +         (take (count names)
   1.152 +               (drop 0x410b1 rom))
   1.153 +         
   1.154 +         names)))))
   1.155 +
   1.156 +#+end_src
   1.157 +
   1.158  * Appendices
   1.159  ** Internal Pok\eacute{}mon IDs
   1.160  ** Type IDs
   1.161 +
   1.162 +#+name: type-ids
   1.163 +#+begin_src clojure
   1.164 +(def pkmn-types
   1.165 +  [:normal    ;;0
   1.166 +   :fighting  ;;1
   1.167 +   :flying    ;;2
   1.168 +   :poison    ;;3
   1.169 +   :ground    ;;4
   1.170 +   :rock      ;;5
   1.171 +   :bird      ;;6
   1.172 +   :bug       ;;7
   1.173 +   :ghost     ;;8
   1.174 +   :A
   1.175 +   :B
   1.176 +   :C
   1.177 +   :D
   1.178 +   :E
   1.179 +   :F
   1.180 +   :G
   1.181 +   :H
   1.182 +   :I
   1.183 +   :J
   1.184 +   :K
   1.185 +   :fire     ;;20 (0x14)
   1.186 +   :water    ;;21 (0x15)
   1.187 +   :grass    ;;22 (0x16)
   1.188 +   :electric ;;23 (0x17)
   1.189 +   :psychic  ;;24 (0x18)
   1.190 +   :ice      ;;25 (0x19)
   1.191 +   :dragon   ;;26 (0x1A)
   1.192 +   ])
   1.193 +#+end_src
   1.194 +
   1.195  ** Basic effects of moves
   1.196 +
   1.197 +*** Table of basic effects
   1.198 +
   1.199 +The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing
   1.200 +damage, leeching health, or potentially poisoning the opponent
   1.201 +\mdash{} are stored in a table. Each move has exactly one effect, and
   1.202 +different moves might have the same effect.
   1.203 +
   1.204 +For example, Leech Life, Mega Drain, and Absorb all have effect ID #3, which is \ldquo{}Leech half of the inflicted damage.\rdquo{}
   1.205 +
   1.206 +All the legitimate move effects are listed in the table
   1.207 +below. Here are some notes for reading it:
   1.208 +
   1.209 +- Whenever an effect has a chance of doing something (like a chance of
   1.210 +  poisoning the opponent), I list the chance as a hexadecimal amount out of 256 to avoid rounding errors. To convert the hex amount into a percentage, divide by 256.
   1.211 +- For some effects, the description is too cumbersome to
   1.212 +  write. Instead, I just write a move name
   1.213 +  in parentheses, like: (leech seed). That move gives a characteristic example
   1.214 +  of the effect.
   1.215 +- I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for
   1.216 +  attack, defense, speed, special, accuracy, and evasion. 
   1.217 +.
   1.218 +
   1.219 +
   1.220 +
   1.221 +| ID (hex) | Description                                                                                     | Notes                                                            |
   1.222 +|----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------|
   1.223 +|        0 | normal damage                                                                                   |                                                                  |
   1.224 +|        1 | no damage, just sleep                                                                           | TODO: find out how many turns                                    |
   1.225 +|        2 | 0x4C chance of poison                                                                           |                                                                  |
   1.226 +|        3 | leech half of inflicted damage                                                                  |                                                                  |
   1.227 +|        4 | 0x19 chance of burn                                                                             |                                                                  |
   1.228 +|        5 | 0x19 chance of freeze                                                                           |                                                                  |
   1.229 +|        6 | 0x19 chance of paralysis                                                                        |                                                                  |
   1.230 +|        7 | user faints; opponent's defense is halved during attack.                                        |                                                                  |
   1.231 +|        8 | leech half of inflicted damage ONLY if the opponent is asleep                                   |                                                                  |
   1.232 +|        9 | imitate last attack                                                                             |                                                                  |
   1.233 +|        A | user atk +1                                                                                     |                                                                  |
   1.234 +|        B | user def +1                                                                                     |                                                                  |
   1.235 +|        C | user spd +1                                                                                     |                                                                  |
   1.236 +|        D | user spc +1                                                                                     |                                                                  |
   1.237 +|        E | user acr +1                                                                                     | This effect is unused.                                           |
   1.238 +|        F | user evd +1                                                                                     |                                                                  |
   1.239 +|       10 | get post-battle money = 2 * level * uses                                                        |                                                                  |
   1.240 +|       11 | move has 0xFE acr, regardless of battle stat modifications.                                     |                                                                  |
   1.241 +|       12 | opponent atk -1                                                                                 |                                                                  |
   1.242 +|       13 | opponent def -1                                                                                 |                                                                  |
   1.243 +|       14 | opponent spd -1                                                                                 |                                                                  |
   1.244 +|       15 | opponent spc -1                                                                                 |                                                                  |
   1.245 +|       16 | opponent acr -1                                                                                 |                                                                  |
   1.246 +|       17 | opponent evd -1                                                                                 |                                                                  |
   1.247 +|       18 | converts user's type to opponent's.                                                             |                                                                  |
   1.248 +|       19 | (haze)                                                                                          |                                                                  |
   1.249 +|       1A | (bide)                                                                                          |                                                                  |
   1.250 +|       1B | (thrash)                                                                                        |                                                                  |
   1.251 +|       1C | (teleport)                                                                                      |                                                                  |
   1.252 +|       1D | (fury swipes)                                                                                   |                                                                  |
   1.253 +|       1E | attacks 2-5 turns                                                                               | Unused. TODO: find out what it does.                             |
   1.254 +|       1F | 0x19 chance of flinching                                                                        |                                                                  |
   1.255 +|       20 | opponent sleep for 1-7 turns                                                                    |                                                                  |
   1.256 +|       21 | 0x66 chance of poison                                                                           |                                                                  |
   1.257 +|       22 | 0x4D chance of burn                                                                             |                                                                  |
   1.258 +|       23 | 0x4D chance of freeze                                                                           |                                                                  |
   1.259 +|       24 | 0x4D chance of paralysis                                                                        |                                                                  |
   1.260 +|       25 | 0x4D chance of flinching                                                                        |                                                                  |
   1.261 +|       26 | one-hit KO                                                                                      |                                                                  |
   1.262 +|       27 | charge one turn, atk next.                                                                      |                                                                  |
   1.263 +|       28 | fixed damage, leaves 1HP.                                                                       | Is the fixed damage the power of the move?                       |
   1.264 +|       29 | fixed damage.                                                                                   | Like seismic toss, dragon rage, psywave.                         |
   1.265 +|       2A | atk 2-5 turns; opponent can't attack                                                            | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) |
   1.266 +|       2B | charge one turn, atk next. (can't be hit when charging)                                         |                                                                  |
   1.267 +|       2C | atk hits twice.                                                                                 |                                                                  |
   1.268 +|       2D | user takes 1 damage if misses.                                                                  |                                                                  |
   1.269 +|       2E | evade status-lowering effects                                                                   | Caused by you or also your opponent?                             |
   1.270 +|       2F | broken: if user is slower than opponent, makes critical hit impossible, otherwise has no effect | This is the effect of Focus Energy. It's (very) broken.          |
   1.271 +|       30 | atk causes recoil dmg = 1/4 dmg dealt                                                           |                                                                  |
   1.272 +|       31 | confuses opponent                                                                               |                                                                  |
   1.273 +|       32 | user atk +2                                                                                     |                                                                  |
   1.274 +|       33 | user def +2                                                                                     |                                                                  |
   1.275 +|       34 | user spd +2                                                                                     |                                                                  |
   1.276 +|       35 | user spc +2                                                                                     |                                                                  |
   1.277 +|       36 | user acr +2                                                                                     | This effect is unused.                                           |
   1.278 +|       37 | user evd +2                                                                                     | This effect is unused.                                           |
   1.279 +|       38 | restores up to half of user's max hp.                                                           |                                                                  |
   1.280 +|       39 | (transform)                                                                                     |                                                                  |
   1.281 +|       3A | opponent atk -2                                                                                 |                                                                  |
   1.282 +|       3B | opponent def -2                                                                                 |                                                                  |
   1.283 +|       3C | opponent spd -2                                                                                 |                                                                  |
   1.284 +|       3D | opponent spc -2                                                                                 |                                                                  |
   1.285 +|       3E | opponent acr -2                                                                                 |                                                                  |
   1.286 +|       3F | opponent evd -2                                                                                 |                                                                  |
   1.287 +|       40 | doubles user spc when attacked                                                                  |                                                                  |
   1.288 +|       41 | doubles user def when attacked                                                                  |                                                                  |
   1.289 +|       42 | just poisons opponent                                                                           |                                                                  |
   1.290 +|       43 | just paralyzes opponent                                                                         |                                                                  |
   1.291 +|       44 | 0x19 chance opponent atk -1                                                                     |                                                                  |
   1.292 +|       45 | 0x19 chance opponent def -1                                                                     |                                                                  |
   1.293 +|       46 | 0x19 chance opponent spd -1                                                                     |                                                                  |
   1.294 +|       47 | 0x4C chance opponent spc -1                                                                     |                                                                  |
   1.295 +|       48 | 0x19 chance opponent acr -1                                                                     |                                                                  |
   1.296 +|       49 | 0x19 chance opponent evd -1                                                                     |                                                                  |
   1.297 +|       4A | ???                                                                                             | ;; unused? no effect?                                            |
   1.298 +|       4B | ???                                                                                             | ;; unused? no effect?                                            |
   1.299 +|       4C | 0x19 chance of confusing the opponent                                                           |                                                                  |
   1.300 +|       4D | atk hits twice. 0x33 chance opponent poisioned.                                                 |                                                                  |
   1.301 +|       4E | broken. crash the game after attack.                                                            |                                                                  |
   1.302 +|       4F | (substitute)                                                                                    |                                                                  |
   1.303 +|       50 | unless opponent faints, user must recharge after atk. some exceptions apply                     |                                                                  |
   1.304 +|       51 | (rage)                                                                                          |                                                                  |
   1.305 +|       52 | (mimic)                                                                                         |                                                                  |
   1.306 +|       53 | (metronome)                                                                                     |                                                                  |
   1.307 +|       54 | (leech seed)                                                                                    |                                                                  |
   1.308 +|       55 | does nothing (splash)                                                                           |                                                                  |
   1.309 +|       56 | (disable)                                                                                       |                                                                  |
   1.310 +#+end_src
   1.311 +
   1.312 +*** Source
   1.313 +#+name: move-effects
   1.314 +#+begin_src clojure
   1.315 +(def move-effects
   1.316 +  ["normal damage"
   1.317 +   "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
   1.318 +   "0x4C chance of poison"
   1.319 +   "leech half of inflicted damage"
   1.320 +   "0x19 chance of burn"
   1.321 +   "0x19 chance of freeze"
   1.322 +   "0x19 chance of paralyze"
   1.323 +   "user faints; opponent defense halved during attack."
   1.324 +   "leech half of inflicted damage ONLY if sleeping opponent."
   1.325 +   "imitate last attack"
   1.326 +   "user atk +1"
   1.327 +   "user def +1"
   1.328 +   "user spd +1"
   1.329 +   "user spc +1"
   1.330 +   "user acr +1" ;; unused?!
   1.331 +   "user evd +1"
   1.332 +   "get post-battle $ = 2*level*uses"
   1.333 +   "0xFE acr, no matter what."
   1.334 +   "opponent atk -1"     ;; acr taken from move acr?
   1.335 +   "opponent def -1"     ;;
   1.336 +   "opponent spd -1"   ;;
   1.337 +   "opponent spc -1" ;;
   1.338 +   "opponent acr -1";;
   1.339 +   "opponent evd -1"
   1.340 +   "converts user's type to opponent's."
   1.341 +   "(haze)"
   1.342 +   "(bide)"
   1.343 +   "(thrash)"
   1.344 +   "(teleport)"
   1.345 +   "(fury swipes)"
   1.346 +   "attacks 2-5 turns" ;; unused? like rollout?
   1.347 +   "0x19 chance of flinch"
   1.348 +   "opponent sleep for 1-7 turns"
   1.349 +   "0x66 chance of poison"
   1.350 +   "0x4D chance of burn"
   1.351 +   "0x4D chance of freeze"
   1.352 +   "0x4D chance of paralyze"
   1.353 +   "0x4D chance of flinch"
   1.354 +   "one-hit KO"
   1.355 +   "charge one turn, atk next."
   1.356 +   "fixed damage, leaves 1HP." ;; how is dmg determined?
   1.357 +   "fixed damage."             ;; cf seismic toss, dragon rage, psywave.
   1.358 +   "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
   1.359 +   "charge one turn, atk next. (can't be hit when charging)"
   1.360 +   "atk hits twice."
   1.361 +   "user takes 1 damage if misses."
   1.362 +   "evade status-lowering effects" ;;caused by you or also your opponent?
   1.363 +   "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
   1.364 +   "atk causes recoil dmg = 1/4 dmg dealt"
   1.365 +   "confuses opponent" ;; acr taken from move acr
   1.366 +   "user atk +2"
   1.367 +   "user def +2"
   1.368 +   "user spd +2"
   1.369 +   "user spc +2"
   1.370 +   "user acr +2" ;; unused!
   1.371 +   "user evd +2" ;; unused!
   1.372 +   "restores up to half of user's max hp." ;; broken: fails if the difference
   1.373 +   ;; b/w max and current hp is one less than a multiple of 256.
   1.374 +   "(transform)"
   1.375 +   "opponent atk -2"
   1.376 +   "opponent def -2"
   1.377 +   "opponent spd -2"
   1.378 +   "opponent spc -2"
   1.379 +   "opponent acr -2"
   1.380 +   "opponent evd -2"
   1.381 +   "doubles user spc when attacked"
   1.382 +   "doubles user def when attacked"
   1.383 +   "just poisons opponent"   ;;acr taken from move acr
   1.384 +   "just paralyzes opponent" ;;
   1.385 +   "0x19 chance opponent atk -1"
   1.386 +   "0x19 chance opponent def -1"
   1.387 +   "0x19 chance opponent spd -1"
   1.388 +   "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
   1.389 +   "0x19 chance opponent acr -1"
   1.390 +   "0x19 chance opponent evd -1"
   1.391 +   "???" ;; unused? no effect?
   1.392 +   "???" ;; unused? no effect?
   1.393 +   "0x19 chance opponent confused"
   1.394 +   "atk hits twice. 0x33 chance opponent poisioned."
   1.395 +   "broken. crash the game after attack."
   1.396 +   "(substitute)"
   1.397 +   "unless opponent faints, user must recharge after atk. some
   1.398 +  exceptions apply."
   1.399 +   "(rage)"
   1.400 +   "(mimic)"
   1.401 +   "(metronome)"
   1.402 +   "(leech seed)"
   1.403 +   "does nothing (splash)"
   1.404 +   "(disable)"
   1.405 +   ])
   1.406 +#+end_src
   1.407 +
   1.408 +
   1.409  ** Alphabet code
   1.410 +
   1.411 +#+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj
   1.412 +
   1.413 +(ns com.aurellem.gb.hxc
   1.414 +  (:use (com.aurellem.gb assembly characters gb-driver util mem-util
   1.415 +                         constants species))
   1.416 +  (:import [com.aurellem.gb.gb_driver SaveState]))
   1.417 +
   1.418 +
   1.419 +
   1.420 +
   1.421 +; ************* HANDWRITTEN CONSTANTS
   1.422 +
   1.423 +<<type-ids>>
   1.424 +
   1.425 +
   1.426 +;; question: when status effects claim to take
   1.427 +;; their accuracy from the move accuracy, does
   1.428 +;; this mean that the move always "hits" but the
   1.429 +;; status effect may not?
   1.430 +
   1.431 +<<move-effects>>
   1.432 +
   1.433 +;; ************** HARDCODED DATA
   1.434 +
   1.435 +<<hxc-thunks>>
   1.436 +;; --------------------------------------------------
   1.437 +
   1.438 +
   1.439 +<<pokenames>>
   1.440 +
   1.441 +;; http://hax.iimarck.us/topic/581/
   1.442 +(defn hxc-cry
   1.443 +  "The pokemon cry data in internal order. List begins at ROM@39462"
   1.444 +  ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
   1.445 +  ([rom]
   1.446 +     (zipmap
   1.447 +      (hxc-pokenames rom)
   1.448 +      (map
   1.449 +       (fn [[cry-id pitch length]]
   1.450 +         {:cry-id cry-id
   1.451 +         :pitch pitch
   1.452 +          :length length}
   1.453 +         )
   1.454 +       (partition 3
   1.455 +                  (drop 0x39462 rom))))))
   1.456 +
   1.457 +(defn hxc-cry-groups
   1.458 +  ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
   1.459 +  ([rom]
   1.460 +     (map #(mapv first
   1.461 +                (filter
   1.462 +                 (fn [[k v]]
   1.463 +                   (= % (:cry-id v)))
   1.464 +                 (hxc-cry)))
   1.465 +          ((comp
   1.466 +            range
   1.467 +            count
   1.468 +            set
   1.469 +            (partial map :cry-id)
   1.470 +            vals
   1.471 +            hxc-cry)
   1.472 +           rom))))
   1.473 +
   1.474 +
   1.475 +(defn cry-conversion!
   1.476 +  "Convert Porygon's cry in ROM to be the cry of the given pokemon."
   1.477 +  [pkmn]
   1.478 +  (write-rom!
   1.479 +   (rewrite-memory
   1.480 +    (vec(rom))
   1.481 +    0x3965D 
   1.482 +    (map second
   1.483 +         ((hxc-cry) pkmn)))))
   1.484 +
   1.485 +(def hxc-items-raw
   1.486 +  "The hardcoded names of the items in memory. List begins at
   1.487 +ROM@045B7"
   1.488 +  (hxc-thunk-words 0x45B7 870))
   1.489 +
   1.490 +(def hxc-types
   1.491 +  "The hardcoded type names in memory. List begins at ROM@27D99,
   1.492 +  shortly before hxc-titles."
   1.493 +  (hxc-thunk-words 0x27D99 102))
   1.494 +
   1.495 +(def hxc-titles
   1.496 +  "The hardcoded names of the trainer titles in memory. List begins at
   1.497 +ROM@27E77"
   1.498 +  (hxc-thunk-words 0x27E77 196))
   1.499 +
   1.500 +
   1.501 +(def hxc-pokedex-text-raw
   1.502 +  "The hardcoded pokedex entries in memory. List begins at
   1.503 +ROM@B8000, shortly before move names."
   1.504 +  (hxc-thunk-words 0xB8000 14754))
   1.505 +
   1.506 +
   1.507 +
   1.508 +(def hxc-items
   1.509 +  "The hardcoded names of the items in memory, presented as
   1.510 +  keywords. List begins at ROM@045B7. See also, hxc-items-raw."
   1.511 +  (comp (partial map format-name) hxc-items-raw))
   1.512 +
   1.513 +(defn hxc-pokedex-text
   1.514 +  "The hardcoded pokedex entries in memory, presented as an
   1.515 +associative hash map. List begins at ROM@B8000."
   1.516 +  ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
   1.517 +  ([rom]
   1.518 +     (zipmap
   1.519 +      (hxc-pokedex-names rom)
   1.520 +      (cons nil ;; for missingno.
   1.521 +            (hxc-pokedex-text-raw rom)))))
   1.522 +
   1.523 +;; In red/blue, pokedex stats are in internal order.
   1.524 +;; In yellow, pokedex stats are in pokedex order.
   1.525 +
   1.526 +(defn hxc-pokedex-stats
   1.527 +  "The hardcoded pokedex stats (species height weight) in memory. List
   1.528 +begins at ROM@40687"
   1.529 +  ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
   1.530 +  ([rom]
   1.531 +     (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
   1.532 +           pkmn-count (count pokedex-names)
   1.533 +           ]
   1.534 +     ((fn capture-stats
   1.535 +        [n stats data]
   1.536 +        (if (zero? n) stats
   1.537 +            (let [[species
   1.538 +                   [_
   1.539 +                    height-ft
   1.540 +                    height-in
   1.541 +                    weight-1
   1.542 +                    weight-2
   1.543 +                    _
   1.544 +                    dex-ptr-1
   1.545 +                    dex-ptr-2
   1.546 +                    dex-bank
   1.547 +                    _
   1.548 +                    & data]]
   1.549 +                  (split-with (partial not= 0x50) data)]
   1.550 +              (recur (dec n)
   1.551 +                     (assoc stats
   1.552 +                       (pokedex-names (- pkmn-count (dec n)))
   1.553 +                       {:species
   1.554 +                        (format-name (character-codes->str species))
   1.555 +                        :height-ft
   1.556 +                        height-ft
   1.557 +                        :height-in
   1.558 +                        height-in
   1.559 +                        :weight
   1.560 +                        (/ (low-high weight-1 weight-2) 10.)
   1.561 +                        
   1.562 +                    ;;    :text
   1.563 +                    ;;    (character-codes->str
   1.564 +                    ;;     (take-while
   1.565 +                    ;;      (partial not= 0x50)
   1.566 +                    ;;      (drop
   1.567 +                    ;;       (+ 0xB8000
   1.568 +                    ;;          -0x4000
   1.569 +                    ;;          (low-high dex-ptr-1 dex-ptr-2))
   1.570 +                    ;;       rom)))
   1.571 +                        })
   1.572 +                     
   1.573 +                     data)
   1.574 +              
   1.575 +              
   1.576 +              )))
   1.577 +      
   1.578 +      pkmn-count
   1.579 +      {}
   1.580 +      (drop 0x40687 rom)))       ))
   1.581 +
   1.582 +
   1.583 +
   1.584 +
   1.585 +
   1.586 +
   1.587 +
   1.588 +(def hxc-places
   1.589 +  "The hardcoded place names in memory. List begins at
   1.590 +ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
   1.591 +  (hxc-thunk-words 0x71500 560))
   1.592 +
   1.593 +
   1.594 +(defn hxc-dialog
   1.595 +  "The hardcoded dialogue in memory, including in-game alerts. Dialog
   1.596 +  seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
   1.597 +  ([rom]
   1.598 +     (map character-codes->str
   1.599 +          (take-nth 2
   1.600 +                    (partition-by #(= % 0x57)
   1.601 +                                  (take 0x0F728
   1.602 +                                        (drop 0x98000 rom))))))
   1.603 +  ([]
   1.604 +     (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
   1.605 +
   1.606 +
   1.607 +(def hxc-move-names
   1.608 +  "The hardcoded move names in memory. List begins at ROM@BC000"
   1.609 +  (hxc-thunk-words 0xBC000 1551))
   1.610 +
   1.611 +
   1.612 +(defn hxc-move-data
   1.613 +  "The hardcoded (basic (move effects)) in memory. List begins at
   1.614 +0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
   1.615 +  :fx-txt}. The move descriptions are handwritten, not hardcoded."
   1.616 +  ([]
   1.617 +     (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
   1.618 +  ([rom]
   1.619 +     (let [names (vec (hxc-move-names rom))
   1.620 +           move-count (count names)
   1.621 +           move-size 6
   1.622 +           types pkmn-types ;;; !! hardcoded types
   1.623 +           ]
   1.624 +       (zipmap (map format-name names)
   1.625 +               (map
   1.626 +                (fn [[idx effect power type-id accuracy pp]]
   1.627 +                  {:name (names (dec idx))
   1.628 +                   :power power
   1.629 +                   :accuracy  accuracy
   1.630 +                   :pp pp
   1.631 +                   :type (types type-id)
   1.632 +                   :fx-id effect
   1.633 +                   :fx-txt (get move-effects effect) 
   1.634 +                   }
   1.635 +                  )
   1.636 +                
   1.637 +                (partition move-size
   1.638 +                           (take (* move-size move-count)
   1.639 +                                 (drop 0x38000 rom))))))))
   1.640 +  
   1.641 +
   1.642 +
   1.643 +(defn hxc-move-data*
   1.644 +  "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
   1.645 +  ([]
   1.646 +     (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
   1.647 +  ([rom]
   1.648 +     (let [names (vec (hxc-move-names rom))
   1.649 +           move-count (count names)
   1.650 +           move-size 6
   1.651 +           format-name (fn [s]
   1.652 +                         (keyword (.toLowerCase
   1.653 +                                   (apply str
   1.654 +                                          (map #(if (= % \space) "-" %) s)))))
   1.655 +           ]
   1.656 +       (zipmap (map format-name names)
   1.657 +               (map
   1.658 +                (fn [[idx effect power type accuracy pp]]
   1.659 +                  {:name (names (dec idx))
   1.660 +                   :power power
   1.661 +                   :accuracy (hex accuracy)
   1.662 +                   :pp pp
   1.663 +                   :fx-id (hex effect)
   1.664 +                   :fx-txt (get move-effects effect) 
   1.665 +                   }
   1.666 +                  )
   1.667 +                
   1.668 +                (partition move-size
   1.669 +                           (take (* move-size move-count)
   1.670 +                                 (drop 0x38000 rom))))))))
   1.671 +  
   1.672 +
   1.673 +(defn hxc-machines
   1.674 +  "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D."
   1.675 +  ([] (hxc-machines
   1.676 +       com.aurellem.gb.gb-driver/original-rom))
   1.677 +  ([rom]
   1.678 +     (let [moves (hxc-move-names rom)]
   1.679 +       (zipmap
   1.680 +        (range)
   1.681 +        (take-while
   1.682 +            (comp not nil?)
   1.683 +            (map (comp
   1.684 +                  format-name
   1.685 +                  (zipmap
   1.686 +                   (range)
   1.687 +                   moves)
   1.688 +              dec)
   1.689 +                 (take 100
   1.690 +                       (drop 0x1232D rom))))))))
   1.691 +
   1.692 +
   1.693 +
   1.694 +(defn internal-id
   1.695 +  ([rom]
   1.696 +     (zipmap 
   1.697 +      (hxc-pokenames rom)
   1.698 +      (range)))
   1.699 +  ([]
   1.700 +     (internal-id com.aurellem.gb.gb-driver/original-rom)))
   1.701 +
   1.702 +
   1.703 +
   1.704 +
   1.705 +
   1.706 +;; nidoran gender change upon levelup
   1.707 +;; (->
   1.708 +;;  @current-state
   1.709 +;;  rom
   1.710 +;;  vec
   1.711 +;;  (rewrite-memory
   1.712 +;;   (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
   1.713 +;;   [1 1 15])
   1.714 +;;  (rewrite-memory
   1.715 +;;   (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
   1.716 +;;   [1 1 3])
   1.717 +;;  (write-rom!)
   1.718 +
   1.719 +;;  )
   1.720 +
   1.721 +
   1.722 +
   1.723 +
   1.724 +(defn hxc-advantage
   1.725 +  ;; in-game multipliers are stored as 10x their effective value
   1.726 +  ;; to allow for fractional multipliers like 1/2
   1.727 +  
   1.728 +  "The hardcoded type advantages in memory, returned as tuples of
   1.729 +  atk-type def-type multiplier. By default (i.e. if not listed here),
   1.730 +the multiplier is 1. List begins at 0x3E62D."
   1.731 +  ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
   1.732 +  ([rom]
   1.733 +     (map
   1.734 +      (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
   1.735 +                            (get pkmn-types def (hex def))
   1.736 +                            (/ mult 10)])
   1.737 +      (partition 3
   1.738 +                 (take-while (partial not= 0xFF)
   1.739 +                             (drop 0x3E62D rom))))))
   1.740 +
   1.741 +
   1.742 +
   1.743 +(defn format-evo
   1.744 +  "Parse a sequence of evolution data, returning a map. First is the
   1.745 +method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
   1.746 +  method of evolution is by item (only stones will actually make pokemon
   1.747 +  evolve, for some auxillary reason.) Finally, the minimum level for
   1.748 +  evolution to occur (level 1 means no limit, which is used for trade
   1.749 +  and item evolutions), followed by the internal id of the pokemon
   1.750 +  into which to evolve. Hence, level up and trade evolutions are
   1.751 +  described with 3
   1.752 +  bytes; item evolutions with four."
   1.753 +  [coll]
   1.754 +  (let [method (first coll)]
   1.755 +    (cond (empty? coll) []
   1.756 +          (= 0 method) [] ;; just in case
   1.757 +          (= 1 method) ;; level-up evolution
   1.758 +          (conj (format-evo (drop 3 coll))
   1.759 +                            {:method :level-up
   1.760 +                             :min-level (nth coll 1)
   1.761 +                             :into (dec (nth coll 2))})
   1.762 +          
   1.763 +          (= 2 method) ;; item evolution
   1.764 +          (conj (format-evo (drop 4 coll))
   1.765 +                {:method :item
   1.766 +                 :item (dec (nth coll 1))
   1.767 +                 :min-level (nth coll 2)
   1.768 +                 :into (dec (nth coll 3))})
   1.769 +
   1.770 +          (= 3 method) ;; trade evolution
   1.771 +          (conj (format-evo (drop 3 coll))
   1.772 +                {:method :trade
   1.773 +                 :min-level (nth coll 1) ;; always 1 for trade.
   1.774 +                 :into (dec (nth coll 2))}))))
   1.775 +
   1.776 +
   1.777 +(defn hxc-ptrs-evolve
   1.778 +  "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
   1.779 +in internal order."
   1.780 +  ([]
   1.781 +     (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
   1.782 +  ([rom]
   1.783 +     (let [
   1.784 +           pkmn-count (count (hxc-pokenames-raw)) ;; 190
   1.785 +           ptrs
   1.786 +           (map (fn [[a b]] (low-high a b))
   1.787 +                (partition 2
   1.788 +                           (take (* 2 pkmn-count)
   1.789 +                                 (drop 0x3b1e5 rom))))]
   1.790 +       (map (partial + 0x34000) ptrs)
   1.791 +
   1.792 +       )))
   1.793 +
   1.794 +
   1.795 +(defn hxc-learnsets
   1.796 +  "Hardcoded map associating pokemon names to lists of pairs [lvl
   1.797 +  move] of abilities they learn as they level up. The data
   1.798 +exists at ROM@34000, sorted by internal order. Pointers to the data
   1.799 +  exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
   1.800 +  ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
   1.801 +  ([rom]
   1.802 +     (apply assoc
   1.803 +            {}
   1.804 +            (interleave
   1.805 +             (hxc-pokenames rom)
   1.806 +             (map (comp
   1.807 +                   (partial map
   1.808 +                            (fn [[lvl mv]] [lvl (dec mv)]))
   1.809 +                   (partial partition 2)
   1.810 +                   ;; keep the learnset data
   1.811 +                   (partial take-while (comp not zero?))
   1.812 +                   ;; skip the evolution data
   1.813 +                   rest
   1.814 +                   (partial drop-while (comp not zero?)))
   1.815 +                  (map #(drop % rom) 
   1.816 +                       (hxc-ptrs-evolve rom)))))))
   1.817 +
   1.818 +(defn hxc-learnsets-pretty
   1.819 +  "Live hxc-learnsets except it reports the name of each move --- as
   1.820 +it appears in rom --- rather than the move index."
   1.821 +  ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
   1.822 +  ([rom]
   1.823 +     (let [moves (vec(map format-name (hxc-move-names)))]
   1.824 +       (into {}
   1.825 +             (map (fn [[pkmn learnset]]
   1.826 +                    [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
   1.827 +                               learnset)])
   1.828 +                  (hxc-learnsets rom))))))
   1.829 +             
   1.830 +                                  
   1.831 +
   1.832 +
   1.833 +(defn hxc-evolution
   1.834 +  "Hardcoded evolution data in memory. The data exists at ROM@34000,
   1.835 +  sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
   1.836 +  ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
   1.837 +  ([rom]
   1.838 +       (apply assoc {}
   1.839 +               (interleave
   1.840 +                (hxc-pokenames rom)
   1.841 +                (map
   1.842 +                 (comp
   1.843 +                  format-evo
   1.844 +                  (partial take-while (comp not zero?))
   1.845 +                  #(drop % rom))
   1.846 +                 (hxc-ptrs-evolve rom)
   1.847 +                 )))))
   1.848 +
   1.849 +(defn hxc-evolution-pretty
   1.850 +  "Like hxc-evolution, except it uses the names of items and pokemon
   1.851 +--- grabbed from ROM --- rather than their numerical identifiers."
   1.852 +  ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
   1.853 +  ([rom]
   1.854 +     (let
   1.855 +         [poke-names (vec (hxc-pokenames rom))
   1.856 +          item-names (vec (hxc-items rom))
   1.857 +          use-names
   1.858 +          (fn [m]
   1.859 +            (loop [ks (keys m) new-map m]
   1.860 +              (let [k (first ks)]
   1.861 +                (cond (nil? ks) new-map
   1.862 +                      (= k :into)
   1.863 +                      (recur
   1.864 +                       (next ks)
   1.865 +                       (assoc new-map
   1.866 +                         :into
   1.867 +                         (poke-names
   1.868 +                          (:into
   1.869 +                           new-map))))
   1.870 +                      (= k :item)
   1.871 +                      (recur
   1.872 +                       (next ks)
   1.873 +                       (assoc new-map
   1.874 +                         :item
   1.875 +                         (item-names
   1.876 +                          (:item new-map))))
   1.877 +                      :else
   1.878 +                      (recur
   1.879 +                       (next ks)
   1.880 +                       new-map)
   1.881 +                      ))))]
   1.882 +
   1.883 +       (into {}
   1.884 +             (map (fn [[pkmn evo-coll]]
   1.885 +                    [pkmn (map use-names evo-coll)])
   1.886 +                  (hxc-evolution rom))))))
   1.887 +
   1.888 +
   1.889 +(defn hxc-pokemon-base
   1.890 +  ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
   1.891 +  ([rom]
   1.892 +     (let [entry-size 28
   1.893 +           pkmn-count (count (hxc-pokedex-text rom))
   1.894 +           pokemon (rest (hxc-pokedex-names))
   1.895 +           types (apply assoc {}
   1.896 +                        (interleave
   1.897 +                         (range)
   1.898 +                         pkmn-types)) ;;!! softcoded
   1.899 +           moves (apply assoc {}
   1.900 +                        (interleave
   1.901 +                         (range)
   1.902 +                         (map format-name
   1.903 +                              (hxc-move-names rom))))
   1.904 +           machines (hxc-machines)
   1.905 +           ]
   1.906 +       (zipmap
   1.907 +        pokemon
   1.908 +        (map
   1.909 +         (fn [[n
   1.910 +               rating-hp
   1.911 +               rating-atk
   1.912 +               rating-def
   1.913 +               rating-speed
   1.914 +               rating-special
   1.915 +               type-1
   1.916 +               type-2
   1.917 +               rarity
   1.918 +               rating-xp
   1.919 +               pic-dimensions ;; tile_width|tile_height (8px/tile)
   1.920 +               ptr-pic-obverse-1
   1.921 +               ptr-pic-obverse-2
   1.922 +               ptr-pic-reverse-1
   1.923 +               ptr-pic-reverse-2
   1.924 +               move-1
   1.925 +               move-2
   1.926 +               move-3
   1.927 +               move-4
   1.928 +               growth-rate
   1.929 +               &
   1.930 +               TMs|HMs]]
   1.931 +           (let
   1.932 +               [base-moves
   1.933 +                (mapv moves
   1.934 +                      ((comp
   1.935 +                        ;; since the game uses zero as a delimiter,
   1.936 +                        ;; it must also increment all move indices by 1.
   1.937 +                        ;; heren we decrement to correct this.
   1.938 +                        (partial map dec)
   1.939 +                        (partial take-while (comp not zero?)))
   1.940 +                       [move-1 move-2 move-3 move-4]))
   1.941 +                
   1.942 +                types
   1.943 +                (set (list (types type-1)
   1.944 +                           (types type-2)))
   1.945 +                TMs|HMs
   1.946 +                (map
   1.947 +                 (comp
   1.948 +                  (partial map first)
   1.949 +                  (partial remove (comp zero? second)))
   1.950 +                 (split-at
   1.951 +                  50
   1.952 +                  (map vector
   1.953 +                       (rest(range))
   1.954 +                       (reduce concat
   1.955 +                               (map
   1.956 +                                #(take 8
   1.957 +                                       (concat (bit-list %)
   1.958 +                                               (repeat 0)))
   1.959 +                                
   1.960 +                                TMs|HMs)))))
   1.961 +                
   1.962 +                TMs  (vec (first TMs|HMs))
   1.963 +                HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
   1.964 +                
   1.965 +                
   1.966 +                ]
   1.967 +             
   1.968 +             
   1.969 +             {:dex# n
   1.970 +              :base-moves base-moves
   1.971 +              :types types
   1.972 +              :TMs TMs
   1.973 +              :HMs HMs
   1.974 +              :base-hp rating-hp
   1.975 +              :base-atk rating-atk
   1.976 +              :base-def rating-def
   1.977 +              :base-speed rating-speed
   1.978 +              :base-special rating-special
   1.979 +              :o0 pic-dimensions
   1.980 +              :o1 ptr-pic-obverse-1
   1.981 +              :o2 ptr-pic-obverse-2
   1.982 +              }))
   1.983 +         
   1.984 +         (partition entry-size
   1.985 +                    (take (* entry-size pkmn-count)
   1.986 +                          (drop 0x383DE
   1.987 +                                rom))))))))
   1.988 +  
   1.989 +  
   1.990 +(defn hxc-intro-pkmn
   1.991 +  "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
   1.992 +internal id is stored at ROM@5EDB."
   1.993 +  ([] (hxc-intro-pkmn
   1.994 +       com.aurellem.gb.gb-driver/original-rom))
   1.995 +  ([rom]
   1.996 +     (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
   1.997 +
   1.998 +(defn sxc-intro-pkmn!
   1.999 +  "Set the hardcoded pokemon to display in Prof. Oak's introduction."
  1.1000 +  [pokemon]
  1.1001 +  (write-rom! 
  1.1002 +   (rewrite-rom 0x5EDB
  1.1003 +                [
  1.1004 +                 (inc
  1.1005 +                  ((zipmap
  1.1006 +                    (hxc-pokenames)
  1.1007 +                    (range))
  1.1008 +                   pokemon))])))
  1.1009 +  
  1.1010 +
  1.1011 +(defn hxc-item-prices
  1.1012 +  "The hardcoded list of item prices in memory. List begins at ROM@4495"
  1.1013 +  ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
  1.1014 +  ([rom]
  1.1015 +     (let [items (hxc-items rom)
  1.1016 +           price-size 3]
  1.1017 +       (zipmap items
  1.1018 +               (map (comp
  1.1019 +                     ;; zero-cost items are "priceless"
  1.1020 +                     #(if (zero? %) :priceless %)
  1.1021 +                     decode-bcd butlast)
  1.1022 +                    (partition price-size
  1.1023 +                               (take (* price-size (count items))
  1.1024 +                                     (drop 0x4495 rom))))))))
  1.1025 +
  1.1026 +(defn hxc-shops
  1.1027 +  ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
  1.1028 +  ([rom]
  1.1029 +     (let [items (zipmap (range) (hxc-items rom))
  1.1030 +
  1.1031 +           ;; temporarily softcode the TM items
  1.1032 +           items (into
  1.1033 +                  items
  1.1034 +                  (map (juxt identity
  1.1035 +                             (comp keyword
  1.1036 +                                   (partial str "tm-")
  1.1037 +                                   (partial + 1 -200)
  1.1038 +                                   )) 
  1.1039 +                       (take 200 (drop 200 (range)))))
  1.1040 +                       
  1.1041 +           ]
  1.1042 +
  1.1043 +       ((fn parse-shop [coll [num-items & items-etc]]
  1.1044 +          (let [inventory (take-while
  1.1045 +                           (partial not= 0xFF)
  1.1046 +                           items-etc)
  1.1047 +               [separator & items-etc] (drop num-items (rest items-etc))]
  1.1048 +           (if (= separator 0x50)
  1.1049 +             (map (partial mapv (comp items dec)) (conj coll inventory))
  1.1050 +             (recur (conj coll inventory) items-etc)
  1.1051 +             )
  1.1052 +         ))
  1.1053 +
  1.1054 +        '()
  1.1055 +        (drop 0x233C rom))
  1.1056 +
  1.1057 +     
  1.1058 +     )))
  1.1059 +
  1.1060 +
  1.1061 +
  1.1062 +
  1.1063 +
  1.1064 +(defn hxc-ptrs-wild
  1.1065 +  "A list of the hardcoded wild encounter data in memory. Pointers
  1.1066 +  begin at ROM@0CB95; data begins at ROM@0x04D89" 
  1.1067 +  ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
  1.1068 +  ([rom]
  1.1069 +     (let [ptrs
  1.1070 +           (map (fn [[a b]] (+ a (* 0x100 b)))
  1.1071 +            (take-while (partial not= (list 0xFF 0xFF))
  1.1072 +                            (partition 2 (drop 0xCB95 rom))))]
  1.1073 +       ptrs)))
  1.1074 +
  1.1075 +
  1.1076 +
  1.1077 +(defn hxc-wilds
  1.1078 +  "A list of the hardcoded wild encounter data in memory. Pointers
  1.1079 +  begin at ROM@0CB95; data begins at ROM@0x04D89" 
  1.1080 +  ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
  1.1081 +  ([rom]
  1.1082 +     (let [pokenames (zipmap (range) (hxc-pokenames rom))]
  1.1083 +       (map
  1.1084 +        (partial map (fn [[a b]] {:species (pokenames (dec b)) :level
  1.1085 +                                  a}))
  1.1086 +        (partition 10
  1.1087 +                     
  1.1088 +                      (take-while (comp (partial not= 1)
  1.1089 +                                        first) 
  1.1090 +                                 (partition 2
  1.1091 +                                            (drop 0xCD8C rom))
  1.1092 +                   
  1.1093 +                   ))))))
  1.1094 +
  1.1095 +
  1.1096 +
  1.1097 +
  1.1098 +
  1.1099 +
  1.1100 +
  1.1101 +
  1.1102 +
  1.1103 +
  1.1104 +
  1.1105 +
  1.1106 +
  1.1107 +
  1.1108 +;; ********************** MANIPULATION FNS
  1.1109 +
  1.1110 +
  1.1111 +(defn same-type
  1.1112 +  ([pkmn move]
  1.1113 +     (same-type
  1.1114 +      com.aurellem.gb.gb-driver/original-rom pkmn move))
  1.1115 +  ([rom pkmn move]
  1.1116 +     (((comp :types (hxc-pokemon-base rom)) pkmn)
  1.1117 +      ((comp :type (hxc-move-data rom)) move))))
  1.1118 +
  1.1119 +
  1.1120 +
  1.1121 +
  1.1122 +(defn submap?
  1.1123 +  "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false." 
  1.1124 +  [map-small map-big]
  1.1125 +  (cond (empty? map-small) true
  1.1126 +        (and
  1.1127 +         (contains? map-big (ffirst map-small))
  1.1128 +         (= (get map-big (ffirst map-small))
  1.1129 +            (second (first map-small))))
  1.1130 +        (recur (next map-small) map-big)
  1.1131 +
  1.1132 +        :else false))  
  1.1133 +
  1.1134 +
  1.1135 +(defn search-map [proto-map maps]
  1.1136 +  "Returns all the maps that make the same associations as proto-map."
  1.1137 +  (some (partial submap? proto-map) maps))
  1.1138 +
  1.1139 +(defn filter-vals
  1.1140 +  "Returns a map consisting of all the pairs [key val] for
  1.1141 +  which (pred key) returns true."
  1.1142 +  [pred map]
  1.1143 +  (reduce (partial apply assoc) {}
  1.1144 +          (filter (fn [[k v]] (pred v)) map)))
  1.1145 +
  1.1146 +
  1.1147 +(defn search-moves
  1.1148 +  "Returns a subcollection of all hardcoded moves with the
  1.1149 +  given attributes. Attributes consist of :name :power
  1.1150 +  :accuracy :pp :fx-id
  1.1151 +  (and also :fx-txt, but it contains the same information
  1.1152 +  as :fx-id)"
  1.1153 +  ([attribute-map]
  1.1154 +     (search-moves
  1.1155 +      com.aurellem.gb.gb-driver/original-rom attribute-map))
  1.1156 +  ([rom attribute-map]
  1.1157 +     (filter-vals (partial submap? attribute-map)
  1.1158 +                  (hxc-move-data rom))))
  1.1159 +
  1.1160 +
  1.1161 +
  1.1162 +
  1.1163 +
  1.1164 +;; note: 0x2f31 contains the names "TM" "HM"?
  1.1165 +
  1.1166 +;; note for later: credits start at F1290
  1.1167 +
  1.1168 +;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ??
  1.1169 +
  1.1170 +;; note: DD4D spells out pokemon vital stat names ("speed", etc.)
  1.1171 +
  1.1172 +;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
  1.1173 +;; The first instance is for Machines; the second, for stones.
  1.1174 +
  1.1175 +;; 0x251A (in indexable mem): image decompression routine seems to begin here.
  1.1176 +
  1.1177 +
  1.1178 +(comment 
  1.1179 +
  1.1180 +(def hxc-later
  1.1181 +  "Running this code produces, e.g. hardcoded names NPCs give
  1.1182 +their pokemon. Will sort through it later."
  1.1183 +(print (character-codes->str(take 10000
  1.1184 +                          (drop 0x71597
  1.1185 +                                (rom (root)))))))
  1.1186 +
  1.1187 +(let [dex
  1.1188 +      (partition-by #(= 0x50 %)
  1.1189 +                    (take 2540
  1.1190 +                          (drop 0x40687
  1.1191 +                                (rom (root)))))]
  1.1192 +  (def dex dex)
  1.1193 +  (def hxc-species
  1.1194 +    (map character-codes->str
  1.1195 +         (take-nth 4 dex))))
  1.1196 +)
  1.1197 +
  1.1198 +
  1.1199 +#+end_src
  1.1200 +