Skip to content

Instantly share code, notes, and snippets.

@magical
Created August 3, 2019 04:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save magical/c5c626e907c30449dbf7443b361fa566 to your computer and use it in GitHub Desktop.
Save magical/c5c626e907c30449dbf7443b361fa566 to your computer and use it in GitHub Desktop.
hg/ss headbutt data dumper (circa 2012)
# coding: utf-8
from struct import pack, unpack
from narc import parse_narc
from cStringIO import StringIO
from warnings import warn
"""
structure:
u16 tree_count;
u16 special_tree_count;
struct slot slots[12];
struct slot special_slots[6];
struct coords trees[tree_count][6];
struct coords special_trees[special_tree_count][6];
struct slot {
u16 pokemon;
u8 min_level;
u8 max_level;
}
struct coords { u16 x; u16 y; }
"""
def chunkit(seq, n):
for i in range(0, len(seq), n):
yield seq[i:i+n]
def parse_encounters(narc_file):
records = parse_narc(narc_file)
stuff = []
for i, record in enumerate(records):
f = StringIO(record)
tree_count, extra_count = unpack("<HH", f.read(4))
if tree_count == 0 and extra_count != 0:
warn("tree_count == 0 but extra_count == %d" % extra_count)
if tree_count == 0:
continue
slots = [unpack("<HBB", x) for x in chunkit(f.read(12*4), 4)]
extra = [unpack("<HBB", x) for x in chunkit(f.read(6*4), 4)]
trees = [[unpack("<HH", x) for x in chunkit(tree, 4)] for tree in
chunkit(f.read(tree_count*6*4), 6*4)]
extra_trees = [[unpack("<HH", x) for x in chunkit(tree, 4)] for tree in
chunkit(f.read(extra_count * 6*4), 6*4)]
if f.read():
warn("record %d: trailing junk" % i)
if not extra_count and any(pokemon for pokemon, _, _ in extra):
warn("no special trees but special pokemon are defined")
elif extra_count and not all(pokemon for pokemon, _, _ in extra):
warn("special trees present but special pokemon not defined")
#print tree_count, extra_count
stuff.append((i, slots, extra, trees, extra_trees))
return stuff
def dump_text(narc_file, out):
encounters = parse_encounters(narc_file)
for i, slots, extra, trees, extra_trees in encounters:
print "Record", i
print "Location:", location_names[i]
print "Pokémon:", ", ".join(
"%s %s-%s" % (names[pokemon], min_level, max_level)
for pokemon, min_level, max_level in slots[:6]
)
print "Pokémon:", ", ".join(
"%s %s-%s" % (names[pokemon], min_level, max_level)
for pokemon, min_level, max_level in slots[6:]
)
if extra_trees:
print "Special Pokémon:", ", ".join(
"%s %s-%s" % (names[pokemon], min_level, max_level)
for pokemon, min_level, max_level in extra
if pokemon
)
print "Trees:", len(trees)
for coords in trees:
print "Tree:", " ".join(
"(%d %d)" % c for c in coords if c != (0xffff, 0xffff)
)
if extra_trees:
print "Special trees:", len(extra_trees)
for coords in extra_trees:
print "Special tree:", " ".join(
"(%d %d)" % c for c in coords if c != (0xffff, 0xffff)
)
print
def dump_text2(narc_file, out):
encounters = parse_encounters(narc_file)
rates = [20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
extra_rates = [50, 15, 15, 10, 5, 5]
for i, slots, extra, trees, extra_trees in encounters:
print "%%%"
print
print "Record", i
print
print "Location:", location_names[i]
print
print "Pokémon"
for i, (pokemon, min_level, max_level) in enumerate(slots):
print "Slot %d: %d%% %d-%d %s" % (i, rates[i], min_level, max_level, names[pokemon])
print "Trees [%d]" % len(trees)
for coords in trees:
print "Tree:", " ".join(
"(%d %d)" % c for c in coords if c != (0xffff, 0xffff)
)
print
if extra_trees:
print "Special Pokémon"
for i, (pokemon, min_level, max_level) in enumerate(extra):
print "Slot %d: %d%% %d-%d %s" % (i, extra_rates[i], min_level, max_level, names[pokemon])
print "Special trees [%d]" % len(extra_trees)
for coords in extra_trees:
print "Tree:", " ".join(
"(%d %d)" % c for c in coords if c != (0xffff, 0xffff)
)
print
names = None
def load_names():
global names
if names is None:
import os.path
namefile = os.path.join(os.path.dirname(__file__), "../names.txt")
names = open(namefile).read().splitlines()
location_names = {
0: u'',
1: u'',
2: u'',
3: u'',
4: u'',
5: u'',
6: u'Bellchime Trail',
7: u'Burned Tower',
8: u'Ruins of Alph',
9: u'Route 1',
10: u'Route 2',
11: u'Route 3',
12: u'Route 4',
13: u'Route 5',
14: u'Route 6',
15: u'Route 7',
16: u'Route 8',
17: u'Route 9',
18: u'Route 10',
19: u'Route 11',
20: u'Route 12',
21: u'Route 13',
22: u'Route 14',
23: u'Route 15',
24: u'Route 16',
25: u'Route 17',
26: u'Route 18',
27: u'Route 22',
28: u'Route 24',
29: u'Route 25',
30: u'Route 26',
31: u'Route 27',
32: u'Route 28',
33: u'Route 29',
34: u'Route 30',
35: u'Route 31',
36: u'Route 32',
37: u'Route 33',
38: u'Route 34',
39: u'Route 35',
40: u'Route 36',
41: u'Route 37',
42: u'Route 38',
43: u'Route 39',
44: u'Route 42',
45: u'Route 43',
46: u'Route 44',
47: u'Route 45',
48: u'Route 46',
49: u'Pallet Town',
50: u'Viridian City',
51: u'Pewter City',
52: u'Cerulean City',
53: u'Lavender Town',
54: u'Vermilion City',
55: u'Celadon City',
56: u'Fuchsia City',
57: u'Cinnabar Island',
58: u'Indigo Plateau',
59: u'Saffron City',
60: u'New Bark Town',
61: u'New Bark Town',
62: u'New Bark Town',
63: u'New Bark Town',
64: u'New Bark Town',
65: u'New Bark Town',
66: u'New Bark Town',
67: u'Cherrygrove City',
68: u'Cherrygrove City',
69: u'Cherrygrove City',
70: u'Cherrygrove City',
71: u'Cherrygrove City',
72: u'Cherrygrove City',
73: u'Violet City',
74: u'Azalea Town',
75: u'Cianwood City',
76: u'Goldenrod City',
77: u'Olivine City',
78: u'Ecruteak City',
79: u'Ecruteak City',
80: u'Ecruteak City',
81: u'Ecruteak City',
82: u'Jubilife City',
83: u'Ecruteak City',
84: u'Ecruteak City',
85: u'Ecruteak City',
86: u'Ecruteak City',
87: u'Mahogany Town',
88: u'Lake of Rage',
89: u'Blackthorn City',
90: u'Mt. Silver',
91: u'Sea Route 19',
92: u'Sea Route 20',
93: u'Sea Route 21',
94: u'Sea Route 40',
95: u'Sea Route 41',
96: u'National Park',
97: u'Route 31',
98: u'Route 32',
99: u'Union Cave',
100: u'Azalea Town',
101: u'Route 35',
102: u'Route 35',
103: u'Route 36',
104: u'Route 36',
105: u'Jubilife City',
106: u"Diglett's Cave",
107: u'Mt. Moon',
108: u'Rock Tunnel',
109: u'Pal Park',
110: u'Sprout Tower',
111: u'Bell Tower',
112: u'Radio Tower',
113: u'Ruins of Alph',
114: u'Slowpoke Well',
115: u'Lighthouse',
116: u'Mahogany Town',
117: u'Ilex Forest',
118: u'Goldenrod Tunnel',
119: u'Mt. Mortar',
120: u'Ice Path',
121: u'Whirl Islands',
122: u'Mt. Silver Cave',
123: u'Dark Cave',
124: u'Victory Road',
125: u"Dragon's Den",
126: u'Tohjo Falls',
127: u'Route 30',
128: u'Ecruteak City',
129: u'Ecruteak City',
130: u'Ecruteak City',
131: u'Ecruteak City',
132: u'Route 42',
133: u'Mahogany Town',
134: u'Route 29',
135: u'Violet City',
136: u'Azalea Town',
137: u'Goldenrod City',
138: u'Olivine City',
139: u'Cianwood City',
140: u'Mahogany Town',
141: u'Blackthorn City',
142: u'Route 43',
143: u'Route 30',
144: u'Cherrygrove City',
145: u'Cerulean Cave',
146: u'Seafoam Islands',
147: u'Viridian Forest',
148: u'Power Plant',
149: u'Route 36',
150: u'Pok\xe9athlon Dome',
151: u'Route 47',
152: u'Route 48',
153: u'Union Cave',
154: u'Union Cave',
155: u'Sprout Tower',
156: u'Sprout Tower',
157: u'Violet City',
158: u'Violet City',
159: u'Violet City',
160: u'Violet City',
161: u'Jubilife City',
162: u'Violet City',
163: u'Azalea Town',
164: u'Azalea Town',
165: u'Azalea Town',
166: u'Azalea Town',
167: u'Violet City',
168: u'Azalea Town',
169: u'Route 32',
170: u'Route 32',
171: u'Route 34',
172: u'Route 38',
173: u'Safari Zone Gate',
174: u'Safari Zone Gate',
175: u'Jubilife City',
176: u'Dark Cave',
177: u'Slowpoke Well',
178: u'Victory Road',
179: u'Victory Road',
180: u'Azalea Town',
181: u'Slowpoke Well',
182: u'Goldenrod City',
183: u'Goldenrod City',
184: u'Goldenrod City',
185: u'Goldenrod City',
186: u'Radio Tower',
187: u'Radio Tower',
188: u'Radio Tower',
189: u'Radio Tower',
190: u'Radio Tower',
191: u'Goldenrod City',
192: u'Goldenrod City',
193: u'Goldenrod City',
194: u'Goldenrod City',
195: u'Goldenrod City',
196: u'Goldenrod City',
197: u'Goldenrod City',
198: u'Goldenrod City',
199: u'Goldenrod Tunnel',
200: u'Goldenrod City',
201: u'Goldenrod City',
202: u'Goldenrod City',
203: u'Goldenrod City',
204: u'Goldenrod City',
205: u'Goldenrod City',
206: u'Goldenrod City',
207: u'Global Terminal',
208: u'Goldenrod City',
209: u'Goldenrod City',
210: u'Goldenrod City',
211: u'Goldenrod City',
212: u'Goldenrod City',
213: u'Goldenrod City',
214: u'Route 39',
215: u'Route 39',
216: u'Ecruteak City',
217: u'Burned Tower',
218: u'Ruins of Alph',
219: u'Goldenrod City',
220: u'Lighthouse',
221: u'Lighthouse',
222: u'Lighthouse',
223: u'Lighthouse',
224: u'Lighthouse',
225: u'Lighthouse',
226: u'Olivine City',
227: u'Olivine City',
228: u'Olivine City',
229: u'Olivine City',
230: u'Olivine City',
231: u'Olivine City',
232: u'Cianwood City',
233: u'Cianwood City',
234: u'Cianwood City',
235: u'Cianwood City',
236: u'Cianwood City',
237: u'Ice Path',
238: u'Ice Path',
239: u'Ice Path',
240: u'Olivine City',
241: u'Cianwood City',
242: u'Whirl Islands',
243: u'Whirl Islands',
244: u'Whirl Islands',
245: u'Route 43',
246: u'Mahogany Town',
247: u'Team Rocket HQ',
248: u'Team Rocket HQ',
249: u'Team Rocket HQ',
250: u'Mt. Mortar',
251: u'Mt. Mortar',
252: u'Mt. Mortar',
253: u"Dragon's Den",
254: u'Fight Area',
255: u'Fight Area',
256: u'Fight Area',
257: u'Fight Area',
258: u'Fight Area',
259: u'Fight Area',
260: u'Fight Area',
261: u'Fight Area',
262: u'Fight Area',
263: u'Battle Park',
264: u'Battle Park',
265: u'Battle Tower',
266: u'Battle Tower',
267: u'Battle Tower',
268: u'Battle Tower',
269: u'Battle Tower',
270: u'Battle Tower',
271: u'Battle Tower',
272: u'Battle Frontier',
273: u'Battle Frontier',
274: u'Battle Tower',
275: u'Battle Factory',
276: u'Battle Hall',
277: u'Battle Castle',
278: u'Battle Arcade',
279: u'Cliff Edge Gate',
280: u'Pok\xe9athlon Dome',
281: u'Pok\xe9athlon Dome',
282: u'Pok\xe9athlon Dome',
283: u'Pok\xe9athlon Dome',
284: u'Pok\xe9athlon Dome',
285: u'Pok\xe9athlon Dome',
286: u'Pok\xe9athlon Dome',
287: u'Pok\xe9athlon Dome',
288: u"Dragon's Den",
289: u'Blackthorn City',
290: u'Blackthorn City',
291: u'Blackthorn City',
292: u'Blackthorn City',
293: u'Blackthorn City',
294: u'Lake of Rage',
295: u'Lake of Rage',
296: u'Route 26',
297: u'Route 26',
298: u'Tohjo Falls',
299: u'Route 26',
300: u'Pok\xe9mon League',
301: u'Pok\xe9mon League',
302: u'Pok\xe9mon League',
303: u'Pok\xe9mon League',
304: u'Pok\xe9mon League',
305: u'Pok\xe9mon League',
306: u'Pok\xe9mon League',
307: u'S.S. Aqua',
308: u'S.S. Aqua',
309: u'S.S. Aqua',
310: u'S.S. Aqua',
311: u'S.S. Aqua',
312: u'Ruins of Alph',
313: u'Ruins of Alph',
314: u'Ruins of Alph',
315: u'Ruins of Alph',
316: u'Ruins of Alph',
317: u'Ruins of Alph',
318: u'Ruins of Alph',
319: u'Ruins of Alph',
320: u'Ruins of Alph',
321: u'Ruins of Alph',
322: u'Route 27',
323: u'Ruins of Alph',
324: u'Ruins of Alph',
325: u'Ruins of Alph',
326: u'Ruins of Alph',
327: u'Ruins of Alph',
328: u'S.S. Aqua',
329: u'S.S. Aqua',
330: u'Olivine City',
331: u'Route 34',
332: u'Bell Tower',
333: u'Bell Tower',
334: u'Bell Tower',
335: u'Bell Tower',
336: u'Bell Tower',
337: u'Bell Tower',
338: u'Bell Tower',
339: u'Bell Tower',
340: u'Bell Tower',
341: u'Bell Tower',
342: u'Cliff Cave',
343: u'Safari Zone',
344: u'Safari Zone',
345: u'Safari Zone',
346: u'Safari Zone',
347: u'Safari Zone',
348: u'Safari Zone',
349: u'Safari Zone',
350: u'Safari Zone',
351: u'Safari Zone',
352: u'Safari Zone',
353: u'Safari Zone',
354: u'Safari Zone',
355: u'Safari Zone',
356: u'Safari Zone',
357: u'Safari Zone',
358: u'Vermilion City',
359: u'Vermilion City',
360: u'Vermilion City',
361: u'Vermilion City',
362: u'Vermilion City',
363: u'Vermilion City',
364: u'Vermilion City',
365: u'Vermilion City',
366: u'Sea Route 40',
367: u'Olivine City',
368: u'Mahogany Town',
369: u'Blackthorn City',
370: u'Celadon City',
371: u'Celadon City',
372: u'Celadon City',
373: u'Celadon City',
374: u'Celadon City',
375: u'Celadon City',
376: u'Celadon City',
377: u'Celadon City',
378: u'Celadon City',
379: u'Celadon City',
380: u'Celadon City',
381: u'Celadon City',
382: u'Celadon City',
383: u'Celadon City',
384: u'New Bark Town',
385: u'Cianwood City',
386: u'Vermilion City',
387: u'Vermilion City',
388: u'Route 10',
389: u'Route 6',
390: u'Route 8',
391: u'Route 5',
392: u'Route 15',
393: u'Celadon City',
394: u'Celadon City',
395: u'Celadon City',
396: u'Mahogany Town',
397: u'Mahogany Town',
398: u'Saffron City',
399: u'Saffron City',
400: u'Saffron City',
401: u'Saffron City',
402: u'Saffron City',
403: u"ROTOM's Room",
404: u'Saffron City',
405: u'Saffron City',
406: u'Saffron City',
407: u'Saffron City',
408: u'Saffron City',
409: u'Saffron City',
410: u'Saffron City',
411: u'Frontier Access',
412: u'Global Terminal',
413: u'Global Terminal',
414: u'Route 2',
415: u'Route 16',
416: u'Sea Route 20',
417: u'Route 2',
418: u'Route 2',
419: u'Route 2',
420: u'Route 2',
421: u'Route 16',
422: u'Route 16',
423: u'Route 18',
424: u'Sea Route 19',
425: u'Route 11',
426: u'Cerulean City',
427: u'Cerulean City',
428: u'Cerulean City',
429: u'Cerulean City',
430: u'Cerulean City',
431: u'Cerulean City',
432: u'Cerulean City',
433: u'Lavender Town',
434: u'Lavender Town',
435: u'Lavender Town',
436: u'Lavender Town',
437: u'Lavender Town',
438: u'Lavender Town',
439: u'Lavender Town',
440: u'Route 25',
441: u'Goldenrod City',
442: u'Celadon City',
443: u'Celadon City',
444: u'Celadon City',
445: u'Saffron City',
446: u'Lighthouse',
447: u'Radio Tower',
448: u'Mt. Moon',
449: u'Mt. Moon',
450: u'Cerulean Cave',
451: u'Cerulean Cave',
452: u'Rock Tunnel',
453: u'Seafoam Islands',
454: u'Seafoam Islands',
455: u'Seafoam Islands',
456: u'Seafoam Islands',
457: u'Seafoam Islands',
458: u'Seafoam Islands',
459: u'Mt. Silver Cave',
460: u'Mt. Silver Cave',
461: u'Mt. Silver Cave',
462: u'Mt. Silver Cave',
463: u'Mt. Silver Cave',
464: u'Mt. Silver Cave',
465: u'Mt. Silver Cave',
466: u'Route 10',
467: u'Power Plant',
468: u'Route 5',
469: u'Route 5',
470: u'Route 6',
471: u'Pewter City',
472: u'Pewter City',
473: u'Pewter City',
474: u'Pewter City',
475: u'Pewter City',
476: u'Pewter City',
477: u'Pewter City',
478: u'Fuchsia City',
479: u'Pal Park',
480: u'Fuchsia City',
481: u'Fuchsia City',
482: u'Fuchsia City',
483: u'Fuchsia City',
484: u'Route 10',
485: u'Fuchsia City',
486: u'Whirl Islands',
487: u'National Park',
488: u'National Park',
489: u'Power Plant',
490: u'Ruins of Alph',
491: u'Ruins of Alph',
492: u'Ruins of Alph',
493: u'Route 7',
494: u'Lavender Town',
495: u'Cerulean City',
496: u'Viridian City',
497: u'Viridian City',
498: u'Viridian City',
499: u'Viridian City',
500: u'Viridian City',
501: u'Viridian City',
502: u'Viridian City',
503: u'Pallet Town',
504: u'Pallet Town',
505: u'Pallet Town',
506: u'Pallet Town',
507: u'Pallet Town',
508: u'Cinnabar Island',
509: u'Cinnabar Island',
510: u'Route 28',
511: u'Route 3',
512: u'Route 3',
513: u'Mt. Moon',
514: u'Mt. Silver',
515: u'Mt. Silver',
516: u'',
517: u'Route 5',
518: u'Mt. Moon',
519: u'Goldenrod City',
520: u'Saffron City',
521: u'Sinjoh Ruins',
522: u'Sinjoh Ruins',
523: u'Sinjoh Ruins',
524: u'Embedded Tower',
525: u'Embedded Tower',
526: u'Embedded Tower',
527: u'Route 1',
528: u'Frontier Access',
529: u'Frontier Access',
530: u'Frontier Access',
531: u'Frontier Access',
532: u'Route 5',
533: u'Route 12',
534: u'Safari Zone Gate',
535: u'Safari Zone Gate',
536: u'Goldenrod City',
537: u'Celadon City',
538: u'',
539: u'Pok\xe9mon League',
}
load_names()
dump_text(open("data/headbutt-heartgold.narc", "rb"), None)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment