├── .gitignore ├── beyondchaos.exe ├── gallery ├── daryl.png ├── sabins.png ├── crazyparty.png ├── tinaparty.png ├── usableitems.png ├── daryl_native.png ├── sabins_native.png ├── tinaparty_native.png ├── crazyparty_native.png ├── floatingcontinent.png ├── usableitems_native.png └── floatingcontinent_native.png ├── sprites ├── zeemis-ff4-kain.bin ├── zeemis-red-mage.bin ├── badass-mario-mario.bin ├── dr-blank-ff5-faris.bin ├── badass-earthbound-ness.bin ├── matthew50-ff-white-mage.bin ├── sutebenukun-ff4-tellah.bin ├── sutebenukun-ff7-aerith.bin ├── badass-metroid-samus-zero.bin └── metroidquest-ec-dark-cecil.bin ├── tables ├── finaldungeonmaps.txt ├── unusedlocs.txt ├── treasurerooms.txt ├── wobonlytreasure.txt ├── charpaloptions.txt ├── spritereplacements.txt ├── locationpaletteswaps.txt ├── battlebgpalettes.txt ├── espercodes.txt ├── eventpalettes.txt ├── text.txt ├── shorttext.txt ├── charcodes.txt ├── finaldungeoncheckpoints.txt ├── ancientcheckpoints.txt ├── locationformations.txt ├── finalai.txt ├── commandcodes.txt ├── worstartingitems.txt ├── spellbans.txt ├── locationmaps.txt ├── shopcodes.txt ├── femalenames.txt ├── malenames.txt ├── mapbattlebgs.txt ├── usedlocs.txt ├── wobeventbits.txt ├── enemynames.txt ├── chestcodes.txt ├── spellcodes.txt ├── enemycodes.txt ├── reachability.txt ├── itemcodes.txt ├── mapnames.txt ├── moves.txt └── customitems.txt ├── testrun.sh ├── devtools └── dump_spellsets.py ├── unittests.sh ├── namerandomizer.py ├── shoprandomizer.py ├── esperrandomizer.py ├── decompress.py ├── README ├── chestrandomizer.py ├── formationrandomizer.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /beyondchaos.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/beyondchaos.exe -------------------------------------------------------------------------------- /gallery/daryl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/daryl.png -------------------------------------------------------------------------------- /gallery/sabins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/sabins.png -------------------------------------------------------------------------------- /gallery/crazyparty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/crazyparty.png -------------------------------------------------------------------------------- /gallery/tinaparty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/tinaparty.png -------------------------------------------------------------------------------- /gallery/usableitems.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/usableitems.png -------------------------------------------------------------------------------- /gallery/daryl_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/daryl_native.png -------------------------------------------------------------------------------- /gallery/sabins_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/sabins_native.png -------------------------------------------------------------------------------- /gallery/tinaparty_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/tinaparty_native.png -------------------------------------------------------------------------------- /sprites/zeemis-ff4-kain.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/zeemis-ff4-kain.bin -------------------------------------------------------------------------------- /sprites/zeemis-red-mage.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/zeemis-red-mage.bin -------------------------------------------------------------------------------- /gallery/crazyparty_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/crazyparty_native.png -------------------------------------------------------------------------------- /gallery/floatingcontinent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/floatingcontinent.png -------------------------------------------------------------------------------- /gallery/usableitems_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/usableitems_native.png -------------------------------------------------------------------------------- /sprites/badass-mario-mario.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/badass-mario-mario.bin -------------------------------------------------------------------------------- /sprites/dr-blank-ff5-faris.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/dr-blank-ff5-faris.bin -------------------------------------------------------------------------------- /sprites/badass-earthbound-ness.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/badass-earthbound-ness.bin -------------------------------------------------------------------------------- /sprites/matthew50-ff-white-mage.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/matthew50-ff-white-mage.bin -------------------------------------------------------------------------------- /sprites/sutebenukun-ff4-tellah.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/sutebenukun-ff4-tellah.bin -------------------------------------------------------------------------------- /sprites/sutebenukun-ff7-aerith.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/sutebenukun-ff7-aerith.bin -------------------------------------------------------------------------------- /gallery/floatingcontinent_native.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/gallery/floatingcontinent_native.png -------------------------------------------------------------------------------- /sprites/badass-metroid-samus-zero.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/badass-metroid-samus-zero.bin -------------------------------------------------------------------------------- /sprites/metroidquest-ec-dark-cecil.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abyssonym/beyondchaos/HEAD/sprites/metroidquest-ec-dark-cecil.bin -------------------------------------------------------------------------------- /tables/finaldungeonmaps.txt: -------------------------------------------------------------------------------- 1 | 10b 2 | 11f 3 | 123 4 | 124 5 | 125 6 | 126 7 | 127 8 | 128 9 | 12f 10 | 130 11 | 149 12 | 14b 13 | 14e 14 | 14f 15 | 151 16 | 152 17 | 153 18 | 160 19 | 162 20 | 163 21 | 199 22 | 19a 23 | 19b 24 | 19c 25 | -------------------------------------------------------------------------------- /tables/unusedlocs.txt: -------------------------------------------------------------------------------- 1 | 1d 2 | 1f 3 | 28 4 | 2d 5 | 2e 6 | 4f 7 | 52 8 | 63 9 | 76 10 | 7a 11 | c0 12 | c1 13 | c7 14 | dc 15 | de 16 | df 17 | e0 18 | e3 19 | e4 20 | e5 21 | e6 22 | 101 23 | 109 24 | 113 25 | 11e 26 | 14d 27 | 156 28 | 17b 29 | 183 30 | 184 31 | 193 32 | 19e 33 | -------------------------------------------------------------------------------- /tables/treasurerooms.txt: -------------------------------------------------------------------------------- 1 | 65,0,0 2 | 86,0,1 3 | 94,0,0 4 | 105,0,0 5 | 110,3,0 6 | 124,0,0 7 | 146,0,0 8 | 186,0,0 9 | 195,3,0 10 | 197,0,0 11 | 209,0,0 12 | 225,9,2 13 | 250,17,3 14 | 262,0,4 15 | 349,2,0 16 | 351,10,0 17 | 353,10,2 18 | 366,0,0 19 | 374,0,0 20 | 406,2,3 21 | 408,0,0 22 | -------------------------------------------------------------------------------- /tables/wobonlytreasure.txt: -------------------------------------------------------------------------------- 1 | ALBROOK (WOB) 2 | ESPER MOUNTAIN 3 | FLOATING CONTINENT 4 | HOUSE AT DRAGON'S NECK 5 | IMPERIAL BASE 6 | IMPERIAL CAMP 7 | MAGITEK FACILITY 8 | MOBLIZ (WOB) 9 | MT. KOLTZ 10 | NARSHE (WOB) 11 | PHANTOM TRAIN 12 | RETURNER'S HIDEOUT 13 | SEALED GATE 14 | SERPENT TRENCH 15 | SOUTH FIGARO (WOB) 16 | THAMASA 17 | VECTOR 18 | -------------------------------------------------------------------------------- /tables/charpaloptions.txt: -------------------------------------------------------------------------------- 1 | 0:0,1,2,4 2 | 1:0,1,2 3 | 2:4,5 4 | 3:0,1,4,5 5 | 4:0,1,2,3,4 6 | 5:0,1,2,5 7 | 6:0,1,2,4,5 8 | 7:1,2,3,4 9 | 8:1,2,3,4 10 | 9:0,1,2,4 11 | a:3,4,5 12 | b:0,1,2,3,4,5 13 | c:0,1,3,4,5 14 | d:5 15 | e:0,1,2,3,4,5 16 | f:0,1,2,5 17 | 10:0,1,2,3,4 18 | 11:0,1,2,3 19 | 12:0,1,2,3,4,5 20 | 13:0,1,2,5 21 | 14:0,1,2,5 22 | 15:0,1,3 23 | -------------------------------------------------------------------------------- /tables/spritereplacements.txt: -------------------------------------------------------------------------------- 1 | badass-earthbound-ness.bin,Ness,male,true 2 | badass-mario-mario.bin,Mario,male,true 3 | badass-metroid-samus-zero.bin,Samus,female,true 4 | dr-blank-ff5-faris.bin,Faris,female,true 5 | matthew50-ff-white-mage.bin,White Mage,neutral,false 6 | metroidquest-ec-dark-cecil.bin,Cecil,male,true 7 | sutebenukun-ff4-tellah.bin,Tellah,male,true 8 | sutebenukun-ff7-aerith.bin,Aerith,female,false 9 | zeemis-red-mage.bin,Red Mage,neutral,false 10 | zeemis-ff4-kain.bin,Kain,male,true -------------------------------------------------------------------------------- /testrun.sh: -------------------------------------------------------------------------------- 1 | SEED=42069 2 | rm program.$SEED.rom program.$SEED.rom.bak program.$SEED.rom.wine 3 | python randomizer.py program.rom .$1.$SEED test 4 | mv program.$SEED.rom program.$SEED.rom.bak 5 | wine-development beyondchaos.exe program.rom .$1.$SEED 6 | mv program.$SEED.rom program.$SEED.rom.wine 7 | python randomizer.py program.rom .$1.$SEED test 8 | diff program.$SEED.rom program.$SEED.rom.bak 9 | diff program.$SEED.rom program.$SEED.rom.wine 10 | diff program.$SEED.rom.bak program.$SEED.rom.wine 11 | -------------------------------------------------------------------------------- /tables/locationpaletteswaps.txt: -------------------------------------------------------------------------------- 1 | magitek facility,kefka's tower indoors:2ddc80,2de180,2de380:1b,1d,14 2 | kefka's tower:2de680,2def80 3 | phoenix cave,sealed gate:2de480 4 | fanatics tower:2dee80 5 | zozo:2dd480 6 | fanatics tower indoors:2dd880 7 | zozo indoors*:2dd880,2dce80 8 | floating continent:2dd780 9 | daryl's tomb:2dec80 10 | phantom forest,phantom train outdoors:2de080,2dd280:21,f,3 11 | phantom train:2dd380 12 | cyan's dream:2ddf80 13 | opera house:2dcf80,2deb80:17,18 14 | sealed bridge:2de580:22 15 | 33,34,35,36 16 | 1c 17 | -------------------------------------------------------------------------------- /tables/battlebgpalettes.txt: -------------------------------------------------------------------------------- 1 | 0 0 2 | 1 31 3 | 2 b 4 | 3 c 5 | 4 23 6 | 5 d 7 | 6 e 8 | 7 26 9 | 8 1 10 | 9 2 11 | a 3 12 | b 4 13 | c 5 14 | d 6 15 | e 7 16 | f 8 17 | 10 9 18 | 11 2 19 | 12 f 20 | 13 10 21 | 14 11 22 | 15 12 23 | 16 13 24 | 17 14 25 | 18 15 26 | 19 16 27 | 1a 17 28 | 1b 18 29 | 1c 19 30 | 1d 18 31 | 1e 1b 32 | 1f 1c 33 | 20 2b 34 | 21 1e 35 | 22 1a 36 | 23 24 37 | 24 25 38 | 25 26 39 | 26 27 40 | 27 28 41 | 28 29 42 | 29 33 43 | 2a 21 44 | 2b 22 45 | 2c 2f 46 | 2d a 47 | 2e 32 48 | 2f 34 49 | 30 26 50 | 33 2c 51 | 34 2d 52 | 35 2e 53 | 36 30 54 | 37 20 55 | -------------------------------------------------------------------------------- /tables/espercodes.txt: -------------------------------------------------------------------------------- 1 | 186e00,Ramuh,0 2 | 186e0b,Ifrit,1 3 | 186e16,Shiva,1 4 | 186e21,Siren,0 5 | 186e2c,Terrato,2 6 | 186e37,Shoat,1 7 | 186e42,Maduin,1 8 | 186e4d,Bismark,1 9 | 186e58,Stray,0 10 | 186e63,Palidor,2 11 | 186e6e,Tritoch,3 12 | 186e79,Odin,3 13 | 186e84,Raiden,4 14 | 186e8f,Bahamut,4 15 | 186e9a,Alexandr,3 16 | 186ea5,Crusader,4 17 | 186eb0,Ragnarok,4 18 | 186ebb,Kirin,0 19 | 186ec6,ZoneSeek,2 20 | 186ed1,Carbunkl,1 21 | 186edc,Phantom,1 22 | 186ee7,Sraphim,2 23 | 186ef2,Golem,2 24 | 186efd,Unicorn,1 25 | 186f08,Fenrir,2 26 | 186f13,Starlet,3 27 | 186f1e,Phoenix,4 28 | -------------------------------------------------------------------------------- /tables/eventpalettes.txt: -------------------------------------------------------------------------------- 1 | AFDC5 2 | A8708 3 | AB395 4 | ABE24 5 | AC273 6 | B9AB8 7 | A66BA 8 | BAB39 9 | BAB57 10 | BAB86 11 | BABA4 12 | BABD3 13 | BABF1 14 | BAC20 15 | BAC3E 16 | BAC6D 17 | BAC8B 18 | BACBA 19 | BACD8 20 | BC183 21 | B81E0 22 | CA4C7 23 | B1139 24 | B3AC9 25 | C0009 26 | C0301 27 | BFF37 28 | CA627 29 | A860E 30 | A7DD5 31 | A7EC6 32 | A85C2 33 | A867D 34 | CA946 35 | CA970 36 | CA97E 37 | CA9A8 38 | CA9B6 39 | CA9C4 40 | CA9D2 41 | AAD5A 42 | CD5EB 43 | C3A52 44 | BDAEA 45 | A6CAC 46 | A6D29 47 | A945B 48 | A7CA8 49 | B0A8B 50 | C6FB4 51 | BCD57 52 | BD9DD 53 | BE561 54 | A5E40 55 | B38FE 56 | B3B91 57 | A6D4A 58 | CD7A0 59 | A5E66 60 | A5E55 61 | -------------------------------------------------------------------------------- /tables/text.txt: -------------------------------------------------------------------------------- 1 | A 80 2 | B 81 3 | C 82 4 | D 83 5 | E 84 6 | F 85 7 | G 86 8 | H 87 9 | I 88 10 | J 89 11 | K 8a 12 | L 8b 13 | M 8c 14 | N 8d 15 | O 8e 16 | P 8f 17 | Q 90 18 | R 91 19 | S 92 20 | T 93 21 | U 94 22 | V 95 23 | W 96 24 | X 97 25 | Y 98 26 | Z 99 27 | 0 86 28 | 1 87 29 | 2 88 30 | 3 89 31 | 4 8a 32 | 5 8b 33 | 6 8c 34 | 7 8d 35 | 8 8e 36 | 9 8f 37 | a 9a 38 | b 9b 39 | c 9c 40 | d 9d 41 | e 9e 42 | f 9f 43 | g a0 44 | h a1 45 | i a2 46 | j a3 47 | k a4 48 | l a5 49 | m a6 50 | n a7 51 | o a8 52 | p a9 53 | q aa 54 | r ab 55 | s ac 56 | t ad 57 | u ae 58 | v af 59 | w b0 60 | x b1 61 | y b2 62 | z b3 63 | 0 b4 64 | 1 b5 65 | 2 b6 66 | 3 b7 67 | 4 b8 68 | 5 b9 69 | 6 ba 70 | 7 bb 71 | 8 bc 72 | 9 bd 73 | ? bf 74 | - c4 75 | . c5 76 | -------------------------------------------------------------------------------- /tables/shorttext.txt: -------------------------------------------------------------------------------- 1 | A 80 2 | B 81 3 | C 82 4 | D 83 5 | E 84 6 | F 85 7 | G 86 8 | H 87 9 | I 88 10 | J 89 11 | K 8A 12 | L 8B 13 | M 8C 14 | N 8D 15 | O 8E 16 | P 8F 17 | Q 90 18 | R 91 19 | S 92 20 | T 93 21 | U 94 22 | V 95 23 | W 96 24 | X 97 25 | Y 98 26 | Z 99 27 | a 9A 28 | b 9B 29 | c 9C 30 | d 9D 31 | e 9E 32 | f 9F 33 | g A0 34 | h A1 35 | i A2 36 | j A3 37 | k A4 38 | l A5 39 | m A6 40 | n A7 41 | o A8 42 | p A9 43 | q AA 44 | r AB 45 | s AC 46 | t AD 47 | u AE 48 | v AF 49 | w B0 50 | x B1 51 | y B2 52 | z B3 53 | 0 B4 54 | 1 B5 55 | 2 B6 56 | 3 B7 57 | 4 B8 58 | 5 B9 59 | 6 BA 60 | 7 BB 61 | 8 BC 62 | 9 BD 63 | ! BE 64 | ? BF 65 | : C1 66 | " C2 67 | ' C3 68 | - C4 69 | . C5 70 | . C6 71 | ; C8 72 | # C9 73 | + CA 74 | ( CB 75 | ) CC 76 | % CD 77 | ~ CE 78 | -------------------------------------------------------------------------------- /tables/charcodes.txt: -------------------------------------------------------------------------------- 1 | 2D7CA0,Terra 2 | 2D7CB6,Locke 3 | 2D7CCC,Cyan 4 | 2D7CE2,Shadow 5 | 2D7CF8,Edgar 6 | 2D7D0E,Sabin 7 | 2D7D24,Celes 8 | 2D7D3A,Strago 9 | 2D7D50,Relm 10 | 2D7D66,Setzer 11 | 2D7D7C,Mog 12 | 2D7D92,Gau 13 | 2D7DA8,Gogo 14 | 2D7DBE,Umaro 15 | 2D7DD4,Banon 16 | 2D7DEA,Leo 17 | 2D7E00,Ghost1 18 | 2D7E16,Ghost2 19 | 2D7E2C,Kupek 20 | 2D7E42,Kupop 21 | 2D7E58,Kumama 22 | 2D7E6E,Kuku 23 | 2D7E84,Kutan 24 | 2D7E9A,Kupan 25 | 2D7EB0,Kushu 26 | 2D7EC6,Kurin 27 | 2D7EDC,Kuru 28 | 2D7EF2,Kamog 29 | 2D7F08,Mog2 30 | 2D7F1E,Terra2 31 | 2D7F34,Maduin 32 | 2D7F4A,Terra3 33 | 2D7F60,Wedge 34 | 2D7F76,Vicks 35 | 2D7F8C,Empty 36 | 2D7FA2,Empty2 37 | 2D7FB8,Empty3 38 | 2D7FCE,Empty4 39 | 2D7FE4,Empty5 40 | 2D7FFA,Empty6 41 | 2D7F10,Empty7 42 | 2D8026,Kefka 43 | 2D803C,Kefka2 44 | 2D8052,Kefka3 45 | -------------------------------------------------------------------------------- /tables/finaldungeoncheckpoints.txt: -------------------------------------------------------------------------------- 1 | !334:0,334:8,334:11|12 2 | # first switch room 3 | 292:0,292:1|2 4 | # Dragons 5 | 335:0|1,354:5|6 6 | $293:0|1,293:2|3,294:0|1 7 | 8 | !293:0|1,293:2|3,294:0|1 9 | # second switch room 10 | 334:5|10,334:3|7 11 | # Inferno and Atma 12 | 410:0|9,331:0 13 | &410:1,4,5,8 14 | -410:2,3,6,7 15 | # there's only 1 entrance on 331, but there's a one-way event to 329 16 | 331:0>>329:1 17 | -329:0 18 | -338:4 19 | # Weight rooms 20 | $337:0,337:7,337:8 21 | &355:4,6 22 | &337:1,2,4,6 23 | 24 | !337:3,337:5,355:7 25 | # Guardian 26 | 291:4>5 27 | # Three Statues 28 | 355:0>8,354:4>7,334:13>14 29 | # dummied stairs 30 | 267:0|1 31 | # Last rooms 32 | $412:0,411:0,411:2 33 | -411:1 34 | 35 | # various other removals 36 | -20:15 37 | -32:15 38 | -38:2 39 | -50:2 40 | -126:2 41 | -287:2 42 | -------------------------------------------------------------------------------- /tables/ancientcheckpoints.txt: -------------------------------------------------------------------------------- 1 | !334:0,334:8,334:11|12 2 | R1 3 | # first switch room 4 | 292:0,292:1|2 5 | $293:0|1,293:2|3,294:0|1 6 | 7 | !293:0|1,293:2|3,294:0|1 8 | R2 9 | # second switch room 10 | 334:5|10,334:3|7 11 | $339:2|3,339:0|1,295:0|1 12 | 13 | !339:2|3,339:0|1,295:0|1 14 | R3 15 | # Gold Dragon and Atma 16 | 335:0|1,331:0 17 | # there's only 1 entrance on 331, but there's a one-way event to 329 18 | 331:0>>329:1 19 | -329:0 20 | -338:4 21 | # Weight rooms 22 | $337:0,337:7,337:8 23 | &355:4,6 24 | &337:1,2,4,6 25 | 26 | !337:3,337:5,355:7 27 | R4 28 | # Inferno and Guardian and Skull Dragon 29 | 410:0|9,291:4>5,354:5|6 30 | &410:1,4,5,8 31 | -410:2,3,6,7 32 | $354:0|1,354:2|3,334:1|2 33 | 34 | !354:0|1,354:2|3,334:1|2 35 | # Three Statues 36 | 355:0>8,354:4>7,334:13>14 37 | # dummied stairs 38 | 267:0|1 39 | # Last rooms 40 | $412:0,411:0,411:2 41 | -411:1 42 | 43 | # various other removals 44 | -20:15 45 | -32:15 46 | -38:2 47 | -50:2 48 | -126:2 49 | -287:2 50 | -------------------------------------------------------------------------------- /devtools/dump_spellsets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Usage: dump_spellsets.py 4 | 5 | Dump the spellsets that skillrandomizer uses for generating new PC commands 6 | (R-Nuke, 3xBeast, W-Sword, etc.) 7 | """ 8 | 9 | import os 10 | import sys 11 | import textwrap 12 | sys.path.append(os.path.dirname(os.path.dirname(__file__))) 13 | 14 | from skillrandomizer import SpellBlock, get_spellsets, spelldict 15 | 16 | sourcefile = sys.argv[1] 17 | 18 | print("Loading skills from '{0}'".format(sourcefile)) 19 | 20 | all_spells = [SpellBlock(i, sourcefile) for i in xrange(0xFF)] 21 | 22 | for s in all_spells: 23 | spelldict[s.spellid] = s 24 | 25 | spellsets = get_spellsets(all_spells) 26 | 27 | for name in sorted(spellsets.keys()): 28 | desc, spells = spellsets[name] 29 | print("\n\n{0}\n==========".format(name)) 30 | print("Set members are described as '{0}'".format(desc)) 31 | print(textwrap.fill("".join("{0:13}".format(s.name) for s in spells), 76)) 32 | -------------------------------------------------------------------------------- /tables/locationformations.txt: -------------------------------------------------------------------------------- 1 | narshe mines wob,39,3a,79 2 | south figaro cave 1,3b,3c 3 | mt koltz,3f 4 | mt koltz outdoors,3d,3e,40 5 | south figaro,41 6 | phantom forest,43,44,45 7 | phantom train,46,47,48,4a,4b 8 | phantom train outdoors,4c 9 | zozo,4e 10 | zozo indoors,4d 11 | magitek facility,50,51,68,69,6a,6b 12 | magitek facility outdoors,6c 13 | sealed gate,49,5c,5d,5e,5f 14 | esper caves,5a,5b,60,61,62 15 | esper caves outdoors,59 16 | floating continent,70,71,72,73,74,7b 17 | south figaro cave 2,7a 18 | collapsing house,80 19 | veldt cave,84 20 | south figaro cave 3,89,8a 21 | figaro castle basement,8b,8c 22 | ancient castle,90,91 23 | cave to ancient castle,8f 24 | daryl's tomb,95,96,97 25 | fanatics tower,98,99,9a,9b 26 | fanatics tower indoors,9c,9f 27 | owzer's mansion,9d,9e 28 | mt zozo,a0 29 | mt zozo outdoors,a1,a2 30 | yeti's cave,a6,a7,a8 31 | gogo's domain,aa,ab,ac 32 | phoenix cave,ae,af,b0,b1 33 | cyan's dream,b5,b6,b7,b8 34 | narshe wor,bd 35 | narshe mines wor,be,bf 36 | ebot's rock,c1,c2,c3 37 | kefka's tower,c5,c6,c7,c8,c9,ca,cb,cd,ce,cf,d0,d1,d5,d6,d9,de,e1 38 | kefka's tower indoors,d2,d3,d4,d7,d8,da,db,dc,dd,df,e0,e2,e3 39 | -------------------------------------------------------------------------------- /tables/finalai.txt: -------------------------------------------------------------------------------- 1 | ! KEFKA 1 2 | # opening dialogue 3 | fc 15 24 0 4 | f7 20 5 | f9 1 24 0 6 | fe 7 | # basic loop 8 | f1 43 9 | c0 10 | fd 11 | f1 47 12 | f0 ee d2 ef 13 | fd 14 | f0 9 a ef 15 | fd 16 | f0 a b ef 17 | fd 18 | f0 b 9 ef 19 | ff 20 | 21 | # replace with KEFKA 2 22 | fc 12 0 0 23 | f5 3 3 0 24 | f2 0 ff 81 25 | f5 5 0 0 26 | f1 43 27 | f0 d1 d2 d2 28 | f0 d1 c0 c0 29 | ff 30 | 31 | ! KEFKA 2 32 | # use Goner when below 15360 HP 33 | fc 6 36 78 34 | fc 15 0 1 35 | f3 8c 0 36 | f9 1 0 0 37 | fa a 1 0 38 | fd 39 | f1 43 40 | de 41 | # extra attack 42 | f0 de ef d1 43 | fd 44 | # followed by Meteor 45 | f1 43 46 | 13 47 | f9 2 0 0 48 | fe 49 | 50 | # use goner at any HP 51 | f3 8c 0 52 | f9 1 0 0 53 | f9 1 0 1 54 | fa a 1 0 55 | fd 56 | f1 43 57 | de 58 | # extra attack 59 | f0 de ef c0 60 | fd 61 | f9 2 0 0 62 | f9 2 0 1 63 | f1 43 64 | # followed by various attacks 65 | f0 ef d2 e0 66 | f0 ef c0 fe 67 | fd 68 | f1 43 69 | f0 d2 ef e0 70 | f0 ef ef fe 71 | ff 72 | 73 | # death animation 74 | fc 12 0 0 75 | fa d 1 0 76 | f5 11 1 ff 77 | fe 78 | 79 | # counterattack with ultima below 20480 HP 80 | fc 6 36 a0 81 | fc 15 0 0 82 | fc 5 0 0 83 | f1 43 84 | f0 ef ee 14 85 | fe 86 | 87 | # counterattack with hyperdrive at any HP 88 | fc 15 0 0 89 | fc 5 0 0 90 | f1 45 91 | f0 fe ee d1 92 | ff 93 | -------------------------------------------------------------------------------- /tables/commandcodes.txt: -------------------------------------------------------------------------------- 1 | 219C7,215C8,21676,17CE9,18cea0,Fight,enemy 2 | 219C9,21897,21907,17CEB,18cea7,Item,self 3 | 219CB,21741,2177D,17CED,18ceae,Magic,self 4 | 219CD,21936,2194C,17CEF,18ceb5,Morph,self 5 | 219CF,21927,21936,17CF1,18cebc,Revert,self 6 | 219D1,21591,2159D,17CF3,18cec3,Steal,enemy 7 | 219D3,21610,21676,17CF5,18ceca,Capture,enemy 8 | 219D5,21847,21885,17CF7,18ced1,Swdtech,self 9 | 219D7,2188D,21897,17CF9,18ced8,Throw,self 10 | 219D9,21885,2188D,17CFB,18cedf,Tools,self 11 | 219DB,2159D,215C8,17CFD,18cee6,Blitz,self 12 | 219DD,2195B,2196A,17CFF,18ceed,Runic,self 13 | 219DF,2175F,2177D,17D01,18cef4,Lore,self 14 | 219E1,2151F,21560,17D03,18cefb,Sketch,enemy 15 | 219E3,21976,2199D,17D05,18cf02,Control,enemy 16 | 219E5,21726,2177D,17D07,18cf09,Slot,self 17 | 219E7,21560,21591,17D09,18cf10,Rage,self 18 | 219E9,2199D,219B2,17D0B,18cf17,Leap,self 19 | 219EB,2151E,2151F,17D0D,18cf1e,Mimic,self 20 | 219ED,2177D,217E5,17D0F,18cf25,Dance,self 21 | 219EF,2194C,2195B,17D11,18cf2c,Row,self 22 | 219F1,2196A,21976,17D13,18cf33,Def,self 23 | 219F3,217F6,21847,17D15,18cf3a,Jump,enemy 24 | 219F5,21741,2177D,17D17,18cf41,XMagic,randally 25 | 219F7,21907,21927,17D19,18cf48,GPRain,enemies 26 | 219F9,21763,2177D,17D1B,18cf4f,Summon,self 27 | 219FB,2171E,21726,17D1D,18cf56,Health,allies 28 | 219FD,2171A,21726,17D1F,18cf5d,Shock,enemies 29 | 219FF,217E5,217F6,17D21,18cf64,Possess,enemy 30 | 21A01,2175F,2177D,17D23,18cf6b,Magitek,self 31 | -------------------------------------------------------------------------------- /tables/worstartingitems.txt: -------------------------------------------------------------------------------- 1 | 1,1 2 | 3,1 3 | a,1 4 | b,1 5 | c,1 6 | 10,1 7 | 1d,1 8 | 1e,1 9 | 1f,1 10 | 25,1 11 | 26,1 12 | 27,1 13 | 28,1 14 | 2b,4 15 | 2c,1 16 | 2d,1 17 | 2e,1 18 | 34,1 19 | 35,1 20 | 36,1 21 | 37,1 22 | 38,1 23 | 3d,1 24 | 3e,1 25 | 41,50 26 | 42,3 27 | 44,1 28 | 45,1 29 | 49,1 30 | 4d,1 31 | 4e,1 32 | 51,1 33 | 53,1 34 | 54,1 35 | 55,1 36 | 5a,2 37 | 5b,2 38 | 5c,2 39 | 5d,2 40 | 5f,1 41 | 69,2 42 | 6a,2 43 | 6b,2 44 | 6c,2 45 | 6d,2 46 | 6e,2 47 | 6f,2 48 | 71,1 49 | 72,1 50 | 73,2 51 | 74,2 52 | 75,2 53 | 76,2 54 | 77,2 55 | 79,2 56 | 7c,1 57 | 84,2 58 | 85,2 59 | 86,2 60 | 87,2 61 | 88,2 62 | 89,2 63 | 8a,2 64 | 8b,2 65 | 8c,2 66 | 8d,2 67 | 8f,2 68 | 90,1 69 | 92,1 70 | 95,1 71 | a3,5 72 | a4,5 73 | a5,5 74 | a6,1 75 | a8,2 76 | aa,7 77 | ab,10 78 | ac,10 79 | ad,10 80 | ae,10 81 | af,10 82 | b0,2 83 | b1,2 84 | b2,2 85 | b3,1 86 | b4,1 87 | b5,1 88 | b6,2 89 | b7,2 90 | b8,2 91 | b9,1 92 | ba,1 93 | bb,4 94 | bc,1 95 | bd,1 96 | be,2 97 | bf,1 98 | c0,1 99 | c3,2 100 | c4,1 101 | c7,1 102 | cd,1 103 | d1,1 104 | d2,2 105 | d4,2 106 | d5,1 107 | db,1 108 | df,1 109 | e1,1 110 | e2,1 111 | e3,2 112 | e5,2 113 | e6,5 114 | e8,40 115 | e9,40 116 | ea,1 117 | eb,6 118 | ec,1 119 | ed,1 120 | ee,1 121 | f0,30 122 | f1,10 123 | f2,5 124 | f3,5 125 | f4,5 126 | f5,1 127 | f6,4 128 | f7,5 129 | f8,5 130 | f9,1 131 | fb,5 132 | fc,5 133 | fd,3 134 | fe,40 135 | -------------------------------------------------------------------------------- /tables/spellbans.txt: -------------------------------------------------------------------------------- 1 | 00,5,Fire,noban 2 | 01,5,Ice,noban 3 | 02,5,Bolt,noban 4 | 12,100,X-Zone,noban 5 | 1F,20,Haste,noban 6 | 24,20,Rflect,noban 7 | 26,20,Vanish,noban 8 | 27,50,Haste 2,noban 9 | 28,35,Slow 2,noban 10 | 2A,10,Warp,noban 11 | 2B,200,Quick,noban 12 | 2D,3,Cure,noban 13 | 2E,10,Cure 2,noban 14 | 2F,25,Cure 3,noban 15 | 30,25,Life,noban 16 | 31,100,Life 2,noban 17 | 32,2,Antdot,noban 18 | 33,20,Remedy,noban 19 | 35,100,Life 3,noban 20 | 3F,300,Palidor,noban 21 | 41,150,Odin,noban 22 | 42,200,Raiden,noban 23 | 46,100,Ragnarok,noban 24 | 4C,80,Golem,noban 25 | 4E,80,Fenrir,noban 26 | 50,75,Phoenix,noban 27 | 5C,150,Cleave,noban 28 | 8C,10,Roulette,noban 29 | 90,65,Blow Fish,noban 30 | 91,50,Big Guard,noban 31 | 93,75,Pearl Wind,noban 32 | 9A,100,ForceField,noban 33 | 9D,1,Pep Up,ban 34 | A4,1,Clear,ban 35 | A6,1,ChokeSmoke,ban 36 | AF,100,Delta Hit,noban 37 | C0,500,Fallen One,ban 38 | C1,100,WallChange,noban 39 | C2,1000,Escape,ban 40 | C3,1,50 Gs,ban 41 | C5,500,N. Cross,ban 42 | C7,50,Love Token,noban 43 | C8,1,Seize,ban 44 | C9,40,R.Polarity,noban 45 | CA,1,Targetting,ban 46 | CB,1000,Sneeze,ban 47 | CE,500,Charm,ban 48 | CF,500,Cold Dust,ban 49 | D5,5000,Engulf,ban 50 | D8,1,Bomblet,ban 51 | DA,1,Zinger,ban 52 | DB,1,Discard,ban 53 | DC,50,Overcast,noban 54 | E5,100,Soul Out,noban 55 | EA,1000,BabaBreath,ban 56 | EE,3,Battle,ban 57 | EF,5,Special,ban 58 | F7,100,Sabre Soul,noban 59 | F8,100,Star Prism,noban 60 | FC,150,Takedown,noban 61 | FD,150,Wild Fang,noban 62 | FE,1,Lagomorph,noban 63 | -------------------------------------------------------------------------------- /tables/locationmaps.txt: -------------------------------------------------------------------------------- 1 | Albrook (WoB):323,326,327,330,332 2 | Albrook (WoR):324 3 | Ancient Castle:401,406,407,408 4 | Cave on the Veldt:353 5 | Collapsing House:311 6 | Cyan's Dream:125,126,143,144,317,319,320,321,322 7 | Doma Castle:123,124 8 | Daryl's Tomb:298,299,300 9 | Esper Mountain:372,373,374,375 10 | Fanatics Tower:359,360,361,363,364,365,366,367,368,369,370 11 | Figaro Castle Basement:62,63,64,65,66 12 | Figaro Castle:59 13 | Final Dungeon:287,291,292,293,294,295,296,303,304,329,331,334,335,338,339,352,354,355,409,410 14 | Floating Continent:393,394+ 15 | Hidon's Cave:404,405 16 | House at Dragon's Neck:186 17 | Imperial Base:378 18 | Imperial Camp:117 19 | Kohlingen:195,197 20 | Magitek Facility:262,263,264,269,271,273 21 | Maranda:284 22 | Mobliz (WoB):163 23 | Mobliz (WoR):150,158 24 | Mt. Koltz:96,97,98,100,101,102 25 | Mt. Zozo:176,177,178,179,180 26 | Narshe (WoB):20,30,41,42,48,50,52,105,106,107 27 | Narshe (WoR):32,33,34,35,36,37,38,44 28 | Nikeah:171 29 | Owzer's Mansion:207,209 30 | Phantom Forest:130,132,133,134,135 31 | Phantom Train:141,142,145,146,147,149,151,152,153 32 | Phoenix Cave:313,315 33 | Returner's Hideout:109,110 34 | Sabin's House:94 35 | Sealed Gate:382,383,384,385,386 36 | Serpent Trench:175 37 | South Figaro Basement:84,86,87,89 38 | South Figaro Cave (WoB):69,70,72,73 39 | South Figaro Cave (WoR):53,68,90,92 40 | South Figaro (WoB):75 41 | South Figaro (WoR):74 42 | Thamasa:343,349,351 43 | Vector:240,250,252 44 | Yeti's Lair:281,282,283 45 | Zone Eater's Belly:276,277,278,280 46 | Zozo:221,225,226 47 | Bad:380 48 | -------------------------------------------------------------------------------- /tables/shopcodes.txt: -------------------------------------------------------------------------------- 1 | Narshe (Unused) 2 | Narshe (Unused) 3 | Narshe (Unused) 4 | Narshe (Unused) 5 | Figaro Castle (WoB) 6 | South Figaro (WoB) 7 | South Figaro (WoB) 8 | South Figaro (WoB) 9 | South Figaro (WoB) 10 | Mobliz 11 | Mobliz 12 | Mobliz 13 | Mobliz 14 | Nikeah (WoB) 15 | Nikeah (WoB) 16 | Nikeah (WoB) 17 | Nikeah (WoB) 18 | Kohlingen (WoB) 19 | Kohlingen (WoB) 20 | Kohlingen (WoB) 21 | Jidoor (WoB) 22 | Jidoor (WoB) 23 | Jidoor (WoB) 24 | Jidoor (WoB) 25 | Albrook (WoB) 26 | Albrook (WoB) 27 | Albrook (WoB) 28 | Vector 29 | Vector 30 | Tzen (WoB) 31 | Tzen (WoB) 32 | Tzen (WoB) 33 | Tzen (WoB) 34 | Thamasa (WoB) 35 | Thamasa (WoB) 36 | Thamasa (WoB) 37 | Returner's Hideout 38 | Maranda (WoB) 39 | Maranda (WoB) 40 | Chocobo Merchant 41 | Albrook (WoB) 42 | Narshe 43 | Narshe 44 | Narshe 45 | Narshe 46 | Thamasa (WoB) 47 | Blackjack 48 | Figaro Castle (WoB) - After Narshe Battle 49 | Albrook (WoR) 50 | Albrook (WoR) 51 | Albrook (WoR) 52 | Albrook (WoR) 53 | Tzen (WoR) 54 | Tzen (WoR) 55 | Tzen (WoR) 56 | Tzen (WoR) 57 | Nikeah (WoR) 58 | Nikeah (WoR) 59 | Nikeah (WoR) 60 | Nikeah (WoR) 61 | South Figaro (WoR) 62 | South Figaro (WoR) 63 | South Figaro (WoR) 64 | South Figaro (WoR) 65 | Figaro Castle (WoR) 66 | Kohlingen (WoR) 67 | Kohlingen (WoR) 68 | Kohlingen (WoR) 69 | Unused 70 | Unused 71 | Unused 72 | Unused 73 | Thamasa (WoR) 74 | Thamasa (WoR) 75 | Thamasa (WoR) 76 | Thamasa (WoR) 77 | Jidoor (WoR) 78 | Jidoor (WoR) 79 | Jidoor (WoR) 80 | Jidoor (WoR) 81 | Maranda (WoR) 82 | Maranda (WoR) 83 | Figaro Castle (WoB) 84 | Figaro Castle (WoB) - After Narshe Battle 85 | Figaro Castle (WoR) 86 | Phantom Train 87 | -------------------------------------------------------------------------------- /tables/femalenames.txt: -------------------------------------------------------------------------------- 1 | Casca 2 | Yanagi 3 | Fuuko 4 | Kaoru 5 | Kage 6 | Megumi 7 | Ryoko 8 | Ayeka 9 | Sasami 10 | Miho 11 | Washu 12 | Kiyone 13 | Faye 14 | Julia 15 | Meryl 16 | Milly 17 | Rem 18 | Dejiko 19 | Pchiko 20 | RaRose 21 | Excel 22 | Hyatt 23 | Mince 24 | Yuuki 25 | Motoko 26 | Lina 27 | Luna 28 | Amelia 29 | Naga 30 | Lime 31 | Cherry 32 | Berry 33 | Serena 34 | Usagi 35 | Iria 36 | Fred 37 | Ranma 38 | Akane 39 | Nabiki 40 | Kasumi 41 | Xianpu 42 | Ukyo 43 | Rei 44 | Asuka 45 | Misato 46 | Maya 47 | Yui 48 | Hikari 49 | Misa 50 | Saber 51 | Rin 52 | Sakura 53 | Ilya 54 | Rider 55 | Caster 56 | Haruhi 57 | Yuki 58 | Mikuru 59 | Yin 60 | Suou 61 | Yoko 62 | Nia 63 | Adiane 64 | Taiga 65 | Minori 66 | Ami 67 | Fumi 68 | Akira 69 | Saki 70 | Juiz 71 | Nodoka 72 | Hisa 73 | Mako 74 | Shizu 75 | Touka 76 | Koromo 77 | Momoko 78 | Teru 79 | Toki 80 | Eva 81 | Rosa 82 | Kyrie 83 | Shanon 84 | Jessie 85 | Ange 86 | Beato 87 | Berne 88 | Lambda 89 | Erika 90 | Iris 91 | Haruko 92 | Mamimi 93 | Eri 94 | Naru 95 | Anzu 96 | Seras 97 | Chi 98 | Winry 99 | Izumi 100 | Riza 101 | Saya 102 | Ohno 103 | Ogiue 104 | Sue 105 | Hato 106 | Misaki 107 | Hitomi 108 | Relena 109 | Une 110 | Dorthy 111 | Rinko 112 | Bulma 113 | ChiChi 114 | Lunch 115 | Videl 116 | Lisa 117 | Yua 118 | Koharu 119 | Hina 120 | Aoi 121 | Mobuko 122 | Akiko 123 | Hilda 124 | Jill 125 | Salia 126 | Salako 127 | Haruka 128 | Hazuki 129 | Madoka 130 | Homura 131 | Sayaka 132 | Mami 133 | Kyouko 134 | Ema 135 | Sizuka 136 | Midori 137 | Mimi 138 | Kurisu 139 | Mayuri 140 | Yuzuki 141 | Miki 142 | Miko 143 | Silene 144 | Kaguya 145 | Karen 146 | Riku 147 | Mitty 148 | Nanaci 149 | Belfy 150 | Popuko 151 | Pipimi 152 | Yuu 153 | Touko 154 | Marcil 155 | Mai 156 | -------------------------------------------------------------------------------- /tables/malenames.txt: -------------------------------------------------------------------------------- 1 | Guts 2 | Griff 3 | Recca 4 | Domon 5 | Tokiya 6 | Kaoru 7 | Kurei 8 | Kensin 9 | Tenchi 10 | Spike 11 | Jet 12 | Vash 13 | Wolf 14 | Legato 15 | Knives 16 | Gema 17 | Palazo 18 | Batou 19 | Togusa 20 | Gourry 21 | Zel 22 | Xellos 23 | Otaru 24 | Rein 25 | Yang 26 | Julian 27 | Dusty 28 | Walter 29 | Poplin 30 | Adrian 31 | Ranma 32 | Genma 33 | Soun 34 | Ryoga 35 | Mousse 36 | Kuno 37 | Shinji 38 | Toji 39 | Kaworu 40 | Gendo 41 | Kaji 42 | Light 43 | L 44 | Shirou 45 | Kirei 46 | Archer 47 | Lancer 48 | Rider 49 | Zerker 50 | Caster 51 | Gilga 52 | Hassan 53 | Kyon 54 | Itsuki 55 | Hei 56 | BK-201 57 | Wei 58 | Kaiji 59 | Sahara 60 | Simon 61 | Kamina 62 | Viral 63 | Genome 64 | Ryuuji 65 | Akira 66 | Johnny 67 | Batora 68 | George 69 | Kinzo 70 | Krauss 71 | Rudolf 72 | Kanon 73 | Ronove 74 | Waver 75 | Naota 76 | Canti 77 | Kei 78 | Yugi 79 | Bakura 80 | Kaiba 81 | Hideki 82 | Edward 83 | Al 84 | Roy 85 | Scar 86 | Hughes 87 | Strong 88 | Sasara 89 | Kosaka 90 | Madara 91 | Tanaka 92 | Hato 93 | Satou 94 | Hiiro 95 | Duo 96 | Trowa 97 | Quatre 98 | WuFei 99 | Zechs 100 | Treize 101 | Takeo 102 | Suna 103 | Goku 104 | Kame 105 | Yamcha 106 | Krilin 107 | Tensin 108 | Picolo 109 | Gohan 110 | Vegeta 111 | Freeza 112 | Trunks 113 | Cell 114 | Buu 115 | Oolong 116 | Goten 117 | Ginyu 118 | Nappa 119 | Jon 120 | Dio 121 | Zepeli 122 | Swagon 123 | Joseph 124 | Caesar 125 | Rudol 126 | Kars 127 | Wham 128 | ACDC 129 | Jotaro 130 | Avdol 131 | Kakoin 132 | Jean 133 | Iggy 134 | Hol 135 | Tusk 136 | Embryo 137 | Tadaya 138 | Keizou 139 | Kyubey 140 | Seichi 141 | Maeno 142 | Okabe 143 | Itaru 144 | Nozaki 145 | Amon 146 | Ryou 147 | Ketaro 148 | Miyuki 149 | Keita 150 | Reg 151 | Nanaci 152 | Lilbit 153 | Napo 154 | Laios 155 | Senshi 156 | Tiltak 157 | Kouta 158 | Kaito 159 | Micchi 160 | Ryoma 161 | Eiji 162 | Ankh 163 | Genta 164 | -------------------------------------------------------------------------------- /tables/mapbattlebgs.txt: -------------------------------------------------------------------------------- 1 | 6 30 2 | 7 2b 3 | 8 2b 4 | 10 30 5 | 11 29 6 | 12 2b 7 | 13 30 8 | 14 1e 9 | 15 1e 10 | 16 1e 11 | 17 29 12 | 18 12 13 | 24 2b 14 | 25 2b 15 | 26 2b 16 | 27 2b 17 | 28 2b 18 | 29 2b 19 | 30 2b 20 | 31 2b 21 | 40 11 22 | 43 11 23 | 44 a 24 | 47 13 25 | 52 a 26 | 54 2 27 | 55 2 28 | 56 2 29 | 57 1a 30 | 58 1a 31 | 59 1a 32 | 60 1a 33 | 61 1a 34 | 65 1a 35 | 66 1a 36 | 67 2 37 | 71 b 38 | 74 13 39 | 75 13 40 | 76 2b 41 | 77 2b 42 | 78 2b 43 | 79 2b 44 | 80 2b 45 | 81 2b 46 | 82 2b 47 | 83 2b 48 | 84 2b 49 | 85 2b 50 | 86 2b 51 | 88 2b 52 | 89 1a 53 | 91 13 54 | 93 1e 55 | 94 1e 56 | 95 b 57 | 108 b 58 | 109 a 59 | 110 a 60 | 111 a 61 | 112 a 62 | 115 1e 63 | 116 1e 64 | 122 13 65 | 123 1a 66 | 124 1a 67 | 127 1e 68 | 128 1e 69 | 129 b 70 | 131 1e 71 | 136 b 72 | 137 21 73 | 138 21 74 | 139 21 75 | 140 21 76 | 146 10 77 | 147 10 78 | 148 1e 79 | 150 a 80 | 154 a 81 | 155 c 82 | 157 1e 83 | 158 5 84 | 159 1e 85 | 160 1e 86 | 161 1e 87 | 162 1e 88 | 163 1e 89 | 164 1e 90 | 165 1e 91 | 166 b 92 | 168 b 93 | 169 13 94 | 170 1e 95 | 171 2b 96 | 172 2b 97 | 173 2b 98 | 181 b 99 | 182 1e 100 | 183 a 101 | 184 1e 102 | 185 1e 103 | 186 1e 104 | 187 13 105 | 188 1e 106 | 189 1e 107 | 191 1e 108 | 192 1e 109 | 193 1e 110 | 194 1e 111 | 195 1e 112 | 196 1e 113 | 197 1e 114 | 198 13 115 | 200 2b 116 | 201 2b 117 | 202 2b 118 | 203 2b 119 | 204 2b 120 | 205 2b 121 | 206 2b 122 | 208 2b 123 | 211 12 124 | 215 30 125 | 217 1e 126 | 219 a 127 | 220 13 128 | 226 4 129 | 232 1a 130 | 238 1a 131 | 256 16 132 | 259 16 133 | 261 16 134 | 284 13 135 | 288 2b 136 | 289 2b 137 | 290 2b 138 | 297 1e 139 | 302 1e 140 | 305 13 141 | 306 13 142 | 307 2b 143 | 308 2b 144 | 309 2b 145 | 310 2b 146 | 312 2b 147 | 318 b 148 | 323 13 149 | 324 13 150 | 325 2b 151 | 326 2b 152 | 327 2b 153 | 328 2b 154 | 330 2b 155 | 332 13 156 | 340 1e 157 | 342 1e 158 | 343 1e 159 | 344 1e 160 | 345 1e 161 | 346 1e 162 | 347 1e 163 | 348 1e 164 | 349 1e 165 | 350 1e 166 | 389 1e 167 | 390 b 168 | 392 13 169 | 395 1e 170 | 396 1e 171 | 397 1e 172 | 398 2f 173 | 399 b 174 | 400 2f 175 | 402 a 176 | 403 2f 177 | 411 16 178 | 413 1a 179 | 414 1e 180 | -------------------------------------------------------------------------------- /tables/usedlocs.txt: -------------------------------------------------------------------------------- 1 | 000 2 | 001 3 | 002 4 | 003 5 | 004 6 | 005 7 | 006 8 | 007 9 | 008 10 | 009 11 | 00A 12 | 00B 13 | 00D 14 | 00E 15 | 00F 16 | 010 17 | 011 18 | 012 19 | 013 20 | 014 21 | 015 22 | 016 23 | 017 24 | 01C 25 | 01E 26 | 020 27 | 021 28 | 022 29 | 023 30 | 027 31 | 029 32 | 02A 33 | 02F 34 | 031 35 | 033 36 | 035 37 | 036 38 | 037 39 | 038 40 | 039 41 | 03A 42 | 03B 43 | 03C 44 | 03D 45 | 043 46 | 045 47 | 046 48 | 048 49 | 049 50 | 04A 51 | 04B 52 | 04C 53 | 050 54 | 053 55 | 056 56 | 05B 57 | 05D 58 | 064 59 | 06D 60 | 06E 61 | 06F 62 | 070 63 | 071 64 | 072 65 | 073 66 | 074 67 | 075 68 | 077 69 | 078 70 | 079 71 | 07B 72 | 07E 73 | 081 74 | 082 75 | 083 76 | 087 77 | 088 78 | 089 79 | 08A 80 | 08B 81 | 08D 82 | 08E 83 | 08F 84 | 091 85 | 092 86 | 094 87 | 095 88 | 096 89 | 097 90 | 099 91 | 09A 92 | 09B 93 | 09C 94 | 09D 95 | 09E 96 | 09F 97 | 0A0 98 | 0A8 99 | 0A9 100 | 0AA 101 | 0AB 102 | 0AD 103 | 0AE 104 | 0AF 105 | 0B4 106 | 0B5 107 | 0B6 108 | 0B7 109 | 0B8 110 | 0BB 111 | 0BC 112 | 0BD 113 | 0BE 114 | 0BF 115 | 0C3 116 | 0C5 117 | 0C6 118 | 0C9 119 | 0CD 120 | 0CE 121 | 0CF 122 | 0D1 123 | 0D2 124 | 0D3 125 | 0D4 126 | 0D5 127 | 0D6 128 | 0D7 129 | 0D8 130 | 0D9 131 | 0DA 132 | 0DB 133 | 0DD 134 | 0E2 135 | 0E7 136 | 0E8 137 | 0E9 138 | 0EA 139 | 0EB 140 | 0EC 141 | 0ED 142 | 0EE 143 | 0EF 144 | 0F0 145 | 0F1 146 | 0F2 147 | 0F3 148 | 0F4 149 | 0FA 150 | 0FB 151 | 0FD 152 | 0FE 153 | 0FF 154 | 100 155 | 102 156 | 103 157 | 104 158 | 105 159 | 107 160 | 108 161 | 10A 162 | 10C 163 | 110 164 | 114 165 | 115 166 | 117 167 | 119 168 | 11B 169 | 11C 170 | 11D 171 | 120 172 | 12C 173 | 12D 174 | 12E 175 | 131 176 | 132 177 | 134 178 | 139 179 | 13B 180 | 13D 181 | 13E 182 | 140 183 | 143 184 | 144 185 | 145 186 | 149 187 | 14A 188 | 14C 189 | 14E 190 | 150 191 | 151 192 | 154 193 | 155 194 | 157 195 | 158 196 | 15A 197 | 15D 198 | 15F 199 | 164 200 | 165 201 | 166 202 | 16A 203 | 16C 204 | 173 205 | 177 206 | 178 207 | 179 208 | 17C 209 | 17D 210 | 17E 211 | 180 212 | 185 213 | 186 214 | 187 215 | 188 216 | 189 217 | 18A 218 | 18B 219 | 18C 220 | 18D 221 | 18E 222 | 18F 223 | 190 224 | 191 225 | 194 226 | 195 227 | 196 228 | 197 229 | 19A 230 | 19B 231 | 19D 232 | 1FE 233 | 1FF 234 | -------------------------------------------------------------------------------- /unittests.sh: -------------------------------------------------------------------------------- 1 | #TIME=`date +%s` 2 | TIME=1426615861 3 | rm program.*.rom 4 | rm program.*.txt 5 | set -e 6 | yes | python randomizer.py program.rom .owzbmciqetulnfspdah.$TIME test 7 | yes | python randomizer.py program.rom .wzbmciqetulnfspdah.$TIME test 8 | yes | python randomizer.py program.rom .ozbmciqetulnfspdah.$TIME test 9 | yes | python randomizer.py program.rom .owbmciqetulnfspdah.$TIME test 10 | yes | python randomizer.py program.rom .owzmciqetulnfspdah.$TIME test 11 | yes | python randomizer.py program.rom .owzbciqetulnfspdah.$TIME test 12 | yes | python randomizer.py program.rom .owzbmiqetulnfspdah.$TIME test 13 | yes | python randomizer.py program.rom .owzbmcqetulnfspdah.$TIME test 14 | yes | python randomizer.py program.rom .owzbmcietulnfspdah.$TIME test 15 | yes | python randomizer.py program.rom .owzbmciqtulnfspdah.$TIME test 16 | yes | python randomizer.py program.rom .owzbmciqeulnfspdah.$TIME test 17 | yes | python randomizer.py program.rom .owzbmciqetlnfspdah.$TIME test 18 | yes | python randomizer.py program.rom .owzbmciqetunfspdah.$TIME test 19 | yes | python randomizer.py program.rom .owzbmciqetulfspdah.$TIME test 20 | yes | python randomizer.py program.rom .owzbmciqetulnspdah.$TIME test 21 | yes | python randomizer.py program.rom .owzbmciqetulnfpdah.$TIME test 22 | yes | python randomizer.py program.rom .owzbmciqetulnfsdah.$TIME test 23 | yes | python randomizer.py program.rom .owzbmciqetulnfspah.$TIME test 24 | yes | python randomizer.py program.rom .owzbmciqetulnfspdh.$TIME test 25 | yes | python randomizer.py program.rom .owzbmciqetulnfspda.$TIME test 26 | yes | python randomizer.py program.rom .o.$TIME test 27 | yes | python randomizer.py program.rom .w.$TIME test 28 | yes | python randomizer.py program.rom .z.$TIME test 29 | yes | python randomizer.py program.rom .b.$TIME test 30 | yes | python randomizer.py program.rom .m.$TIME test 31 | yes | python randomizer.py program.rom .c.$TIME test 32 | yes | python randomizer.py program.rom .i.$TIME test 33 | yes | python randomizer.py program.rom .q.$TIME test 34 | yes | python randomizer.py program.rom .e.$TIME test 35 | yes | python randomizer.py program.rom .t.$TIME test 36 | yes | python randomizer.py program.rom .u.$TIME test 37 | yes | python randomizer.py program.rom .l.$TIME test 38 | yes | python randomizer.py program.rom .n.$TIME test 39 | yes | python randomizer.py program.rom .f.$TIME test 40 | yes | python randomizer.py program.rom .s.$TIME test 41 | yes | python randomizer.py program.rom .p.$TIME test 42 | yes | python randomizer.py program.rom .d.$TIME test 43 | yes | python randomizer.py program.rom .a.$TIME test 44 | yes | python randomizer.py program.rom .h.$TIME test 45 | yes | python randomizer.py program.rom ._.$TIME test 46 | echo "TEST RUNS SUCCESSFUL" 47 | rm program.*.rom 48 | rm program.*.txt 49 | -------------------------------------------------------------------------------- /namerandomizer.py: -------------------------------------------------------------------------------- 1 | from utils import (ENEMY_NAMES_TABLE, MODIFIERS_TABLE, MOVES_TABLE, 2 | NAMEGEN_TABLE, utilrandom as random) 3 | 4 | modifiers = [line.strip() for line in open(MODIFIERS_TABLE)] 5 | moves = [line.strip() for line in open(MOVES_TABLE)] 6 | enemynames = [line.strip() for line in open(ENEMY_NAMES_TABLE).readlines()] 7 | 8 | generator = {} 9 | lookback = None 10 | for line in open(NAMEGEN_TABLE): 11 | key, values = tuple(line.strip().split()) 12 | generator[key] = values 13 | if not lookback: 14 | lookback = len(key) 15 | 16 | 17 | def generate_name(size=None, maxsize=10): 18 | if not size: 19 | size = random.randint(1, 5) + random.randint(1, 5) 20 | if size < 4: 21 | size += random.randint(0, 5) 22 | 23 | def has_vowel(text): 24 | for c in text: 25 | if c.lower() in "aeiouy": 26 | return True 27 | return False 28 | 29 | while True: 30 | starts = sorted([s for s in generator if s[0].isupper()]) 31 | name = random.choice(starts) 32 | name = name[:size] 33 | while len(name) < size: 34 | key = name[-lookback:] 35 | if key not in generator and size - len(name) < len(key): 36 | name = random.choice(starts) 37 | continue 38 | if key not in generator or (random.randint(1, 15) == 15 39 | and has_vowel(name[-2:])): 40 | if len(name) <= size - lookback: 41 | if len(name) + len(key) < maxsize: 42 | name += " " 43 | name += random.choice(starts) 44 | continue 45 | else: 46 | name = random.choice(starts) 47 | continue 48 | 49 | c = random.choice(generator[key]) 50 | name = name + c 51 | 52 | for ename in enemynames: 53 | if name == ename: 54 | name = "" 55 | break 56 | 57 | if name: 58 | for ename in enemynames: 59 | if len(name) > (lookback+1): 60 | length = min(len(name), len(ename)) 61 | if name[:length] == ename[:length]: 62 | 63 | name = "" 64 | break 65 | 66 | if len(name) >= size: 67 | enemynames.append(name) 68 | return name 69 | 70 | 71 | def generate_attack(): 72 | if random.randint(1, 7) != 7: 73 | while True: 74 | modifier = random.choice(modifiers) 75 | move = random.choice(moves) 76 | if len(modifier) + len(move) <= 10: 77 | break 78 | else: 79 | modifier = "" 80 | if random.randint(1, 4) != 4: 81 | candidates = list(moves) 82 | else: 83 | candidates = list(modifiers) 84 | candidates = [c for c in candidates if len(c) >= 3] 85 | move = random.choice(candidates) 86 | 87 | if len(modifier) + len(move) < 10: 88 | return ("%s %s" % (modifier, move)).strip() 89 | else: 90 | return modifier + move 91 | 92 | if __name__ == "__main__": 93 | for i in xrange(0x100): 94 | print generate_name() 95 | -------------------------------------------------------------------------------- /tables/wobeventbits.txt: -------------------------------------------------------------------------------- 1 | 001,1 2 | 003,1 3 | 004,1 4 | 005,1 5 | 006,1 6 | 00A,1 7 | 00B,1 8 | 00D,1 9 | 00E,1 10 | 00F,1 11 | 010,1 12 | 011,1 13 | 014,1 14 | 015,1 15 | 016,1 16 | 017,1 17 | 018,1 18 | 019,1 19 | 01A,1 20 | 01B,1 21 | 01C,1 22 | 01D,1 23 | 01E,1 24 | 020,1 25 | 021,1 26 | 02A,1 27 | 02B,1 28 | 02C,1 29 | 02D,1 30 | 02E,1 31 | 02F,1 32 | 030,1 33 | 031,1 34 | 032,1 35 | 033,1 36 | 034,1 37 | 035,1 38 | 036,1 39 | 037,1 40 | 038,1 41 | 039,1 42 | 03A,1 43 | 03B,1 44 | 03C,1 45 | 03F,1 46 | 041,1 47 | 044,1 48 | 045,1 49 | 046,1 50 | 048,1 51 | 053,1 52 | 054,1 53 | 055,1 54 | 056,1 55 | 057,1 56 | 058,1 57 | 059,1 58 | 05A,1 59 | 05C,1 60 | 05D,1 61 | 05E,1 62 | 05F,1 63 | 060,1 64 | 068,1 65 | 069,1 66 | 06A,1 67 | 06B,1 68 | 06C,1 69 | 06E,1 70 | 06F,1 71 | 070,1 72 | 076,1 73 | 079,1 74 | 07A,1 75 | 07B,1 76 | 07C,1 77 | 07D,1 78 | 083,1 79 | 084,1 80 | 085,1 81 | 086,1 82 | 087,1 83 | 089,1 84 | 08D,1 85 | 08E,1 86 | 08F,1 87 | 090,1 88 | 091,1 89 | 092,1 90 | 095,1 91 | 096,1 92 | 097,1 93 | 098,1 94 | 099,1 95 | 09B,1 96 | 09C,1 97 | 09D,1 98 | 09E,1 99 | 0A0,1 100 | 0A4,1 101 | 0AE,1 102 | 0AF,1 103 | 0B0,1 104 | 0B1,1 105 | 0B3,1 106 | 105,1 107 | 107,1 108 | 108,1 109 | 10A,1 110 | 10C,1 111 | 10D,1 112 | 10E,1 113 | 110,1 114 | 111,1 115 | 116,1 116 | 117,1 117 | 118,1 118 | 128,1 119 | 129,1 120 | 12A,1 121 | 12B,1 122 | 12C,1 123 | 12D,1 124 | 12E,1 125 | 12F,1 126 | 130,1 127 | 131,1 128 | 132,1 129 | 133,1 130 | 134,1 131 | 135,1 132 | 13A,1 133 | 13B,1 134 | 13C,1 135 | 151,1 136 | 155,1 137 | 15A,1 138 | 15B,1 139 | 15C,1 140 | 15D,1 141 | 15E,1 142 | 162,1 143 | 167,1 144 | 168,1 145 | 16F,1 146 | 170,1 147 | 172,1 148 | 173,1 149 | 174,1 150 | 175,1 151 | 17F,1 152 | 182,1 153 | 183,1 154 | 18E,1 155 | 192,1 156 | 1D0,1 157 | 1D1,1 158 | 1D2,1 159 | 1E3,1 160 | 238,1 161 | 242,1 162 | 272,1 163 | 274,1 164 | 276,1 165 | 277,1 166 | 278,1 167 | 2B7,1 168 | 2BA,1 169 | 2BD,1 170 | 2D8,1 171 | 2E0,1 172 | 2E1,1 173 | 2E2,1 174 | 2E3,1 175 | 2E4,1 176 | 2E5,1 177 | 2E7,1 178 | 2E8,1 179 | 2E9,1 180 | 2EA,1 181 | 2EB,1 182 | 2FB,1 183 | 303,1 184 | 305,0 185 | 307,0 186 | 308,0 187 | 30C,0 188 | 30D,0 189 | 30E,1 190 | 314,0 191 | 315,0 192 | 316,1 193 | 318,0 194 | 319,0 195 | 31B,0 196 | 31E,0 197 | 332,0 198 | 340,0 199 | 341,0 200 | 342,0 201 | 346,0 202 | 347,0 203 | 348,0 204 | 349,0 205 | 34A,0 206 | 34B,0 207 | 34C,0 208 | 34D,0 209 | 34E,0 210 | 34F,0 211 | 350,0 212 | 355,0 213 | 358,0 214 | 359,0 215 | 367,0 216 | 368,0 217 | 36D,0 218 | 36E,1 219 | 36F,1 220 | 370,0 221 | 371,1 222 | 373,0 223 | 374,1 224 | 379,0 225 | 37A,1 226 | 37E,1 227 | 380,0 228 | 381,0 229 | 382,1 230 | 385,1 231 | 386,1 232 | 387,1 233 | 397,1 234 | 39B,1 235 | 3F4,0 236 | 426,0 237 | 427,0 238 | 492,1 239 | 4F2,0 240 | 501,0 241 | 502,0 242 | 506,0 243 | 507,0 244 | 508,0 245 | 509,0 246 | 511,0 247 | 512,0 248 | 516,0 249 | 518,0 250 | 519,0 251 | 50A,0 252 | 542,0 253 | 55A,0 254 | 564,1 255 | 568,0 256 | 56A,0 257 | 5F7,0 258 | 600,0 259 | 602,0 260 | 603,0 261 | 606,0 262 | 607,0 263 | 615,0 264 | 616,0 265 | 617,0 266 | 618,0 267 | 619,0 268 | 61A,0 269 | 636,0 270 | 637,0 271 | 638,0 272 | 63D,0 273 | 63E,0 274 | 64E,0 275 | 651,0 276 | 652,0 277 | 653,0 278 | 654,0 279 | 65C,0 280 | 65D,0 281 | 65E,1 282 | 661,0 283 | 666,1 284 | 667,0 285 | 67A,0 286 | 67B,1 287 | 67C,1 288 | 67E,1 289 | 67F,1 290 | 688,0 291 | 68B,1 292 | 69A,1 293 | 6AD,1 294 | -------------------------------------------------------------------------------- /tables/enemynames.txt: -------------------------------------------------------------------------------- 1 | 1stClass 2 | Abolisher 3 | Actaneon 4 | Adamanchyt 5 | AirForce 6 | AlloVer 7 | Allosaurus 8 | Anemone 9 | Anguiform 10 | Apokryphos 11 | Apparite 12 | Aquila 13 | Areneid 14 | Aspik 15 | Atma 16 | AtmaWeapon 17 | BDaySuit 18 | Balloon 19 | Barbe 20 | Baskervor 21 | Beakor 22 | Behemoth 23 | BlackDrgn 24 | Bleary 25 | Bloompire 26 | BlueDrgn 27 | Bogy 28 | Bomb 29 | Borras 30 | BountyMan 31 | BoxedSet 32 | Brachosaur 33 | Brainpan 34 | Brawler 35 | Brontaur 36 | Buffalax 37 | Bug 38 | Cactrot 39 | Cadet 40 | Cephaler 41 | Ceritops 42 | Chadarnook 43 | Chadarnook 44 | ChaosDrgn 45 | Chaser 46 | ChickenLip 47 | Chimera 48 | Chitonid 49 | Chupon 50 | Chupon 51 | Cirpius 52 | Cluck 53 | Coelecite 54 | Colossus 55 | Commander 56 | Commando 57 | Covert 58 | Crane 59 | Crane 60 | CrassHoppr 61 | Crawler 62 | Crawly 63 | Critic 64 | Cruller 65 | Crusher 66 | Curley 67 | CzarDragon 68 | Dadaluma 69 | Dahling 70 | Dante 71 | DarkForce 72 | DarkSide 73 | DarkWind 74 | DeepEye 75 | DeltaBug 76 | Didalos 77 | DirtDrgn 78 | Displayer 79 | Doberman 80 | Doom 81 | DoomDrgn 82 | DoomGaze 83 | Dragon 84 | Drop 85 | Dueller 86 | Dullahan 87 | EarthGuard 88 | Eland 89 | Enuo 90 | EvilOscar 91 | Exocite 92 | Exoray 93 | Face 94 | Fidor 95 | Figaliz 96 | FlameEater 97 | Flan 98 | Fortis 99 | FossilFang 100 | Gabbldegak 101 | Garm 102 | Geckorex 103 | General 104 | Ghost 105 | GhostTrain 106 | GiganToad 107 | Gigantos 108 | Gilomantis 109 | Girl 110 | GloomShell 111 | Gobbler 112 | Goblin 113 | Goddess 114 | GoldBear 115 | GoldDrgn 116 | GreaseMonk 117 | Grenade 118 | Grunt 119 | GtBehemoth 120 | Guard 121 | Guardian 122 | Guardian 123 | HadesGigas 124 | Harpiai 125 | Harpy 126 | Harvester 127 | Hazer 128 | Head 129 | HeavyArmor 130 | Hemophyte 131 | HermitCrab 132 | Hidon 133 | Hidonite 134 | Hidonite 135 | Hidonite 136 | Hidonite 137 | Hipocampus 138 | Hit 139 | Hoover 140 | Hornet 141 | Humpty 142 | IceDragon 143 | Ifrit 144 | Inferno 145 | Ing 146 | Innoc 147 | Insecare 148 | Intangir 149 | Io 150 | Ipooh 151 | IronFist 152 | IronHitman 153 | Joker 154 | Junk 155 | Karkass 156 | KatanaSoul 157 | Kefka 158 | Kefka 159 | Kefka 160 | Kiwok 161 | L10Magic 162 | L20Magic 163 | L30Magic 164 | L40Magic 165 | L50Magic 166 | L60Magic 167 | L70Magic 168 | L80Magic 169 | L90Magic 170 | LandWorm 171 | Larry 172 | LaserGun 173 | Latimeria 174 | Leader 175 | Leafer 176 | LeftBlade 177 | LethalWpn 178 | Lich 179 | Lizard 180 | Lobo 181 | LongArm 182 | Lunaris 183 | Luridan 184 | MTekArmor 185 | MadOscar 186 | Madam 187 | MagRoader 188 | MagRoader 189 | MagRoader 190 | MagRoader 191 | MagiMaster 192 | Magic 193 | MagicUrn 194 | Maliga 195 | Mandrake 196 | Mantodea 197 | Marshal 198 | MasterPug 199 | MegaArmor 200 | Merchant 201 | Mesosaur 202 | MindCandy 203 | Misfit 204 | MissileBay 205 | Moe 206 | Mover 207 | Muus 208 | Nastidon 209 | Naughty 210 | Nautiloid 211 | NeckHunter 212 | Necromancr 213 | Nerapa 214 | Nightshade 215 | Ninja 216 | Nohrabbit 217 | Number024 218 | Number128 219 | Officer 220 | Ogor 221 | Opinicus 222 | Orog 223 | Osprey 224 | Osteosaur 225 | Outsider 226 | OverGrunk 227 | OverMind 228 | PanDora 229 | Parasite 230 | Parasoul 231 | Peepers 232 | Phase 233 | Phunbaba 234 | Phunbaba 235 | Phunbaba 236 | Phunbaba 237 | Pipsqueak 238 | Piranha 239 | PlutoArmor 240 | PmStalker 241 | Poltrgeist 242 | Poplium 243 | Poppers 244 | PowerDemon 245 | Presenter 246 | Primordite 247 | Prometheus 248 | ProtoArmor 249 | Prussian 250 | Psychot 251 | Pterodon 252 | Pug 253 | Pugs 254 | Punisher 255 | RainMan 256 | Ralph 257 | ReachFrog 258 | RedDragon 259 | RedFang 260 | RedWolf 261 | RepoMan 262 | Retainer 263 | Rhinotaur 264 | Rhinox 265 | Rhobite 266 | Rhodox 267 | Rhyos 268 | Rider 269 | RightBlade 270 | Rinn 271 | Rizopas 272 | Rough 273 | Samurai 274 | SandHorse 275 | SandRay 276 | Scorpion 277 | Scrapper 278 | Scullion 279 | SeaFlower 280 | SewerRat 281 | Shiva 282 | ShortArm 283 | Siegfried 284 | Siegfried 285 | SkullDrgn 286 | SkyArmor 287 | SkyBase 288 | SkyCap 289 | SlamDancer 290 | Slatter 291 | Sleep 292 | Slurm 293 | Soldier 294 | Soldier 295 | SoulDancer 296 | SoulSaver 297 | SpForces 298 | Speck 299 | Specter 300 | Spectre 301 | SpekTor 302 | SpitFire 303 | Sprinter 304 | SrBehemoth 305 | SrBehemoth 306 | Steroidite 307 | StillLife 308 | StillGoing 309 | StormDrgn 310 | StrayCat 311 | Striker 312 | Suriander 313 | TapDancer 314 | Telstar 315 | Templar 316 | Tentacle 317 | Tentacle 318 | Tentacle 319 | Tentacle 320 | TestRider 321 | Tiger 322 | ToeCutter 323 | TombThumb 324 | Tools 325 | Trapper 326 | Trilium 327 | Trilobiter 328 | Tritoch 329 | Tritoch 330 | Tritoch 331 | Trixter 332 | Trooper 333 | TumbleWeed 334 | TunnelArmr 335 | Tusker 336 | Tyranosaur 337 | Ultros 338 | Ultros 339 | Ultros 340 | Ultros 341 | Umaro 342 | Umaro 343 | Uroburos 344 | Ursus 345 | Vaporite 346 | Vargas 347 | Vectagoyle 348 | Vectaur 349 | VectorPup 350 | Vermin 351 | Veteran 352 | Vindr 353 | Vomammoth 354 | Vulture 355 | Warlock 356 | WartPuck 357 | WeedFeeder 358 | WereRat 359 | Whelk 360 | WhelkHead 361 | Whisper 362 | WhiteDrgn 363 | WildCat 364 | WildRat 365 | WireyDrgn 366 | Wizard 367 | Woolly 368 | Wrexsoul 369 | Wyvern 370 | Zombone 371 | ZoneEater 372 | -------------------------------------------------------------------------------- /shoprandomizer.py: -------------------------------------------------------------------------------- 1 | from utils import utilrandom as random 2 | from itemrandomizer import get_ranked_items, get_item 3 | 4 | # Despite documentation, these are the only pricings available. 5 | # 0 x1 price 6 | # 1 x2 price 7 | # 2 x1.5 price female discount 8 | # 3 x1 price figaro discount 9 | price_multipliers = {0: 1, 10 | 1: 2, 11 | 2: 1.5, 12 | 3: 1} 13 | 14 | 15 | class ShopBlock: 16 | def __init__(self, pointer, name): 17 | #self.pointer = hex2int(pointer) 18 | self.pointer = pointer 19 | self.name = name 20 | 21 | def set_id(self, shopid): 22 | self.shopid = shopid 23 | 24 | def read_data(self, filename): 25 | f = open(filename, 'r+b') 26 | f.seek(self.pointer) 27 | self.misc = ord(f.read(1)) 28 | self.items = map(ord, f.read(8)) 29 | f.close() 30 | 31 | def write_data(self, fout): 32 | fout.seek(self.pointer) 33 | fout.write(chr(self.misc)) 34 | fout.write("".join(map(chr, self.items))) 35 | 36 | def __repr__(self): 37 | multiplier = price_multipliers[self.discount] 38 | s = "%s %s\n" % (self.name, self.shoptype_pretty) 39 | s = s.upper() 40 | if self.discount == 2: 41 | s += "Discounts for female characters.\n" 42 | items = [get_item(i) for i in self.items] 43 | items = [i for i in items if i is not None] 44 | for i in items: 45 | s2 = "{0:13} {1:>5}\n".format(i.name, int(i.price * multiplier)) 46 | s += s2 47 | return s.strip() 48 | 49 | @property 50 | def discount(self): 51 | return (self.misc & 0xF0) >> 4 52 | 53 | @property 54 | def shoptype(self): 55 | return self.misc & 0x0F 56 | 57 | @property 58 | def shoptype_pretty(self): 59 | shoptypes = {1: "weapons", 2: "armor", 3: "items", 60 | 4: "relics", 5: "misc"} 61 | return shoptypes[self.shoptype] 62 | 63 | def mutate_misc(self): 64 | self.misc &= 0x0F 65 | value = random.randint(1, 20) 66 | if value <= 3: 67 | self.misc |= 0x20 68 | elif value <= 9: 69 | self.misc |= 0x10 70 | 71 | for i in self.items: 72 | i = get_item(i) 73 | if i is None: 74 | continue 75 | if i.price * price_multipliers[self.discount] > 65535: 76 | self.misc &= 0x0F 77 | break 78 | 79 | def mutate_items(self, fout): 80 | items = get_ranked_items() 81 | if self.shoptype == 1: 82 | valid_items = [c for c in items if c.is_weapon or c.is_tool] 83 | elif self.shoptype == 2: 84 | valid_items = [c for c in items if c.is_armor] 85 | elif self.shoptype == 3: 86 | valid_items = [c for c in items if not (c.is_weapon or c.is_armor or c.is_relic)] 87 | elif self.shoptype == 4: 88 | valid_items = [c for c in items if c.is_relic] 89 | elif self.shoptype == 5: 90 | valid_items = list(items) 91 | 92 | old_items = [i for i in self.items if i != 0xFF] 93 | if not old_items: 94 | return 95 | old_items = [get_item(i) for i in old_items] 96 | old_items = [i for i in old_items if i] 97 | 98 | if len(old_items) == 0: 99 | average_value = 0 100 | else: 101 | average_value = sum([i.rank() for i in old_items]) / len(old_items) 102 | average_item = len([i for i in valid_items if i.rank() <= average_value]) 103 | average_item += -1 104 | average_item = valid_items[average_item] 105 | 106 | while random.randint(1, 3) == 3 and len(old_items) < 8: 107 | old_items.append(average_item) 108 | new_items = [] 109 | for item in old_items: 110 | if random.randint(1, 10) == 10: 111 | candidates = items 112 | else: 113 | candidates = valid_items 114 | 115 | try: 116 | index = candidates.index(item) 117 | except ValueError: 118 | continue 119 | 120 | while random.randint(1, 3) < 3: 121 | index += random.randint(-2, 2) 122 | index = max(0, min(index, len(candidates)-1)) 123 | new_items.append(candidates[index]) 124 | 125 | if not new_items: 126 | return 127 | 128 | for i in new_items: 129 | if i.price < 3: 130 | price = i.rank() 131 | modifier = price / 2 132 | price += random.randint(0, modifier) 133 | while random.randint(1, 4) < 4: 134 | price += random.randint(0, modifier) 135 | price = min(price, 0xFEFE) 136 | i.price = price 137 | 138 | zerocount = 0 139 | while i.price > 100: 140 | i.price = i.price / 10 141 | zerocount += 1 142 | 143 | while zerocount > 0: 144 | i.price = i.price * 10 145 | zerocount += -1 146 | 147 | i.write_stats(fout) 148 | 149 | self.items = [i.itemid for i in new_items] 150 | self.items = sorted(set(self.items)) 151 | while len(self.items) < 8: 152 | self.items.append(0xFF) 153 | 154 | assert len(self.items) == 8 155 | 156 | def rank(self): 157 | items = [get_item(i) for i in self.items] 158 | items = [i for i in items if i] 159 | priciest = max(items, key=lambda i: i.price) 160 | return priciest.price 161 | -------------------------------------------------------------------------------- /tables/chestcodes.txt: -------------------------------------------------------------------------------- 1 | 2D8634,014,wob 2 | 2D8639,01E,wob 3 | 2D863E,01E,wob 4 | 2D8643,01E,wob 5 | 2D8648,01E,wob 6 | 2D864D,01E,wob 7 | 2D8652,01E,wob 8 | 2D8657,01E,wob 9 | 2D865C,01E,wob 10 | 2D8661,01E,wob 11 | 2D8666,026,wor 12 | 2D866B,026,wor 13 | 2D8670,02C,wor 14 | 2D8675,02C,wor 15 | 2D867A,032,wob 16 | 2D867F,032,wob 17 | 2D8684,034,wob 18 | 2D8689,03B,wob 19 | 2D868E,03B,wob 20 | 2D8693,03B,wob 21 | 2D8698,03B,wob 22 | 2D869D,03F,wor 23 | 2D86A2,03F,wor 24 | 2D86A7,03F,wor 25 | 2D86AC,03F,wor 26 | 2D86B1,041,wor 27 | 2D86B6,042,wor 28 | 2D86BB,044,wor 29 | 2D86C0,044,wor 30 | 2D86C5,045,wob 31 | 2D86CA,045,wob 32 | 2D86CF,046,wob 33 | 2D86D4,048,wob 34 | 2D86D9,048,wob 35 | 2D86DE,049,wob 36 | 2D86E3,04A,wor 37 | 2D86E8,04A,wor 38 | 2D86ED,04A,wor 39 | 2D86F2,04A,wor 40 | 2D86F7,04A,wor 41 | 2D86FC,04A,wor 42 | 2D8701,04A,wor 43 | 2D8706,04A,wor 44 | 2D870B,04B,wob 45 | 2D8710,04B,wob 46 | 2D8715,04B,wob 47 | 2D871A,04B,wob 48 | 2D871F,04B,wob 49 | 2D8724,04B,wob 50 | 2D8729,04B,wob 51 | 2D872E,04B,wob 52 | 2D8733,054,wob 53 | 2D8738,054,wob 54 | 2D873D,054,wob 55 | 2D8742,054,wob 56 | 2D8747,056,wob 57 | 2D874C,056,wob 58 | 2D8751,057,wob 59 | 2D8756,057,wob 60 | 2D875B,057,wob 61 | 2D8760,057,wob 62 | 2D8765,059,wob 63 | 2D876A,059,wob 64 | 2D876F,059,wob 65 | 2D8774,059,wob 66 | 2D8779,059,wob 67 | 2D877E,05A,wor 68 | 2D8783,05E,wob 69 | 2D8788,060,wob 70 | 2D878D,060,wob 71 | 2D8792,061,wob 72 | 2D8797,061,wob 73 | 2D879C,064,wob 74 | 2D87A1,064,wob 75 | 2D87A6,069,wob 76 | 2D87AB,06A,wob 77 | 2D87B0,06B,wob 78 | 2D87B5,06B,wob 79 | 2D87BA,06D,wob 80 | 2D87BF,06E,wob 81 | 2D87C4,06E,wob 82 | 2D87C9,06E,wob 83 | 2D87CE,06E,wob 84 | 2D87D3,06E,wob 85 | 2D87D8,06E,wob 86 | 2D87DD,06E,wob 87 | 2D87E2,06E,wob 88 | 2D87E7,075,wob 89 | 2D87EC,075,wob 90 | 2D87F1,075,wob 91 | 2D87F6,075,wob 92 | 2D87FB,07B,wob 93 | 2D8800,07B,wob 94 | 2D8805,07B,wob 95 | 2D880A,07B,wob 96 | 2D880F,07B,wob 97 | 2D8814,07B,wob 98 | 2D8819,07C,wob 99 | 2D881E,07E,wor 100 | 2D8823,07E,wor 101 | 2D8828,07E,wor 102 | 2D882D,07E,wor 103 | 2D8832,07E,wor 104 | 2D8837,07E,wor 105 | 2D883C,090,wor 106 | 2D8841,090,wor 107 | 2D8846,092,wob 108 | 2D884B,093,wob 109 | 2D8850,096,wor 110 | 2D8855,099,wob 111 | 2D885A,099,wob 112 | 2D885F,099,wob 113 | 2D8864,099,wob 114 | 2D8869,099,wob 115 | 2D886E,099,wob 116 | 2D8873,09E,wor 117 | 2D8878,0A3,wob 118 | 2D887D,0AB,wob 119 | 2D8882,0AF,wob 120 | 2D8887,0AF,wob 121 | 2D888C,0B1,wor 122 | 2D8891,0B3,wor 123 | 2D8896,0B3,wor 124 | 2D889B,0B3,wor 125 | 2D88A0,0B3,wor 126 | 2D88A5,0B4,wor 127 | 2D88AA,0BA,wob 128 | 2D88AF,0C3,wob 129 | 2D88B4,0C5,wob 130 | 2D88B9,0CF,wor 131 | 2D88BE,0CF,wor 132 | 2D88C3,0D1,wob 133 | 2D88C8,0E1,wob 134 | 2D88CD,0E1,wob 135 | 2D88D2,0E1,wob 136 | 2D88D7,0E1,wob 137 | 2D88DC,0E1,wob 138 | 2D88E1,0E1,wob 139 | 2D88E6,0E1,wob 140 | 2D88EB,0E2,wob 141 | 2D88F0,0E2,wob 142 | 2D88F5,0FA,wob 143 | 2D88FA,0FA,wob 144 | 2D88FF,0FA,wob 145 | 2D8904,0FA,wob 146 | 2D8909,0FC,wob 147 | 2D890E,106,wob 148 | 2D8913,106,wob 149 | 2D8918,106,wob 150 | 2D891D,106,wob 151 | 2D8922,106,wob 152 | 2D8927,106,wob 153 | 2D892C,107,wob 154 | 2D8931,107,wob 155 | 2D8936,107,wob 156 | 2D893B,107,wob 157 | 2D8940,107,wob 158 | 2D8945,107,wob 159 | 2D894A,10F,wob 160 | 2D894F,114,wor 161 | 2D8954,114,wor 162 | 2D8959,114,wor 163 | 2D895E,114,wor 164 | 2D8963,114,wor 165 | 2D8968,118,wor 166 | 2D896D,118,wor 167 | 2D8972,118,wor 168 | 2D8977,118,wor 169 | 2D897C,119,wor 170 | 2D8981,11A,wor 171 | 2D8986,11A,wor 172 | 2D898B,11C,wob 173 | 2D8990,11C,wob 174 | 2D8995,124,wor 175 | 2D899A,128,wor 176 | 2D899F,128,wor 177 | 2D89A4,12B,wor 178 | 2D89A9,12B,wor 179 | 2D89AE,12C,wor 180 | 2D89B3,12C,wor 181 | 2D89B8,12C,wor 182 | 2D89BD,12C,wor 183 | 2D89C2,130,wor 184 | 2D89C7,137,wor 185 | 2D89CC,137,wor 186 | 2D89D1,137,wor 187 | 2D89D6,137,wor 188 | 2D89DB,137,wor 189 | 2D89E0,137,wor 190 | 2D89E5,137,wor 191 | 2D89EA,137,wor 192 | 2D89EF,139,wor 193 | 2D89F4,139,wor 194 | 2D89F9,139,wor 195 | 2D89FE,139,wor 196 | 2D8A03,139,wor 197 | 2D8A08,13B,wor 198 | 2D8A0D,13B,wor 199 | 2D8A12,13B,wor 200 | 2D8A17,13B,wor 201 | 2D8A1C,141,wor 202 | 2D8A21,141,wor 203 | 2D8A26,143,wob 204 | 2D8A2B,144,wor 205 | 2D8A30,146,wob 206 | 2D8A35,147,wob 207 | 2D8A3A,147,wob 208 | 2D8A3F,14A,wob 209 | 2D8A44,14C,wob 210 | 2D8A49,14E,wor 211 | 2D8A4E,14E,wor 212 | 2D8A53,14E,wor 213 | 2D8A58,14E,wor 214 | 2D8A5D,14E,wor 215 | 2D8A62,14E,wor 216 | 2D8A67,14E,wor 217 | 2D8A6C,14E,wor 218 | 2D8A71,152,wor 219 | 2D8A76,152,wor 220 | 2D8A7B,157,wob 221 | 2D8A80,157,wob 222 | 2D8A85,157,wob 223 | 2D8A8A,157,wob 224 | 2D8A8F,157,wob 225 | 2D8A94,15D,wob 226 | 2D8A99,15F,wob 227 | 2D8A9E,15F,wob 228 | 2D8AA3,161,wor 229 | 2D8AA8,161,wor 230 | 2D8AAD,161,wor 231 | 2D8AB2,16D,wor 232 | 2D8AB7,16E,wor 233 | 2D8ABC,16F,wor 234 | 2D8AC1,170,wor 235 | 2D8AC6,171,wor 236 | 2D8ACB,172,wor 237 | 2D8AD0,174,wob 238 | 2D8AD5,175,wob 239 | 2D8ADA,176,wob 240 | 2D8ADF,177,wob 241 | 2D8AE4,17A,wob 242 | 2D8AE9,17A,wob 243 | 2D8AEE,17A,wob 244 | 2D8AF3,17A,wob 245 | 2D8AF8,17A,wob 246 | 2D8AFD,17A,wob 247 | 2D8B02,17A,wob 248 | 2D8B07,17A,wob 249 | 2D8B0C,17A,wob 250 | 2D8B11,17A,wob 251 | 2D8B16,17A,wob 252 | 2D8B1B,17A,wob 253 | 2D8B20,17A,wob 254 | 2D8B25,17E,wob 255 | 2D8B2A,17F,wob 256 | 2D8B2F,180,wob 257 | 2D8B34,180,wob 258 | 2D8B39,180,wob 259 | 2D8B3E,180,wob 260 | 2D8B43,180,wob 261 | 2D8B48,180,wob 262 | 2D8B4D,180,wob 263 | 2D8B52,180,wob 264 | 2D8B57,180,wob 265 | 2D8B5C,181,wob 266 | 2D8B61,181,wob 267 | 2D8B66,182,wob 268 | 2D8B6B,189,wor 269 | 2D8B70,18A,wor 270 | 2D8B75,18A,wor 271 | 2D8B7A,18A,wor 272 | 2D8B7F,191,wor 273 | 2D8B84,191,wor 274 | 2D8B89,191,wor 275 | 2D8B8E,191,wor 276 | 2D8B93,191,wor 277 | 2D8B98,191,wor 278 | 2D8B9D,196,wor 279 | 2D8BA2,196,wor 280 | 2D8BA7,196,wor 281 | 2D8BAC,196,wor 282 | 2D8BB1,198,wor 283 | 2D8BB6,19A,wor 284 | 2D8BBB,19A,wor 285 | 2D8BC0,19A,wor 286 | 2D8BC5,19A,wor 287 | -------------------------------------------------------------------------------- /tables/spellcodes.txt: -------------------------------------------------------------------------------- 1 | 00,weak,Fire 2 | 01,weak,Ice 3 | 02,weak,Bolt 4 | 03,weak,Poison 5 | 04,medium,Drain 6 | 05,medium,Fire 2 7 | 06,medium,Ice 2 8 | 07,medium,Bolt 2 9 | 08,medium,Bio 10 | 09,strong,Fire 3 11 | 0A,strong,Ice 3 12 | 0B,strong,Bolt 3 13 | 0C,medium,Break 14 | 0D,medium,Doom 15 | 0E,strong,Pearl 16 | 0F,strong,Flare 17 | 10,weak,Demi 18 | 11,weak,Quartr 19 | 12,strong,X-Zone 20 | 13,broken,Meteor 21 | 14,broken,Ultima 22 | 15,medium,Quake 23 | 16,medium,W Wind 24 | 17,medium,Merton 25 | 18,weak,Scan 26 | 19,weak,Slow 27 | 1A,weak,Rasp 28 | 1B,weak,Mute 29 | 1C,weak,Safe 30 | 1D,weak,Sleep 31 | 1E,weak,Muddle 32 | 1F,weak,Haste 33 | 20,weak,Stop 34 | 21,weak,Bserk 35 | 22,weak,Float 36 | 23,weak,Imp 37 | 24,weak,Rflect 38 | 25,weak,Shell 39 | 26,medium,Vanish 40 | 27,medium,Haste2 41 | 28,medium,Slow 2 42 | 29,medium,Osmose 43 | 2A,weak,Warp 44 | 2B,strong,Quick 45 | 2C,weak,Dispel 46 | 2D,weak,Cure 47 | 2E,weak,Cure 2 48 | 2F,medium,Cure 3 49 | 30,worthless,Life 50 | 31,worthless,Life 2 51 | 32,weak,Antdot 52 | 33,weak,Remedy 53 | 34,weak,Regen 54 | 35,strong,Life 3 55 | 36,medium,Ramuh 56 | 37,medium,Ifrit 57 | 38,medium,Shiva 58 | 39,weak,Siren 59 | 3A,medium,Terrato 60 | 3B,medium,Shoat 61 | 3C,medium,Maduin 62 | 3D,medium,Bismark 63 | 3E,weak,Stray 64 | 3F,strong,Palidor 65 | 40,strong,Tritoch 66 | 41,strong,Odin 67 | 42,strong,Raiden 68 | 43,strong,Bahamut 69 | 44,strong,Alexandr 70 | 45,medium,Crusader 71 | 46,strong,Ragnarok 72 | 47,weak,Kirin 73 | 48,weak,ZoneSeek 74 | 49,weak,Carbunkl 75 | 4A,medium,Phantom 76 | 4B,weak,Sraphim 77 | 4C,medium,Golem 78 | 4D,weak,Unicorn 79 | 4E,medium,Fenrir 80 | 4F,medium,Starlet 81 | 50,medium,Phoenix 82 | 51,medium,Fire Skean 83 | 52,medium,Water Edge 84 | 53,medium,Bolt Edge 85 | 54,medium,Storm 86 | 55,weak,Dispatch 87 | 56,weak,Retort 88 | 57,medium,Slash 89 | 58,medium,Quadra Slam 90 | 59,medium,Empowerer 91 | 5A,strong,Stunner 92 | 5B,strong,Quadra Slice 93 | 5C,strong,Cleave 94 | 5D,weak,Pummel 95 | 5E,weak,AuraBolt 96 | 5F,weak,Suplex 97 | 60,medium,Fire Dance 98 | 61,medium,Mantra 99 | 62,medium,Air Blade 100 | 63,weak,Spiraler 101 | 64,strong,Bum Rush 102 | 65,medium,Wind Slash 103 | 66,weak,Sun Bath 104 | 67,medium,Rage 105 | 68,weak,Harvester 106 | 69,medium,Sand Storm 107 | 6A,weak,Antlion 108 | 6B,medium,Elf Fire 109 | 6C,weak,Specter 110 | 6D,medium,Land Slide 111 | 6E,medium,Sonic Boom 112 | 6F,medium,El Nino 113 | 70,strong,Plasma 114 | 71,strong,Snare 115 | 72,medium,Cave In 116 | 73,medium,Snowball 117 | 74,medium,Surge 118 | 75,strong,Cokatrice 119 | 76,strong,Wombat 120 | 77,weak,Kitty 121 | 78,weak,Tapir 122 | 79,strong,Whump 123 | 7A,strong,Wild Bear 124 | 7B,medium,Pois. Frog 125 | 7C,weak,Ice Rabbit 126 | 7D,weak,Super Ball 127 | 7E,medium,Flash 128 | 7F,medium,Chocobop 129 | 80,strong,H-Bomb 130 | 81,medium,7-Flush 131 | 82,strong,Megahit 132 | 83,strong,Fire Beam 133 | 84,strong,Bolt Beam 134 | 85,strong,Ice Beam 135 | 86,strong,Bio Blast 136 | 87,weak,Heal Force 137 | 88,weak,Confuser 138 | 89,medium,X-Fer 139 | 8A,strong,TekMissile 140 | 8B,weak,Condemned 141 | 8C,broken,Roulette 142 | 8D,medium,CleanSweep 143 | 8E,medium,Aqua Rake 144 | 8F,medium,Aero 145 | 90,weak,Blow Fish 146 | 91,medium,Big Guard 147 | 92,weak,Revenge 148 | 93,weak,Pearl Wind 149 | 94,weak,L.5 Doom 150 | 95,medium,L.4 Flare 151 | 96,weak,L.3 Muddle 152 | 97,weak,Reflect??? 153 | 98,weak,L.? Pearl 154 | 99,weak,Step Mine 155 | 9A,strong,ForceField 156 | 9B,medium,Dischord 157 | 9C,medium,Sour Mouth 158 | 9D,worthless,Pep Up 159 | 9E,weak,Rippler 160 | 9F,weak,Stone 161 | A0,strong,Quasar 162 | A1,strong,GrandTrain 163 | A2,weak,Exploder 164 | A3,weak,Imp Song 165 | A4,weak,Clear 166 | A5,weak,Virite 167 | A6,worthless,ChokeSmoke 168 | A7,worthless,Schiller 169 | A8,weak,Lullaby 170 | A9,medium,Acid Rain 171 | AA,weak,Confusion 172 | AB,weak,Megazerk 173 | AC,weak,Mute 174 | AD,weak,Net 175 | AE,weak,Slimer 176 | AF,medium,Delta Hit 177 | B0,weak,Entwine 178 | B1,medium,Blaster 179 | B2,medium,Cyclonic 180 | B3,medium,Fire Ball 181 | B4,medium,Atomic Ray 182 | B5,medium,Tek Laser 183 | B6,medium,Diffuser 184 | B7,medium,WaveCannon 185 | B8,medium,Mega Volt 186 | B9,strong,Giga Volt 187 | BA,weak,Blizzard 188 | BB,medium,Absolute 0 189 | BC,medium,Magnitude8 190 | BD,medium,Raid 191 | BE,weak,Flash Rain 192 | BF,weak,TekBarrier 193 | C0,broken,Fallen One 194 | C1,strong,WallChange 195 | C2,broken,Escape 196 | C3,worthless,50 Gs 197 | C4,medium,Mind Blast 198 | C5,medium,N. Cross 199 | C6,strong,Flare Star 200 | C7,medium,Love Token 201 | C8,broken,Seize 202 | C9,worthless,R.Polarity 203 | CA,worthless,Targetting 204 | CB,broken,Sneeze 205 | CC,strong,S. Cross 206 | CD,strong,Launcher 207 | CE,broken,Charm 208 | CF,strong,Cold Dust 209 | D0,weak,Tentacle 210 | D1,broken,HyperDrive 211 | D2,strong,Train 212 | D3,medium,Evil Toot 213 | D4,medium,Grav Bomb 214 | D5,broken,Engulf 215 | D6,medium,Disaster 216 | D7,strong,Shrapnel 217 | D8,worthless,Bomblet 218 | D9,weak,Heart Burn 219 | DA,broken,Zinger 220 | DB,broken,Discard 221 | DC,worthless,Overcast 222 | DD,medium,Missile 223 | DE,broken,Goner 224 | DF,strong,Meteo 225 | E0,medium,Revenger 226 | E1,weak,Phantasm 227 | E2,medium,Dread 228 | E3,medium,Shock Wave 229 | E4,medium,Blaze 230 | E5,worthless,Soul Out 231 | E6,medium,Gale Cut 232 | E7,weak,Shimsham 233 | E8,medium,Lode Stone 234 | E9,medium,Scar Beam 235 | EA,broken,BabaBreath 236 | EB,medium,LifeShaver 237 | EC,medium,Fire Wall 238 | ED,medium,Slide 239 | EE,broken,Battle 240 | EF,broken,Special 241 | F0,broken,Riot Blade 242 | F1,broken,Mirager 243 | F2,broken,Back Blade 244 | F3,broken,ShadowFang 245 | F4,broken,RoyalShock 246 | F5,broken,TigerBreak 247 | F6,broken,Spin Edge 248 | F7,broken,Sabre Soul 249 | F8,broken,Star Prism 250 | F9,broken,Red Card 251 | FA,broken,MoogleRush 252 | FB,broken,X-Meteo 253 | FC,broken,Takedown 254 | FD,broken,Wild Fang 255 | FE,weak,Lagomorph 256 | -------------------------------------------------------------------------------- /tables/enemycodes.txt: -------------------------------------------------------------------------------- 1 | Guard_____ 2 | Soldier___ 3 | Templar___ 4 | Ninja_____ 5 | Samurai___ 6 | Orog______ 7 | Mag Roader 8 | Retainer__ 9 | Hazer_____ 10 | Dahling___ 11 | Rain Man__ 12 | Brawler___ 13 | Apokryphos 14 | Dark Force 15 | Whisper___ 16 | Over-Mind_ 17 | Osteosaur_ 18 | Commander_ 19 | Rhodox____ 20 | Were-Rat__ 21 | Ursus_____ 22 | Rhinotaur_ 23 | Steroidite 24 | Leafer____ 25 | Stray Cat_ 26 | Lobo______ 27 | Doberman__ 28 | Vomammoth_ 29 | Fidor_____ 30 | Baskervor_ 31 | Suriander_ 32 | Chimera___ 33 | Behemoth__ 34 | Mesosaur__ 35 | Pterodon__ 36 | FossilFang 37 | White Drgn 38 | Doom Drgn_ 39 | Brachosaur 40 | Tyranosaur 41 | Dark Wind_ 42 | Beakor____ 43 | Vulture___ 44 | Harpy_____ 45 | HermitCrab 46 | Trapper___ 47 | Hornet____ 48 | CrassHoppr 49 | Delta Bug_ 50 | Gilomantis 51 | Trilium___ 52 | Nightshade 53 | TumbleWeed 54 | Bloompire_ 55 | Trilobiter 56 | Siegfried_ 57 | Nautiloid_ 58 | Exocite___ 59 | Anguiform_ 60 | Reach Frog 61 | Lizard____ 62 | ChickenLip 63 | Hoover____ 64 | Rider_____ 65 | Chupon____ 66 | Pipsqueak_ 67 | M-TekArmor 68 | Sky Armor_ 69 | Telstar___ 70 | Lethal Wpn 71 | Vaporite__ 72 | Flan______ 73 | Ing_______ 74 | Humpty____ 75 | Brainpan__ 76 | Cruller___ 77 | Cactrot___ 78 | Repo Man__ 79 | Harvester_ 80 | Bomb______ 81 | Still Life 82 | Boxed Set_ 83 | SlamDancer 84 | HadesGigas 85 | Pug_______ 86 | Magic Urn_ 87 | Mover_____ 88 | Figaliz___ 89 | Buffalax__ 90 | Aspik_____ 91 | Ghost_____ 92 | Crawler___ 93 | Sand Ray__ 94 | Areneid___ 95 | Actaneon__ 96 | Sand Horse 97 | Dark Side_ 98 | Mad Oscar_ 99 | Crawly____ 100 | Bleary____ 101 | Marshal___ 102 | Trooper___ 103 | General___ 104 | Covert____ 105 | Ogor______ 106 | Warlock___ 107 | Madam_____ 108 | Joker_____ 109 | Iron Fist_ 110 | Goblin____ 111 | Apparite__ 112 | PowerDemon 113 | Displayer_ 114 | Vector Pup 115 | Peepers___ 116 | Sewer Rat_ 117 | Slatter___ 118 | Rhinox____ 119 | Rhobite___ 120 | Wild Cat__ 121 | Red Fang__ 122 | Bounty Man 123 | Tusker____ 124 | Ralph_____ 125 | Chitonid__ 126 | Wart Puck_ 127 | Rhyos_____ 128 | SrBehemoth 129 | Vectaur___ 130 | Wyvern____ 131 | Zombone___ 132 | Dragon____ 133 | Brontaur__ 134 | Allosaurus 135 | Cirpius___ 136 | Sprinter__ 137 | Gobbler___ 138 | Harpiai___ 139 | GloomShell 140 | Drop______ 141 | Mind Candy 142 | WeedFeeder 143 | Luridan___ 144 | Toe Cutter 145 | Over Grunk 146 | Exoray____ 147 | Crusher___ 148 | Uroburos__ 149 | Primordite 150 | Sky Cap___ 151 | Cephaler__ 152 | Maliga____ 153 | Gigan Toad 154 | Geckorex__ 155 | Cluck_____ 156 | Land Worm_ 157 | Test Rider 158 | PlutoArmor 159 | Tomb Thumb 160 | HeavyArmor 161 | Chaser____ 162 | Scullion__ 163 | Poplium___ 164 | Intangir__ 165 | Misfit____ 166 | Eland_____ 167 | Enuo______ 168 | Deep Eye__ 169 | GreaseMonk 170 | NeckHunter 171 | Grenade___ 172 | Critic____ 173 | Pan Dora__ 174 | SoulDancer 175 | Gigantos__ 176 | Mag Roader 177 | Spek Tor__ 178 | Parasite__ 179 | EarthGuard 180 | Coelecite_ 181 | Anemone___ 182 | Hipocampus 183 | Spectre___ 184 | Evil Oscar 185 | Slurm_____ 186 | Latimeria_ 187 | StillGoing 188 | Allo Ver__ 189 | Phase_____ 190 | Outsider__ 191 | Barb-e____ 192 | Parasoul__ 193 | Pm Stalker 194 | Hemophyte_ 195 | Sp Forces_ 196 | Nohrabbit_ 197 | Wizard____ 198 | Scrapper__ 199 | Ceritops__ 200 | Commando__ 201 | Opinicus__ 202 | Poppers___ 203 | Lunaris___ 204 | Garm______ 205 | Vindr_____ 206 | Kiwok_____ 207 | Nastidon__ 208 | Rinn______ 209 | Insecare__ 210 | Vermin____ 211 | Mantodea__ 212 | Bogy______ 213 | Prussian__ 214 | Black Drgn 215 | Adamanchyt 216 | Dante_____ 217 | Wirey Drgn 218 | Dueller___ 219 | Psychot___ 220 | Muus______ 221 | Karkass___ 222 | Punisher__ 223 | Balloon___ 224 | Gabbldegak 225 | GtBehemoth 226 | Scorpion__ 227 | Chaos Drgn 228 | Spit Fire_ 229 | Vectagoyle 230 | Lich______ 231 | Osprey____ 232 | Mag Roader 233 | Bug_______ 234 | Sea Flower 235 | Fortis____ 236 | Abolisher_ 237 | Aquila____ 238 | Junk______ 239 | Mandrake__ 240 | 1st Class_ 241 | Tap Dancer 242 | Necromancr 243 | Borras____ 244 | Mag Roader 245 | Wild Rat__ 246 | Gold Bear_ 247 | Innoc_____ 248 | Trixter___ 249 | Red Wolf__ 250 | Didalos___ 251 | Woolly____ 252 | Veteran___ 253 | Sky Base__ 254 | IronHitman 255 | Io________ 256 | Pugs______ 257 | Whelk_____ 258 | Presenter_ 259 | Mega Armor 260 | Vargas____ 261 | TunnelArmr 262 | Prometheus 263 | GhostTrain 264 | Dadaluma__ 265 | Shiva_____ 266 | Ifrit_____ 267 | Number 024 268 | Number 128 269 | Inferno___ 270 | Crane_____ 271 | Crane_____ 272 | Umaro_____ 273 | Umaro_____ 274 | Guardian__ 275 | Guardian__ 276 | Air Force_ 277 | Tritoch___ 278 | Tritoch___ 279 | FlameEater 280 | AtmaWeapon 281 | Nerapa____ 282 | SrBehemoth 283 | Kefka_____ 284 | Tentacle__ 285 | Dullahan__ 286 | Doom Gaze_ 287 | Chadarnook 288 | Curley____ 289 | Larry_____ 290 | Moe_______ 291 | Wrexsoul__ 292 | Hidon_____ 293 | KatanaSoul 294 | L.30 Magic 295 | Hidonite__ 296 | Doom______ 297 | Goddess___ 298 | Poltrgeist 299 | Kefka_____ 300 | L.40 Magic 301 | Ultros____ 302 | Ultros____ 303 | Ultros____ 304 | Chupon____ 305 | L.20 Magic 306 | Siegfried_ 307 | L.10 Magic 308 | L.50 Magic 309 | Head______ 310 | Whelk Head 311 | Colossus__ 312 | CzarDragon 313 | Master Pug 314 | L.60 Magic 315 | Merchant__ 316 | B.Day Suit 317 | Tentacle__ 318 | Tentacle__ 319 | Tentacle__ 320 | RightBlade 321 | Left Blade 322 | Rough_____ 323 | Striker___ 324 | L.70 Magic 325 | Tritoch___ 326 | Laser Gun_ 327 | Speck_____ 328 | MissileBay 329 | Chadarnook 330 | Ice Dragon 331 | Kefka_____ 332 | Storm Drgn 333 | Dirt Drgn_ 334 | Ipooh_____ 335 | Leader____ 336 | Grunt_____ 337 | Gold Drgn_ 338 | Skull Drgn 339 | Blue Drgn_ 340 | Red Dragon 341 | Piranha___ 342 | Rizopas___ 343 | Specter___ 344 | Short Arm_ 345 | Long Arm__ 346 | Face______ 347 | Tiger_____ 348 | Tools_____ 349 | Magic_____ 350 | Hit_______ 351 | Girl______ 352 | Sleep_____ 353 | Hidonite__ 354 | Hidonite__ 355 | Hidonite__ 356 | L.80 Magic 357 | L.90 Magic 358 | ProtoArmor 359 | MagiMaster 360 | SoulSaver_ 361 | Ultros____ 362 | Naughty___ 363 | Phunbaba__ 364 | Phunbaba__ 365 | Phunbaba__ 366 | Phunbaba__ 367 | __________ 368 | __________ 369 | __________ 370 | Zone Eater 371 | __________ 372 | __________ 373 | __________ 374 | Officer___ 375 | Cadet_____ 376 | __________ 377 | __________ 378 | Soldier___ 379 | __________ 380 | __________ 381 | __________ 382 | Atma______ 383 | __________ 384 | __________ 385 | -------------------------------------------------------------------------------- /tables/reachability.txt: -------------------------------------------------------------------------------- 1 | 6:0 2 | 7:0,1 3 | 7:2,3,5 4 | 7:4 5 | 7:6,7 6 | 8:0 7 | 11:0 8 | 12:0,1,3 9 | 12:2 10 | 12:4 11 | 20:0,1,2,3,4,5,6,7,8,9,15 12 | 20:10,14 13 | 20:12,13 14 | 21:0,1 15 | 24:0,1 16 | 24:2 17 | 25:0,1 18 | 26:0 19 | 27:0 20 | 28:0 21 | 30:0,1 22 | 30:2 23 | 30:3 24 | 30:4 25 | 33:0,1 26 | 33:3,4 27 | 36:0,1 28 | 36:2,3 29 | 36:4,5 30 | 36:6,7 31 | 36:8,9 32 | 36:10 33 | 37:0,1 34 | 38:0,1,3 35 | 38:4,5 36 | 38:6,7 37 | 41:0,1 38 | 41:2,3 39 | 41:4,5 40 | 41:6,7 41 | 42:0 42 | 43:0,1 43 | 43:2 44 | 44:0,1 45 | 48:0,1 46 | 49:0,1 47 | 51:0,1 48 | 52:0,1 49 | 53:0,1 50 | 55:5,8,10,11 51 | 55:1,2,4,7 52 | 55:3 53 | 55:6 54 | 55:9 55 | 57:0,1 56 | 59:0,1,2,3 57 | 59:4,5,6,7,8,9 58 | 59:10,11,12 59 | 59:13,14 60 | 59:15,16 61 | 59:17 62 | 59:18 63 | 59:19,20 64 | 59:21,22 65 | 60:0,1 66 | 61:0,2 67 | 61:1 68 | 62:0,1 69 | 62:2,3 70 | 62:4,5 71 | 63:0,2 72 | 63:1,3 73 | 63:4,5,6 74 | 64:0,1 75 | 65:0 76 | 66:0 77 | 68:0,1 78 | 68:2,3,4 79 | 68:5,6 80 | 70:0 81 | 70:1,2 82 | 72:0,1 83 | 72:2,3,4 84 | 72:5,6 85 | 73:0 86 | 73:1,2 87 | 74:0,3,4,5,6,7,8,9,10,11 88 | 74:1,2 89 | 75:0,3,4,5,6,7,8,9,10,11 90 | 75:1,2 91 | 76:0,1 92 | 76:2,3 93 | 77:0,1 94 | 78:0,1,3 95 | 78:2 96 | 81:0,1,2 97 | 81:3,4,7 98 | 81:5,8 99 | 81:6 100 | 83:0,1 101 | 83:2,3,5,6,7 102 | 83:4 103 | 84:1 104 | 84:2 105 | 85:0 106 | 86:0 107 | 86:1,6 108 | 86:2,5 109 | 86:3,4 110 | 86:7,9 111 | 86:8 112 | 87:0,1,2 113 | 88:0 114 | 89:0 115 | 89:1 116 | 90:0 117 | 90:1 118 | 90:2 119 | 92:0,1 120 | 94:0 121 | 95:0 122 | 96:0,1,2 123 | 96:3 124 | 96:4 125 | 96:5 126 | 97:0,1 127 | 98:0,1 128 | 100:0,1 129 | 100:2,3,4,11 130 | 100:5,6 131 | 100:7,8 132 | 100:9,10 133 | 100:12 134 | 102:0,1,2 135 | 103:0,1 136 | 104:0,1,2,3 137 | 105:0 138 | 106:0 139 | 107:0 140 | 109:0,1,2,3,4 141 | 110:0 142 | 110:1,2 143 | 110:3 144 | 111:0 145 | 112:0,1 146 | 115:0 147 | 116:0 148 | 121:0 149 | 121:1 150 | 121:2,3 151 | 123:0,15 152 | 123:1,2,7,11,13,14,16 153 | 123:3 154 | 123:4 155 | 123:5,8,10,12 156 | 123:6 157 | 123:9 158 | 124:0 159 | 125:0 160 | 125:1 161 | 125:2,3 162 | 128:0 163 | 131:0 164 | 132:0 165 | 133:0,1 166 | 134:0,1,2 167 | 135:0,1 168 | 141:0,1,2,3 169 | 142:0,1,2 170 | 143:0,2,3,4,5,6 171 | 144:0,1,2,3 172 | 146:0 173 | 147:0,1,2,3 174 | 149:0,1 175 | 150:0 176 | 152:0,1,2,3,4,5 177 | 153:0 178 | 154:0 179 | 155:0,1 180 | 157:0,1,2,3,4,5,6 181 | 158:0,1,2 182 | 160:0 183 | 161:0,1 184 | 163:0 185 | 164:0 186 | 165:0 187 | 167:0,1 188 | 169:0,1 189 | 171:0 190 | 172:0 191 | 175:0 192 | 175:1 193 | 176:0,1,2 194 | 177:0 195 | 178:0,1 196 | 179:0,1,2 197 | 179:3,4 198 | 180:0,1 199 | 185:0 200 | 186:0 201 | 188:0,1,2,3,4,5 202 | 189:0,1,2,3,4,5 203 | 191:0 204 | 194:0,1 205 | 195:0,2 206 | 195:1 207 | 195:3 208 | 196:0 209 | 197:0 210 | 198:0,1,2,3,4,5,6 211 | 200:0 212 | 201:0 213 | 202:0 214 | 203:0 215 | 204:0 216 | 206:0 217 | 207:0,1 218 | 207:2,3,5 219 | 207:4 220 | 207:6,7 221 | 207:8 222 | 207:9 223 | 208:0 224 | 209:0 225 | 218:0 226 | 219:0 227 | 219:1 228 | 219:2 229 | 219:3 230 | 219:4 231 | 221:0,1,2,4,8 232 | 221:3 233 | 221:5 234 | 221:6,7,18 235 | 221:9,10 236 | 221:11,12 237 | 221:13 238 | 221:14,15,19 239 | 221:16 240 | 221:17 241 | 225:0,1,2 242 | 225:3,4 243 | 225:5,6 244 | 225:7,8 245 | 225:9 246 | 225:10 247 | 225:11 248 | 225:12 249 | 225:13 250 | 225:15,16 251 | 231:0,1,2,3 252 | 232:0,1 253 | 232:2 254 | 233:0,1,2,3 255 | 235:0 256 | 237:0,1 257 | 237:2 258 | 237:3 259 | 238:0 260 | 238:1 261 | 238:2 262 | 243:0 263 | 244:0,1,2 264 | 250:0,2,4,5,6,8,10 265 | 250:1 266 | 250:3 267 | 250:7,14 268 | 250:9,19 269 | 250:11,20 270 | 250:12,13 271 | 250:15,16 272 | 250:17 273 | 250:18 274 | 252:0,1 275 | 253:0,1,2,3,4 276 | 262:0 277 | 262:1 278 | 263:0 279 | 264:0,1 280 | 267:0,1 281 | 269:0,1 282 | 270:0 283 | 271:0,1 284 | 273:0,1 285 | 274:0 286 | 276:0 287 | 276:1,2 288 | 276:3 289 | 276:4 290 | 277:0,1 291 | 278:0 292 | 279:0,1 293 | 280:0 294 | 280:1 295 | 281:0,1,2 296 | 281:3,4 297 | 281:5 298 | 282:0,1,2,3 299 | 284:0,1,2,3 300 | 285:0 301 | 285:1 302 | 285:2,3 303 | 287:0,1 304 | 288:0 305 | 289:0 306 | 290:0 307 | 291:0,1 308 | 291:2,3 309 | 291:4,5 310 | 292:0 311 | 292:1,2 312 | 293:0,1 313 | 293:2,3 314 | 294:0,1 315 | 295:0,1 316 | 296:0 317 | 298:0,1 318 | 299:0,1,3,5,7,10 319 | 299:2 320 | 299:4 321 | 299:6,12 322 | 299:8 323 | 299:9 324 | 299:11 325 | 299:14 326 | 299:15 327 | 299:16 328 | 300:0,1 329 | 300:2 330 | 300:3,4 331 | 300:6 332 | 300:7,8 333 | 303:0,1 334 | 304:0,1 335 | 305:0,1,2,3,4,5 336 | 306:0,1,2,3,4 337 | 311:0 338 | 311:1 339 | 313:0,1 340 | 313:2 341 | 313:3 342 | 313:4 343 | 313:5 344 | 313:6 345 | 313:7 346 | 313:8 347 | 313:9,10 348 | 315:0 349 | 315:1 350 | 315:2 351 | 315:3 352 | 315:4 353 | 315:5,6,7 354 | 315:8 355 | 315:9 356 | 315:10 357 | 315:11 358 | 317:0,1 359 | 317:2 360 | 317:3 361 | 317:4,5,6 362 | 317:7,9 363 | 317:8 364 | 317:10 365 | 317:11,12 366 | 317:13 367 | 318:0 368 | 319:0,1 369 | 319:2,3 370 | 320:0 371 | 320:1,2 372 | 321:0,1 373 | 321:2 374 | 322:0,1,2,3 375 | 323:0,1,2,3,4,5 376 | 324:0,1,2,3,4,5 377 | 329:1 378 | 331:0 379 | 334:0 380 | 334:1,2 381 | 334:3,7 382 | 334:4,6,9 383 | 334:5,10 384 | 334:8 385 | 334:11,12 386 | 334:13,14 387 | 335:0,1 388 | 337:0 389 | 337:3 390 | 337:5 391 | 337:7 392 | 337:8 393 | 338:0,1,2 394 | 338:3 395 | 339:0,1 396 | 339:2,3 397 | 343:0,1,2,3,4,5,6 398 | 344:0,1,2,3,4,5,6 399 | 345:0,1 400 | 346:0 401 | 347:0 402 | 348:0 403 | 349:0,1 404 | 349:2 405 | 350:0 406 | 351:0 407 | 351:1,2,3 408 | 351:6,7,9 409 | 351:8,11,13 410 | 351:10 411 | 351:12 412 | 351:14,15 413 | 351:16 414 | 352:0,1 415 | 353:0,1,7 416 | 353:2 417 | 353:3,8 418 | 353:4,5 419 | 353:6,9 420 | 353:10 421 | 353:11 422 | 353:12,14 423 | 353:13 424 | 354:0,1 425 | 354:2,3 426 | 354:4,7 427 | 354:5,6 428 | 355:0,8 429 | 355:1,3 430 | 355:2,5 431 | 355:7 432 | 359:0,1,2 433 | 360:0,1,2 434 | 361:0,1,2 435 | 362:0 436 | 363:1,2,3 437 | 364:0,1 438 | 365:0 439 | 366:0 440 | 367:0 441 | 368:0 442 | 369:0 443 | 370:0 444 | 371:0,1 445 | 372:0,1,2 446 | 372:3 447 | 372:4,5,6,7 448 | 373:0,1 449 | 373:2 450 | 374:0 451 | 375:0,1,2,3 452 | 375:4,5 453 | 375:6 454 | 375:7,8 455 | 375:9 456 | 375:10 457 | 375:11 458 | 377:0,1,2 459 | 378:0,1 460 | 378:2 461 | 382:0,1 462 | 383:0,1 463 | 384:1 464 | 384:2 465 | 384:3 466 | 384:6 467 | 385:0,1 468 | 385:2 469 | 386:0 470 | 396:0 471 | 397:0 472 | 401:0,1,3,5 473 | 401:2,4,6 474 | 401:7 475 | 402:0,1 476 | 406:0,1 477 | 406:2 478 | 406:3 479 | 406:4 480 | 406:5 481 | 406:6,7,8 482 | 407:0,1,2,3 483 | 408:0 484 | 408:2 485 | 409:0,1,2 486 | 410:0,9 487 | 411:0 488 | 411:2 489 | 412:0 490 | 413:0,1 491 | 413:2 492 | 413:3 493 | -------------------------------------------------------------------------------- /tables/itemcodes.txt: -------------------------------------------------------------------------------- 1 | 0,185000,Dirk 2 | 1,18501e,MithrilKnife 3 | 2,18503c,Guardian 4 | 3,18505a,Air Lancet 5 | 4,185078,ThiefKnife 6 | 5,185096,Assassin 7 | 6,1850b4,Man Eater 8 | 7,1850d2,SwordBreaker 9 | 8,1850f0,Graedus 10 | 9,18510e,ValiantKnife 11 | a,18512c,MithrilBlade 12 | b,18514a,RegalCutlass 13 | c,185168,Rune Edge 14 | d,185186,Flame Sabre 15 | e,1851a4,Blizzard 16 | f,1851c2,ThunderBlade 17 | 10,1851e0,Epee 18 | 11,1851fe,BreakBlade 19 | 12,18521c,Drainer 20 | 13,18523a,Enhancer 21 | 14,185258,Crystal 22 | 15,185276,Falchion 23 | 16,185294,Soul Sabre 24 | 17,1852b2,Ogre Nix 25 | 18,1852d0,Excalibur 26 | 19,1852ee,Scimitar 27 | 1a,18530c,Illumina 28 | 1b,18532a,Ragnarok 29 | 1c,185348,Atma Weapon 30 | 1d,185366,Mithril Pike 31 | 1e,185384,Trident 32 | 1f,1853a2,Stout Spear 33 | 20,1853c0,Partisan 34 | 21,1853de,Pearl Lance 35 | 22,1853fc,Gold Lance 36 | 23,18541a,Aura Lance 37 | 24,185438,Imp Halberd 38 | 25,185456,Imperial 39 | 26,185474,Kodachi 40 | 27,185492,Blossom 41 | 28,1854b0,Hardened 42 | 29,1854ce,Striker 43 | 2a,1854ec,Stunner 44 | 2b,18550a,Ashura 45 | 2c,185528,Kotetsu 46 | 2d,185546,Forged 47 | 2e,185564,Tempest 48 | 2f,185582,Murasame 49 | 30,1855a0,Aura 50 | 31,1855be,Strato 51 | 32,1855dc,Sky Render 52 | 33,1855fa,Heal Rod 53 | 34,185618,Mithril Rod 54 | 35,185636,Fire Rod 55 | 36,185654,Ice Rod 56 | 37,185672,Thunder Rod 57 | 38,185690,Poison Rod 58 | 39,1856ae,Pearl Rod 59 | 3a,1856cc,Gravity Rod 60 | 3b,1856ea,Punisher 61 | 3c,185708,Magus Rod 62 | 3d,185726,Chocobo Brsh 63 | 3e,185744,DaVinci Brsh 64 | 3f,185762,Magical Brsh 65 | 40,185780,Rainbow Brsh 66 | 41,18579e,Shuriken 67 | 42,1857bc,Ninja Star 68 | 43,1857da,Tack Star 69 | 44,1857f8,Flail 70 | 45,185816,Full Moon 71 | 46,185834,Morning Star 72 | 47,185852,Boomerang 73 | 48,185870,Rising Sun 74 | 49,18588e,Hawk Eye 75 | 4a,1858ac,Bone Club 76 | 4b,1858ca,Sniper 77 | 4c,1858e8,Wing Edge 78 | 4d,185906,Cards 79 | 4e,185924,Darts 80 | 4f,185942,Doom Darts 81 | 50,185960,Trump 82 | 51,18597e,Dice 83 | 52,18599c,Fixed Dice 84 | 53,1859ba,MetalKnuckle 85 | 54,1859d8,MithrilClaw 86 | 55,1859f6,Kaiser 87 | 56,185a14,Poison Claw 88 | 57,185a32,Fire Knuckle 89 | 58,185a50,Dragon Claw 90 | 59,185a6e,Tiger Fangs 91 | 5a,185a8c,Buckler 92 | 5b,185aaa,Heavy Shld 93 | 5c,185ac8,Mithril Shld 94 | 5d,185ae6,Gold Shld 95 | 5e,185b04,Aegis Shld 96 | 5f,185b22,Diamond Shld 97 | 60,185b40,Flame Shld 98 | 61,185b5e,Ice Shld 99 | 62,185b7c,Thunder Shld 100 | 63,185b9a,Crystal Shld 101 | 64,185bb8,Genji Shld 102 | 65,185bd6,TortoiseShld 103 | 66,185bf4,Cursed Shld 104 | 67,185c12,Paladin Shld 105 | 68,185c30,Force Shld 106 | 69,185c4e,Leather Hat 107 | 6a,185c6c,Hair Band 108 | 6b,185c8a,Plumed Hat 109 | 6c,185ca8,Beret 110 | 6d,185cc6,Magus Hat 111 | 6e,185ce4,Bandana 112 | 6f,185d02,Iron Helmet 113 | 70,185d20,Coronet 114 | 71,185d3e,Bard's Hat 115 | 72,185d5c,Green Beret 116 | 73,185d7a,Head Band 117 | 74,185d98,Mithril Helm 118 | 75,185db6,Tiara 119 | 76,185dd4,Gold Helmet 120 | 77,185df2,Tiger Mask 121 | 78,185e10,Red Cap 122 | 79,185e2e,Mystery Veil 123 | 7a,185e4c,Circlet 124 | 7b,185e6a,Regal Crown 125 | 7c,185e88,Diamond Helm 126 | 7d,185ea6,Dark Hood 127 | 7e,185ec4,Crystal Helm 128 | 7f,185ee2,Oath Veil 129 | 80,185f00,Cat Hood 130 | 81,185f1e,Genji Helmet 131 | 82,185f3c,Thornlet 132 | 83,185f5a,Titanium 133 | 84,185f78,LeatherArmor 134 | 85,185f96,Cotton Robe 135 | 86,185fb4,Kung Fu Suit 136 | 87,185fd2,Iron Armor 137 | 88,185ff0,Silk Robe 138 | 89,18600e,Mithril Vest 139 | 8a,18602c,Ninja Gear 140 | 8b,18604a,White Dress 141 | 8c,186068,Mithril Mail 142 | 8d,186086,Gaia Gear 143 | 8e,1860a4,Mirage Vest 144 | 8f,1860c2,Gold Armor 145 | 90,1860e0,Power Sash 146 | 91,1860fe,Light Robe 147 | 92,18611c,Diamond Vest 148 | 93,18613a,Red Jacket 149 | 94,186158,Force Armor 150 | 95,186176,DiamondArmor 151 | 96,186194,Dark Gear 152 | 97,1861b2,Tao Robe 153 | 98,1861d0,Crystal Mail 154 | 99,1861ee,Czarina Gown 155 | 9a,18620c,Genji Armor 156 | 9b,18622a,Imp's Armor 157 | 9c,186248,Minerva 158 | 9d,186266,Tabby Suit 159 | 9e,186284,Chocobo Suit 160 | 9f,1862a2,Moogle Suit 161 | a0,1862c0,Nutkin Suit 162 | a1,1862de,BehemothSuit 163 | a2,1862fc,Snow Muffler 164 | a3,18631a,NoiseBlaster 165 | a4,186338,Bio Blaster 166 | a5,186356,Flash 167 | a6,186374,Chain Saw 168 | a7,186392,Debilitator 169 | a8,1863b0,Drill 170 | a9,1863ce,Air Anchor 171 | aa,1863ec,AutoCrossbow 172 | ab,18640a,Fire Skean 173 | ac,186428,Water Edge 174 | ad,186446,Bolt Edge 175 | ae,186464,Inviz Edge 176 | af,186482,Shadow Edge 177 | b0,1864a0,Goggles 178 | b1,1864be,Star Pendant 179 | b2,1864dc,Peace Ring 180 | b3,1864fa,Amulet 181 | b4,186518,White Cape 182 | b5,186536,Jewel Ring 183 | b6,186554,Fairy Ring 184 | b7,186572,Barrier Ring 185 | b8,186590,MithrilGlove 186 | b9,1865ae,Guard Ring 187 | ba,1865cc,RunningShoes 188 | bb,1865ea,Wall Ring 189 | bc,186608,Cherub Down 190 | bd,186626,Cure Ring 191 | be,186644,True Knight 192 | bf,186662,DragoonBoots 193 | c0,186680,Zephyr Cape 194 | c1,18669e,Czarina Ring 195 | c2,1866bc,Cursed Ring 196 | c3,1866da,Earrings 197 | c4,1866f8,Atlas Armlet 198 | c5,186716,Blizzard Orb 199 | c6,186734,Rage Ring 200 | c7,186752,Sneak Ring 201 | c8,186770,Pod Bracelet 202 | c9,18678e,Hero Ring 203 | ca,1867ac,Ribbon 204 | cb,1867ca,Muscle Belt 205 | cc,1867e8,Crystal Orb 206 | cd,186806,Gold Hairpin 207 | ce,186824,Economizer 208 | cf,186842,Thief Glove 209 | d0,186860,Gauntlet 210 | d1,18687e,Genji Glove 211 | d2,18689c,Hyper Wrist 212 | d3,1868ba,Offering 213 | d4,1868d8,Beads 214 | d5,1868f6,Black Belt 215 | d6,186914,Coin Toss 216 | d7,186932,FakeMustache 217 | d8,186950,Gem Box 218 | d9,18696e,Dragon Horn 219 | da,18698c,Merit Award 220 | db,1869aa,Memento Ring 221 | dc,1869c8,Safety Bit 222 | dd,1869e6,Relic Ring 223 | de,186a04,Moogle Charm 224 | df,186a22,Charm Bangle 225 | e0,186a40,Marvel Shoes 226 | e1,186a5e,Back Guard 227 | e2,186a7c,Gale Hairpin 228 | e3,186a9a,Sniper Sight 229 | e4,186ab8,Exp. Egg 230 | e5,186ad6,Tintinabar 231 | e6,186af4,Sprint Shoes 232 | e7,186b12,Rename Card 233 | e8,186b30,Tonic 234 | e9,186b4e,Potion 235 | ea,186b6c,X-Potion 236 | eb,186b8a,Tincture 237 | ec,186ba8,Ether 238 | ed,186bc6,X-Ether 239 | ee,186be4,Elixir 240 | ef,186c02,Megalixir 241 | f0,186c20,Fenix Down 242 | f1,186c3e,Revivify 243 | f2,186c5c,Antidote 244 | f3,186c7a,Eyedrop 245 | f4,186c98,Soft 246 | f5,186cb6,Remedy 247 | f6,186cd4,Sleeping Bag 248 | f7,186cf2,Tent 249 | f8,186d10,Green Cherry 250 | f9,186d2e,Magicite 251 | fa,186d4c,Super Ball 252 | fb,186d6a,Echo Screen 253 | fc,186d88,Smoke Bomb 254 | fd,186da6,Warp Stone 255 | fe,186dc4,Dried Meat 256 | -------------------------------------------------------------------------------- /esperrandomizer.py: -------------------------------------------------------------------------------- 1 | from utils import hex2int, utilrandom as random 2 | from skillrandomizer import get_ranked_spells, get_spell 3 | 4 | items = None 5 | 6 | rankbounds = {0: 25, 7 | 1: 50, 8 | 2: 80, 9 | 3: 105, 10 | 4: None} 11 | 12 | bonus_ranks = {0: [0xFF, 0x0, 0x3, 0xD], 13 | 1: [0x9, 0xB, 0xF], 14 | 2: [0x1, 0x4, 0xA, 0xC, 0xE], 15 | 3: [0x2, 0x5, 0x8, 0x10], 16 | 4: [0x6]} # Lv -1 bonus decided elsewhere 17 | 18 | bonus_strings = {0: "HP + 10%", 19 | 1: "HP + 30%", 20 | 2: "HP + 50%", 21 | 3: "MP + 10%", 22 | 4: "MP + 30%", 23 | 5: "MP + 50%", 24 | 6: "HP + 100%", 25 | 7: "LV - 1", 26 | 8: "LV + 50%", 27 | 9: "STR + 1", 28 | 0xA: "STR + 2", 29 | 0xB: "SPD + 1", 30 | 0xC: "SPD + 2", 31 | 0xD: "STA + 1", 32 | 0xE: "STA + 2", 33 | 0xF: "MAG + 1", 34 | 0x10: "MAG + 2"} 35 | 36 | spells = None 37 | used = set([]) 38 | used_bonuses = set([]) 39 | 40 | 41 | def get_candidates(myrank, set_lower=True): 42 | global used 43 | lower_bound, upper_bound = None, None 44 | if myrank in rankbounds: 45 | upper_bound = rankbounds[myrank] 46 | if upper_bound is None: 47 | upper_bound = 999 48 | 49 | if myrank-1 in rankbounds and set_lower: 50 | lower_bound = rankbounds[myrank-1] 51 | else: 52 | lower_bound = 0 53 | candidates = filter(lambda s: s.rank() in 54 | range(lower_bound, upper_bound), spells) 55 | fresh = filter(lambda s: s not in used, candidates) 56 | if not fresh: 57 | fresh = candidates 58 | 59 | return fresh 60 | 61 | 62 | class EsperBlock: 63 | def __init__(self, pointer, name, rank): 64 | self.pointer = hex2int(pointer) 65 | self.name = name 66 | self.rank = int(rank) 67 | 68 | def set_id(self, esperid): 69 | self.id = esperid 70 | 71 | def __repr__(self): 72 | assert len(self.spells) == len(self.learnrates) 73 | s = self.name.upper() + "\n" 74 | for spell, learnrate in zip(self.spells, self.learnrates): 75 | s += "{0:6} x{1}\n".format(spell.name, learnrate) 76 | s += "BONUS: " 77 | if self.bonus in bonus_strings: 78 | s += bonus_strings[self.bonus] 79 | else: 80 | s += "None" 81 | return s 82 | 83 | def read_data(self, filename): 84 | global spells 85 | f = open(filename, 'r+b') 86 | f.seek(self.pointer) 87 | if spells is None: 88 | spells = get_ranked_spells(filename, magic_only=True) 89 | self.spells, self.learnrates = [], [] 90 | for i in xrange(5): 91 | learnrate = ord(f.read(1)) 92 | spell = ord(f.read(1)) 93 | if spell != 0xFF and learnrate != 0: 94 | self.spells.append(get_spell(spell)) 95 | self.learnrates.append(learnrate) 96 | self.bonus = ord(f.read(1)) 97 | f.close() 98 | 99 | def write_data(self, fout): 100 | fout.seek(self.pointer) 101 | for learnrate, spell in zip(self.learnrates, self.spells): 102 | fout.write(chr(learnrate)) 103 | fout.write(chr(spell.spellid)) 104 | for i in xrange(5 - len(self.spells)): 105 | fout.write(chr(0x0)) 106 | fout.write(chr(0xFF)) 107 | fout.write(chr(self.bonus)) 108 | 109 | def get_candidates(self, rank, set_lower=True): 110 | candidates = get_candidates(rank, set_lower=set_lower) 111 | quick = [s for s in candidates if s.name == "Quick"] 112 | if quick: 113 | quick = quick[0] 114 | candidates.remove(quick) 115 | return candidates 116 | 117 | def generate_spells(self): 118 | global used 119 | 120 | self.spells, self.learnrates = [], [] 121 | rank = self.rank 122 | if random.randint(1, 5) == 5: 123 | rank += 1 124 | rank = min(rank, max(rankbounds.keys())) 125 | 126 | if random.randint(1, 10) != 10: 127 | candidates = self.get_candidates(rank) 128 | if candidates: 129 | s = random.choice(candidates) 130 | self.spells.append(s) 131 | used.add(s) 132 | 133 | rank = self.rank 134 | for _ in xrange(random.randint(0, 2) + random.randint(0, 2)): 135 | candidates = self.get_candidates(rank, set_lower=False) 136 | if candidates: 137 | s = random.choice(candidates) 138 | if s in self.spells: 139 | continue 140 | self.spells.append(s) 141 | used.add(s) 142 | 143 | self.spells = sorted(self.spells, key=lambda s: s.spellid) 144 | self.learnrates = [] 145 | esperrank = rankbounds[self.rank] 146 | if esperrank is None: 147 | esperrank = rankbounds[self.rank-1] 148 | esperrank = esperrank * 3 149 | for s in self.spells: 150 | spellrank = s.rank() 151 | learnrate = int(esperrank / float(spellrank)) 152 | learnrate = random.randint(0, learnrate) + random.randint(0, learnrate) 153 | while random.randint(1, 3) == 3: 154 | learnrate += 1 155 | learnrate = max(1, min(learnrate, 20)) 156 | self.learnrates.append(learnrate) 157 | 158 | def generate_bonus(self): 159 | rank = self.rank 160 | candidates = set(bonus_ranks[rank]) 161 | candidates = candidates - used_bonuses 162 | if candidates: 163 | candidates = sorted(candidates) 164 | self.bonus = random.choice(candidates) 165 | used_bonuses.add(self.bonus) 166 | return 167 | 168 | if random.randint(1, 2) == 2: 169 | rank += 1 170 | while random.randint(1, 10) == 10: 171 | rank += 1 172 | rank = min(rank, 4) 173 | candidates = [] 174 | for i in range(rank+1): 175 | candidates.extend(bonus_ranks[i]) 176 | if candidates: 177 | self.bonus = random.choice(candidates) 178 | used_bonuses.add(self.bonus) 179 | 180 | def add_spell(self, spellid, learnrate): 181 | spell = [s for s in spells if s.spellid == spellid][0] 182 | spellrates = zip(self.spells, self.learnrates) 183 | if len(spellrates) == 5: 184 | spellrates = sorted(spellrates, key=lambda (s, l): s.rank()) 185 | spellrates = spellrates[1:] 186 | spellrates.append((spell, learnrate)) 187 | spellrates = sorted(spellrates, key=lambda (s, l): s.spellid) 188 | self.spells, self.learnrates = zip(*spellrates) 189 | -------------------------------------------------------------------------------- /decompress.py: -------------------------------------------------------------------------------- 1 | from utils import read_multi, write_multi 2 | from sys import argv 3 | from shutil import copyfile 4 | 5 | 6 | def decompress(bytestring, simple=False, complicated=True, debug=False): 7 | result = "" 8 | buff = [chr(0)] * 2048 9 | buffaddr = 0x7DE 10 | 11 | while bytestring: 12 | flags, bytestring = ord(bytestring[0]), bytestring[1:] 13 | for i in xrange(8): 14 | if not bytestring: 15 | break 16 | 17 | if flags & (1 << i): 18 | byte, bytestring = bytestring[0], bytestring[1:] 19 | result += byte 20 | buff[buffaddr] = byte 21 | buffaddr += 1 22 | if buffaddr == 0x800: 23 | buffaddr = 0 24 | if debug: 25 | print "%x" % ord(byte), 26 | else: 27 | low, high, bytestring = ( 28 | ord(bytestring[0]), ord(bytestring[1]), bytestring[2:]) 29 | seekaddr = low | ((high & 0x07) << 8) 30 | length = ((high & 0xF8) >> 3) + 3 31 | if simple: 32 | copied = "".join([buff[seekaddr]] * length) 33 | elif complicated: 34 | if buffaddr == seekaddr: 35 | raise Exception("buffaddr equals seekaddr") 36 | cycle = buffaddr - seekaddr 37 | if cycle < 0: 38 | cycle += 0x800 39 | subbuff = "".join((buff+buff)[seekaddr:seekaddr+cycle]) 40 | while len(subbuff) < length: 41 | subbuff = subbuff + subbuff 42 | copied = "".join(subbuff[:length]) 43 | else: 44 | copied = "".join((buff+buff)[seekaddr:seekaddr+length]) 45 | assert len(copied) == length 46 | result += copied 47 | if debug: 48 | print "%x" % seekaddr, length, 49 | while copied: 50 | byte, copied = copied[0], copied[1:] 51 | buff[buffaddr] = byte 52 | buffaddr += 1 53 | if buffaddr == 0x800: 54 | buffaddr = 0 55 | if debug: 56 | print "%x" % ord(byte), 57 | if debug: 58 | print 59 | import pdb; pdb.set_trace() 60 | return result 61 | 62 | 63 | def recompress(bytestring): 64 | global buffaddr 65 | bytestring = "".join([chr(c) if type(c) is int else c for c in bytestring]) 66 | result = "" 67 | buff = [chr(0)] * 2048 68 | buffaddr = 0x7DE 69 | 70 | def add_buff(c): 71 | global buffaddr 72 | buff[buffaddr] = c 73 | buffaddr += 1 74 | buffaddr = buffaddr % 0x800 75 | 76 | while bytestring: 77 | control = 0x00 78 | subresult = "" 79 | for i in xrange(8): 80 | searchbuff = "".join(buff + buff) 81 | for j in xrange(3, 35): 82 | searchstr = bytestring[:j] 83 | if searchstr not in searchbuff: 84 | break 85 | location = searchbuff.find(searchstr) 86 | if location == buffaddr: 87 | location = searchbuff[location+1:].find(searchstr) 88 | if location < 0: 89 | break 90 | location = buffaddr + location + 1 91 | if location % 0x800 == buffaddr: 92 | break 93 | else: 94 | j = 0 95 | j = j - 1 96 | goodloop = None 97 | loopbuff = "".join(buff[:buffaddr]) 98 | #if len(loopbuff) < 35: 99 | # loopbuff = "".join(buff) + loopbuff 100 | for k in xrange(j+1, 35): 101 | searchstr = bytestring[:k] 102 | for h in xrange(1, len(searchstr)+1): 103 | loopstr = searchstr[:h] 104 | mult = (len(searchstr) / len(loopstr)) + 1 105 | if searchstr == (loopstr * mult)[:len(searchstr)]: 106 | if loopbuff.endswith(loopstr): 107 | j = k 108 | goodloop = loopstr 109 | if len(bytestring) <= 8: 110 | j = 0 111 | if j >= 3: 112 | substr = bytestring[:j] 113 | bytestring = bytestring[j:] 114 | if not goodloop: 115 | index = searchbuff.find(substr) 116 | if index % 0x800 == buffaddr: 117 | index = searchbuff[index+1:].find(substr) 118 | index += buffaddr + 1 119 | assert index >= 0 120 | assert index % 0x800 != buffaddr 121 | else: 122 | index = len(loopbuff) - len(goodloop) 123 | if index < 0: 124 | index += 0x800 125 | index = index % 0x800 126 | 127 | try: 128 | assert 0 <= index < 0x800 129 | assert (j-3) & 0xFFE0 == 0 130 | except: 131 | import pdb; pdb.set_trace() 132 | value = index << 5 133 | value = value | (j - 3) 134 | while substr: 135 | c = substr[0] 136 | substr = substr[1:] 137 | add_buff(c) 138 | byte1 = index & 0xFF 139 | byte2 = (index >> 8) | ((j-3) << 3) 140 | assert byte1 | ((byte2 & 0x07) << 8) == index 141 | assert ((byte2 & 0xF8) >> 3) + 3 == j 142 | subresult += chr(byte1) + chr(byte2) 143 | else: 144 | control |= (1 << i) 145 | if bytestring: 146 | c, bytestring = bytestring[0], bytestring[1:] 147 | else: 148 | c = chr(0) 149 | subresult += c 150 | add_buff(c) 151 | result += chr(control) + subresult 152 | if not bytestring and ( 153 | control != 0xFF 154 | or not subresult.endswith("".join([chr(0), chr(0)]))): 155 | result += chr(0xFF) + "".join(map(chr, [0]*8)) 156 | return result 157 | 158 | 159 | def decompress_at_location(filename, address): 160 | f = open(filename, 'r+b') 161 | f.seek(address) 162 | size = read_multi(f, length=2) 163 | #print "Size is %s" % size 164 | bytestring = f.read(size) 165 | decompressed = decompress(bytestring, complicated=True) 166 | return decompressed 167 | 168 | 169 | class Decompressor(): 170 | def __init__(self, address, fakeaddress=None, maxaddress=None): 171 | self.address = address 172 | self.fakeaddress = fakeaddress 173 | self.maxaddress = maxaddress 174 | self.data = None 175 | 176 | def read_data(self, filename): 177 | self.data = decompress_at_location(filename, self.address) 178 | self.backup = str(self.data) 179 | #assert decompress(recompress(self.backup)) == self.backup 180 | 181 | def writeover(self, address, to_write): 182 | to_write = "".join([chr(c) if type(c) is int else c for c in to_write]) 183 | if self.fakeaddress: 184 | address = address - self.fakeaddress 185 | self.data = (self.data[:address] + to_write + 186 | self.data[address+len(to_write):]) 187 | 188 | def get_bytestring(self, address, length): 189 | if self.fakeaddress: 190 | address = address - self.fakeaddress 191 | return map(ord, self.data[address:address+length]) 192 | 193 | def compress_and_write(self, fout): 194 | compressed = recompress(self.data) 195 | size = len(compressed) 196 | #print "Recompressed is %s" % size 197 | if self.maxaddress: 198 | length = self.maxaddress - self.address 199 | fout.seek(self.address) 200 | fout.write("".join([chr(0xFF)]*length)) 201 | fout.seek(self.address) 202 | write_multi(fout, size, length=2) 203 | fout.write(compressed) 204 | if self.maxaddress and fout.tell() >= self.maxaddress: 205 | raise Exception("Recompressed data out of bounds.") 206 | 207 | if __name__ == "__main__": 208 | sourcefile = argv[1] 209 | outfile = argv[2] 210 | copyfile(sourcefile, outfile) 211 | d = Decompressor(0x2686C, fakeaddress=0x7E5000, maxaddress=0x28A70) 212 | d.read_data(sourcefile) 213 | print ["%x" % i for i in d.get_bytestring(0x7E7C43, 0x20)] 214 | d.writeover(0x7E50F7, [0x0] * 57) 215 | d.writeover(0x7E501A, [0xEA] * 3) 216 | d.compress_and_write(outfile) 217 | -------------------------------------------------------------------------------- /tables/mapnames.txt: -------------------------------------------------------------------------------- 1 | 000:World of Balance 2 | 001:World of Ruin 3 | 002:Serpent Trench 4 | 006:Setzer's Airship (black background) 5 | 007:Setzer's Airship--Rooms 6 | 009:Scenario Selection Screen 7 | 00A:Setzer's Airship, flying through the sky 8 | 00B:Darryl's Airship, with Darryl at the helm 9 | 00C:Setzer's Airship--Casino Room (no exits) 10 | 00D:Setzer's Airship, party standing on deck 11 | 00E:Chocobo Stable (World of Balance) 12 | 00F:Houses in South Figaro 13 | 010:Chocobo Stable (World of Ruin) 14 | 011:Airship (World of Ruin, Bahamut magicite received) 15 | 012:Narshe (WoB)-Mountaintop cliff (from intro) 16 | 013:Narshe (WoB) (from intro--some places are inaccessible) 17 | 014:Narshe (WoB) (normal) 18 | 015:Narshe-Mountains between Narshe and the caves above Narshe 19 | 016:Narshe-Mountaintop maze above Narshe 20 | 017:Narshe-Mountaintop cliff (normal) 21 | 018:Narshe-Weapon Shop 22 | 019:Narshe-Armor Shop 23 | 01A:Narshe-Item Shop 24 | 01B:Narshe-Relic Shop 25 | 01C:Narshe-Inn 26 | 01D:Narshe-Cafe 27 | 01E:Narshe-Elder's House 28 | 01F:Chocobo Stable 29 | 020:Narshe (WoR) 30 | 021:Narshe (WoR)-Mountains between Narshe and the caves above Narshe 31 | 022:Narshe (WoR)-Mountaintop maze above Narshe (Ice Dragon) 32 | 023:Narshe (WoR)-Mountaintop cliff 33 | 024:Narshe Caves (Mag Roader?) 34 | 025:Underneath Narshe 35 | 026:Moogle's Cave 36 | 027:Narshe-Mountain Path to Maze 37 | 028:Narshe Caves (no enemies) 38 | 029:Narhse Caves (beginning) 39 | 02C:Underneath Narshe (doesn't work) 40 | 02F:South Figaro (doesn't work) 41 | 032:Underneath Narshe 42 | 037:Figaro Castle 43 | 039:Figaro Castle-various rooms 44 | 03B:Figaro Castle-various rooms 45 | 03D:Figaro Castle-various basement rooms 46 | 044:Cave to South Figaro (World of Ruin) 47 | 045:Cave to South Figaro (World of Balance) 48 | 04A:South Figaro (World of Ruin) 49 | 04B:South Figaro (World of Balance) 50 | 051:South Figaro-Large House 51 | 053:South Figaro-Large House, basement 52 | 054:South Figaro-Duncan's House, basement 53 | 056:South Figaro-Duncan's House 54 | 058:South Figaro-Inn 55 | 05E:Nikeah (?)-Some rooms (as well as Cid's house on the Solitary Island) 56 | 060:Mt. Kolts 57 | 061:Mt. Kolts with Fog 58 | 062:Mt. Kolts-last area (where Vargas is) 59 | 064:Mt. Kolts-Inner caves 60 | 069:Classroom-Advanced Battle Tactics 61 | 06A:Classroom-Battle Tactics 62 | 06B:Classroom-Environmental Science 63 | 06D:Returners' Hideout 64 | 06F:Returners' Hideout-Inn 65 | 071:Lete River 66 | 072:Lete River-Inner Caves 67 | 073:Crazy Old Man's House 68 | 074:Albrook-Shops 69 | 075:Imperial Camp 70 | 078:Doma Castle-from poison scene? 71 | 079:Doma Castle-World of Balance 72 | 07B:Doma Castle-inner rooms 73 | 07D:Doma Castle-dimmed with enemies (from Cyan's dream) 74 | 07E:Doma Castle-dimmed rooms with enemies (from Cyan's dream) 75 | 07F:Duncan's House--World of Ruin 76 | 083:Crazy Old Man's House--World of Ruin 77 | 084:Phantom Forest--Entrance 78 | 085:Phantom Forest--Recovery Spring 79 | 086:Phantom Forest--Exit 80 | 087:Phantom Forest--to train platform 81 | 089:Phantom Train Platform--Train left, Cyan sad 82 | 08E:Phantom Train 83 | 090:Phantom Train--Switch car, from Cyan's dream 84 | 091:Phantom Train--Seating car 85 | 092:Phantom Train--Engine room 86 | 093:Phantom Train--Dining car 87 | 095:Phantom Train--Seating car 2 88 | 097:Phantom Train--Rroom car 1 89 | 098:Phantom Train--Car with ghost 90 | 099:Phantom Train--Save point 91 | 09B:Baren Falls--Cave 92 | 09C:Baren Falls--Cliff 93 | 09D:Mobliz--World of Balance 94 | 09E:Mobliz--World of Ruin 95 | 09F:Riverbank where Gau finds the party 96 | 0A0:Mobliz--Inn 97 | 0A1:Mobliz--Arsenal 98 | 0A2:Mobliz--Relics 99 | 0A3:Mobliz--Armor Shop 100 | 0A4:Mobliz--Item Shop 101 | 0A5:Mobliz--Wounded Soldier's House 102 | 0A6:Baren Falls--Entrance 103 | 0A7:Mt. Crescent 104 | 0A8:River leading to Serpent Trench 105 | 0A9:Nikeah--World of Balance 106 | 0AA:Riverbank with Clyde and Baram 107 | 0AF:Serpent Trench--Caves 108 | 0B0:Mt. Zozo--Outside 109 | 0B1:Mt. Zozo--Outside, cliff with treasure chest 110 | 0B2:Mt. Zozo--Outside, cliff connecting dragon room to Cyan's room 111 | 0B3:Mt. Zozo--First inner chamber 112 | 0B5:Mt. Zozo--Cliff outside Cyan's room 113 | 0B9:Colloseum Builder's House--World of Balance 114 | 0BB:Nikeah--Port 115 | 0BC:Kohlingen--World of Balance 116 | 0BD:Kohlingen--World of Ruin 117 | 0BF:Kohlingen--Inn 118 | 0C0:Kohlingen--? 119 | 0C1:Kohlingen--Arsenal 120 | 0C2:Kohlingen--General Store 121 | 0C6:Jidoor--World of Balance 122 | 0C8:Jidoor--Auction House 123 | 0C9:Jidoor--Item Shop 124 | 0CA:Jidoor--Relics 125 | 0CB:Jidoor--Armor Shop 126 | 0CC:Jidoor--Weapon Shop 127 | 0CE:Jidoor--Inn 128 | 0CF:Jidoor--Owzer's House (dimmed, enemies) 129 | 0D0:Jidoor--Owzer's House (dimmed, no enemies) 130 | 0D1:Jidoor--Owzer's House 131 | 0D7:Airship flying scene 132 | 0D8:Gestahl, Madonna, and Maduin outside Esperville 133 | 0D9:Esperville 134 | 0DA:Esper Cave 135 | 0DB:Esperville Houses 136 | 0DD:Zozo 137 | 0E1:Zozo--Buildings 138 | 0E2:Zozo--Buildings 139 | 0E7:Opera House--Stage, dancing 140 | 0E9:Opera House--Stage, fighting 141 | 0EB:Opera House--Rafters 142 | 0EC:Opera House--Castle Scene 143 | 0EF:Opera House--Rafters (alone) 144 | 0F2:Vector 145 | 0F3:Vector--Imperial Castle 146 | 0F4:Vector--Imperial Castle, roof 147 | 0F5:Vector--Inn 148 | 0F6:Vector--Weapon Shop 149 | 0F7:Vector--Cafe 150 | 0F8:Vector--Armor Shop 151 | 0F9:Vector--? 152 | 0FA:Vector--Imperial Castle, inside 153 | 0FD:Vector--on fire 154 | 106:Magitek Factory--Inside 155 | 107:Magitek Factory--Inside, 2nd 156 | 108:Magitek Factory--Chamber where Shiva and Ifrit are found 157 | 10A:Magitek Factory--Elevator with Cid 158 | 112:Magitek Research Facility--Tube Room 159 | 114:The place Zone Eater sucks you into 160 | 116:Gogo's Room 161 | 119:Umaro's Lair 162 | 11C:Maranda--World of Balance 163 | 11D:Doma (after liberation?) 164 | 11F:Kefka's Domain 165 | 120:(?)--Inn 166 | 121:(?)--Weapon Shop 167 | 122:(?)--Armor Shop 168 | 125:Kefka's Domain 169 | 126:Kefka's Domain 170 | 127:Kefka's Domain 171 | 128:Kefka's Domain 172 | 129:Daryll's Tomb 173 | 12A:Daryll's Tomb--Basement 1 174 | 12B:Daryll's Tomb--Basement 2 175 | 12C:Daryll's Tomb--Basement 3 176 | 12D:Daryll's Tomb--Long Staircase 177 | 12F:Kefka's Domain 178 | 131:Tzen--World of Ruin, predestruction 179 | 132:Tzen--World of Ruin, postdestruction 180 | 133:Jidoor (WoR)--Item Shop 181 | 134:Jidoor (WoR)--Inn 182 | 135:Jidoor (WoR)--Weapon Shop 183 | 136:Jidoor (WoR)--Armor Shop 184 | 138:Jidoor (WoR)--Relics 185 | 139:Phoenix Cave--Small Lava Room 186 | 13A:Phoenix Cave--Foggy Lava Room 187 | 13B:Phoenix Cave--Top Level 188 | 13E:Phoenix Cave--Entrance 189 | 13F:Mountain Cliff from Cyan's dream 190 | 140:Mines from Cyan's dream 191 | 141:Switch car from Cyan's dream 192 | 142:Seating car from Cyan's dream 193 | 143:Albrook--World of Balance 194 | 144:Albrook--World of Ruin 195 | 145:Albrook--Inn 196 | 146:Albrook--Weapon Shop 197 | 147:Albrook--Armor Shop 198 | 148:Albrook--Item Shop 199 | 14A:Albrook--Cafe 200 | 14C:Albrook--Docks 201 | 14E:Kefka's Domain--Main Area 202 | 150:Final Room--Confrontation with Kefka 203 | 151:Kefka's Domain--Room with Weights and Switches 204 | 154:Thamasa--World of Balance 205 | 155:Thamasa--World of Balance (people lying on ground) 206 | 157:Thamasa--World of Balance 207 | 158:Thamasa--World of Ruin 208 | 159:Thamasa--Arsenal 209 | 15A:Thamasa--Inn 210 | 15B:Thamasa--Item Shop 211 | 15C:Thamasa--Elder's House 212 | 15F:Thamasa--Burning House 213 | 160:Magitek Research Facility 214 | 161:Cave in the Veldt 215 | 162:Kefka's Domain--Goddess room, etc. 216 | 164:Final Room--Confrontation with Kefka 217 | 165:Final Room--Confrontation with Kefka 218 | 166:Floating Island--Save Point 219 | 167:Fanatics Tower 220 | 168:Fanatics Tower 221 | 169:Fanatics Tower 222 | 16A:Fanatics Tower--Entrance 223 | 16B:Fanatics Tower 224 | 16C:Fanatics Tower--Roof 225 | 16D:Fanatics Tower--Treasure Room 226 | 16E:Fanatics Tower--Treasure Room, on roof 227 | 16F:Fanatics Tower--Treasure Room 228 | 170:Fanatics Tower--Treasure Room, White Dragon 229 | 171:Fanatics Tower--Treasure Room 230 | 172:Fanatics Tower--Treasure Room 231 | 173:Cave near Thamasa, with the Three Statues 232 | 175:Cave near Thamasa, outside cliffs, left 233 | 176:Cave near Thamasa, outside cliffs, right 234 | 177:Cave near Thamasa, Esper room 235 | 179:Imperial Base 236 | 17A:Rooms in Vector and Imperial Base 237 | 17B:Rooms in Vector and Imperial Base 238 | 17C:Large Overworld Map (from Floating Island) 239 | 17E:Cave to the Sealed Gate 240 | 17F:Cave to the Sealed Gate--Basement 1 241 | 180:Cave to the Sealed Gate--Basement 1 (Lava colored) 242 | 181:Cave to the Sealed Gate--Small Lava Room with moving bridges 243 | 182:Cave to the Sealed Gate--Basement 4 244 | 183:Cave to the Sealed Gate--Basement 4 245 | 186:Land that rises and breaks for the World of Ruin 246 | 187:Sealed Gate 247 | 188:Jidoor--Floating Island casting shadow 248 | 189:Floating Island--being destroyed, Naughtys attack 249 | 18A:Floating Island 250 | 18B:Piece of land that gets torn apart 251 | 18C:Cid's House on Solitary Island--Outside 252 | 18E:Solitary Island--Beach 253 | 18F:Solitary Island--Cliff 254 | 190:Solitary Island--Beach 255 | 191:Caves to the Ancient Castle 256 | 192:Caves to the Ancient Castle 257 | 194:Hidon's Cave 258 | 195:Hidon's Cave 259 | 196:Ancient Castle--Basement 1 260 | 197:Ancient Castle--Entrance 261 | 198:Ancient Castle--Basement 1 262 | 199:Kefka's Domain--Pipe Room 263 | 19A:Kefka's Domain 264 | 19D:Colloseum--Rooms 265 | -------------------------------------------------------------------------------- /tables/moves.txt: -------------------------------------------------------------------------------- 1 | 1000 2 | A 3 | Absolute 4 | Absorb 5 | Ace 6 | Acid 7 | Acrobatics 8 | Aerial 9 | Aero 10 | Aether 11 | After 12 | Agility 13 | Air 14 | Ally 15 | Amnesia 16 | Anchor 17 | Ancient 18 | Angel 19 | Aqua 20 | Arctic 21 | Arise 22 | Arm 23 | Armor 24 | Aromatic 25 | Arrows 26 | Ascent 27 | Assassin 28 | Atomic 29 | Attack 30 | Aura 31 | Aurora 32 | Avalanche 33 | Away 34 | B 35 | Baba 36 | BabyDoll 37 | Back 38 | Backlash 39 | Bad 40 | Ball 41 | Bane 42 | Banish 43 | Bare 44 | Barrage 45 | Barrier 46 | Bash 47 | Bath 48 | Baton 49 | Battle 50 | Beak 51 | Beam 52 | Bear 53 | Beat 54 | Beatdown 55 | Belch 56 | Bell 57 | Belly 58 | Berserk 59 | Bestow 60 | Bide 61 | Big 62 | Bind 63 | Bio 64 | Bird 65 | Bite 66 | Blade 67 | Blades 68 | Blast 69 | Blaze 70 | Blind 71 | Blinder 72 | Blinding 73 | Blitz 74 | Blizzard 75 | Block 76 | Blood 77 | Bloop 78 | Blossom 79 | Blow 80 | Blue 81 | Body 82 | Boiled 83 | Bolt 84 | Bomb 85 | Bond 86 | Bone 87 | Boog 88 | Boom 89 | Boost 90 | Booty 91 | Bounce 92 | Brain 93 | Brave 94 | Break 95 | Breath 96 | Brick 97 | Brine 98 | Bubble 99 | Bug 100 | Bulk 101 | Bull 102 | Bullet 103 | Burn 104 | Burst 105 | Butt 106 | Buzz 107 | C 108 | Calm 109 | Calmness 110 | Cannon 111 | Captivate 112 | Capture 113 | Card 114 | Cast 115 | Cat 116 | Change 117 | Chant 118 | Charge 119 | Charm 120 | Chatter 121 | Chill 122 | Chip 123 | Choke 124 | Chomp 125 | Chop 126 | Cinder 127 | Circle 128 | Clamp 129 | Claw 130 | Claws 131 | Clean 132 | Clear 133 | Cleaver 134 | Climb 135 | Cling 136 | Clobber 137 | Close 138 | Cloudy 139 | Club 140 | Coat 141 | Coil 142 | Cold 143 | Combat 144 | Combo 145 | Comet 146 | Compress 147 | Condemned 148 | Confuclaw 149 | Confuse 150 | Confusion 151 | Constrict 152 | Corkscrew 153 | Cosmic 154 | Cotton 155 | Counter 156 | Covet 157 | Crab 158 | Crafty 159 | Crash 160 | Crazed 161 | Cross 162 | Crunch 163 | Crush 164 | Crypt 165 | Crystal 166 | Curl 167 | Curse 168 | Cursed 169 | Cut 170 | Cutter 171 | Cyclone 172 | D 173 | Dagger 174 | Dance 175 | Dancing 176 | Dark 177 | Dash 178 | Day 179 | Daze 180 | Dazzling 181 | Dead 182 | Deadly 183 | Death 184 | Defend 185 | Defense 186 | Defog 187 | Delta 188 | Deluge 189 | Demi 190 | Demon 191 | Demonic 192 | Desire 193 | Desperate 194 | Destiny 195 | Destroy 196 | Destruct 197 | Deva 198 | Devastate 199 | Devil 200 | Diablo 201 | Diabolic 202 | Diamond 203 | Diffuser 204 | Dig 205 | Digestive 206 | Direct 207 | Dirk 208 | Disable 209 | Disarming 210 | Discard 211 | Discharge 212 | Dispatch 213 | Dissolve 214 | Dive 215 | Dizzy 216 | Doom 217 | Double 218 | Down 219 | Doze 220 | Draco 221 | Dragon 222 | Drain 223 | Drainbeak 224 | Draining 225 | Dread 226 | Dream 227 | Drench 228 | Drill 229 | Drive 230 | Drool 231 | Drop 232 | Drum 233 | Dry 234 | Dual 235 | Dust 236 | Duster 237 | Dynamic 238 | E 239 | Earth 240 | East 241 | Eastern 242 | Eater 243 | Echoed 244 | Edge 245 | Eerie 246 | Egg 247 | Electric 248 | Electro 249 | Electrode 250 | Elf 251 | Ember 252 | End 253 | Energy 254 | Engulf 255 | Entangle 256 | Entice 257 | Eruption 258 | Escape 259 | Ether 260 | Evil 261 | Ex 262 | Exploder 263 | Extra 264 | Extract 265 | Extreme 266 | Eye 267 | Eyes 268 | Eyeshadow 269 | F 270 | Face 271 | Fairy 272 | Fake 273 | Fall 274 | Fallen 275 | False 276 | Fang 277 | Fatal 278 | Fear 279 | Feast 280 | Feather 281 | Feeler 282 | Feint 283 | Fell 284 | Field 285 | Fiend 286 | Fiendish 287 | Fiery 288 | Figaro 289 | Final 290 | Fire 291 | Fireball 292 | First 293 | Fish 294 | Fissure 295 | Flail 296 | Flame 297 | Flap 298 | Flare 299 | Flash 300 | Flee 301 | Fling 302 | Flower 303 | Fluid 304 | Flux 305 | Fly 306 | Flying 307 | Focus 308 | Follow 309 | Footsteps 310 | Force 311 | Fore 312 | Forest 313 | Forged 314 | Forsaken 315 | Forty 316 | Fossil 317 | Foul 318 | Freeze 319 | Freezing 320 | Frenzy 321 | Frisky 322 | Frost 323 | Full 324 | Fuma 325 | Fury 326 | Fusion 327 | Future 328 | G 329 | GP 330 | Gale 331 | Gambit 332 | Gamma 333 | Gas 334 | Gastro 335 | Gauche 336 | Gaze 337 | Gear 338 | Geist 339 | Gem 340 | Ghost 341 | Gift 342 | Giga 343 | Gil 344 | Glare 345 | Gleam 346 | Glow 347 | Gold 348 | Golden 349 | Goner 350 | Goo 351 | Gouge 352 | Grab 353 | Grand 354 | Grass 355 | Grassy 356 | Grav 357 | Gravity 358 | Green 359 | Grind 360 | Grip 361 | Growl 362 | Growth 363 | Grudge 364 | Guard 365 | Guardian 366 | Guillotine 367 | Gulf 368 | Gun 369 | Gunk 370 | Gust 371 | Gut 372 | Gyro 373 | H 374 | Hail 375 | Hailstone 376 | Half 377 | Hammer 378 | Hand 379 | Hands 380 | Happy 381 | Hard 382 | Hardened 383 | Hare 384 | Harvester 385 | Havoc 386 | Hay 387 | Haymaker 388 | Haze 389 | Head 390 | Headbutt 391 | Heart 392 | Heartless 393 | Heat 394 | Heave 395 | Heaven 396 | Heavenly 397 | Heavy 398 | Helping 399 | Hex 400 | Hi 401 | Hidden 402 | High 403 | Hit 404 | Hits 405 | Hold 406 | Hole 407 | Holy 408 | Hone 409 | Horn 410 | Hour 411 | Howl 412 | Hurricane 413 | Husk 414 | Hydro 415 | Hyper 416 | Hypno 417 | I 418 | Icarus 419 | Ice 420 | Icicle 421 | Icy 422 | Imp 423 | Impact 424 | Impulse 425 | Incinerate 426 | Infernal 427 | Inferno 428 | Inhale 429 | Ink 430 | Insane 431 | Insanity 432 | Inviz 433 | Ion 434 | Iron 435 | J 436 | Jab 437 | Jarring 438 | Jet 439 | Judgment 440 | Jump 441 | K 442 | Kama 443 | Karate 444 | Karma 445 | Karmic 446 | Kick 447 | Kinesis 448 | King 449 | Kiss 450 | Kitty 451 | Knee 452 | Knife 453 | Knock 454 | Knockdown 455 | Knot 456 | Knuckle 457 | Knuckles 458 | Kunai 459 | L 460 | Lance 461 | Lancet 462 | Land 463 | Laser 464 | Lash 465 | Last 466 | Lava 467 | Leaf 468 | Leech 469 | Leer 470 | Lethal 471 | Libra 472 | Lick 473 | Life 474 | Light 475 | Lightning 476 | Lock 477 | Lode 478 | Look 479 | Love 480 | Lovely 481 | Low 482 | Lucky 483 | Lunar 484 | Luster 485 | M 486 | Mach 487 | Mad 488 | Magic 489 | Magical 490 | Magma 491 | Magnet 492 | Magnetic 493 | Main 494 | Maker 495 | Malt 496 | Mash 497 | Mat 498 | Maul 499 | Mean 500 | Mega 501 | Megaton 502 | Melt 503 | Meltdown 504 | Merton 505 | Metal 506 | Meteo 507 | Meteor 508 | Mezmer 509 | Mighty 510 | Mimic 511 | Mind 512 | Mindprick 513 | Mine 514 | Miracle 515 | Mirror 516 | Missile 517 | Mist 518 | Misty 519 | Mithril 520 | Moldy 521 | Moon 522 | Morn 523 | Morning 524 | Mouth 525 | Move 526 | Mud 527 | Muddle 528 | Muddy 529 | Mug 530 | Mute 531 | Mysterious 532 | Mystery 533 | Mystic 534 | Mythril 535 | N 536 | Nail 537 | Nasty 538 | Natural 539 | Nature 540 | Near 541 | Needle 542 | Needles 543 | Nega 544 | Nice 545 | Nickel 546 | Night 547 | Nightmare 548 | Ninja 549 | Noble 550 | Noise 551 | North 552 | Northern 553 | Numb 554 | Nuzzle 555 | O 556 | Oblivion 557 | Octo 558 | Odor 559 | Off 560 | Omega 561 | Ominous 562 | One 563 | Oogy 564 | Ooze 565 | Orb 566 | Order 567 | Ore 568 | Origin 569 | Osmose 570 | Out 571 | Outrage 572 | Over 573 | Overture 574 | P 575 | Pain 576 | Pal 577 | Palm 578 | Panic 579 | Para 580 | Parabolic 581 | Parting 582 | Pass 583 | Pause 584 | Pay 585 | Payback 586 | Pearl 587 | Peck 588 | Peep 589 | Pep 590 | Perish 591 | Petal 592 | Phantasm 593 | Phantom 594 | Pick 595 | Pike 596 | Pile 597 | Pin 598 | Pincer 599 | Plant 600 | Plasma 601 | Play 602 | Pledge 603 | Plex 604 | Plexus 605 | Plot 606 | Pluck 607 | Plume 608 | Pod 609 | Poison 610 | Polarity 611 | Polish 612 | Pollen 613 | Potion 614 | Pound 615 | Powder 616 | Power 617 | PowerUp 618 | Pox 619 | Precipice 620 | Press 621 | Protect 622 | Psy 623 | Psych 624 | Psycho 625 | Pulse 626 | Pummel 627 | Pump 628 | Punch 629 | Punish 630 | Punishment 631 | Purge 632 | Pursuit 633 | Q 634 | Quake 635 | Quarter 636 | Quartz 637 | Quash 638 | Quick 639 | Quiver 640 | R 641 | Rabbit 642 | Rage 643 | Raid 644 | Rain 645 | Raise 646 | Rake 647 | Ram 648 | Rampage 649 | Rapid 650 | Rave 651 | Ray 652 | Rays 653 | Razor 654 | Re 655 | Reader 656 | Red 657 | Redline 658 | Reflect 659 | Release 660 | Relic 661 | Remedy 662 | Rend 663 | Repose 664 | Reraise 665 | Resort 666 | Rest 667 | Retaliate 668 | Revenge 669 | Revenger 670 | Reversal 671 | Reverse 672 | Rib 673 | Ring 674 | Riot 675 | Rip 676 | Rise 677 | Roar 678 | Rock 679 | Role 680 | Roller 681 | Rolling 682 | Rollout 683 | Romp 684 | Room 685 | Roost 686 | Rough 687 | Round 688 | Ruin 689 | Run 690 | Rush 691 | S 692 | Sacred 693 | Safe 694 | Saint 695 | Saintly 696 | Sakura 697 | Sand 698 | Sap 699 | Sapping 700 | Sasuke 701 | Savage 702 | Scald 703 | Scan 704 | Scar 705 | Scary 706 | Scent 707 | Schiller 708 | Scissor 709 | Scissors 710 | Scratch 711 | Screech 712 | Screen 713 | Scroll 714 | Searing 715 | Secret 716 | Seed 717 | Seismic 718 | Seize 719 | Self 720 | Sensory 721 | Shade 722 | Shadow 723 | Shake 724 | Sham 725 | Shamshir 726 | Shard 727 | Sharp 728 | Sharpen 729 | Sharpened 730 | Shed 731 | Sheer 732 | Shell 733 | Shield 734 | Shift 735 | Shim 736 | Shock 737 | Shot 738 | Shrapnel 739 | Sickle 740 | Sight 741 | Sightless 742 | Signal 743 | Silence 744 | Silencer 745 | Silencing 746 | Silver 747 | Simple 748 | Sing 749 | Skean 750 | Skill 751 | Skull 752 | Sky 753 | Slack 754 | Slam 755 | Slap 756 | Slash 757 | Slay 758 | Slayer 759 | Sleep 760 | Sleeping 761 | Sleuth 762 | Slice 763 | Slide 764 | Slime 765 | Slimer 766 | Slip 767 | Sludge 768 | Slumber 769 | Smack 770 | Smash 771 | Smirk 772 | Smog 773 | Smoke 774 | Snap 775 | Snarl 776 | Snatch 777 | Sneak 778 | Sneeze 779 | Snore 780 | Snort 781 | Snow 782 | Soak 783 | Sobat 784 | Soft 785 | Solar 786 | Song 787 | Sonic 788 | Soul 789 | Sound 790 | Sour 791 | South 792 | Southern 793 | Space 794 | Spacial 795 | Spark 796 | Spear 797 | Speed 798 | Sphere 799 | Spider 800 | Spike 801 | Spikes 802 | Spiky 803 | Spin 804 | Spine 805 | Spines 806 | Spinning 807 | Spirit 808 | Spit 809 | Spite 810 | Splash 811 | Split 812 | Spore 813 | Sport 814 | Spout 815 | Spray 816 | Stamp 817 | Star 818 | Stealth 819 | Steam 820 | Steel 821 | Step 822 | Stick 823 | Sticky 824 | Sting 825 | Stinger 826 | Stock 827 | Stomp 828 | Stone 829 | Stored 830 | Storm 831 | Strength 832 | Strike 833 | Striker 834 | String 835 | Struggle 836 | Stun 837 | Submission 838 | Sucker 839 | Sun 840 | Sunbath 841 | Sunny 842 | Super 843 | Surf 844 | Surge 845 | Swagger 846 | Swallow 847 | Swap 848 | Sweep 849 | Sweet 850 | Swift 851 | Swing 852 | Swipe 853 | Swipes 854 | Swirl 855 | Switch 856 | Sword 857 | Swords 858 | Synchro 859 | Synthesis 860 | T 861 | Tack 862 | Tackle 863 | Tail 864 | Take 865 | Talk 866 | Talon 867 | Taunt 868 | Tea 869 | Team 870 | Tears 871 | Techno 872 | Teeter 873 | Tek 874 | Tele 875 | Tempest 876 | Tentacle 877 | Terrain 878 | Thief 879 | Thousand 880 | Thrash 881 | Throw 882 | Thrower 883 | Thrust 884 | Thruster 885 | Thunder 886 | Tickle 887 | Time 888 | Token 889 | Tomb 890 | Tongue 891 | Tonic 892 | Toot 893 | Topsy 894 | Torment 895 | Tornado 896 | Toss 897 | Touch 898 | Toxic 899 | Tradeoff 900 | Train 901 | Traveler 902 | Tri 903 | Trick 904 | Trine 905 | Triple 906 | Trump 907 | Tsunami 908 | Turvy 909 | Tusk 910 | Twin 911 | Twister 912 | Type 913 | Tyrfing 914 | U 915 | Ultra 916 | Umbrella 917 | Unseen 918 | Up 919 | Uppercut 920 | Uproar 921 | V 922 | Vacuum 923 | Vanish 924 | Vengeance 925 | Venom 926 | Venomist 927 | Vertical 928 | Vice 929 | Vine 930 | Virite 931 | Vital 932 | Voice 933 | Void 934 | Volt 935 | W 936 | Wail 937 | Waist 938 | WakeUp 939 | Wall 940 | Waltz 941 | Water 942 | Wave 943 | Waves 944 | Weather 945 | Web 946 | West 947 | Western 948 | Wheel 949 | Whip 950 | Whirl 951 | Whirling 952 | Whisp 953 | Whistle 954 | White 955 | Wide 956 | Wild 957 | Wind 958 | Wing 959 | Winks 960 | Wish 961 | Wonder 962 | Wood 963 | Work 964 | Worry 965 | Wrap 966 | Wrath 967 | Wrecker 968 | Wrecking 969 | Wrench 970 | Wring 971 | X 972 | Y 973 | Yawn 974 | Z 975 | Zap 976 | Zen 977 | Zerk 978 | Zero 979 | Zing 980 | Zinger 981 | Zombi 982 | Zombie 983 | Zombite 984 | Zone 985 | Zooka 986 | -------------------------------------------------------------------------------- /tables/customitems.txt: -------------------------------------------------------------------------------- 1 | # right, left, weapon palette, effect, effect palette, misc, sound, 0 2 | 3 | ! Gades Blade 4 | price ea60 5 | itemtype 11 6 | equippable 3fff 7 | statusacquire3 8 8 | special2 1 9 | elements 8 10 | otherproperties c2 11 | power c8 12 | specialaction 75 13 | hitmdef 96 14 | weapon_animation 2c 2c 2d 0 34 0 a4 0 15 | name_icon d9 16 | name_text Gades Blade 17 | description Sword of the evil Gades 18 | 19 | ! Dekar Blade 20 | price 3a98 21 | itemtype 31 22 | equippable 3fff 23 | breakeffect 10 24 | targeting 41 25 | otherproperties c2 26 | power bc 27 | specialaction 75 28 | hitmdef 96 29 | weapon_animation 20 20 22 0 33 0 a8 0 30 | name_icon df 31 | name_text Dekar Blade 32 | description Dekar's powerful sword 33 | 34 | ! Dragon Slave 35 | price 2 36 | itemtype 25 37 | equippable 141 38 | breakeffect 17 39 | learnspell 17 40 | learnrate 32 41 | targeting 04 42 | magstam 7f 43 | speedvigor 70 44 | statboost1 42 45 | statboost2 40 46 | special3 10 47 | statusacquire2 80 48 | statusacquire3 09 49 | elemabsorbs 01 50 | elemweaks 01 51 | name_icon e7 52 | name_text Dragon Slave 53 | description Darkness beyond twilight... 54 | 55 | ! Demonica 56 | price fde8 57 | itemtype 22 58 | equippable 3FFF 59 | breakeffect 18 60 | learnspell 18 61 | learnrate 2 62 | targeting 43 63 | magstam 77 64 | speedvigor 77 65 | fieldeffect DD 66 | statboost1 09 67 | statboost2 98 68 | statusacquire2 08 69 | statusacquire3 42 70 | special2 06 71 | special3 0d 72 | power 5a 73 | hitmdef 50 74 | mblockevade 12 75 | name_icon e4 76 | name_text Demonica 77 | 78 | ! FluoriteDice 79 | price 4570 80 | itemtype 31 81 | equippable 3fff 82 | breakeffect 3E 83 | targeting 6E 84 | fieldeffect 5E 85 | statboost2 19 86 | statusprotect1 80 87 | statusacquire2 04 88 | statusacquire3 01 89 | special1 03 90 | special2 07 91 | special3 18 92 | otherproperties 01 93 | power 58 94 | hitmdef 02 95 | mblockevade 55 96 | specialaction 90 97 | weapon_animation 12 12 00 b 00 81 5b 0 98 | name_icon e0 99 | name_text FluoriteDice 100 | 101 | ! SORD..... 102 | price 0 103 | itemtype 11 104 | equippable 3fff 105 | breakeffect 7F 106 | targeting 02 107 | fieldeffect 00 108 | statusacquire2 FF 109 | statusacquire3 FF 110 | special1 FF 111 | special2 00 112 | special3 FF 113 | elements FF 114 | power 00 115 | hitmdef 00 116 | magstam FF 117 | speedvigor FF 118 | mblockevade AA 119 | specialaction 50 120 | weapon_animation 61 61 b4 0 99 0 08,34,63,81,97,b8,b9,bf,f1 0 121 | name_icon d9 122 | name_text SORD..... 123 | 124 | ! Death Note 125 | price 2 126 | itemtype 25 127 | equippable 3FFF 128 | breakeffect 0D 129 | targeting 41 130 | fieldeffect 5E 131 | special3 88 132 | elemabsorbs 20 133 | elemweaks 20 134 | statusacquire2 01 135 | name_icon e7 136 | name_text Death Note 137 | 138 | ! White Lily 139 | price 2 140 | itemtype 25 141 | equippable 141 142 | breakeffect 06 143 | learnspell 0a 144 | learnrate 01 145 | targeting 41 146 | fieldeffect 01 147 | statboost1 42 148 | statboost2 04 149 | elemabsorbs 02 150 | elemweaks 0a 151 | elemnulls 25 152 | mblockevade 66 153 | statusacquire2 41 154 | name_icon e7 155 | name_text White Lily 156 | 157 | ! White Clover 158 | price 2 159 | itemtype 25 160 | equippable 141 161 | breakeffect 07 162 | learnspell 0b 163 | learnrate 01 164 | targeting 41 165 | fieldeffect 5D 166 | statboost1 02 167 | statboost2 24 168 | special2 40 169 | special3 10 170 | elemabsorbs 04 171 | elemweaks 04 172 | elemnulls 03 173 | name_icon e7 174 | name_text White Clover 175 | 176 | ! White Lotus 177 | price 2 178 | itemtype 25 179 | equippable 0abe 180 | breakeffect 05 181 | learnspell 09 182 | learnrate 01 183 | targeting 41 184 | statboost1 44 185 | statboost2 84 186 | speedvigor 07 187 | elemabsorbs 01 188 | elemweaks 01 189 | elemnulls 06 190 | name_icon e7 191 | name_text White Lotus 192 | 193 | ! OOO 194 | price 02 195 | itemtype 22 196 | equippable 3FFF 197 | breakeffect 3F 198 | targeting 2e 199 | magstam 77 200 | speedvigor 77 201 | fieldeffect DD 202 | statboost2 9F 203 | statusacquire2 04 204 | statusacquire3 6a 205 | special1 83 206 | special2 c7 207 | special3 78 208 | power 38 209 | hitmdef 26 210 | mblockevade 23 211 | name_icon e4 212 | name_text OOO 213 | 214 | ! Portal Gun 215 | price 2 216 | itemtype 11 217 | equippable 3fff 218 | breakeffect 52 219 | targeting 6a 220 | specialaction D0 221 | power 00 222 | hitmdef FF 223 | statboost2 10 224 | special2 02 225 | weapon_animation 15 15 1f 34 78 81 a3 0 226 | name_icon e5 227 | name_text Portal Gun 228 | 229 | ! Angel Arm 230 | price 2 231 | itemtype 11 232 | equippable 3fff 233 | breakeffect 54 234 | targeting 6e 235 | specialaction 75 236 | power FF 237 | hitmdef 96 238 | special2 42 239 | elements 20 240 | weapon_animation 15 15 29 34 33 82 19 0 241 | name_icon df 242 | name_text Angel Arm 243 | 244 | ! Red Duster 245 | price 2 246 | itemtype 22 247 | equippable 3FFF 248 | specialaction 07 249 | breakeffect 35 250 | learnspell 2B 251 | learnrate 1 252 | targeting 4 253 | magstam 07 254 | speedvigor 70 255 | fieldeffect DD 256 | statboost1 48 257 | statboost2 3F 258 | statusprotect1 80 259 | statusacquire2 04 260 | statusacquire3 6a 261 | special1 83 262 | special2 46 263 | otherproperties 01 264 | power 4e 265 | hitmdef 37 266 | mblockevade 55 267 | elemnulls 20 268 | elements d8 269 | name_icon e4 270 | name_text Red Duster 271 | 272 | ! Rose Shield 273 | price 2 274 | itemtype 23 275 | equippable 3FFF 276 | breakeffect 24 277 | learnspell 2F 278 | learnrate 05 279 | targeting 29 280 | specialaction 06 281 | power 50 282 | statusacquire3 84 283 | statboost2 08 284 | special2 40 285 | special3 03 286 | hitmdef FF 287 | mblockevade 51 288 | name_icon e2 289 | name_text Rose Shield 290 | 291 | ! Ukyo Spatula 292 | price 2 293 | itemtype 23 294 | equippable 141 295 | breakeffect 37 296 | specialaction 06 297 | statusacquire3 0a 298 | statboost1 91 299 | statboost2 84 300 | special1 80 301 | special2 07 302 | special3 10 303 | power 1c 304 | hitmdef 13 305 | mblockevade 12 306 | elemnulls 01 307 | magstam 07 308 | speedvigor 77 309 | name_icon e2 310 | name_text Ukyo Spatula 311 | 312 | ! KingOfGames 313 | price 2 314 | itemtype 24 315 | equippable 3FFF 316 | breakeffect 2B 317 | learnspell 12 318 | learnrate 05 319 | targeting 02 320 | fieldeffect 5C 321 | statboost2 0F 322 | statusprotect1 80 323 | statusacquire2 55 324 | statusacquire3 09 325 | special1 7F 326 | special2 FA 327 | special3 FF 328 | otherproperties 01 329 | power 0 330 | hitmdef 0 331 | mblockevade 0 332 | name_icon e3 333 | name_text KingOfGames 334 | 335 | ! Murderface 336 | price 2 337 | itemtype 4 338 | equippable 3FFF 339 | statboost1 01 340 | statboost2 91 341 | statusacquire2 10 342 | statusacquire3 08 343 | special1 80 344 | special2 03 345 | special3 90 346 | power 0 347 | hitmdef 0 348 | mblockevade 0 349 | name_icon e3 350 | name_text Murderface 351 | 352 | ! Neku Phones 353 | price 2 354 | itemtype 4 355 | equippable 3FFF 356 | statboost1 42 357 | statboost2 24 358 | special2 04 359 | power 0 360 | hitmdef 0 361 | mblockevade 50 362 | speedvigor 70 363 | name_icon e3 364 | name_text Neku Phones 365 | 366 | ! No.21 Wings 367 | price 2 368 | itemtype 2 369 | equippable 3FFF 370 | statusprotect1 80 371 | statboost1 10 372 | statusacquire3 05 373 | special1 80 374 | power 3a 375 | hitmdef 34 376 | mblockevade AA 377 | speedvigor f0 378 | name_icon e4 379 | name_text No.21 Wings 380 | 381 | ! Scenes Hat 382 | price 2 383 | itemtype 24 384 | equippable 3FFF 385 | breakeffect 23 386 | learnspell 1E 387 | learnrate 05 388 | targeting c0 389 | statboost2 0c 390 | statusacquire2 04 391 | special1 7C 392 | special2 FA 393 | special3 18 394 | power 13 395 | hitmdef 15 396 | mblockevade 0 397 | name_icon e3 398 | name_text Scenes Hat 399 | 400 | ! Contessa 401 | price 2 402 | itemtype 4 403 | equippable 141 404 | targeting 02 405 | fieldeffect 03 406 | statboost2 19 407 | statusacquire2 04 408 | statusacquire3 08 409 | special1 83 410 | special2 46 411 | power ff 412 | hitmdef ff 413 | mblockevade 55 414 | name_icon e3 415 | name_text Contessa 416 | 417 | ! Behaim Watch 418 | price 2 419 | itemtype 25 420 | breakeffect 2B 421 | targeting 01 422 | equippable 00 423 | name_icon df 424 | name_text Behaim Watch 425 | 426 | ! Wyvern Drug 427 | price 2 428 | itemtype 5 429 | equippable 3fff 430 | magstam 7f 431 | speedvigor 7f 432 | fieldeffect 01 433 | statboost1 42 434 | statboost2 21 435 | statusprotect1 04 436 | statusprotect2 10 437 | statusacquire2 61 438 | special1 81 439 | special2 46 440 | special3 18 441 | elemnulls 08 442 | mblockevade 55 443 | name_icon e7 444 | name_text Wyvern Drug 445 | 446 | ! Mary Ribbon 447 | price 2 448 | itemtype 4 449 | equippable 141 450 | speedvigor 77 451 | fieldeffect 01 452 | statboost1 01 453 | statboost2 80 454 | statusprotect1 01 455 | statusprotect2 80 456 | special1 83 457 | special2 57 458 | special3 0b 459 | mblockevade 55 460 | name_icon e3 461 | name_text Mary Ribbon 462 | 463 | ! Laylania 464 | price 2 465 | itemtype 22 466 | equippable 141 467 | breakeffect 39 468 | targeting 6e 469 | magstam 70 470 | statboost1 42 471 | statboost2 4c 472 | statusprotect2 08 473 | power 2f 474 | hitmdef 23 475 | elemabsorbs F1 476 | elemnulls 06 477 | name_icon e4 478 | name_text Laylania 479 | 480 | ! Page Jacket 481 | price 2 482 | itemtype 2 483 | equippable 3FFF 484 | speedvigor 30 485 | fieldeffect 80 486 | statboost1 08 487 | statusprotect1 67 488 | statusprotect2 88 489 | statusacquire2 01 490 | special2 40 491 | special3 80 492 | otherproperties 01 493 | power 37 494 | hitmdef 55 495 | elemabsorbs 20 496 | name_icon e4 497 | name_text Page Jacket 498 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ===== 2 | THIS FORK IS NO LONGER BEING MAINTAINED!! 3 | Go to https://github.com/subtractionsoup/beyondchaos ya goober! 4 | ===== 5 | 6 | 7 | FF6 Beyond Chaos Randomizer 8 | Version: 63 9 | Date: January 27, 2018 10 | URL: https://github.com/abyssonym/beyondchaos 11 | Contact: https://twitter.com/abyssonym 12 | https://www.twitch.tv/abyssonym 13 | 14 | --- QUICKSTART --- 15 | Running the randomizer: 16 | Windows users may use the executable file, "beyondchaos.exe". Other users, please run "randomizer.py" using Python version 2.7 17 | 18 | Source rom file: 19 | The randomizer will ask for a rom file. Beyond Chaos does not provide this rom. Put the file in the same directory as Beyond Chaos and simply input the file name. The rom used should be the FF3 US 1.0 rom. Both unheadered and headered roms will work. If you use an incorrect or modified rom, the randomizer will warn you before continuing. To be sure, you can check that your rom is correct by comparing the unheadered checksum/hash: 20 | MD5 - e986575b98300f721ce27c180264d890 21 | CRC32 - a27f1c7a 22 | 23 | Seed value: 24 | Next, the randomizer will ask for a seed value. If you don't know which seed you want, just leave this blank and the randomizer will choose one for you. The seed value is an integer number that can be used to share the same randomization with other people. It's like a signature for the game that Beyond Chaos creates. If you want to play the game along with a friend, you can use the same seed. 25 | 26 | Flags: 27 | Finally, the randomizer will ask for a list of flags. If you don't know which flags you want, just leave this blank and the randomizer will give you the standard setting: all flags. If you would like to customize your experience, here is a list of flags and what they do: 28 | o Shuffle characters' in-battle commands. 29 | w Generate new commands for characters, replacing old commands. 30 | z Always have "Sprint Shoes" effect. 31 | b Make the game more balanced by removing exploits such as Joker Doom, 32 | Vanish/Doom, and the Evade/Mblock bug. 33 | m Randomize enemy stats. 34 | c Randomize palettes and names of various things. 35 | i Randomize the stats of equippable items. 36 | q Randomize what equipment each character can wear and character stats. 37 | e Randomize esper spells and levelup bonuses. 38 | t Randomize treasure, including chests, colosseum, shops, and enemy drops. 39 | u Umaro risk. (Random character will be berserk) 40 | l Randomize blitz inputs. 41 | n Randomize window background colors. 42 | f Randomize enemy formations. 43 | s Swap character graphics around. 44 | p Randomize the palettes of spells and weapon animations. 45 | d Randomize final dungeon. 46 | a Organize rages alphabetically (default) 47 | h Organize rages by highest level first 48 | g Randomize dances 49 | k Randomize the clock in Zozo 50 | 51 | Output rom file: 52 | The randomizer generates two files, a patched rom file, and a mini-FAQ. Both files will have the seed value in their name. To play the game, load the patched rom file in your emulator. The mini-FAQ is a text file that mainly includes information about where to get items; colosseum rewards, monster steals and drops, shop info, and monster rages are all included. 53 | 54 | --- OVERVIEW --- 55 | 56 | Beyond Chaos is a randomizer, a program that remixes game content randomly, for FF6. Every time you run Beyond Chaos, it will generate a completely unique, brand-new mod of FF6 for you to challenge and explore. There are over 10 billion different possible randomizations! Nearly everything is randomized, including treasure, enemies, colors, graphics, character abilities, and more. 57 | Beyond Chaos is also customizable. Using the flags in the above section, you can choose to only randomize certain parts of the game. Every flag you select will make the game a little more random, and also a little more difficult. Therefore, even experienced players should be able to find some challenge in the resulting game. As the game progresses, enemies may become more and more difficult, so that it becomes necessary to develop specialized strategies for individual formations. 58 | Because of the extent and the severity of the modifications made by Beyond Chaos, it is not recommended for competitive play. It is mainly intended for casual play, though if you would like to play it competitively anyway, go for it. Also note that there is another FF6 randomizer intended for races, made by Dessyreqt and Lenophis, that makes more conservative changes. That one is simply called "FF6 Randomizer", or "FF6 Rando Classic Original Flavor". 59 | 60 | --- OBJECTIVES --- 61 | 62 | 1. To remix game content so thoroughly that even veteran FF6 fans can feel as though they are playing the game for the first time all over again. 63 | 2. To create a challenging and festive result that encourages memorable scenarios, without making the game impossible for a casual player to complete. 64 | 3. To create a tool that is useful to the FF6 rom hacking community by being both open source and accessible, and by showing off a wide variety of potential mods. 65 | 66 | --- FAQ/KNOWN ISSUES --- 67 | Q: How do I play Beyond Chaos Ancient Cave mode? 68 | A: There are two codes you can use. "ancientcave" is for the standard Ancient Cave mode with ~200 maps and takes a very long time to complete. "speedcave" is a shorter, faster mode (~100 maps) that is designed to be completed in one sitting. Input the code in the flags. For vanilla Ancient Cave mode, I recommend using "ancientcavez". 69 | 70 | Q: How do I play Beyond Chaos Bingo? 71 | A: The code is "bingoboingo". Use the code in the flags and the randomizer will ask you some more questions when the randomization is complete. 72 | 73 | Q: I lost my seed number but I still have the rom. Can I find my seed number again? 74 | A: The seed is displayed in the auto-generated guide, in the rom's SNES header, and in the opening sequence with the magitek armor. 75 | 76 | Q: I'm at Vargas but I don't have Blitz. How do I beat him? 77 | A: You can defeat him normally without Blitz. His HP was lowered to make him beatable without much (if any) grinding. 78 | 79 | Q: How do I defeat TunnelArmr without Runic? 80 | A: Just kill it. 81 | 82 | Q: How do I defeat Ultros at the Esper's hideout without Sketch? 83 | A: Just kill it. 84 | 85 | Q: Speaking of Sketch, was the Sketch Glitch patched? 86 | A: No. Believe it or not, there are people out there who want to play using the Sketch Glitch, which is why the randomizer is based off of the FF3 US 1.0 rom. In an ideal world you would be able to choose whether or not to patch the glitch, but since there is such small demand for that kind of feature and it would take considerable effort, I haven't implemented it. 87 | 88 | Q: The Moogle Charm doesn't work. 89 | A: It was nerfed. FF6 uses a threat level based random encounter system, and Moogle Charm increases threat level by the lowest possible value without removing encounters altogether. The specifics are a bit complex, but you should think of it as having about a 1/256 encounter rate if you've been wearing it for a while. Also, some later dungeons might randomly ignore Moogle Charm altogether. 90 | 91 | Q: I'm in a dungeon and the encounter rate is insanely high. 92 | A: Some later dungeons have a chance to become high encounter rate dungeons. However, these dungeons are twice as vulnerable to the effects of Charm Bangle and Moogle Charm. 93 | 94 | Q: The switches in the final dungeon don't seem to be working. 95 | A: They work, I assure you... it seems like the game is a bit buggy when there are parties standing on multiple switches and one of the parties is standing on a switch it doesn't expect. Try moving everyone else off of any switches or in the worst case have them leave the room entirely. 96 | 97 | Q: The Fanatics Tower is really long. What gives? 98 | A: I've made some changes to the Tower, with the intent to make it the most frustrating, obnoxious dungeon possible. If you're stuck, here are some hints in ROT13 format. Decode them if you're having trouble. 99 | Hint #1: Vg'f zber qvssvphyg tbvat hc guna pbzvat qbja. 100 | Hint #2: Qba'g trg qvfgenpgrq. Fgnl sbphfrq ba lbhe tbny, naq riraghnyyl lbh jvyy ernpu vg. 101 | Solution: Fbzr gernfher ebbzf ner gencf gung qebc lbh gb n ybjre yriry bs gur gbjre. Nibvq gur gernfher ebbzf naq lbh jba'g trg fghpx. 102 | 103 | Q: The old man in Narshe won't give me the Ragnarok esper. Is this a bug? 104 | A: It's not a bug. Ragnarok (esper) is at a different location. Location: Gur obff ng gur gbc bs Snangvpf Gbjre unf vg. 105 | 106 | Q: I heard that there's a secret item. How do I get it? 107 | A: Va gur svany qhatrba, gurer'f n fznyy vagrevbe ebbz jvgu n qbbe cnfg n pbairlbe oryg gung vf vanpprffvoyr. Gb ernpu gur qbbe, lbh zhfg hfr na rkcybvg gung vf abeznyyl hfrq gb fxvc Cbygetrvfg va inavyyn SS6. Ybbx hc gur Cbygetrvfg fxvc gb svaq bhg ubj gb qb gur gevpx. 108 | 109 | Q: I heard that there are secret codes. What are they? 110 | A: I'll give you the codes, but be aware that these are codes that were used during development for testing the randomizer. I make no guarantees about their playability, and it's recommended that you play through the randomizer without codes at least once before you use them. Here they are, as always, in ROT13: 111 | nvefuvc 112 | phgfprarf 113 | cneglcnegl 114 | oenirahqrjbeyq 115 | fhcyrkjerpxf 116 | fgenatrwbhearl 117 | qrnerfgzbyhyh 118 | pnaggbhpuguvf 119 | rnflzbqb 120 | abeat 121 | raqyrff9 122 | rdhvcnalguvat 123 | pbyyngrenyqnzntr 124 | yyt 125 | anghenyzntvp 126 | anghenyfgngf 127 | cynlfvgfrys 128 | jbeevatgevnq 129 | zrgebabzr 130 | dhvxqenj 131 | xhcbxhcb 132 | pncfybpxbss 133 | znxrbire 134 | ercynprrirelguvat 135 | nyypbzobf 136 | enaqbzobbfg 137 | 138 | Q: What level should I be for the final dungeon? 139 | A: It really depends on your gear and what builds you have access to. I usually end up going there around level 35-40, but it doesn't hurt to have a few absurdly high level characters to tank hits. 140 | 141 | Q: Yo this is really hard. 142 | A: Yeah I guess so. I was pretty careful to make sure it was always beatable, though. Obviously the difficulty depends on your specific randomization though, so if you're having trouble, don't feel bad about using savestates or anything. I tried to design the randomizer in such a way that savestates aren't necessary, but I can't account for everything. If you encounter anything that is absolutely absurd in difficulty, please let me know so I can try to adjust the balance for future versions. Also, save often! You never know when you'll randomly encounter a boss on the overworld or in a chest. 143 | 144 | Q: I encountered as a random encounter/monster in a box! Is this a bug? 145 | A: No. 146 | 147 | Q: I can't choose my party for the final battle. Is this a bug? 148 | A: No. 149 | 150 | Q: It says my character can use Blitz/Lore/etc. in their skills menu, but they don't actually know it. 151 | A: This is a side effect of replacing the old commands. I'm not sure how to fix it, but it doesn't really affect the game so I haven't really looked into it. 152 | 153 | Q: I used Control on an enemy and ordered him to use a skill on his own party, but he attacked me instead! 154 | A: Some skills are just like that. They're flagged to never be used on your own party. 155 | 156 | Q: The final boss is impossible! How do I win? 157 | A: Gur orfg cerpnhgvba lbh pna gnxr vf univat rabhtu UC gb fheivir Zrgrbe (hfhnyyl nobhg 5000) naq vaihyarenovyvgl gb znal fgnghf rssrpgf, rfcrpvnyyl Fvyrapr. Xrsxn jba'g pbhagre juvyr ur'f pnfgvat Tbare naq gur fperra vf funxvat, fb guvf vf gur orfg gvzr gb fgevxr. 158 | 159 | Q: The boss of the Fanatics Tower is impossible! How do I win without Life 3? 160 | A: Gur pynffvp fgengrtl bs Enfcvat uvz gb qrngu fgvyy jbexf, naq ur vf bsgra ihyarenoyr gb Ofrex. Hfvat Cnyvqbe gb ynaq gur svany uvg pna jbex, ohg or jnel gung ur zvtug fgneg gur onggyr jvgu vaangr Yvsr 3. Nyfb, vs lbh unir n Trz Obk be fvzvyne vgrz, vg zvtug nyybj lbh gb hfr na novyvgl va gur gbjre gung lbh abeznyyl pna'g hfr... Hygvzn pna or Ehavpxrq, sbe rknzcyr. 161 | 162 | Q: Dude I've got like six cursed shields. 163 | A: Fun fact, if you equip cursed shields on multiple party members, you can uncurse one of them 2x or 3x or 4x as quickly. 164 | 165 | Q: Why can't Gogo select X ability? 166 | A: It's probably there. You just have to scroll past the edge of the menu. Unless it's an ability Shadow had and you let him die, in which case, it won't be there. 167 | 168 | Q: I just got a Game Over, but I didn't get to keep my experience levels. 169 | A: This feature was removed because it didn't work properly with one of the new esper boosts. I also wasn't very fond of it to begin with, because I would often get a Game Over and forget to reset so I don't miss out on valuable esper levels. 170 | 171 | Q: Can you add X to the mini-guide that gets generated? 172 | A: Let me know. I'm not sure what kinds of things people want in the mini-FAQ. 173 | 174 | Q: The guide says a character can learn a spell naturally, but they haven't learned it. 175 | A: Yeah, that's a bug I haven't bothered to figure out yet. I think it has to do with characters joining at a higher level than the magic they learn. They'll still learn the rest of their natural magic, though. 176 | 177 | Q: Can you add X feature? 178 | A: Maybe. I'm open to suggestions, but things that require a lot of effort probably won't get made. 179 | 180 | Q: Can I add X feature? 181 | A: Possibly! Even if I don't think it's a good idea for the standard settings, it could be a secret code. Send me a pull request to the project's Github. 182 | 183 | Q: Does Beyond Chaos work with X mod? 184 | A: Maybe, maybe not. I haven't tested Beyond Chaos with anyone else's mods. If it's an elaborate, full-game mod than the answer is no. Some small mods might be compatible, since Beyond Chaos doesn't do rom expansion or anything like that... but it uses up a lot of commonly used free space, so conflicts are likely. 185 | 186 | Q: Does Beyond Chaos work on a real Super Nintendo? 187 | A: Absolutely! Beyond Chaos has been tested on both Super Everdrive and SD2SNES, and it works 100% perfectly. 188 | 189 | Q: I found a bug! 190 | A: The best thing to do is open an issue on the Beyond Chaos github page, but if that's too much of a hassle you can also send me a tweet and I might check it out. Note that by this point A LOT of the bugs have been discovered, but if you just want to show it off or something that's cool too. 191 | 192 | --- CONTRIBUTORS --- 193 | subtractionsoup - TONS of features in v62 and v63 194 | Lockirby2 - The worringtriad code 195 | glennmatthews - Command descriptions in logfile 196 | 197 | --- SPECIAL THANKS --- 198 | cecil188 - OG beyond chaos fan 199 | fathlo23 - RPG speedrunner and BC challenge runner 200 | ffmasterfoobar - twitch broadcaster who did a lot of initial playtesting for my entertainment 201 | greenknight5 - bc_cecilbot programmer 202 | kupofasa - original permadeath runner 203 | quikdraw7777 - permadeath community leader and pioneer 204 | tenkarider - romhacker who gave me lots of early feedback, and creator of the Ultimate Czar Dragon hack, FF6 Curse of the Gods, and many other challenges 205 | badass, dr blank, matthew50, metroidquest, sutebenukun, and zeemis - additional sprites 206 | AND YOU 207 | 208 | Like this randomizer? Then check out my other projects! I've made like a billion randomizers! 209 | http://www.abyssonym.com 210 | -------------------------------------------------------------------------------- /chestrandomizer.py: -------------------------------------------------------------------------------- 1 | from utils import read_multi, write_multi, mutate_index, utilrandom as random 2 | from itemrandomizer import get_ranked_items, get_item 3 | from formationrandomizer import get_formations, get_fsets 4 | 5 | valid_ids = range(1, 0x200) 6 | banned_formids = [0] 7 | extra_miabs = [] 8 | orphaned_formations = None 9 | used_formations = [] 10 | done_items = [] 11 | 12 | appropriate_formations = None 13 | 14 | EVENT_ENEMIES = [0x00, 0x01, 0x02, 0x09, 0x19, 0x1b, 0x22, 0x24, 0x33, 0x38, 15 | 0x39, 0x3a, 0x42, 0x43, 0x50, 0x59, 0x5e, 0x64, 0x73, 0x7f, 16 | 0xd1, 0xe3] 17 | 18 | 19 | def add_orphaned_formation(formation): 20 | global orphaned_formations 21 | orphaned_formations.append(formation) 22 | 23 | 24 | def get_orphaned_formations(): 25 | global orphaned_formations 26 | if orphaned_formations is not None: 27 | return orphaned_formations 28 | 29 | orphaned_formations = set([]) 30 | from monsterrandomizer import get_monsters 31 | monsters = get_monsters() 32 | extra_miabs = get_extra_miabs(0) 33 | for m in monsters: 34 | if m.id in EVENT_ENEMIES: 35 | m.auxloc = "Event Battle" 36 | continue 37 | if not m.is_boss: 38 | location = m.determine_location() 39 | if "missing" in location.lower() or not location.strip(): 40 | formations = set([f for f in get_formations() 41 | if m in f.present_enemies 42 | and not f.has_boss]) 43 | formations = sorted(formations, key=lambda f: f.formid) 44 | try: 45 | f = random.choice(formations) 46 | orphaned_formations.add(f) 47 | except IndexError: 48 | pass 49 | for x in extra_miabs: 50 | if m in x.present_enemies: 51 | if x == f: 52 | continue 53 | ens = set(x.present_enemies) 54 | if len(ens) == 1: 55 | banned_formids.append(x.formid) 56 | 57 | orphaned_formations = sorted(orphaned_formations, key=lambda f: f.formid) 58 | return get_orphaned_formations() 59 | 60 | 61 | def get_appropriate_formations(): 62 | global appropriate_formations 63 | if appropriate_formations is not None: 64 | return appropriate_formations 65 | 66 | from randomizer import NOREPLACE_FORMATIONS 67 | formations = get_formations() 68 | formations = [f for f in formations if not f.battle_event] 69 | formations = [f for f in formations if f.formid not in 70 | banned_formids + NOREPLACE_FORMATIONS] 71 | formations = [f for f in formations if len(f.present_enemies) >= 1] 72 | formations = [f for f in formations if 273 not in 73 | [e.id for e in f.present_enemies]] 74 | formations = [f for f in formations if all( 75 | e.display_name.strip('_') for e in f.present_enemies)] 76 | 77 | def get_enames(f): 78 | return " ".join(sorted([e.display_name for e in f.present_enemies])) 79 | 80 | form_enames = [get_enames(f) for f in formations] 81 | for f in list(formations): 82 | enames = get_enames(f) 83 | assert form_enames.count(enames) >= 1 84 | if form_enames.count(enames) >= 2: 85 | if f.get_music() == 0: 86 | formations.remove(f) 87 | form_enames.remove(enames) 88 | 89 | appropriate_formations = formations 90 | return get_appropriate_formations() 91 | 92 | 93 | def get_2pack(formation): 94 | fsets = [fs for fs in get_fsets() if fs.setid >= 0x100] 95 | for fs in fsets: 96 | if fs.formations[0] == formation and fs.formations[1] == formation: 97 | return fs 98 | 99 | unused = [fs for fs in fsets if fs.unused][0] 100 | unused.formids = [formation.formid] * 2 101 | return unused 102 | 103 | 104 | def add_extra_miab(setid): 105 | setid |= 0x100 106 | fset = [fs for fs in get_fsets() if fs.setid == setid][0] 107 | formation = fset.formations[0] 108 | if formation not in extra_miabs: 109 | extra_miabs.append(fset.formations[0]) 110 | 111 | 112 | def get_extra_miabs(lowest_rank): 113 | candidates = [f for f in extra_miabs if f.rank() >= lowest_rank and 114 | f.formid not in banned_formids] 115 | return sorted(candidates, key=lambda f: f.rank()) 116 | 117 | 118 | def get_valid_chest_id(): 119 | global valid_ids 120 | try: 121 | valid = valid_ids[0] 122 | except IndexError: 123 | raise Exception("Not enough chest IDs available.") 124 | mark_taken_id(valid) 125 | return valid 126 | 127 | 128 | def mark_taken_id(taken): 129 | global valid_ids 130 | assert 1 <= taken < 0x200 131 | if taken in valid_ids: 132 | valid_ids = [i for i in valid_ids if i != taken] 133 | 134 | 135 | class ChestBlock: 136 | def __init__(self, pointer, location): 137 | self.pointer = pointer 138 | self.location = location 139 | self.value = None 140 | self.do_not_mutate = False 141 | self.ignore_dummy = False 142 | self.rank = None 143 | 144 | def set_id(self, chestid): 145 | self.chestid = chestid 146 | 147 | def read_data(self, filename): 148 | global extra_miabs 149 | 150 | f = open(filename, 'r+b') 151 | f.seek(self.pointer) 152 | self.position = read_multi(f, length=2) 153 | self.memid = ord(f.read(1)) 154 | self.contenttype = ord(f.read(1)) 155 | self.contents = ord(f.read(1)) 156 | f.close() 157 | self.oldid = self.memid | ((self.contenttype & 1) << 8) 158 | 159 | mark_taken_id(self.effective_id) 160 | if self.monster: 161 | add_extra_miab(self.contents) 162 | 163 | def copy(self, other): 164 | self.position = other.position 165 | self.memid = other.memid 166 | self.contenttype = other.contenttype 167 | self.contents = other.contents 168 | self.oldid = other.oldid 169 | 170 | def set_rank(self, rank): 171 | self.rank = rank 172 | 173 | @property 174 | def empty(self): 175 | return self.contenttype & 0x18 176 | 177 | @property 178 | def treasure(self): 179 | return self.contenttype & 0x40 180 | 181 | @property 182 | def gold(self): 183 | return self.contenttype & 0x80 184 | 185 | @property 186 | def monster(self): 187 | return self.contenttype & 0x20 188 | 189 | @property 190 | def effective_id(self): 191 | return self.memid | ((self.contenttype & 1) << 8) 192 | 193 | @property 194 | def description(self): 195 | if self.monster: 196 | from formationrandomizer import get_fset 197 | s = "Enemy {0:03d}: ".format(self.effective_id) 198 | fset = get_fset(self.contents + 0x100) 199 | s += fset.formations[0].description(renamed=True, simple=True) 200 | elif self.empty: 201 | s = "Empty! ({0:03d})".format(self.effective_id) 202 | else: 203 | s = "Treasure {0:03d}: ".format(self.effective_id) 204 | if self.gold: 205 | s += "%s GP" % (self.contents * 100) 206 | else: 207 | item = get_item(self.contents) 208 | s += item.name 209 | return s 210 | 211 | def set_content_type(self, contenttype): 212 | if self.effective_id >= 0x100: 213 | self.contenttype = contenttype | 1 214 | else: 215 | self.contenttype = contenttype 216 | 217 | def set_new_id(self): 218 | nextid = get_valid_chest_id() 219 | if nextid >= 0x100: 220 | if nextid >= 0x200: 221 | raise Exception("Too many chests.") 222 | self.contenttype |= 1 223 | else: 224 | self.contenttype &= 0xFE 225 | self.memid = nextid & 0xFF 226 | 227 | def write_data(self, fout, nextpointer): 228 | fout.seek(nextpointer) 229 | write_multi(fout, self.position, length=2) 230 | 231 | if self.memid is None: 232 | self.set_new_id() 233 | 234 | # TODO: Preserve same IDs on chests like in Figaro Cave 235 | fout.write(chr(self.memid)) 236 | fout.write(chr(self.contenttype)) 237 | fout.write(chr(self.contents)) 238 | 239 | def get_current_value(self, guideline=None): 240 | if self.treasure: 241 | items = get_ranked_items() 242 | itemids = [i.itemid for i in items] 243 | try: 244 | index = itemids.index(self.contents) 245 | value = items[index].rank() / 100 246 | except ValueError: 247 | value = 100 248 | elif self.gold or self.empty: 249 | if self.empty: 250 | if guideline is not None: 251 | value = guideline / 100 252 | else: 253 | raise Exception("No guideline provided for empty chest.") 254 | else: 255 | value = self.contents 256 | elif self.monster: 257 | from formationrandomizer import get_fset 258 | formation = get_fset(self.contents | 0x100).formations[0] 259 | items = [] 260 | for monster in formation.present_enemies: 261 | mitems = [i for i in monster.drops if i is not None] 262 | if mitems: 263 | items.append(min(mitems, key=lambda i: i.rank())) 264 | if items: 265 | highest = max(items, key=lambda i: i.rank()) 266 | value = highest.rank() / 100 267 | else: 268 | value = 1 269 | 270 | assert value < 10000 271 | return value 272 | 273 | def dummy_item(self, item): 274 | if self.ignore_dummy: 275 | return False 276 | 277 | if self.treasure and self.contents == item.itemid: 278 | self.set_content_type(0x10) 279 | self.contents = 0 280 | return True 281 | return False 282 | 283 | def mutate_contents(self, guideline=None, monster=None, 284 | guarantee_miab_treasure=False, enemy_limit=None, 285 | uniqueness=False): 286 | global used_formations, done_items 287 | 288 | if self.do_not_mutate and self.contents is not None: 289 | return 290 | 291 | if self.value is not None: 292 | value = self.value 293 | else: 294 | value = self.get_current_value(guideline=guideline) 295 | 296 | items = get_ranked_items() 297 | itemids = [i.itemid for i in items] 298 | if self.treasure: 299 | try: 300 | index = itemids.index(self.contents) 301 | except ValueError: 302 | index = 0 303 | indexed_item = items[index] 304 | else: 305 | lowpriced = [i for i in items if i.rank() <= value*100] 306 | if not lowpriced: 307 | lowpriced = items[:random.randint(1, 16)] 308 | index = max(0, len(lowpriced)-1) 309 | indexed_item = lowpriced[index] 310 | 311 | chance = random.randint(1, 50) 312 | orphaned_formations = get_orphaned_formations() 313 | orphaned_formations = [f for f in orphaned_formations 314 | if f not in used_formations] 315 | extra_miabs = get_extra_miabs(0) 316 | if orphaned_formations or extra_miabs: 317 | chance -= 2 318 | chance = max(chance, 1) 319 | 320 | if monster is True: 321 | chance = 1 322 | elif monster is False: 323 | chance += 3 324 | chance = min(chance, 50) 325 | 326 | formations = get_appropriate_formations() 327 | formations = [f for f in formations if 328 | f.get_guaranteed_drop_value() >= value * 100] 329 | if 1 <= chance <= 3 and (self.rank or formations): 330 | # monster 331 | self.set_content_type(0x20) 332 | 333 | rank = self.rank or min(formations, key=lambda f: f.rank()).rank() 334 | if guarantee_miab_treasure: 335 | extra_miabs = [] 336 | orphaned_formations = [] 337 | candidates = [] 338 | else: 339 | if len(extra_miabs) > 1: 340 | extra_miabs = get_extra_miabs(rank) 341 | if orphaned_formations or extra_miabs: 342 | formations = [f for f in formations if f.rank() >= rank] 343 | formations = formations[:random.randint(1, 3)] 344 | 345 | candidates = (orphaned_formations + extra_miabs) 346 | candidates = sorted(set(candidates)) 347 | if len(candidates) != 1: 348 | candidates += formations 349 | candidates = [c for c in candidates if c not in used_formations] 350 | candidates = [c for c in candidates 351 | if c.formid not in banned_formids] 352 | 353 | if enemy_limit is not None: 354 | candidates = [f for f in candidates if f.rank() <= enemy_limit] 355 | 356 | if not candidates: 357 | candidates = (formations + 358 | get_orphaned_formations() + get_extra_miabs(0)) 359 | if enemy_limit is not None: 360 | candidates = [f for f in candidates 361 | if f.rank() <= enemy_limit] 362 | candidates = sorted(candidates, key=lambda f: f.rank()) 363 | half = len(candidates) / 2 364 | candidates = candidates[half:] 365 | index = random.randint(0, half) + random.randint(0, half) 366 | index = min(index, len(candidates)-1) 367 | candidates = candidates[index:] 368 | 369 | candidates = sorted(candidates, key=lambda f: f.rank()) 370 | if orphaned_formations: 371 | index = max( 372 | 0, len([c for c in candidates if c.rank() <= rank])-1) 373 | index = mutate_index(index, len(candidates), [False, True], 374 | (-3, 2), (-1, 1)) 375 | else: 376 | index = 0 377 | index = mutate_index(index, len(candidates), [False, True], 378 | (-1, 4), (-1, 1)) 379 | 380 | chosen = candidates[index] 381 | for m in chosen.present_enemies: 382 | m.auxloc = "Monster-in-a-Box" 383 | 384 | banned_formids.append(chosen.formid) 385 | used_formations.append(chosen) 386 | chosen = get_2pack(chosen) 387 | # only 2-packs are allowed 388 | self.contents = chosen.setid & 0xFF 389 | elif 4 <= chance <= 5: 390 | # gold 391 | self.set_content_type(0x80) 392 | value = value / 2 393 | value += (random.randint(0, value) + random.randint(0, value)) 394 | self.contents = min(0xFF, max(1, value)) 395 | if self.contents == 0xFF: 396 | self.contents -= random.randint(0, 20) + random.randint(0, 20) 397 | else: 398 | # treasure 399 | self.set_content_type(0x40) 400 | if uniqueness and random.randint(1, 7) != 7: 401 | if len(done_items) >= len(items): 402 | done_items = [] 403 | temp = [i for i in items 404 | if i == indexed_item or i not in done_items] 405 | if len(temp) > 1: 406 | items = temp 407 | index = items.index(indexed_item) 408 | if indexed_item in done_items: 409 | items.remove(indexed_item) 410 | index = mutate_index(index, len(items), [False, True], 411 | (-4, 2), (-2, 2)) 412 | self.contents = items[index].itemid 413 | done_items.append(items[index]) 414 | 415 | assert self.contents <= 0xFF 416 | self.value = value 417 | -------------------------------------------------------------------------------- /formationrandomizer.py: -------------------------------------------------------------------------------- 1 | from utils import read_multi, write_multi, utilrandom as random 2 | from math import log 3 | from monsterrandomizer import monsterdict 4 | 5 | fsetdict = None 6 | formdict = None 7 | 8 | 9 | class Formation(): 10 | def __init__(self, formid): 11 | self.formid = formid 12 | self.pointer = 0xf6200 + (formid*15) 13 | self.auxpointer = 0xf5900 + (formid*4) 14 | 15 | def __repr__(self): 16 | return self.description() 17 | 18 | def description(self, renamed=False, simple=False): 19 | counter = {} 20 | for e in self.present_enemies: 21 | if renamed: 22 | name = e.display_name 23 | else: 24 | name = e.name 25 | name = name.strip('_') 26 | if name not in counter: 27 | counter[name] = 0 28 | counter[name] += 1 29 | s = "" 30 | for name, count in sorted(counter.items()): 31 | s = ', '.join([s, "%s x%s" % (name, count)]) 32 | s = s[2:] 33 | if simple: 34 | return s 35 | s = "%s (%x)" % (s, self.formid) 36 | #s += " " + " ".join(["%x" % e.id for e in self.present_enemies]) 37 | return s 38 | 39 | @property 40 | def has_boss(self): 41 | return any([e.is_boss or e.boss_death for e in self.present_enemies]) 42 | 43 | @property 44 | def is_fanatics(self): 45 | for e in self.present_enemies: 46 | if e.id in [0x125, 0x12b, 0x130, 0x132, 0x133, 47 | 0x139, 0x143, 0x163, 0x164]: 48 | return True 49 | return False 50 | 51 | def get_guaranteed_drop_value(self, value=0): 52 | if len(self.present_enemies) == 0: 53 | return False 54 | 55 | values = [] 56 | for e in self.present_enemies: 57 | for d in e.drops: 58 | value = 1000000 59 | if d is None: 60 | value = 0 61 | else: 62 | value = min(value, d.rank()) 63 | values.append(value) 64 | return max(values) 65 | 66 | def get_best_drop(self): 67 | drops = [] 68 | for e in self.present_enemies: 69 | for d in e.drops: 70 | if d is not None: 71 | drops.append(d) 72 | 73 | if not drops: 74 | return None 75 | return max(drops, key=lambda d: d.rank()) 76 | 77 | @property 78 | def veldty(self): 79 | return self.formid <= 0x1af 80 | 81 | @property 82 | def pincer_prohibited(self): 83 | return self.misc1 & 0x40 84 | 85 | @property 86 | def back_prohibited(self): 87 | return self.misc1 & 0x20 88 | 89 | @property 90 | def battle_event(self): 91 | return any([m.battle_event for m in self.present_enemies]) 92 | 93 | def read_data(self, filename): 94 | f = open(filename, 'r+b') 95 | f.seek(self.pointer) 96 | self.mouldbyte = ord(f.read(1)) 97 | self.mould = self.mouldbyte >> 4 98 | self.enemies_present = ord(f.read(1)) 99 | self.enemy_ids = map(ord, f.read(6)) 100 | self.enemy_pos = map(ord, f.read(6)) 101 | self.bosses = ord(f.read(1)) 102 | 103 | f.seek(self.auxpointer) 104 | self.misc1 = ord(f.read(1)) 105 | self.misc2 = ord(f.read(1)) 106 | self.eventscript = ord(f.read(1)) 107 | self.misc3 = ord(f.read(1)) 108 | 109 | appointer = 0x1fb400 + self.formid 110 | if appointer < 0x1fb600: 111 | f.seek(0x1fb400 + self.formid) 112 | self.ap = ord(f.read(1)) 113 | else: 114 | self.ap = None 115 | 116 | f.close() 117 | 118 | @property 119 | def mould(self): 120 | return self.mouldbyte >> 4 121 | 122 | @property 123 | def has_event(self): 124 | return bool(self.misc2 & 0x80) 125 | 126 | @property 127 | def present_enemies(self): 128 | return [e for e in self.enemies if e] 129 | 130 | @property 131 | def ambusher(self): 132 | return any([e.ambusher for e in self.present_enemies]) 133 | 134 | @property 135 | def inescapable(self): 136 | return any([e.inescapable for e in self.present_enemies]) 137 | 138 | def set_attack_type(self, normal=True, back=False, 139 | pincer=False, side=False): 140 | self.misc1 &= 0x0F 141 | self.misc1 |= 0x10 if not normal else 0 142 | self.misc1 |= 0x20 if not back else 0 143 | self.misc1 |= 0x40 if not pincer else 0 144 | self.misc1 |= 0x80 if not side else 0 145 | 146 | def get_music(self): 147 | return (self.misc3 >> 3) & 0b111 148 | 149 | def set_music(self, value): 150 | # BATTLE THEMES 151 | # 0 regular 152 | # 1 boss 153 | # 2 atmaweapon 154 | # 3 returners theme 155 | # 4 minecart 156 | # 5 dancing mad 157 | # 6-7 no change 158 | self.misc3 &= 0b11000111 159 | self.misc3 |= (value << 3) 160 | 161 | def set_continuous_music(self): 162 | self.misc3 |= 0x80 163 | self.misc2 |= 0x02 164 | 165 | def set_music_appropriate(self): 166 | music = random.randint(1, 5) if self.rank() > 35 else random.choice([1, 3, 4]) 167 | self.set_music(music) 168 | 169 | def set_fanfare(self, value=False): 170 | if value: 171 | self.misc1 &= 0xFE 172 | else: 173 | self.misc1 |= 1 174 | 175 | def set_event(self, value=False): 176 | if value: 177 | self.misc2 |= 0x80 178 | else: 179 | self.misc2 &= 0x7F 180 | self.eventscript = 0 181 | 182 | def set_windows(self, value=True): 183 | if value: 184 | self.misc3 |= 0x04 185 | else: 186 | self.misc3 &= 0xFB 187 | 188 | def set_appearing(self, value): 189 | # 0 none 190 | # 1 smoke 191 | # 2 dropdown 192 | # 3 from left 193 | # 4 splash from below 194 | # 5 float down 195 | # 6 splash from below (sand?) 196 | # 7 from left (fast?) 197 | # 8 fade in (top-bottom) 198 | # 9 fade in (bottom-top) 199 | # 10 fade in (wavey) 200 | # 11 fade in (slicey) 201 | # 12 none 202 | # 13 blink in 203 | # 14 stay below screen 204 | # 15 slowly fall, play Dancing Mad 205 | if type(value) in [list, tuple, set]: 206 | value = random.choice(sorted(value)) 207 | self.misc1 &= 0xF0 208 | self.misc1 |= value 209 | if value == 15: 210 | self.set_music(6) 211 | 212 | def write_data(self, fout): 213 | fout.seek(self.pointer) 214 | fout.write(chr(self.mouldbyte)) 215 | fout.write(chr(self.enemies_present)) 216 | fout.write("".join(map(chr, self.enemy_ids))) 217 | fout.write("".join(map(chr, self.enemy_pos))) 218 | fout.write(chr(self.bosses)) 219 | 220 | fout.seek(self.auxpointer) 221 | fout.write(chr(self.misc1)) 222 | fout.write(chr(self.misc2)) 223 | fout.write(chr(self.eventscript)) 224 | fout.write(chr(self.misc3)) 225 | 226 | if self.ap is not None: 227 | fout.seek(0x1fb400 + self.formid) 228 | fout.write(chr(self.ap)) 229 | 230 | def lookup_enemies(self): 231 | self.enemies = [] 232 | self.big_enemy_ids = [] 233 | for i, eid in enumerate(self.enemy_ids): 234 | if eid == 0xFF and not self.enemies_present & (1 << i): 235 | self.enemies.append(None) 236 | continue 237 | if self.bosses & (1 << i): 238 | eid += 0x100 239 | self.big_enemy_ids.append(eid) 240 | self.enemies.append(monsterdict[eid]) 241 | enemy_pos = self.enemy_pos[i] 242 | x, y = enemy_pos >> 4, enemy_pos & 0xF 243 | self.enemies[i].update_pos(x, y) 244 | for e in self.enemies: 245 | if not e: 246 | continue 247 | e.add_mould(self.mould) 248 | 249 | def set_big_enemy_ids(self, eids): 250 | self.bosses = 0 251 | self.enemy_ids = [] 252 | for n, eid in enumerate(eids): 253 | if eid & 0x100: 254 | self.bosses |= (1 << n) 255 | if not self.enemies_present & (1 << n): 256 | self.bosses |= (1 << n) 257 | self.enemy_ids.append(eid & 0xFF) 258 | 259 | def read_mould(self, filename): 260 | mouldspecsptrs = 0x2D01A 261 | f = open(filename, 'r+b') 262 | pointer = mouldspecsptrs + (2*self.mould) 263 | f.seek(pointer) 264 | pointer = read_multi(f, length=2) | 0x20000 265 | for i in xrange(6): 266 | f.seek(pointer + (i*4)) 267 | a, b = tuple(map(ord, f.read(2))) 268 | width = ord(f.read(1)) 269 | height = ord(f.read(1)) 270 | enemy = self.enemies[i] 271 | if enemy: 272 | enemy.update_size(width, height) 273 | 274 | def copy_data(self, other): 275 | attributes = [ 276 | "mouldbyte", "enemies_present", "enemy_ids", 277 | "enemy_pos", "bosses", "misc1", "misc2", "eventscript", 278 | "misc3"] 279 | for attribute in attributes: 280 | value = getattr(other, attribute) 281 | value = type(value)(value) 282 | setattr(self, attribute, value) 283 | 284 | def levelrank(self): 285 | ranks = [e.stats['level'] for e in self.present_enemies if e] 286 | if len(ranks) == 0: 287 | return 0 288 | balance = sum(ranks) / (log(len(ranks))+1) 289 | average = sum(ranks) / len(ranks) 290 | score = (max(ranks) + balance + average) / 3.0 291 | return score 292 | 293 | def rank(self): 294 | ranks = [e.rank() for e in self.present_enemies if e] 295 | if len(ranks) == 0: 296 | return 0 297 | balance = sum(ranks) / (log(len(ranks))+1) 298 | average = sum(ranks) / len(ranks) 299 | score = (max(ranks) + balance + average) / 3.0 300 | return score 301 | 302 | @property 303 | def exp(self): 304 | return sum(e.stats['xp'] for e in self.present_enemies) 305 | 306 | def mutate(self, ap=False): 307 | if ap and self.ap is not None and 0 < self.ap < 100: 308 | factor = self.levelrank() / 100 309 | self.ap += int(round(self.ap * factor)) 310 | while random.choice([True, False]): 311 | self.ap += random.randint(-1, 1) 312 | self.ap = min(100, max(self.ap, 0)) 313 | if self.ambusher: 314 | if not (self.pincer_prohibited and self.back_prohibited): 315 | self.misc1 |= 0x90 316 | 317 | def get_special_ap(self): 318 | levels = [e.stats['level'] for e in self.present_enemies if e] 319 | ap = int(sum(levels) / len(levels)) 320 | low = ap / 2 321 | ap = low + random.randint(0, low) + random.randint(0, low) 322 | ap = random.randint(0, ap) 323 | self.ap = min(100, max(ap, 0)) 324 | 325 | 326 | class FormationSet(): 327 | def __init__(self, setid): 328 | baseptr = 0xf4800 329 | self.setid = setid 330 | if self.setid <= 0xFF: 331 | self.pointer = baseptr + (setid * 8) 332 | else: 333 | self.pointer = baseptr + (0x100 * 8) + ((setid - 0x100) * 4) 334 | 335 | def __repr__(self): 336 | s = "" 337 | s += "SET ID %x\n" % self.setid 338 | for f in self.formations: 339 | s += "%s " % f.formid 340 | for i in range(8): 341 | s += '* ' if f.misc1 & (1 << i) else ' ' 342 | s += str([e.name for e in f.present_enemies]) + "\n" 343 | return s.strip() 344 | 345 | @property 346 | def formations(self): 347 | return [formdict[i & 0x7FFF] for i in self.formids] 348 | 349 | @property 350 | def unused(self): 351 | if self.setid == 0x100: 352 | return False 353 | return all([f.formid == 0 for f in self.formations]) 354 | 355 | @property 356 | def has_boss(self): 357 | return any([f.has_boss for f in self.formations]) 358 | 359 | @property 360 | def veldty(self): 361 | return all([f.veldty for f in self.formations]) 362 | 363 | def read_data(self, filename): 364 | f = open(filename, 'r+b') 365 | f.seek(self.pointer) 366 | self.formids = [] 367 | if self.setid <= 0xFF: 368 | num_encounters = 4 369 | else: 370 | num_encounters = 2 371 | for i in xrange(num_encounters): 372 | self.formids.append(read_multi(f, length=2)) 373 | if any(map(lambda f: f & 0x8000, self.formids)): 374 | assert all(map(lambda f: f & 0x8000, self.formids)) 375 | self.sixteen_pack = True 376 | else: 377 | self.sixteen_pack = False 378 | f.close() 379 | 380 | 381 | def write_data(self, fout): 382 | fout.seek(self.pointer) 383 | for value in self.formids: 384 | if self.sixteen_pack: 385 | value |= 0x8000 386 | else: 387 | value &= 0x7FFF 388 | write_multi(fout, value, length=2) 389 | 390 | def remove_redundant_formation(self, fsets, replacement=None, 391 | check_only=False): 392 | result = False 393 | if len(set(self.formations)) == 1: 394 | pass 395 | elif len(set(self.formations)) < 4: 396 | result = True 397 | if replacement: 398 | for i in xrange(4): 399 | if self.formids[i] in self.formids[i+1:]: 400 | formid = self.formids[i] 401 | self.formids.remove(formid) 402 | random.shuffle(self.formids) 403 | self.formids.append(replacement.formid) 404 | else: 405 | formations = list(self.formations) 406 | random.shuffle(formations) 407 | for i in xrange(4): 408 | f = self.formations[i] 409 | for fs2 in fsets: 410 | if fs2 != self and f in fs2.formations: 411 | result = True 412 | if replacement: 413 | formid = self.formids[i] 414 | self.formids.remove(formid) 415 | random.shuffle(self.formids) 416 | self.formids.append(replacement.formid) 417 | break 418 | if result is True: 419 | break 420 | 421 | if replacement: 422 | try: 423 | assert len(self.formations) == 4 424 | assert self.formations[3] == replacement 425 | except: 426 | return False 427 | return True 428 | 429 | if check_only: 430 | return result 431 | elif result is False: 432 | raise Exception("Can't use this formation.") 433 | 434 | @property 435 | def swappable(self): 436 | if len(self.formids) < 4 or len(set(self.formids)) == 1: 437 | return False 438 | return True 439 | 440 | def swap_formations(self, other): 441 | if not (self.swappable and other.swappable): 442 | return 443 | 444 | highself = max(self.formations, key=lambda f: f.rank()) 445 | highother = max(other.formations, key=lambda f: f.rank()) 446 | candidates = self.formations + other.formations 447 | if random.randint(1, 7) != 7: 448 | candidates.remove(highself) 449 | candidates.remove(highother) 450 | random.shuffle(candidates) 451 | formids = [f.formid for f in candidates] 452 | self.formids = formids[:len(formids)/2] 453 | other.formids = formids[len(formids)/2:] 454 | if len(formids) == 6: 455 | self.formids.append(highself.formid) 456 | other.formids.append(highother.formid) 457 | self.shuffle_formations() 458 | other.shuffle_formations() 459 | 460 | def shuffle_formations(self): 461 | random.shuffle(self.formids) 462 | 463 | def rank(self): 464 | return sum(f.rank() for f in self.formations) / 4.0 465 | 466 | 467 | def get_formation(formid): 468 | global formdict 469 | return formdict[formid] 470 | 471 | 472 | def get_formations(filename=None): 473 | global formdict 474 | if formdict: 475 | return [f for (_, f) in sorted(formdict.items())] 476 | 477 | formdict = {} 478 | for i in xrange(576): 479 | f = Formation(i) 480 | f.read_data(filename) 481 | f.lookup_enemies() 482 | f.read_mould(filename) 483 | formdict[i] = f 484 | 485 | return get_formations() 486 | 487 | 488 | def get_fsets(filename=None): 489 | global fsetdict 490 | if filename is None or fsetdict: 491 | fsets = [fs for (_, fs) in sorted(fsetdict.items())] 492 | return fsets 493 | else: 494 | fsetdict = {} 495 | for i in xrange(512): 496 | fs = FormationSet(setid=i) 497 | fs.read_data(filename) 498 | fsetdict[i] = fs 499 | return get_fsets() 500 | 501 | 502 | def get_fset(setid): 503 | return fsetdict[setid] 504 | 505 | 506 | if __name__ == "__main__": 507 | from sys import argv 508 | from monsterrandomizer import get_monsters 509 | filename = argv[1] 510 | monsters = get_monsters(filename) 511 | for m in monsters: 512 | m.read_stats(filename) 513 | formations = get_formations(filename=filename) 514 | fsets = get_fsets(filename=filename) 515 | for f in formations: 516 | print f, f.ap 517 | 518 | #for f in fsets: 519 | # print f 520 | # print f.formids 521 | -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | from collections import defaultdict 3 | import random 4 | 5 | try: 6 | from sys import _MEIPASS 7 | tblpath = path.join(_MEIPASS, "tables") 8 | except ImportError: 9 | tblpath = "tables" 10 | 11 | ENEMY_TABLE = path.join(tblpath, "enemycodes.txt") 12 | ITEM_TABLE = path.join(tblpath, "itemcodes.txt") 13 | SPELL_TABLE = path.join(tblpath, "spellcodes.txt") 14 | SPELLBANS_TABLE = path.join(tblpath, "spellbans.txt") 15 | ESPER_TABLE = path.join(tblpath, "espercodes.txt") 16 | CHEST_TABLE = path.join(tblpath, "chestcodes.txt") 17 | COMMAND_TABLE = path.join(tblpath, "commandcodes.txt") 18 | CHAR_TABLE = path.join(tblpath, "charcodes.txt") 19 | TEXT_TABLE = path.join(tblpath, "text.txt") 20 | SHORT_TEXT_TABLE = path.join(tblpath, "shorttext.txt") 21 | ENEMY_NAMES_TABLE = path.join(tblpath, "enemynames.txt") 22 | MODIFIERS_TABLE = path.join(tblpath, "moves.txt") 23 | MOVES_TABLE = path.join(tblpath, "moves.txt") 24 | LOCATION_TABLE = path.join(tblpath, "locationformations.txt") 25 | LOCATION_PALETTE_TABLE = path.join(tblpath, "locationpaletteswaps.txt") 26 | BATTLE_BG_PALETTE_TABLE = path.join(tblpath, "battlebgpalettes.txt") 27 | CHARACTER_PALETTE_TABLE = path.join(tblpath, "charpaloptions.txt") 28 | EVENT_PALETTE_TABLE = path.join(tblpath, "eventpalettes.txt") 29 | MALE_NAMES_TABLE = path.join(tblpath, "malenames.txt") 30 | FEMALE_NAMES_TABLE = path.join(tblpath, "femalenames.txt") 31 | MAP_NAMES_TABLE = path.join(tblpath, "mapnames.txt") 32 | USED_LOCATIONS_TABLE = path.join(tblpath, "usedlocs.txt") 33 | UNUSED_LOCATIONS_TABLE = path.join(tblpath, "unusedlocs.txt") 34 | TOWER_LOCATIONS_TABLE = path.join(tblpath, "finaldungeonmaps.txt") 35 | TOWER_CHECKPOINTS_TABLE = path.join(tblpath, "finaldungeoncheckpoints.txt") 36 | ANCIENT_CHECKPOINTS_TABLE = path.join(tblpath, "ancientcheckpoints.txt") 37 | MAP_BATTLE_BG_TABLE = path.join(tblpath, "mapbattlebgs.txt") 38 | ENTRANCE_REACHABILITY_TABLE = path.join(tblpath, "reachability.txt") 39 | FINAL_BOSS_AI_TABLE = path.join(tblpath, "finalai.txt") 40 | TREASURE_ROOMS_TABLE = path.join(tblpath, "treasurerooms.txt") 41 | NAMEGEN_TABLE = path.join(tblpath, "generator.txt") 42 | CUSTOM_ITEMS_TABLE = path.join(tblpath, "customitems.txt") 43 | SHOP_TABLE = path.join(tblpath, "shopcodes.txt") 44 | LOCATION_MAPS_TABLE = path.join(tblpath, "locationmaps.txt") 45 | WOB_TREASURE_TABLE = path.join(tblpath, "wobonlytreasure.txt") 46 | WOR_ITEMS_TABLE = path.join(tblpath, "worstartingitems.txt") 47 | WOB_EVENTS_TABLE = path.join(tblpath, "wobeventbits.txt") 48 | SPRITE_REPLACEMENT_TABLE = path.join(tblpath, "spritereplacements.txt") 49 | 50 | 51 | class Substitution(object): 52 | location = None 53 | 54 | @property 55 | def size(self): 56 | return len(self.bytestring) 57 | 58 | def set_location(self, location): 59 | self.location = location 60 | 61 | def write(self, fout): 62 | bs = "".join(map(chr, self.bytestring)) 63 | fout.seek(self.location) 64 | fout.write(bs) 65 | 66 | 67 | texttable = {} 68 | f = open(TEXT_TABLE) 69 | for line in f: 70 | line = line.strip() 71 | char, value = tuple(line.split()) 72 | texttable[char] = value 73 | texttable[' '] = 'FE' 74 | f.close() 75 | 76 | 77 | def name_to_bytes(name, length): 78 | name = map(lambda c: hex2int(texttable[c]), name) 79 | assert len(name) <= length 80 | while len(name) < length: 81 | name.append(0xFF) 82 | return name 83 | 84 | 85 | shorttexttable = {} 86 | f = open(SHORT_TEXT_TABLE) 87 | for line in f: 88 | line = line.strip() 89 | char, value = tuple(line.split()) 90 | shorttexttable[char] = value 91 | shorttexttable[' '] = 'FF' 92 | f.close() 93 | 94 | 95 | def hex2int(hexstr): 96 | return int(hexstr, 16) 97 | 98 | 99 | battlebg_palettes = {} 100 | f = open(BATTLE_BG_PALETTE_TABLE) 101 | for line in f: 102 | line = line.strip() 103 | bg, palette = tuple(line.split()) 104 | bg, palette = hex2int(bg), hex2int(palette) 105 | battlebg_palettes[bg] = palette 106 | f.close() 107 | 108 | 109 | def int2bytes(value, length=2, reverse=True): 110 | # reverse=True means high-order byte first 111 | bs = [] 112 | while value: 113 | bs.append(value & 255) 114 | value = value >> 8 115 | 116 | while len(bs) < length: 117 | bs.append(0) 118 | 119 | if not reverse: 120 | bs = reversed(bs) 121 | 122 | return bs[:length] 123 | 124 | 125 | def read_multi(f, length=2, reverse=True): 126 | vals = map(ord, f.read(length)) 127 | if reverse: 128 | vals = list(reversed(vals)) 129 | value = 0 130 | for val in vals: 131 | value = value << 8 132 | value = value | val 133 | return value 134 | 135 | 136 | def write_multi(f, value, length=2, reverse=True): 137 | vals = [] 138 | while value: 139 | vals.append(value & 0xFF) 140 | value = value >> 8 141 | if len(vals) > length: 142 | raise Exception("Value length mismatch.") 143 | 144 | while len(vals) < length: 145 | vals.append(0x00) 146 | 147 | if not reverse: 148 | vals = reversed(vals) 149 | 150 | f.write(''.join(map(chr, vals))) 151 | 152 | 153 | utilrandom = random.Random() 154 | utran = utilrandom 155 | random = utilrandom 156 | 157 | RANDOM_MULTIPLIER = 1 158 | 159 | def set_randomness_multiplier(multiplier): 160 | global RANDOM_MULTIPLIER 161 | RANDOM_MULTIPLIER = multiplier 162 | 163 | 164 | def mutate_index(index, length, continuation=None, basic_range=None, 165 | extended_range=None, disregard_multiplier=False): 166 | if length == 0: 167 | return None 168 | 169 | highest = length - 1 170 | if RANDOM_MULTIPLIER is None and not disregard_multiplier: 171 | return utran.randint(0, highest) 172 | 173 | continuation = continuation or [True, False] 174 | basic_range = basic_range or (-3, 3) 175 | extended_range = extended_range or (-1, 1) 176 | if not disregard_multiplier: 177 | basic_range = tuple(int(round(RANDOM_MULTIPLIER*v)) 178 | for v in basic_range) 179 | extended_range = tuple(int(round(RANDOM_MULTIPLIER*v)) 180 | for v in extended_range) 181 | 182 | index += utran.randint(*basic_range) 183 | index = max(0, min(index, highest)) 184 | while utran.choice(continuation): 185 | index += utran.randint(*extended_range) 186 | index = max(0, min(index, highest)) 187 | 188 | return index 189 | 190 | 191 | def generate_swapfunc(swapcode=None): 192 | if swapcode is None: 193 | swapcode = utran.randint(0, 7) 194 | 195 | f = lambda w: w 196 | g = lambda w: w 197 | h = lambda w: w 198 | if swapcode & 1: 199 | f = lambda (x, y, z): (y, x, z) 200 | if swapcode & 2: 201 | g = lambda (x, y, z): (z, y, x) 202 | if swapcode & 4: 203 | h = lambda (x, y, z): (x, z, y) 204 | swapfunc = lambda w: f(g(h(w))) 205 | 206 | return swapfunc 207 | 208 | 209 | def shift_middle(triple, degree, ungray=False): 210 | low, medium, high = tuple(sorted(triple)) 211 | triple = list(triple) 212 | mediumdex = triple.index(medium) 213 | if ungray: 214 | lowdex, highdex = triple.index(low), triple.index(high) 215 | while utran.choice([True, False]): 216 | low -= 1 217 | high += 1 218 | 219 | low = max(0, low) 220 | high = min(31, high) 221 | 222 | triple[lowdex] = low 223 | triple[highdex] = high 224 | 225 | if degree < 0: 226 | value = low 227 | else: 228 | value = high 229 | degree = abs(degree) 230 | a = (1 - (degree/90.0)) * medium 231 | b = (degree/90.0) * value 232 | medium = a + b 233 | medium = int(round(medium)) 234 | triple[mediumdex] = medium 235 | return tuple(triple) 236 | 237 | 238 | def get_palette_transformer(use_luma=False, always=None, middle=True, 239 | basepalette=None): 240 | def get_ratio(a, b): 241 | if a > 0 and b > 0: 242 | return max(a, b) / float(min(a, b)) 243 | elif abs(a-b) <= 1: 244 | return 1.0 245 | else: 246 | return 9999 247 | 248 | def color_to_components(color): 249 | blue = (color & 0x7c00) >> 10 250 | green = (color & 0x03e0) >> 5 251 | red = color & 0x001f 252 | return (red, green, blue) 253 | 254 | def components_to_color((red, green, blue)): 255 | return red | (green << 5) | (blue << 10) 256 | 257 | if always is not None and basepalette is not None: 258 | raise Exception("'always' argument incompatible with 'basepalette'") 259 | 260 | swapmap = {} 261 | if basepalette is not None and not use_luma: 262 | threshold = 1.2 263 | 264 | def color_to_index(color): 265 | red, green, blue = color_to_components(color) 266 | a = red >= green 267 | b = red >= blue 268 | c = green >= blue 269 | d = get_ratio(red, green) >= threshold 270 | e = get_ratio(red, blue) >= threshold 271 | f = get_ratio(green, blue) >= threshold 272 | 273 | index = (d << 2) | (e << 1) | f 274 | index |= ((a and not d) << 5) 275 | index |= ((b and not e) << 4) 276 | index |= ((c and not f) << 3) 277 | 278 | return index 279 | 280 | colordict = defaultdict(set) 281 | for color in basepalette: 282 | index = color_to_index(color) 283 | colordict[index].add(color) 284 | 285 | saturated = dict((k, v) for (k, v) in colordict.items() if k & 0x7) 286 | satlist = sorted(saturated) 287 | random.shuffle(satlist) 288 | grouporder = sorted(satlist, key=lambda k: len(saturated[k]), 289 | reverse=True) 290 | if grouporder: 291 | dominant = grouporder[0] 292 | domhue, domsat = dominant >> 3, dominant & 0x7 293 | for key in grouporder[1:]: 294 | colhue, colsat = key >> 3, key & 0x7 295 | if (domhue ^ colhue) & (domsat | colsat) == 0: 296 | continue 297 | secondary = key 298 | break 299 | else: 300 | secondary = dominant 301 | sechue, secsat = secondary >> 3, secondary & 0x7 302 | else: 303 | dominant, domhue, domsat = 0, 0, 0 304 | secondary, sechue, secsat = 0, 0, 0 305 | 306 | while True: 307 | domswap = random.randint(0, 7) 308 | secswap = random.randint(0, 7) 309 | tertswap = random.randint(0, 7) 310 | if domswap == secswap: 311 | continue 312 | break 313 | 314 | for key in colordict: 315 | colhue, colsat = key >> 3, key & 0x7 316 | if ((domhue ^ colhue) & (domsat | colsat)) == 0: 317 | if ((sechue ^ colhue) & (secsat | colsat)) == 0: 318 | swapmap[key] = random.choice([domswap, secswap]) 319 | else: 320 | swapmap[key] = domswap 321 | elif ((sechue ^ colhue) & (secsat | colsat)) == 0: 322 | swapmap[key] = secswap 323 | elif ((domhue ^ colhue) & domsat) == 0: 324 | if ((sechue ^ colhue) & secsat) == 0: 325 | swapmap[key] = random.choice([domswap, secswap]) 326 | else: 327 | swapmap[key] = domswap 328 | elif ((sechue ^ colhue) & secsat) == 0: 329 | swapmap[key] = secswap 330 | elif ((domhue ^ colhue) & colsat) == 0: 331 | if ((sechue ^ colhue) & colsat) == 0: 332 | swapmap[key] = random.choice([domswap, secswap]) 333 | else: 334 | swapmap[key] = domswap 335 | elif ((sechue ^ colhue) & colsat) == 0: 336 | swapmap[key] = secswap 337 | else: 338 | swapmap[key] = tertswap 339 | 340 | elif basepalette is not None and use_luma: 341 | def color_to_index(color): 342 | red, green, blue = color_to_components(color) 343 | index = red + green + blue 344 | return index 345 | 346 | values = [] 347 | for color in basepalette: 348 | index = color_to_index(color) 349 | values.append(index) 350 | values = sorted(values) 351 | low, high = min(values), max(values) 352 | median = values[len(values)/2] 353 | clusters = [set([low]), set([high])] 354 | done = set([low, high]) 355 | if median not in done and random.choice([True, False]): 356 | clusters.append(set([median])) 357 | done.add(median) 358 | 359 | to_cluster = sorted(basepalette) 360 | random.shuffle(to_cluster) 361 | for color in to_cluster: 362 | index = color_to_index(color) 363 | if index in done: 364 | continue 365 | done.add(index) 366 | 367 | def cluster_distance(cluster): 368 | distances = [abs(index-i) for i in cluster] 369 | return sum(distances) / len(distances) 370 | nearest = min(cluster, key=lambda x: abs(x-index)) 371 | return abs(nearest-index) 372 | 373 | chosen = min(clusters, key=cluster_distance) 374 | chosen.add(index) 375 | 376 | swapmap = {} 377 | for cluster in clusters: 378 | swapcode = random.randint(0, 7) 379 | for index in cluster: 380 | try: 381 | assert index not in swapmap 382 | except: 383 | import pdb; pdb.set_trace() 384 | swapmap[index] = swapcode 385 | 386 | remaining = [i for i in xrange(94) if i not in swapmap.keys()] 387 | random.shuffle(remaining) 388 | 389 | def get_nearest_swapcode(index): 390 | nearest = min(swapmap, key=lambda x: abs(x-index)) 391 | return nearest 392 | 393 | for i in remaining: 394 | nearest = get_nearest_swapcode(i) 395 | swapmap[i] = swapmap[nearest] 396 | 397 | else: 398 | def color_to_index(color): 399 | return 0 400 | 401 | if always: 402 | swapmap[0] = random.randint(1, 7) 403 | else: 404 | swapmap[0] = random.randint(0, 7) 405 | 406 | for key in swapmap: 407 | swapmap[key] = generate_swapfunc(swapmap[key]) 408 | 409 | if middle: 410 | degree = utran.randint(-75, 75) 411 | 412 | def palette_transformer(raw_palette, single_bytes=False): 413 | if single_bytes: 414 | raw_palette = zip(raw_palette, raw_palette[1:]) 415 | raw_palette = [p for (i, p) in enumerate(raw_palette) if not i % 2] 416 | raw_palette = [(b << 8) | a for (a, b) in raw_palette] 417 | transformed = [] 418 | for color in raw_palette: 419 | index = color_to_index(color) 420 | swapfunc = swapmap[index] 421 | red, green, blue = color_to_components(color) 422 | red, green, blue = swapfunc((red, green, blue)) 423 | if middle: 424 | red, green, blue = shift_middle((red, green, blue), degree) 425 | color = components_to_color((red, green, blue)) 426 | transformed.append(color) 427 | if single_bytes: 428 | major = [p >> 8 for p in transformed] 429 | minor = [p & 0xFF for p in transformed] 430 | transformed = [] 431 | for a, b in zip(minor, major): 432 | transformed.append(a) 433 | transformed.append(b) 434 | return transformed 435 | 436 | return palette_transformer 437 | 438 | 439 | def decompress(bytestring, simple=False, complicated=False, debug=False): 440 | result = "" 441 | buff = [chr(0)] * 2048 442 | buffaddr = 0x7DE 443 | while bytestring: 444 | flags, bytestring = ord(bytestring[0]), bytestring[1:] 445 | for i in xrange(8): 446 | if not bytestring: 447 | break 448 | 449 | if flags & (1 << i): 450 | byte, bytestring = bytestring[0], bytestring[1:] 451 | result += byte 452 | buff[buffaddr] = byte 453 | buffaddr += 1 454 | if buffaddr == 0x800: 455 | buffaddr = 0 456 | if debug: 457 | print "%x" % ord(byte), 458 | else: 459 | low, high, bytestring = ( 460 | ord(bytestring[0]), ord(bytestring[1]), bytestring[2:]) 461 | seekaddr = low | ((high & 0x07) << 8) 462 | length = ((high & 0xF8) >> 3) + 3 463 | if simple: 464 | copied = "".join([buff[seekaddr]] * length) 465 | elif complicated: 466 | cycle = buffaddr - seekaddr 467 | if cycle < 0: 468 | cycle += 0x800 469 | subbuff = "".join((buff+buff)[seekaddr:seekaddr+cycle]) 470 | while len(subbuff) < length: 471 | subbuff = subbuff + subbuff 472 | copied = "".join(subbuff[:length]) 473 | else: 474 | copied = "".join((buff+buff)[seekaddr:seekaddr+length]) 475 | assert len(copied) == length 476 | result += copied 477 | if debug: 478 | print "%x" % seekaddr, length, 479 | while copied: 480 | byte, copied = copied[0], copied[1:] 481 | buff[buffaddr] = byte 482 | buffaddr += 1 483 | if buffaddr == 0x800: 484 | buffaddr = 0 485 | if debug: 486 | print "%x" % ord(byte), 487 | if debug: 488 | print 489 | import pdb; pdb.set_trace() 490 | return result 491 | 492 | 493 | def line_wrap(things, width=16): 494 | newthings = [] 495 | while things: 496 | newthings.append(things[:width]) 497 | things = things[width:] 498 | return newthings 499 | 500 | 501 | def get_matrix_reachability(M): 502 | M2 = zip(*M) 503 | new = [0]*len(M) 504 | new = [list(new) for _ in range(len(M))] 505 | for i, row in enumerate(M): 506 | for j, row2 in enumerate(M2): 507 | for a, b in zip(row, row2): 508 | if a & b: 509 | new[i][j] = a & b 510 | break 511 | else: 512 | new[i][j] = 0 | M[i][j] 513 | return new 514 | 515 | 516 | def make_table(cols): 517 | table = "" 518 | num_rows = max(len(c) for c in cols) 519 | for i, c in enumerate(cols): 520 | while len(c) < num_rows: 521 | c.append("") 522 | maxwidth = max(len(b) for b in c) 523 | new_c = [] 524 | for b in c: 525 | while len(b) < maxwidth: 526 | b += " " 527 | new_c.append(b) 528 | cols[i] = new_c 529 | 530 | while any(cols): 531 | cols = [c for c in cols if c] 532 | row = zip(*cols)[0] 533 | row = " | ".join(row) 534 | row = "| %s |" % row 535 | table = "\n".join([table, row]) 536 | cols = [col[1:] for col in cols] 537 | table = table.strip() 538 | fullwidth = max([len(r.strip()) for r in table.split("\n")]) 539 | horizborder = "-" * (fullwidth - 2) 540 | horizborder = "/%s\\" % horizborder 541 | table = "\n".join([horizborder, table, horizborder[::-1]]) 542 | return table 543 | 544 | if __name__ == "__main__": 545 | M = [[1,0,0,1], 546 | [0,1,0,0], 547 | [0,0,1,1], 548 | [1,0,0,1]] 549 | M = get_matrix_reachability(M) 550 | for row in M: 551 | print row 552 | --------------------------------------------------------------------------------