changeset 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
files clojure/com/aurellem/gb/hxc.clj org/rom.org
diffstat 2 files changed, 1171 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
     1.1 --- a/clojure/com/aurellem/gb/hxc.clj	Sun Apr 08 01:28:39 2012 -0500
     1.2 +++ b/clojure/com/aurellem/gb/hxc.clj	Sun Apr 08 06:13:39 2012 -0500
     1.3 @@ -1,3 +1,4 @@
     1.4 +
     1.5  (ns com.aurellem.gb.hxc
     1.6    (:use (com.aurellem.gb assembly characters gb-driver util mem-util
     1.7                           constants species))
     1.8 @@ -8,8 +9,6 @@
     1.9  
    1.10  ; ************* HANDWRITTEN CONSTANTS
    1.11  
    1.12 -
    1.13 -
    1.14  (def pkmn-types
    1.15    [:normal    ;;0
    1.16     :fighting  ;;1
    1.17 @@ -138,7 +137,6 @@
    1.18     "(disable)"
    1.19     ])
    1.20  
    1.21 -
    1.22  ;; ************** HARDCODED DATA
    1.23  
    1.24  (defn hxc-thunk
    1.25 @@ -162,7 +160,6 @@
    1.26     (partial comp (partial map character-codes->str))
    1.27     hxc-thunk))
    1.28  
    1.29 -
    1.30  ;; --------------------------------------------------
    1.31  
    1.32  
    1.33 @@ -510,6 +507,15 @@
    1.34  
    1.35  
    1.36  (defn format-evo
    1.37 +  "Parse a sequence of evolution data, returning a map. First is the
    1.38 +method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
    1.39 +  method of evolution is by item (only stones will actually make pokemon
    1.40 +  evolve, for some auxillary reason.) Finally, the minimum level for
    1.41 +  evolution to occur (level 1 means no limit, which is used for trade
    1.42 +  and item evolutions), followed by the internal id of the pokemon
    1.43 +  into which to evolve. Hence, level up and trade evolutions are
    1.44 +  described with 3
    1.45 +  bytes; item evolutions with four."
    1.46    [coll]
    1.47    (let [method (first coll)]
    1.48      (cond (empty? coll) []
    1.49 @@ -555,7 +561,7 @@
    1.50  (defn hxc-learnsets
    1.51    "Hardcoded map associating pokemon names to lists of pairs [lvl
    1.52    move] of abilities they learn as they level up. The data
    1.53 -exists at ROM@3400, sorted by internal order. Pointers to the data
    1.54 +exists at ROM@34000, sorted by internal order. Pointers to the data
    1.55    exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
    1.56    ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
    1.57    ([rom]
    1.58 @@ -932,6 +938,9 @@
    1.59  ;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
    1.60  ;; The first instance is for Machines; the second, for stones.
    1.61  
    1.62 +;; 0x251A (in indexable mem): image decompression routine seems to begin here.
    1.63 +
    1.64 +
    1.65  (comment 
    1.66  
    1.67  (def hxc-later
    1.68 @@ -951,9 +960,3 @@
    1.69      (map character-codes->str
    1.70           (take-nth 4 dex))))
    1.71  )
    1.72 -
    1.73 -
    1.74 -
    1.75 -
    1.76 -
    1.77 -
     2.1 --- a/org/rom.org	Sun Apr 08 01:28:39 2012 -0500
     2.2 +++ b/org/rom.org	Sun Apr 08 06:13:39 2012 -0500
     2.3 @@ -10,7 +10,9 @@
     2.4  # about map headers http://datacrystal.romhacking.net/wiki/Pokemon_Red/Blue:Notes
     2.5  # map headers Yellow http://www.pokecommunity.com/archive/index.php/t-235311.html
     2.6  # pokedollar: U+20B1
     2.7 -* Mapping the ROM
     2.8 +* Introduction
     2.9 +
    2.10 +** Mapping the ROM
    2.11  
    2.12  | ROM address (hex) | Description     | Format          | Example         |
    2.13  |-------------------+-----------------+-----------------+-----------------|
    2.14 @@ -22,18 +24,24 @@
    2.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. |
    2.16  | 06698-            | ? Background music. |                 |                 |
    2.17  | 0822E-082F?       | Pointers to background music, part I. |                 |                 |
    2.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). |
    2.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). |
    2.20 +|-------------------+-----------------+-----------------+-----------------|
    2.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             |
    2.22 +| 0DAE0.            | Amount of HP restored by Super Potion. | "               | 50              |
    2.23 +| 0DAE3.            | Amount of HP restored by Potion. | "               | 20              |
    2.24 +|-------------------+-----------------+-----------------+-----------------|
    2.25  | 0DD4D-DD72        | Names of permanent stats. | Variable-length strings separated by 0x50. | #HEALTH#ATTACK#DEFENSE#SPEED#SPECIAL# |
    2.26  | 1195C-1196A       | The two terms for being able/unable to learn a TM/HM. | Variable-length strings separated by 0x50. | ABLE#NOT ABLE#  |
    2.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#  |
    2.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), ... |
    2.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#... |
    2.30 -| 27E77-            | Trainer title names. |                 | YOUNGSTER#BUG CATCHER#LASS#... |
    2.31 -| 34000-            | Evolution and learnset data. |                 |                 |
    2.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. |
    2.33 +| 27E77-            | Trainer title names. | Variable-length names separated by 0x80. | YOUNGSTER#BUG CATCHER#LASS#... |
    2.34 +| 34000-            |                 |                 |                 |
    2.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. |
    2.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. |                 |                 |
    2.37  | 39462-            | The Pok\eacute{}mon cry data. | Fixed-length (3 byte) descriptions of cries. |                 |
    2.38  | 3B1E5-            | Pointers to evolution/learnset data. |                 |                 |
    2.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. |                 |
    2.40  | 40687-            | Species data from the Pok\eacute{}dex: species name, height, weight, etc. | Fixed-length sequences of bytes. See below for specifics. |                 |
    2.41  | 410B1-            | A conversion table between internal order and Pokedex order. |                 |                 |
    2.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]... |
    2.43 @@ -41,13 +49,1156 @@
    2.44  | 7C249-7C2??       | Pointers to background music, pt II. |                 |                 |
    2.45  | 98000-            | Dialogue        |                 |                 |
    2.46  | B8000-            | The text of each Pokemon's Pok\eacute{}dex entry. |                 |                 |
    2.47 -| BC000-            | Move names.     |                 |                 |
    2.48 +| BC000-BC60E       | Move names.     | Variable-length move names, separated by 0x80. The moves are in internal order. | POUND#KARATE CHOP#DOUBLESLAP#COMET PUNCH#... |
    2.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♂#... |
    2.50  |                   |                 |                 |                 |
    2.51  |                   |                 |                 |                 |
    2.52  
    2.53 +
    2.54 +
    2.55 +
    2.56 +** COMMENT Getting linguistic data: names, words, etc.
    2.57 +
    2.58 +Some of the simplest data 
    2.59 +
    2.60 +
    2.61 +One of the simplest data structures in the Pok\eacute{} ROM is an
    2.62 +unbroken list of strings that either (a) all have a specific length,
    2.63 +or (b) are all separated by the same character.
    2.64 +
    2.65 +Because lots of good data has this format, we'll start by writing a
    2.66 +template function to extract it:
    2.67 +
    2.68 +#+name: hxc-thunks
    2.69 +#+begin_src clojure :results silent
    2.70 +(defn hxc-thunk
    2.71 +  "Creates a thunk (nullary fn) that grabs data in a certain region of rom and
    2.72 +splits it into a collection by 0x50. If rom is not supplied, uses the
    2.73 +  original rom data."
    2.74 +  [start length]
    2.75 +  (fn self
    2.76 +    ([rom]
    2.77 +       (take-nth 2
    2.78 +                 (partition-by #(= % 0x50)
    2.79 +                               (take length
    2.80 +                                     (drop start rom)))))
    2.81 +    ([]
    2.82 +      (self com.aurellem.gb.gb-driver/original-rom))))
    2.83 +
    2.84 +(def hxc-thunk-words
    2.85 +  "Same as hxc-thunk, except it interprets the rom data as characters,
    2.86 +  returning a collection of strings."
    2.87 +  (comp
    2.88 +   (partial comp (partial map character-codes->str))
    2.89 +   hxc-thunk))
    2.90 +
    2.91 +#+end_src
    2.92 +
    2.93 +* Pok\eacute{}mon
    2.94 +** Names of each species
    2.95 +The names of the Pok\eacute{}mon species are stored in
    2.96 +ROM@E8000. This name list is interesting, for a number of reasons:
    2.97 +- The names are stored in [[ ][internal order]] rather than in the familiar
    2.98 +  Pok\eacute{}dex order. This seemingly random order probably represents the order in which the authors created or
    2.99 +  programmed in the Pok\eacute{}mon; it's used throughout the game.
   2.100 +- There is enough space allocated for 190 Pok\eacute{}mon. As I
   2.101 +  understand it, there were originally going to be 190 Pok\eacute{}mon
   2.102 +  in Generation I, but the creators decided to defer some to
   2.103 +  Generation II. This explains why many Gen I and Gen II Pok\eacute{}mon
   2.104 +  have the same aesthetic feel.
   2.105 +- The list is pockmarked with random gaps, due to the strange internal
   2.106 +  ordering
   2.107 +  and 39 unused spaces [fn::190 allocated spaces minus 151 true Pok\eacute{}mon]. These missing spaces are filled with the
   2.108 +  placeholder name,  =MISSINGNO.= (\ldquo{}Missing number\rdquo{}).
   2.109 +
   2.110 +Each name is exactly ten letters long (Whenever a name is too short, the extra
   2.111 +space is padded with the character 0x50). 
   2.112 +
   2.113 +
   2.114 +
   2.115 +#+name: pokenames
   2.116 +#+begin_src clojure
   2.117 +
   2.118 +(defn hxc-pokenames-raw
   2.119 +  "The hardcoded names of the 190 species in memory. List begins at
   2.120 +ROM@E8000. Although names in memory are padded with 0x50 to be 10 characters
   2.121 +  long, these names are stripped of padding. See also, hxc-pokedex-names"
   2.122 +  ([]
   2.123 +     (hxc-pokenames-raw com.aurellem.gb.gb-driver/original-rom))
   2.124 +  ([rom]
   2.125 +     (let [count-species 190
   2.126 +           name-length 10]
   2.127 +       (map character-codes->str
   2.128 +            (partition name-length
   2.129 +                       (map #(if (= 0x50 %) 0x00 %)
   2.130 +                            (take (* count-species name-length)
   2.131 +                                  (drop 0xE8000
   2.132 +                                        rom))))))))
   2.133 +(def hxc-pokenames
   2.134 +  (comp
   2.135 +   (partial map format-name)
   2.136 +   hxc-pokenames-raw))
   2.137 +
   2.138 +
   2.139 +
   2.140 +
   2.141 +(defn hxc-pokedex-names
   2.142 +  "The names of the pokemon in hardcoded pokedex order. List begins at
   2.143 +ROM@410B1. See also, hxc-pokenames."
   2.144 +  ([] (hxc-pokedex-names
   2.145 +       com.aurellem.gb.gb-driver/original-rom))
   2.146 +  ([rom]
   2.147 +     (let [names (hxc-pokenames rom)]
   2.148 +       (#(mapv %
   2.149 +               ((comp range count keys) %))
   2.150 +        (zipmap
   2.151 +         (take (count names)
   2.152 +               (drop 0x410b1 rom))
   2.153 +         
   2.154 +         names)))))
   2.155 +
   2.156 +#+end_src
   2.157 +
   2.158  * Appendices
   2.159  ** Internal Pok\eacute{}mon IDs
   2.160  ** Type IDs
   2.161 +
   2.162 +#+name: type-ids
   2.163 +#+begin_src clojure
   2.164 +(def pkmn-types
   2.165 +  [:normal    ;;0
   2.166 +   :fighting  ;;1
   2.167 +   :flying    ;;2
   2.168 +   :poison    ;;3
   2.169 +   :ground    ;;4
   2.170 +   :rock      ;;5
   2.171 +   :bird      ;;6
   2.172 +   :bug       ;;7
   2.173 +   :ghost     ;;8
   2.174 +   :A
   2.175 +   :B
   2.176 +   :C
   2.177 +   :D
   2.178 +   :E
   2.179 +   :F
   2.180 +   :G
   2.181 +   :H
   2.182 +   :I
   2.183 +   :J
   2.184 +   :K
   2.185 +   :fire     ;;20 (0x14)
   2.186 +   :water    ;;21 (0x15)
   2.187 +   :grass    ;;22 (0x16)
   2.188 +   :electric ;;23 (0x17)
   2.189 +   :psychic  ;;24 (0x18)
   2.190 +   :ice      ;;25 (0x19)
   2.191 +   :dragon   ;;26 (0x1A)
   2.192 +   ])
   2.193 +#+end_src
   2.194 +
   2.195  ** Basic effects of moves
   2.196 +
   2.197 +*** Table of basic effects
   2.198 +
   2.199 +The possible effects of moves in Pok\eacute{}mon \mdash{} for example, dealing
   2.200 +damage, leeching health, or potentially poisoning the opponent
   2.201 +\mdash{} are stored in a table. Each move has exactly one effect, and
   2.202 +different moves might have the same effect.
   2.203 +
   2.204 +For example, Leech Life, Mega Drain, and Absorb all have effect ID #3, which is \ldquo{}Leech half of the inflicted damage.\rdquo{}
   2.205 +
   2.206 +All the legitimate move effects are listed in the table
   2.207 +below. Here are some notes for reading it:
   2.208 +
   2.209 +- Whenever an effect has a chance of doing something (like a chance of
   2.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.
   2.211 +- For some effects, the description is too cumbersome to
   2.212 +  write. Instead, I just write a move name
   2.213 +  in parentheses, like: (leech seed). That move gives a characteristic example
   2.214 +  of the effect.
   2.215 +- I use the abbreviations =atk=, =def=, =spd=, =spc=, =acr=, =evd= for
   2.216 +  attack, defense, speed, special, accuracy, and evasion. 
   2.217 +.
   2.218 +
   2.219 +
   2.220 +
   2.221 +| ID (hex) | Description                                                                                     | Notes                                                            |
   2.222 +|----------+-------------------------------------------------------------------------------------------------+------------------------------------------------------------------|
   2.223 +|        0 | normal damage                                                                                   |                                                                  |
   2.224 +|        1 | no damage, just sleep                                                                           | TODO: find out how many turns                                    |
   2.225 +|        2 | 0x4C chance of poison                                                                           |                                                                  |
   2.226 +|        3 | leech half of inflicted damage                                                                  |                                                                  |
   2.227 +|        4 | 0x19 chance of burn                                                                             |                                                                  |
   2.228 +|        5 | 0x19 chance of freeze                                                                           |                                                                  |
   2.229 +|        6 | 0x19 chance of paralysis                                                                        |                                                                  |
   2.230 +|        7 | user faints; opponent's defense is halved during attack.                                        |                                                                  |
   2.231 +|        8 | leech half of inflicted damage ONLY if the opponent is asleep                                   |                                                                  |
   2.232 +|        9 | imitate last attack                                                                             |                                                                  |
   2.233 +|        A | user atk +1                                                                                     |                                                                  |
   2.234 +|        B | user def +1                                                                                     |                                                                  |
   2.235 +|        C | user spd +1                                                                                     |                                                                  |
   2.236 +|        D | user spc +1                                                                                     |                                                                  |
   2.237 +|        E | user acr +1                                                                                     | This effect is unused.                                           |
   2.238 +|        F | user evd +1                                                                                     |                                                                  |
   2.239 +|       10 | get post-battle money = 2 * level * uses                                                        |                                                                  |
   2.240 +|       11 | move has 0xFE acr, regardless of battle stat modifications.                                     |                                                                  |
   2.241 +|       12 | opponent atk -1                                                                                 |                                                                  |
   2.242 +|       13 | opponent def -1                                                                                 |                                                                  |
   2.243 +|       14 | opponent spd -1                                                                                 |                                                                  |
   2.244 +|       15 | opponent spc -1                                                                                 |                                                                  |
   2.245 +|       16 | opponent acr -1                                                                                 |                                                                  |
   2.246 +|       17 | opponent evd -1                                                                                 |                                                                  |
   2.247 +|       18 | converts user's type to opponent's.                                                             |                                                                  |
   2.248 +|       19 | (haze)                                                                                          |                                                                  |
   2.249 +|       1A | (bide)                                                                                          |                                                                  |
   2.250 +|       1B | (thrash)                                                                                        |                                                                  |
   2.251 +|       1C | (teleport)                                                                                      |                                                                  |
   2.252 +|       1D | (fury swipes)                                                                                   |                                                                  |
   2.253 +|       1E | attacks 2-5 turns                                                                               | Unused. TODO: find out what it does.                             |
   2.254 +|       1F | 0x19 chance of flinching                                                                        |                                                                  |
   2.255 +|       20 | opponent sleep for 1-7 turns                                                                    |                                                                  |
   2.256 +|       21 | 0x66 chance of poison                                                                           |                                                                  |
   2.257 +|       22 | 0x4D chance of burn                                                                             |                                                                  |
   2.258 +|       23 | 0x4D chance of freeze                                                                           |                                                                  |
   2.259 +|       24 | 0x4D chance of paralysis                                                                        |                                                                  |
   2.260 +|       25 | 0x4D chance of flinching                                                                        |                                                                  |
   2.261 +|       26 | one-hit KO                                                                                      |                                                                  |
   2.262 +|       27 | charge one turn, atk next.                                                                      |                                                                  |
   2.263 +|       28 | fixed damage, leaves 1HP.                                                                       | Is the fixed damage the power of the move?                       |
   2.264 +|       29 | fixed damage.                                                                                   | Like seismic toss, dragon rage, psywave.                         |
   2.265 +|       2A | atk 2-5 turns; opponent can't attack                                                            | The odds of attacking for /n/ turns are: (0 0x60 0x60 0x20 0x20) |
   2.266 +|       2B | charge one turn, atk next. (can't be hit when charging)                                         |                                                                  |
   2.267 +|       2C | atk hits twice.                                                                                 |                                                                  |
   2.268 +|       2D | user takes 1 damage if misses.                                                                  |                                                                  |
   2.269 +|       2E | evade status-lowering effects                                                                   | Caused by you or also your opponent?                             |
   2.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.          |
   2.271 +|       30 | atk causes recoil dmg = 1/4 dmg dealt                                                           |                                                                  |
   2.272 +|       31 | confuses opponent                                                                               |                                                                  |
   2.273 +|       32 | user atk +2                                                                                     |                                                                  |
   2.274 +|       33 | user def +2                                                                                     |                                                                  |
   2.275 +|       34 | user spd +2                                                                                     |                                                                  |
   2.276 +|       35 | user spc +2                                                                                     |                                                                  |
   2.277 +|       36 | user acr +2                                                                                     | This effect is unused.                                           |
   2.278 +|       37 | user evd +2                                                                                     | This effect is unused.                                           |
   2.279 +|       38 | restores up to half of user's max hp.                                                           |                                                                  |
   2.280 +|       39 | (transform)                                                                                     |                                                                  |
   2.281 +|       3A | opponent atk -2                                                                                 |                                                                  |
   2.282 +|       3B | opponent def -2                                                                                 |                                                                  |
   2.283 +|       3C | opponent spd -2                                                                                 |                                                                  |
   2.284 +|       3D | opponent spc -2                                                                                 |                                                                  |
   2.285 +|       3E | opponent acr -2                                                                                 |                                                                  |
   2.286 +|       3F | opponent evd -2                                                                                 |                                                                  |
   2.287 +|       40 | doubles user spc when attacked                                                                  |                                                                  |
   2.288 +|       41 | doubles user def when attacked                                                                  |                                                                  |
   2.289 +|       42 | just poisons opponent                                                                           |                                                                  |
   2.290 +|       43 | just paralyzes opponent                                                                         |                                                                  |
   2.291 +|       44 | 0x19 chance opponent atk -1                                                                     |                                                                  |
   2.292 +|       45 | 0x19 chance opponent def -1                                                                     |                                                                  |
   2.293 +|       46 | 0x19 chance opponent spd -1                                                                     |                                                                  |
   2.294 +|       47 | 0x4C chance opponent spc -1                                                                     |                                                                  |
   2.295 +|       48 | 0x19 chance opponent acr -1                                                                     |                                                                  |
   2.296 +|       49 | 0x19 chance opponent evd -1                                                                     |                                                                  |
   2.297 +|       4A | ???                                                                                             | ;; unused? no effect?                                            |
   2.298 +|       4B | ???                                                                                             | ;; unused? no effect?                                            |
   2.299 +|       4C | 0x19 chance of confusing the opponent                                                           |                                                                  |
   2.300 +|       4D | atk hits twice. 0x33 chance opponent poisioned.                                                 |                                                                  |
   2.301 +|       4E | broken. crash the game after attack.                                                            |                                                                  |
   2.302 +|       4F | (substitute)                                                                                    |                                                                  |
   2.303 +|       50 | unless opponent faints, user must recharge after atk. some exceptions apply                     |                                                                  |
   2.304 +|       51 | (rage)                                                                                          |                                                                  |
   2.305 +|       52 | (mimic)                                                                                         |                                                                  |
   2.306 +|       53 | (metronome)                                                                                     |                                                                  |
   2.307 +|       54 | (leech seed)                                                                                    |                                                                  |
   2.308 +|       55 | does nothing (splash)                                                                           |                                                                  |
   2.309 +|       56 | (disable)                                                                                       |                                                                  |
   2.310 +#+end_src
   2.311 +
   2.312 +*** Source
   2.313 +#+name: move-effects
   2.314 +#+begin_src clojure
   2.315 +(def move-effects
   2.316 +  ["normal damage"
   2.317 +   "no damage, just opponent sleep" ;; how many turns? is atk power ignored?
   2.318 +   "0x4C chance of poison"
   2.319 +   "leech half of inflicted damage"
   2.320 +   "0x19 chance of burn"
   2.321 +   "0x19 chance of freeze"
   2.322 +   "0x19 chance of paralyze"
   2.323 +   "user faints; opponent defense halved during attack."
   2.324 +   "leech half of inflicted damage ONLY if sleeping opponent."
   2.325 +   "imitate last attack"
   2.326 +   "user atk +1"
   2.327 +   "user def +1"
   2.328 +   "user spd +1"
   2.329 +   "user spc +1"
   2.330 +   "user acr +1" ;; unused?!
   2.331 +   "user evd +1"
   2.332 +   "get post-battle $ = 2*level*uses"
   2.333 +   "0xFE acr, no matter what."
   2.334 +   "opponent atk -1"     ;; acr taken from move acr?
   2.335 +   "opponent def -1"     ;;
   2.336 +   "opponent spd -1"   ;;
   2.337 +   "opponent spc -1" ;;
   2.338 +   "opponent acr -1";;
   2.339 +   "opponent evd -1"
   2.340 +   "converts user's type to opponent's."
   2.341 +   "(haze)"
   2.342 +   "(bide)"
   2.343 +   "(thrash)"
   2.344 +   "(teleport)"
   2.345 +   "(fury swipes)"
   2.346 +   "attacks 2-5 turns" ;; unused? like rollout?
   2.347 +   "0x19 chance of flinch"
   2.348 +   "opponent sleep for 1-7 turns"
   2.349 +   "0x66 chance of poison"
   2.350 +   "0x4D chance of burn"
   2.351 +   "0x4D chance of freeze"
   2.352 +   "0x4D chance of paralyze"
   2.353 +   "0x4D chance of flinch"
   2.354 +   "one-hit KO"
   2.355 +   "charge one turn, atk next."
   2.356 +   "fixed damage, leaves 1HP." ;; how is dmg determined?
   2.357 +   "fixed damage."             ;; cf seismic toss, dragon rage, psywave.
   2.358 +   "atk 2-5 turns; opponent can't attack" ;; unnormalized? (0 0x60 0x60 0x20 0x20)
   2.359 +   "charge one turn, atk next. (can't be hit when charging)"
   2.360 +   "atk hits twice."
   2.361 +   "user takes 1 damage if misses."
   2.362 +   "evade status-lowering effects" ;;caused by you or also your opponent?
   2.363 +   "(broken) if user is slower than opponent, makes critical hit impossible, otherwise has no effect"
   2.364 +   "atk causes recoil dmg = 1/4 dmg dealt"
   2.365 +   "confuses opponent" ;; acr taken from move acr
   2.366 +   "user atk +2"
   2.367 +   "user def +2"
   2.368 +   "user spd +2"
   2.369 +   "user spc +2"
   2.370 +   "user acr +2" ;; unused!
   2.371 +   "user evd +2" ;; unused!
   2.372 +   "restores up to half of user's max hp." ;; broken: fails if the difference
   2.373 +   ;; b/w max and current hp is one less than a multiple of 256.
   2.374 +   "(transform)"
   2.375 +   "opponent atk -2"
   2.376 +   "opponent def -2"
   2.377 +   "opponent spd -2"
   2.378 +   "opponent spc -2"
   2.379 +   "opponent acr -2"
   2.380 +   "opponent evd -2"
   2.381 +   "doubles user spc when attacked"
   2.382 +   "doubles user def when attacked"
   2.383 +   "just poisons opponent"   ;;acr taken from move acr
   2.384 +   "just paralyzes opponent" ;;
   2.385 +   "0x19 chance opponent atk -1"
   2.386 +   "0x19 chance opponent def -1"
   2.387 +   "0x19 chance opponent spd -1"
   2.388 +   "0x4C chance opponent spc -1" ;; context suggest chance is 0x19
   2.389 +   "0x19 chance opponent acr -1"
   2.390 +   "0x19 chance opponent evd -1"
   2.391 +   "???" ;; unused? no effect?
   2.392 +   "???" ;; unused? no effect?
   2.393 +   "0x19 chance opponent confused"
   2.394 +   "atk hits twice. 0x33 chance opponent poisioned."
   2.395 +   "broken. crash the game after attack."
   2.396 +   "(substitute)"
   2.397 +   "unless opponent faints, user must recharge after atk. some
   2.398 +  exceptions apply."
   2.399 +   "(rage)"
   2.400 +   "(mimic)"
   2.401 +   "(metronome)"
   2.402 +   "(leech seed)"
   2.403 +   "does nothing (splash)"
   2.404 +   "(disable)"
   2.405 +   ])
   2.406 +#+end_src
   2.407 +
   2.408 +
   2.409  ** Alphabet code
   2.410 +
   2.411 +#+begin_src clojure :tangle ../clojure/com/aurellem/gb/hxc.clj
   2.412 +
   2.413 +(ns com.aurellem.gb.hxc
   2.414 +  (:use (com.aurellem.gb assembly characters gb-driver util mem-util
   2.415 +                         constants species))
   2.416 +  (:import [com.aurellem.gb.gb_driver SaveState]))
   2.417 +
   2.418 +
   2.419 +
   2.420 +
   2.421 +; ************* HANDWRITTEN CONSTANTS
   2.422 +
   2.423 +<<type-ids>>
   2.424 +
   2.425 +
   2.426 +;; question: when status effects claim to take
   2.427 +;; their accuracy from the move accuracy, does
   2.428 +;; this mean that the move always "hits" but the
   2.429 +;; status effect may not?
   2.430 +
   2.431 +<<move-effects>>
   2.432 +
   2.433 +;; ************** HARDCODED DATA
   2.434 +
   2.435 +<<hxc-thunks>>
   2.436 +;; --------------------------------------------------
   2.437 +
   2.438 +
   2.439 +<<pokenames>>
   2.440 +
   2.441 +;; http://hax.iimarck.us/topic/581/
   2.442 +(defn hxc-cry
   2.443 +  "The pokemon cry data in internal order. List begins at ROM@39462"
   2.444 +  ([](hxc-cry com.aurellem.gb.gb-driver/original-rom))
   2.445 +  ([rom]
   2.446 +     (zipmap
   2.447 +      (hxc-pokenames rom)
   2.448 +      (map
   2.449 +       (fn [[cry-id pitch length]]
   2.450 +         {:cry-id cry-id
   2.451 +         :pitch pitch
   2.452 +          :length length}
   2.453 +         )
   2.454 +       (partition 3
   2.455 +                  (drop 0x39462 rom))))))
   2.456 +
   2.457 +(defn hxc-cry-groups
   2.458 +  ([] (hxc-cry-groups com.aurellem.gb.gb-driver/original-rom))
   2.459 +  ([rom]
   2.460 +     (map #(mapv first
   2.461 +                (filter
   2.462 +                 (fn [[k v]]
   2.463 +                   (= % (:cry-id v)))
   2.464 +                 (hxc-cry)))
   2.465 +          ((comp
   2.466 +            range
   2.467 +            count
   2.468 +            set
   2.469 +            (partial map :cry-id)
   2.470 +            vals
   2.471 +            hxc-cry)
   2.472 +           rom))))
   2.473 +
   2.474 +
   2.475 +(defn cry-conversion!
   2.476 +  "Convert Porygon's cry in ROM to be the cry of the given pokemon."
   2.477 +  [pkmn]
   2.478 +  (write-rom!
   2.479 +   (rewrite-memory
   2.480 +    (vec(rom))
   2.481 +    0x3965D 
   2.482 +    (map second
   2.483 +         ((hxc-cry) pkmn)))))
   2.484 +
   2.485 +(def hxc-items-raw
   2.486 +  "The hardcoded names of the items in memory. List begins at
   2.487 +ROM@045B7"
   2.488 +  (hxc-thunk-words 0x45B7 870))
   2.489 +
   2.490 +(def hxc-types
   2.491 +  "The hardcoded type names in memory. List begins at ROM@27D99,
   2.492 +  shortly before hxc-titles."
   2.493 +  (hxc-thunk-words 0x27D99 102))
   2.494 +
   2.495 +(def hxc-titles
   2.496 +  "The hardcoded names of the trainer titles in memory. List begins at
   2.497 +ROM@27E77"
   2.498 +  (hxc-thunk-words 0x27E77 196))
   2.499 +
   2.500 +
   2.501 +(def hxc-pokedex-text-raw
   2.502 +  "The hardcoded pokedex entries in memory. List begins at
   2.503 +ROM@B8000, shortly before move names."
   2.504 +  (hxc-thunk-words 0xB8000 14754))
   2.505 +
   2.506 +
   2.507 +
   2.508 +(def hxc-items
   2.509 +  "The hardcoded names of the items in memory, presented as
   2.510 +  keywords. List begins at ROM@045B7. See also, hxc-items-raw."
   2.511 +  (comp (partial map format-name) hxc-items-raw))
   2.512 +
   2.513 +(defn hxc-pokedex-text
   2.514 +  "The hardcoded pokedex entries in memory, presented as an
   2.515 +associative hash map. List begins at ROM@B8000."
   2.516 +  ([] (hxc-pokedex-text com.aurellem.gb.gb-driver/original-rom))
   2.517 +  ([rom]
   2.518 +     (zipmap
   2.519 +      (hxc-pokedex-names rom)
   2.520 +      (cons nil ;; for missingno.
   2.521 +            (hxc-pokedex-text-raw rom)))))
   2.522 +
   2.523 +;; In red/blue, pokedex stats are in internal order.
   2.524 +;; In yellow, pokedex stats are in pokedex order.
   2.525 +
   2.526 +(defn hxc-pokedex-stats
   2.527 +  "The hardcoded pokedex stats (species height weight) in memory. List
   2.528 +begins at ROM@40687"
   2.529 +  ([] (hxc-pokedex-stats com.aurellem.gb.gb-driver/original-rom))
   2.530 +  ([rom]
   2.531 +     (let [pokedex-names (zipmap (range) (hxc-pokedex-names rom))
   2.532 +           pkmn-count (count pokedex-names)
   2.533 +           ]
   2.534 +     ((fn capture-stats
   2.535 +        [n stats data]
   2.536 +        (if (zero? n) stats
   2.537 +            (let [[species
   2.538 +                   [_
   2.539 +                    height-ft
   2.540 +                    height-in
   2.541 +                    weight-1
   2.542 +                    weight-2
   2.543 +                    _
   2.544 +                    dex-ptr-1
   2.545 +                    dex-ptr-2
   2.546 +                    dex-bank
   2.547 +                    _
   2.548 +                    & data]]
   2.549 +                  (split-with (partial not= 0x50) data)]
   2.550 +              (recur (dec n)
   2.551 +                     (assoc stats
   2.552 +                       (pokedex-names (- pkmn-count (dec n)))
   2.553 +                       {:species
   2.554 +                        (format-name (character-codes->str species))
   2.555 +                        :height-ft
   2.556 +                        height-ft
   2.557 +                        :height-in
   2.558 +                        height-in
   2.559 +                        :weight
   2.560 +                        (/ (low-high weight-1 weight-2) 10.)
   2.561 +                        
   2.562 +                    ;;    :text
   2.563 +                    ;;    (character-codes->str
   2.564 +                    ;;     (take-while
   2.565 +                    ;;      (partial not= 0x50)
   2.566 +                    ;;      (drop
   2.567 +                    ;;       (+ 0xB8000
   2.568 +                    ;;          -0x4000
   2.569 +                    ;;          (low-high dex-ptr-1 dex-ptr-2))
   2.570 +                    ;;       rom)))
   2.571 +                        })
   2.572 +                     
   2.573 +                     data)
   2.574 +              
   2.575 +              
   2.576 +              )))
   2.577 +      
   2.578 +      pkmn-count
   2.579 +      {}
   2.580 +      (drop 0x40687 rom)))       ))
   2.581 +
   2.582 +
   2.583 +
   2.584 +
   2.585 +
   2.586 +
   2.587 +
   2.588 +(def hxc-places
   2.589 +  "The hardcoded place names in memory. List begins at
   2.590 +ROM@71500. [Cinnabar] Mansion seems to be dynamically calculated."
   2.591 +  (hxc-thunk-words 0x71500 560))
   2.592 +
   2.593 +
   2.594 +(defn hxc-dialog
   2.595 +  "The hardcoded dialogue in memory, including in-game alerts. Dialog
   2.596 +  seems to be separated by 0x57 instead of 0x50 (END). Begins at ROM@98000."
   2.597 +  ([rom]
   2.598 +     (map character-codes->str
   2.599 +          (take-nth 2
   2.600 +                    (partition-by #(= % 0x57)
   2.601 +                                  (take 0x0F728
   2.602 +                                        (drop 0x98000 rom))))))
   2.603 +  ([]
   2.604 +     (hxc-dialog com.aurellem.gb.gb-driver/original-rom)))
   2.605 +
   2.606 +
   2.607 +(def hxc-move-names
   2.608 +  "The hardcoded move names in memory. List begins at ROM@BC000"
   2.609 +  (hxc-thunk-words 0xBC000 1551))
   2.610 +
   2.611 +
   2.612 +(defn hxc-move-data
   2.613 +  "The hardcoded (basic (move effects)) in memory. List begins at
   2.614 +0x38000. Returns a map of {:name :power :accuracy :pp :fx-id
   2.615 +  :fx-txt}. The move descriptions are handwritten, not hardcoded."
   2.616 +  ([]
   2.617 +     (hxc-move-data com.aurellem.gb.gb-driver/original-rom))
   2.618 +  ([rom]
   2.619 +     (let [names (vec (hxc-move-names rom))
   2.620 +           move-count (count names)
   2.621 +           move-size 6
   2.622 +           types pkmn-types ;;; !! hardcoded types
   2.623 +           ]
   2.624 +       (zipmap (map format-name names)
   2.625 +               (map
   2.626 +                (fn [[idx effect power type-id accuracy pp]]
   2.627 +                  {:name (names (dec idx))
   2.628 +                   :power power
   2.629 +                   :accuracy  accuracy
   2.630 +                   :pp pp
   2.631 +                   :type (types type-id)
   2.632 +                   :fx-id effect
   2.633 +                   :fx-txt (get move-effects effect) 
   2.634 +                   }
   2.635 +                  )
   2.636 +                
   2.637 +                (partition move-size
   2.638 +                           (take (* move-size move-count)
   2.639 +                                 (drop 0x38000 rom))))))))
   2.640 +  
   2.641 +
   2.642 +
   2.643 +(defn hxc-move-data*
   2.644 +  "Like hxc-move-data, but reports numbers as hexadecimal symbols instead."
   2.645 +  ([]
   2.646 +     (hxc-move-data* com.aurellem.gb.gb-driver/original-rom))
   2.647 +  ([rom]
   2.648 +     (let [names (vec (hxc-move-names rom))
   2.649 +           move-count (count names)
   2.650 +           move-size 6
   2.651 +           format-name (fn [s]
   2.652 +                         (keyword (.toLowerCase
   2.653 +                                   (apply str
   2.654 +                                          (map #(if (= % \space) "-" %) s)))))
   2.655 +           ]
   2.656 +       (zipmap (map format-name names)
   2.657 +               (map
   2.658 +                (fn [[idx effect power type accuracy pp]]
   2.659 +                  {:name (names (dec idx))
   2.660 +                   :power power
   2.661 +                   :accuracy (hex accuracy)
   2.662 +                   :pp pp
   2.663 +                   :fx-id (hex effect)
   2.664 +                   :fx-txt (get move-effects effect) 
   2.665 +                   }
   2.666 +                  )
   2.667 +                
   2.668 +                (partition move-size
   2.669 +                           (take (* move-size move-count)
   2.670 +                                 (drop 0x38000 rom))))))))
   2.671 +  
   2.672 +
   2.673 +(defn hxc-machines
   2.674 +  "The hardcoded moves taught by TMs and HMs. List begins at ROM@1232D."
   2.675 +  ([] (hxc-machines
   2.676 +       com.aurellem.gb.gb-driver/original-rom))
   2.677 +  ([rom]
   2.678 +     (let [moves (hxc-move-names rom)]
   2.679 +       (zipmap
   2.680 +        (range)
   2.681 +        (take-while
   2.682 +            (comp not nil?)
   2.683 +            (map (comp
   2.684 +                  format-name
   2.685 +                  (zipmap
   2.686 +                   (range)
   2.687 +                   moves)
   2.688 +              dec)
   2.689 +                 (take 100
   2.690 +                       (drop 0x1232D rom))))))))
   2.691 +
   2.692 +
   2.693 +
   2.694 +(defn internal-id
   2.695 +  ([rom]
   2.696 +     (zipmap 
   2.697 +      (hxc-pokenames rom)
   2.698 +      (range)))
   2.699 +  ([]
   2.700 +     (internal-id com.aurellem.gb.gb-driver/original-rom)))
   2.701 +
   2.702 +
   2.703 +
   2.704 +
   2.705 +
   2.706 +;; nidoran gender change upon levelup
   2.707 +;; (->
   2.708 +;;  @current-state
   2.709 +;;  rom
   2.710 +;;  vec
   2.711 +;;  (rewrite-memory
   2.712 +;;   (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♂))
   2.713 +;;   [1 1 15])
   2.714 +;;  (rewrite-memory
   2.715 +;;   (nth (hxc-ptrs-evolve) ((internal-id) :nidoran♀))
   2.716 +;;   [1 1 3])
   2.717 +;;  (write-rom!)
   2.718 +
   2.719 +;;  )
   2.720 +
   2.721 +
   2.722 +
   2.723 +
   2.724 +(defn hxc-advantage
   2.725 +  ;; in-game multipliers are stored as 10x their effective value
   2.726 +  ;; to allow for fractional multipliers like 1/2
   2.727 +  
   2.728 +  "The hardcoded type advantages in memory, returned as tuples of
   2.729 +  atk-type def-type multiplier. By default (i.e. if not listed here),
   2.730 +the multiplier is 1. List begins at 0x3E62D."
   2.731 +  ([] (hxc-advantage com.aurellem.gb.gb-driver/original-rom))
   2.732 +  ([rom]
   2.733 +     (map
   2.734 +      (fn [[atk def mult]] [(get pkmn-types atk (hex atk))
   2.735 +                            (get pkmn-types def (hex def))
   2.736 +                            (/ mult 10)])
   2.737 +      (partition 3
   2.738 +                 (take-while (partial not= 0xFF)
   2.739 +                             (drop 0x3E62D rom))))))
   2.740 +
   2.741 +
   2.742 +
   2.743 +(defn format-evo
   2.744 +  "Parse a sequence of evolution data, returning a map. First is the
   2.745 +method: 0 = end-evolution-data. 1 = level-up, 2 = item, 3 = trade. Next is an item id, if the
   2.746 +  method of evolution is by item (only stones will actually make pokemon
   2.747 +  evolve, for some auxillary reason.) Finally, the minimum level for
   2.748 +  evolution to occur (level 1 means no limit, which is used for trade
   2.749 +  and item evolutions), followed by the internal id of the pokemon
   2.750 +  into which to evolve. Hence, level up and trade evolutions are
   2.751 +  described with 3
   2.752 +  bytes; item evolutions with four."
   2.753 +  [coll]
   2.754 +  (let [method (first coll)]
   2.755 +    (cond (empty? coll) []
   2.756 +          (= 0 method) [] ;; just in case
   2.757 +          (= 1 method) ;; level-up evolution
   2.758 +          (conj (format-evo (drop 3 coll))
   2.759 +                            {:method :level-up
   2.760 +                             :min-level (nth coll 1)
   2.761 +                             :into (dec (nth coll 2))})
   2.762 +          
   2.763 +          (= 2 method) ;; item evolution
   2.764 +          (conj (format-evo (drop 4 coll))
   2.765 +                {:method :item
   2.766 +                 :item (dec (nth coll 1))
   2.767 +                 :min-level (nth coll 2)
   2.768 +                 :into (dec (nth coll 3))})
   2.769 +
   2.770 +          (= 3 method) ;; trade evolution
   2.771 +          (conj (format-evo (drop 3 coll))
   2.772 +                {:method :trade
   2.773 +                 :min-level (nth coll 1) ;; always 1 for trade.
   2.774 +                 :into (dec (nth coll 2))}))))
   2.775 +
   2.776 +
   2.777 +(defn hxc-ptrs-evolve
   2.778 +  "A hardcoded collection of 190 pointers to alternating evolution/learnset data,
   2.779 +in internal order."
   2.780 +  ([]
   2.781 +     (hxc-ptrs-evolve com.aurellem.gb.gb-driver/original-rom))
   2.782 +  ([rom]
   2.783 +     (let [
   2.784 +           pkmn-count (count (hxc-pokenames-raw)) ;; 190
   2.785 +           ptrs
   2.786 +           (map (fn [[a b]] (low-high a b))
   2.787 +                (partition 2
   2.788 +                           (take (* 2 pkmn-count)
   2.789 +                                 (drop 0x3b1e5 rom))))]
   2.790 +       (map (partial + 0x34000) ptrs)
   2.791 +
   2.792 +       )))
   2.793 +
   2.794 +
   2.795 +(defn hxc-learnsets
   2.796 +  "Hardcoded map associating pokemon names to lists of pairs [lvl
   2.797 +  move] of abilities they learn as they level up. The data
   2.798 +exists at ROM@34000, sorted by internal order. Pointers to the data
   2.799 +  exist at ROM@3B1E5; see also, hxc-ptrs-evolve"
   2.800 +  ([] (hxc-learnsets com.aurellem.gb.gb-driver/original-rom))
   2.801 +  ([rom]
   2.802 +     (apply assoc
   2.803 +            {}
   2.804 +            (interleave
   2.805 +             (hxc-pokenames rom)
   2.806 +             (map (comp
   2.807 +                   (partial map
   2.808 +                            (fn [[lvl mv]] [lvl (dec mv)]))
   2.809 +                   (partial partition 2)
   2.810 +                   ;; keep the learnset data
   2.811 +                   (partial take-while (comp not zero?))
   2.812 +                   ;; skip the evolution data
   2.813 +                   rest
   2.814 +                   (partial drop-while (comp not zero?)))
   2.815 +                  (map #(drop % rom) 
   2.816 +                       (hxc-ptrs-evolve rom)))))))
   2.817 +
   2.818 +(defn hxc-learnsets-pretty
   2.819 +  "Live hxc-learnsets except it reports the name of each move --- as
   2.820 +it appears in rom --- rather than the move index."
   2.821 +  ([] (hxc-learnsets-pretty com.aurellem.gb.gb-driver/original-rom))
   2.822 +  ([rom]
   2.823 +     (let [moves (vec(map format-name (hxc-move-names)))]
   2.824 +       (into {}
   2.825 +             (map (fn [[pkmn learnset]]
   2.826 +                    [pkmn (map (fn [[lvl mv]] [lvl (moves mv)])
   2.827 +                               learnset)])
   2.828 +                  (hxc-learnsets rom))))))
   2.829 +             
   2.830 +                                  
   2.831 +
   2.832 +
   2.833 +(defn hxc-evolution
   2.834 +  "Hardcoded evolution data in memory. The data exists at ROM@34000,
   2.835 +  sorted by internal order. Pointers to the data exist at ROM@3B1E5; see also, hxc-ptrs-evolve."
   2.836 +  ([] (hxc-evolution com.aurellem.gb.gb-driver/original-rom))
   2.837 +  ([rom]
   2.838 +       (apply assoc {}
   2.839 +               (interleave
   2.840 +                (hxc-pokenames rom)
   2.841 +                (map
   2.842 +                 (comp
   2.843 +                  format-evo
   2.844 +                  (partial take-while (comp not zero?))
   2.845 +                  #(drop % rom))
   2.846 +                 (hxc-ptrs-evolve rom)
   2.847 +                 )))))
   2.848 +
   2.849 +(defn hxc-evolution-pretty
   2.850 +  "Like hxc-evolution, except it uses the names of items and pokemon
   2.851 +--- grabbed from ROM --- rather than their numerical identifiers."
   2.852 +  ([] (hxc-evolution-pretty com.aurellem.gb.gb-driver/original-rom))
   2.853 +  ([rom]
   2.854 +     (let
   2.855 +         [poke-names (vec (hxc-pokenames rom))
   2.856 +          item-names (vec (hxc-items rom))
   2.857 +          use-names
   2.858 +          (fn [m]
   2.859 +            (loop [ks (keys m) new-map m]
   2.860 +              (let [k (first ks)]
   2.861 +                (cond (nil? ks) new-map
   2.862 +                      (= k :into)
   2.863 +                      (recur
   2.864 +                       (next ks)
   2.865 +                       (assoc new-map
   2.866 +                         :into
   2.867 +                         (poke-names
   2.868 +                          (:into
   2.869 +                           new-map))))
   2.870 +                      (= k :item)
   2.871 +                      (recur
   2.872 +                       (next ks)
   2.873 +                       (assoc new-map
   2.874 +                         :item
   2.875 +                         (item-names
   2.876 +                          (:item new-map))))
   2.877 +                      :else
   2.878 +                      (recur
   2.879 +                       (next ks)
   2.880 +                       new-map)
   2.881 +                      ))))]
   2.882 +
   2.883 +       (into {}
   2.884 +             (map (fn [[pkmn evo-coll]]
   2.885 +                    [pkmn (map use-names evo-coll)])
   2.886 +                  (hxc-evolution rom))))))
   2.887 +
   2.888 +
   2.889 +(defn hxc-pokemon-base
   2.890 +  ([] (hxc-pokemon-base com.aurellem.gb.gb-driver/original-rom))
   2.891 +  ([rom]
   2.892 +     (let [entry-size 28
   2.893 +           pkmn-count (count (hxc-pokedex-text rom))
   2.894 +           pokemon (rest (hxc-pokedex-names))
   2.895 +           types (apply assoc {}
   2.896 +                        (interleave
   2.897 +                         (range)
   2.898 +                         pkmn-types)) ;;!! softcoded
   2.899 +           moves (apply assoc {}
   2.900 +                        (interleave
   2.901 +                         (range)
   2.902 +                         (map format-name
   2.903 +                              (hxc-move-names rom))))
   2.904 +           machines (hxc-machines)
   2.905 +           ]
   2.906 +       (zipmap
   2.907 +        pokemon
   2.908 +        (map
   2.909 +         (fn [[n
   2.910 +               rating-hp
   2.911 +               rating-atk
   2.912 +               rating-def
   2.913 +               rating-speed
   2.914 +               rating-special
   2.915 +               type-1
   2.916 +               type-2
   2.917 +               rarity
   2.918 +               rating-xp
   2.919 +               pic-dimensions ;; tile_width|tile_height (8px/tile)
   2.920 +               ptr-pic-obverse-1
   2.921 +               ptr-pic-obverse-2
   2.922 +               ptr-pic-reverse-1
   2.923 +               ptr-pic-reverse-2
   2.924 +               move-1
   2.925 +               move-2
   2.926 +               move-3
   2.927 +               move-4
   2.928 +               growth-rate
   2.929 +               &
   2.930 +               TMs|HMs]]
   2.931 +           (let
   2.932 +               [base-moves
   2.933 +                (mapv moves
   2.934 +                      ((comp
   2.935 +                        ;; since the game uses zero as a delimiter,
   2.936 +                        ;; it must also increment all move indices by 1.
   2.937 +                        ;; heren we decrement to correct this.
   2.938 +                        (partial map dec)
   2.939 +                        (partial take-while (comp not zero?)))
   2.940 +                       [move-1 move-2 move-3 move-4]))
   2.941 +                
   2.942 +                types
   2.943 +                (set (list (types type-1)
   2.944 +                           (types type-2)))
   2.945 +                TMs|HMs
   2.946 +                (map
   2.947 +                 (comp
   2.948 +                  (partial map first)
   2.949 +                  (partial remove (comp zero? second)))
   2.950 +                 (split-at
   2.951 +                  50
   2.952 +                  (map vector
   2.953 +                       (rest(range))
   2.954 +                       (reduce concat
   2.955 +                               (map
   2.956 +                                #(take 8
   2.957 +                                       (concat (bit-list %)
   2.958 +                                               (repeat 0)))
   2.959 +                                
   2.960 +                                TMs|HMs)))))
   2.961 +                
   2.962 +                TMs  (vec (first TMs|HMs))
   2.963 +                HMs (take 5 (map (partial + -50) (vec (second TMs|HMs))))
   2.964 +                
   2.965 +                
   2.966 +                ]
   2.967 +             
   2.968 +             
   2.969 +             {:dex# n
   2.970 +              :base-moves base-moves
   2.971 +              :types types
   2.972 +              :TMs TMs
   2.973 +              :HMs HMs
   2.974 +              :base-hp rating-hp
   2.975 +              :base-atk rating-atk
   2.976 +              :base-def rating-def
   2.977 +              :base-speed rating-speed
   2.978 +              :base-special rating-special
   2.979 +              :o0 pic-dimensions
   2.980 +              :o1 ptr-pic-obverse-1
   2.981 +              :o2 ptr-pic-obverse-2
   2.982 +              }))
   2.983 +         
   2.984 +         (partition entry-size
   2.985 +                    (take (* entry-size pkmn-count)
   2.986 +                          (drop 0x383DE
   2.987 +                                rom))))))))
   2.988 +  
   2.989 +  
   2.990 +(defn hxc-intro-pkmn
   2.991 +  "The hardcoded pokemon to display in Prof. Oak's introduction; the pokemon's
   2.992 +internal id is stored at ROM@5EDB."
   2.993 +  ([] (hxc-intro-pkmn
   2.994 +       com.aurellem.gb.gb-driver/original-rom))
   2.995 +  ([rom]
   2.996 +     (nth (hxc-pokenames rom) (nth rom 0x5EDB))))
   2.997 +
   2.998 +(defn sxc-intro-pkmn!
   2.999 +  "Set the hardcoded pokemon to display in Prof. Oak's introduction."
  2.1000 +  [pokemon]
  2.1001 +  (write-rom! 
  2.1002 +   (rewrite-rom 0x5EDB
  2.1003 +                [
  2.1004 +                 (inc
  2.1005 +                  ((zipmap
  2.1006 +                    (hxc-pokenames)
  2.1007 +                    (range))
  2.1008 +                   pokemon))])))
  2.1009 +  
  2.1010 +
  2.1011 +(defn hxc-item-prices
  2.1012 +  "The hardcoded list of item prices in memory. List begins at ROM@4495"
  2.1013 +  ([] (hxc-item-prices com.aurellem.gb.gb-driver/original-rom))
  2.1014 +  ([rom]
  2.1015 +     (let [items (hxc-items rom)
  2.1016 +           price-size 3]
  2.1017 +       (zipmap items
  2.1018 +               (map (comp
  2.1019 +                     ;; zero-cost items are "priceless"
  2.1020 +                     #(if (zero? %) :priceless %)
  2.1021 +                     decode-bcd butlast)
  2.1022 +                    (partition price-size
  2.1023 +                               (take (* price-size (count items))
  2.1024 +                                     (drop 0x4495 rom))))))))
  2.1025 +
  2.1026 +(defn hxc-shops
  2.1027 +  ([] (hxc-shops com.aurellem.gb.gb-driver/original-rom))
  2.1028 +  ([rom]
  2.1029 +     (let [items (zipmap (range) (hxc-items rom))
  2.1030 +
  2.1031 +           ;; temporarily softcode the TM items
  2.1032 +           items (into
  2.1033 +                  items
  2.1034 +                  (map (juxt identity
  2.1035 +                             (comp keyword
  2.1036 +                                   (partial str "tm-")
  2.1037 +                                   (partial + 1 -200)
  2.1038 +                                   )) 
  2.1039 +                       (take 200 (drop 200 (range)))))
  2.1040 +                       
  2.1041 +           ]
  2.1042 +
  2.1043 +       ((fn parse-shop [coll [num-items & items-etc]]
  2.1044 +          (let [inventory (take-while
  2.1045 +                           (partial not= 0xFF)
  2.1046 +                           items-etc)
  2.1047 +               [separator & items-etc] (drop num-items (rest items-etc))]
  2.1048 +           (if (= separator 0x50)
  2.1049 +             (map (partial mapv (comp items dec)) (conj coll inventory))
  2.1050 +             (recur (conj coll inventory) items-etc)
  2.1051 +             )
  2.1052 +         ))
  2.1053 +
  2.1054 +        '()
  2.1055 +        (drop 0x233C rom))
  2.1056 +
  2.1057 +     
  2.1058 +     )))
  2.1059 +
  2.1060 +
  2.1061 +
  2.1062 +
  2.1063 +
  2.1064 +(defn hxc-ptrs-wild
  2.1065 +  "A list of the hardcoded wild encounter data in memory. Pointers
  2.1066 +  begin at ROM@0CB95; data begins at ROM@0x04D89" 
  2.1067 +  ([] (hxc-ptrs-wild com.aurellem.gb.gb-driver/original-rom))
  2.1068 +  ([rom]
  2.1069 +     (let [ptrs
  2.1070 +           (map (fn [[a b]] (+ a (* 0x100 b)))
  2.1071 +            (take-while (partial not= (list 0xFF 0xFF))
  2.1072 +                            (partition 2 (drop 0xCB95 rom))))]
  2.1073 +       ptrs)))
  2.1074 +
  2.1075 +
  2.1076 +
  2.1077 +(defn hxc-wilds
  2.1078 +  "A list of the hardcoded wild encounter data in memory. Pointers
  2.1079 +  begin at ROM@0CB95; data begins at ROM@0x04D89" 
  2.1080 +  ([] (hxc-wilds com.aurellem.gb.gb-driver/original-rom))
  2.1081 +  ([rom]
  2.1082 +     (let [pokenames (zipmap (range) (hxc-pokenames rom))]
  2.1083 +       (map
  2.1084 +        (partial map (fn [[a b]] {:species (pokenames (dec b)) :level
  2.1085 +                                  a}))
  2.1086 +        (partition 10
  2.1087 +                     
  2.1088 +                      (take-while (comp (partial not= 1)
  2.1089 +                                        first) 
  2.1090 +                                 (partition 2
  2.1091 +                                            (drop 0xCD8C rom))
  2.1092 +                   
  2.1093 +                   ))))))
  2.1094 +
  2.1095 +
  2.1096 +
  2.1097 +
  2.1098 +
  2.1099 +
  2.1100 +
  2.1101 +
  2.1102 +
  2.1103 +
  2.1104 +
  2.1105 +
  2.1106 +
  2.1107 +
  2.1108 +;; ********************** MANIPULATION FNS
  2.1109 +
  2.1110 +
  2.1111 +(defn same-type
  2.1112 +  ([pkmn move]
  2.1113 +     (same-type
  2.1114 +      com.aurellem.gb.gb-driver/original-rom pkmn move))
  2.1115 +  ([rom pkmn move]
  2.1116 +     (((comp :types (hxc-pokemon-base rom)) pkmn)
  2.1117 +      ((comp :type (hxc-move-data rom)) move))))
  2.1118 +
  2.1119 +
  2.1120 +
  2.1121 +
  2.1122 +(defn submap?
  2.1123 +  "Compares the two maps. Returns true if map-big has the same associations as map-small, otherwise false." 
  2.1124 +  [map-small map-big]
  2.1125 +  (cond (empty? map-small) true
  2.1126 +        (and
  2.1127 +         (contains? map-big (ffirst map-small))
  2.1128 +         (= (get map-big (ffirst map-small))
  2.1129 +            (second (first map-small))))
  2.1130 +        (recur (next map-small) map-big)
  2.1131 +
  2.1132 +        :else false))  
  2.1133 +
  2.1134 +
  2.1135 +(defn search-map [proto-map maps]
  2.1136 +  "Returns all the maps that make the same associations as proto-map."
  2.1137 +  (some (partial submap? proto-map) maps))
  2.1138 +
  2.1139 +(defn filter-vals
  2.1140 +  "Returns a map consisting of all the pairs [key val] for
  2.1141 +  which (pred key) returns true."
  2.1142 +  [pred map]
  2.1143 +  (reduce (partial apply assoc) {}
  2.1144 +          (filter (fn [[k v]] (pred v)) map)))
  2.1145 +
  2.1146 +
  2.1147 +(defn search-moves
  2.1148 +  "Returns a subcollection of all hardcoded moves with the
  2.1149 +  given attributes. Attributes consist of :name :power
  2.1150 +  :accuracy :pp :fx-id
  2.1151 +  (and also :fx-txt, but it contains the same information
  2.1152 +  as :fx-id)"
  2.1153 +  ([attribute-map]
  2.1154 +     (search-moves
  2.1155 +      com.aurellem.gb.gb-driver/original-rom attribute-map))
  2.1156 +  ([rom attribute-map]
  2.1157 +     (filter-vals (partial submap? attribute-map)
  2.1158 +                  (hxc-move-data rom))))
  2.1159 +
  2.1160 +
  2.1161 +
  2.1162 +
  2.1163 +
  2.1164 +;; note: 0x2f31 contains the names "TM" "HM"?
  2.1165 +
  2.1166 +;; note for later: credits start at F1290
  2.1167 +
  2.1168 +;; note: DADB hyper-potion-hp _ _ _ super-potion-hp _ _ _ potion-hp ??
  2.1169 +
  2.1170 +;; note: DD4D spells out pokemon vital stat names ("speed", etc.)
  2.1171 +
  2.1172 +;; note: 1195C-6A says ABLE#NOT ABLE#, but so does 119C0-119CE.
  2.1173 +;; The first instance is for Machines; the second, for stones.
  2.1174 +
  2.1175 +;; 0x251A (in indexable mem): image decompression routine seems to begin here.
  2.1176 +
  2.1177 +
  2.1178 +(comment 
  2.1179 +
  2.1180 +(def hxc-later
  2.1181 +  "Running this code produces, e.g. hardcoded names NPCs give
  2.1182 +their pokemon. Will sort through it later."
  2.1183 +(print (character-codes->str(take 10000
  2.1184 +                          (drop 0x71597
  2.1185 +                                (rom (root)))))))
  2.1186 +
  2.1187 +(let [dex
  2.1188 +      (partition-by #(= 0x50 %)
  2.1189 +                    (take 2540
  2.1190 +                          (drop 0x40687
  2.1191 +                                (rom (root)))))]
  2.1192 +  (def dex dex)
  2.1193 +  (def hxc-species
  2.1194 +    (map character-codes->str
  2.1195 +         (take-nth 4 dex))))
  2.1196 +)
  2.1197 +
  2.1198 +
  2.1199 +#+end_src
  2.1200 +