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

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