diff --git a/asura/__init__.py b/asura/__init__.py index 63efc86..c600838 100644 --- a/asura/__init__.py +++ b/asura/__init__.py @@ -11,11 +11,11 @@ def generate(rng=None, mode='snes', forbidden=[]): seed(rng) if mode == 'snes': - max_espers = Esper.SNES_Count - max_spells = Spell.SNES_Count + max_espers = Esper.SNES_Count - 1 + max_spells = Spell.SNES_Count - 1 else: - max_espers = Esper.GBA_Count - max_spells = Spell.GBA_Count + max_espers = Esper.GBA_Count - 1 + max_spells = Spell.GBA_Count - 1 espers = {} @@ -39,6 +39,7 @@ remove = [ ] def write_rom(input_name, output_name, mode, espers): + offset = 0 if mode == 'gba': offset = 0x70000 spello = 0x62A480 @@ -55,7 +56,7 @@ def write_rom(input_name, output_name, mode, espers): rom.seek(i[0] + offset, 0) rom.write(b'\xFD' * i[1]) - esper_list = espers.keys() + esper_list = list(espers.keys()) # these four are the espers given when you reach Tina in Zozo rom.seek(0xAA824 + offset, 0); rom.write(bytes([esper_list[0] + 0x36])) @@ -72,7 +73,7 @@ def write_rom(input_name, output_name, mode, espers): rom.seek(spello + esper * 11, 0) for spell in spells: - rom.write(bytes(spell[1], spell[0])) + rom.write(bytes([spell[1], spell[0]])) if leftover > 0: rom.write(b'\x00\xFF' * leftover) diff --git a/asura/data.py b/asura/data.py index f99d06a..88e1456 100644 --- a/asura/data.py +++ b/asura/data.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 -# # Copyright (C) 2019 Kiyoshi Aman # # This program is free software: you can redistribute it and/or modify @@ -14,24 +12,10 @@ # You should have received a copy of the GNU Affero General Public # License along with this program. If not, see # . -# -# This project was made possible by: -# * Lenophis, who told me where the 'give this esper' bytes are -# * ff6hacking.com, which hosts the data tables I used to pick from. -# * CanOfWorms, for figuring out the GBA offsets. -# -# ChangeLog: -# 0.3: -# - GBA support! Purportedly works for J, U, *and* E versions. -# 0.2: -# - Preliminary work toward supporting GBA ROMs. This needs data I -# don't have to complete, however, but the cleanup it required was -# useful. -# - Reworked learning rates. Rates should be overall lower now. -# - Majority of output moved to a spoilers file. from copy import copy from enum import IntEnum +from collections import defaultdict class Bonus(IntEnum): HP_10 = 0x00 @@ -168,7 +152,7 @@ spell_map = { 'Poison': Spell.Poison, 'Firera': Spell.Firera, 'Fira': Spell.Firera, - 'Fire2': Spell.Firera + 'Fire2': Spell.Firera, 'Blizzardra': Spell.Blizzardra, 'Blizzara': Spell.Blizzardra, 'Ice2': Spell.Blizzardra, @@ -269,28 +253,32 @@ spell_map = { } slots = defaultdict(lambda: 1) -slots[Spell.Ultima] = 4 -slots[Spell.Quick] = 4 -slots[Spell.Firega] = 3 -slots[Spell.Thunderga] = 3 -slots[Spell.Blizzardga] = 3 -slots[Spell.Meltdown] = 3 -slots[Spell.Tornado] = 3 -slots[Spell.Quake] = 3 -slots[Spell.Arise] = 3 -slots[Spell.Curega] = 3 +slots[Spell.Quick] = 5 +slots[Spell.Ultima] = 5 +slots[Spell.Arise] = 4 +slots[Spell.Blizzardga] = 4 +slots[Spell.Curega] = 4 +slots[Spell.Firega] = 4 +slots[Spell.Meltdown] = 4 +slots[Spell.Quake] = 4 +slots[Spell.Slowga] = 4 +slots[Spell.Thunderga] = 4 +slots[Spell.Tornado] = 4 +slots[Spell.Death] = 3 +slots[Spell.Gravityga] = 3 slots[Spell.Hastega] = 3 -slots[Spell.Slowga] = 3 +slots[Spell.NullStatus] = 3 slots[Spell.Osmose] = 3 -slots[Spell.Raise] = 2 slots[Spell.Curera] = 2 slots[Spell.Haste] = 2 +slots[Spell.Raise] = 2 +slots[Spell.Reraise] = 2 slots[Spell.Slow] = 2 slots_gba = copy(slots) -slots_gba[Spell.Gravityja] = 3 -slots_gba[Spell.Flood] = 3 -slots_gba[Spell.Valor] = 3 +slots_gba[Spell.Gravityja] = 5 +slots_gba[Spell.Flood] = 4 +slots_gba[Spell.Valor] = 4 class Esper(IntEnum): Ramuh = 0 diff --git a/asura/spells.py b/asura/spells.py index 430bae6..5513998 100644 --- a/asura/spells.py +++ b/asura/spells.py @@ -2,8 +2,8 @@ from random import randint from .data import Spell, slots, slots_gba -def roll_spells(max, forbidden=()): - count = 8 +def roll_spells(cap, forbidden=()): + count = 6 n = 5 spells = [] spells_got = list(forbidden) @@ -12,15 +12,15 @@ def roll_spells(max, forbidden=()): if n <= 0 or count <= 0: break - spell = Spell(randint(0, max)) + spell = Spell(randint(0, cap)) if spell in spells_got: continue if (count - slots[spell]) >= 0: - spells.append([spell, randint(1, 5 - slots[spell]) * 5]) + spells.append([spell, randint(1, max(6 - slots[spell], 2)) * 5]) spells_got.append(spell) - count -= slots + count -= slots[spell] n -= 1 return spells diff --git a/main.py b/main.py new file mode 100755 index 0000000..91cd3ac --- /dev/null +++ b/main.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 + +from sys import argv, exit +from time import time + +import os.path as op + +from asura import generate, write_rom, write_spoilers +from asura.data import spell_map + +if len(argv) < 2 or len(argv) > 4: + print('Usage: {} [seed [forbidden,spells,...]]'.format(argv[0])) + exit(1) + +if len(argv) == 2: + seed = str(time()).split('.')[0] +if len(argv) >= 3: + seed = argv[2] +if len(argv) == 4: + spells = argv[3].split(',') + forbidden = [spell_map[i] for i in spells] +else: + forbidden = [] + +filename = argv[1] +namebase, ext = op.splitext(filename) +ext = ext[1:] +output_rom = '.'.join([namebase, seed, ext]) +output_txt = '.'.join([namebase, seed, 'txt']) + +mode = 'snes' if ext != 'gba' else 'gba' + +espers = generate(seed, mode, forbidden) + +print('Seed: {}\n'.format(seed)) +print('Writing ROM...') +write_rom(filename, output_rom, mode, espers) +print('Writing spoilers...') +write_spoilers(output_txt, espers, seed)