diff --git a/worlds/soe/__init__.py b/worlds/soe/__init__.py index b431e471e2e..74387fb1be8 100644 --- a/worlds/soe/__init__.py +++ b/worlds/soe/__init__.py @@ -13,12 +13,15 @@ from worlds.AutoWorld import WebWorld, World from worlds.generic.Rules import add_item_rule, set_rule from .logic import SoEPlayerLogic -from .options import AvailableFragments, Difficulty, EnergyCore, RequiredFragments, SoEOptions, TrapChance +from .options import Difficulty, EnergyCore, SoEOptions from .patch import SoEDeltaPatch, get_base_rom_path if typing.TYPE_CHECKING: from BaseClasses import MultiWorld, CollectionState +__all__ = ["pyevermizer", "SoEWorld"] + + """ In evermizer: @@ -158,7 +161,7 @@ class RomFile(settings.SNESRomPath): class SoEWorld(World): """ Secret of Evermore is a SNES action RPG. You learn alchemy spells, fight bosses and gather rocket parts to visit a - space station where the final boss must be defeated. + space station where the final boss must be defeated. """ game: typing.ClassVar[str] = "Secret of Evermore" options_dataclass = SoEOptions @@ -370,8 +373,6 @@ def generate_basic(self) -> None: self.evermizer_seed = self.random.randint(0, 2 ** 16 - 1) # TODO: make this an option for "full" plando? def generate_output(self, output_directory: str) -> None: - from dataclasses import asdict - player_name = self.multiworld.get_player_name(self.player) self.connect_name = player_name[:32] while len(self.connect_name.encode('utf-8')) > 32: diff --git a/worlds/soe/options.py b/worlds/soe/options.py index 0436b17618e..cb9e9bb6de2 100644 --- a/worlds/soe/options.py +++ b/worlds/soe/options.py @@ -1,8 +1,8 @@ from dataclasses import dataclass, fields from typing import Any, cast, Dict, Iterator, List, Tuple, Protocol -from Options import AssembleOptions, Choice, DeathLink, DefaultOnToggle, PerGameCommonOptions, ProgressionBalancing, \ - Range, Toggle +from Options import AssembleOptions, Choice, DeathLink, DefaultOnToggle, Option, PerGameCommonOptions, \ + ProgressionBalancing, Range, Toggle # typing boilerplate @@ -294,5 +294,7 @@ def flags(self) -> str: for field in fields(self): option = getattr(self, field.name) if isinstance(option, (EvermizerFlag, EvermizerFlags)): - flags += getattr(self, field.name).to_flag() + assert isinstance(option, Option) + # noinspection PyUnresolvedReferences + flags += option.to_flag() return flags diff --git a/worlds/soe/patch.py b/worlds/soe/patch.py index 8270f2d86df..a322de2af65 100644 --- a/worlds/soe/patch.py +++ b/worlds/soe/patch.py @@ -30,7 +30,7 @@ def get_base_rom_path(file_name: Optional[str] = None) -> str: return file_name -def read_rom(stream: BinaryIO, strip_header: bool=True) -> bytes: +def read_rom(stream: BinaryIO, strip_header: bool = True) -> bytes: """Reads rom into bytearray and optionally strips off any smc header""" data = stream.read() if strip_header and len(data) % 0x400 == 0x200: diff --git a/worlds/soe/test/__init__.py b/worlds/soe/test/__init__.py index b3ba7018e48..1ab85216305 100644 --- a/worlds/soe/test/__init__.py +++ b/worlds/soe/test/__init__.py @@ -6,7 +6,7 @@ class SoETestBase(WorldTestBase): game = "Secret of Evermore" def assertLocationReachability(self, reachable: Iterable[str] = (), unreachable: Iterable[str] = (), - satisfied=True) -> None: + satisfied: bool = True) -> None: """ Tests that unreachable can't be reached. Tests that reachable can be reached if satisfied=True. Usage: test with satisfied=False, collect requirements into state, test again with satisfied=True @@ -19,7 +19,7 @@ def assertLocationReachability(self, reachable: Iterable[str] = (), unreachable: self.assertFalse(self.can_reach_location(location), f"{location} is reachable but shouldn't be") - def testRocketPartsExist(self): + def testRocketPartsExist(self) -> None: """Tests that rocket parts exist and are unique""" self.assertEqual(len(self.get_items_by_name("Gauge")), 1) self.assertEqual(len(self.get_items_by_name("Wheel")), 1) diff --git a/worlds/soe/test/test_access.py b/worlds/soe/test/test_access.py index 81b8818eb52..f1d6ee993b3 100644 --- a/worlds/soe/test/test_access.py +++ b/worlds/soe/test/test_access.py @@ -4,10 +4,10 @@ class AccessTest(SoETestBase): @staticmethod - def _resolveGourds(gourds: typing.Dict[str, typing.Iterable[int]]): + def _resolveGourds(gourds: typing.Mapping[str, typing.Iterable[int]]) -> typing.List[str]: return [f"{name} #{number}" for name, numbers in gourds.items() for number in numbers] - def test_bronze_axe(self): + def test_bronze_axe(self) -> None: gourds = { "Pyramid bottom": (118, 121, 122, 123, 124, 125), "Pyramid top": (140,) @@ -16,7 +16,7 @@ def test_bronze_axe(self): items = [["Bronze Axe"]] self.assertAccessDependency(locations, items) - def test_bronze_spear_plus(self): + def test_bronze_spear_plus(self) -> None: locations = ["Megataur"] items = [["Bronze Spear"], ["Lance (Weapon)"], ["Laser Lance"]] self.assertAccessDependency(locations, items) diff --git a/worlds/soe/test/test_goal.py b/worlds/soe/test/test_goal.py index 885c2a74ef1..bb64b8eca75 100644 --- a/worlds/soe/test/test_goal.py +++ b/worlds/soe/test/test_goal.py @@ -8,7 +8,7 @@ class TestFragmentGoal(SoETestBase): "required_fragments": 20, } - def test_fragments(self): + def test_fragments(self) -> None: self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Gauge"]) self.assertBeatable(False) # 0 fragments fragments = self.get_items_by_name("Energy Core Fragment") @@ -24,11 +24,11 @@ def test_fragments(self): self.assertEqual(self.count("Energy Core Fragment"), 21) self.assertBeatable(True) - def test_no_weapon(self): + def test_no_weapon(self) -> None: self.collect_by_name(["Diamond Eye", "Wheel", "Gauge", "Energy Core Fragment"]) self.assertBeatable(False) - def test_no_rocket(self): + def test_no_rocket(self) -> None: self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Energy Core Fragment"]) self.assertBeatable(False) @@ -38,16 +38,16 @@ class TestShuffleGoal(SoETestBase): "energy_core": "shuffle", } - def test_core(self): + def test_core(self) -> None: self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Gauge"]) self.assertBeatable(False) self.collect_by_name(["Energy Core"]) self.assertBeatable(True) - def test_no_weapon(self): + def test_no_weapon(self) -> None: self.collect_by_name(["Diamond Eye", "Wheel", "Gauge", "Energy Core"]) self.assertBeatable(False) - def test_no_rocket(self): + def test_no_rocket(self) -> None: self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Energy Core"]) self.assertBeatable(False) diff --git a/worlds/soe/test/test_oob.py b/worlds/soe/test/test_oob.py index 969e93d4f6a..3c1a2829de8 100644 --- a/worlds/soe/test/test_oob.py +++ b/worlds/soe/test/test_oob.py @@ -6,7 +6,7 @@ class OoBTest(SoETestBase): """Tests that 'on' doesn't put out-of-bounds in logic. This is also the test base for OoB in logic.""" options: typing.Dict[str, typing.Any] = {"out_of_bounds": "on"} - def test_oob_access(self): + def test_oob_access(self) -> None: in_logic = self.options["out_of_bounds"] == "logic" # some locations that just need a weapon + OoB @@ -37,7 +37,7 @@ def test_oob_access(self): self.collect_by_name("Diamond Eye") self.assertLocationReachability(reachable=de_reachable, unreachable=de_unreachable, satisfied=in_logic) - def test_oob_goal(self): + def test_oob_goal(self) -> None: # still need Energy Core with OoB if sequence breaks are not in logic for item in ["Gladiator Sword", "Diamond Eye", "Wheel", "Gauge"]: self.collect_by_name(item) diff --git a/worlds/soe/test/test_sequence_breaks.py b/worlds/soe/test/test_sequence_breaks.py index 8a7f9c64ede..2da8c9242cb 100644 --- a/worlds/soe/test/test_sequence_breaks.py +++ b/worlds/soe/test/test_sequence_breaks.py @@ -6,7 +6,7 @@ class SequenceBreaksTest(SoETestBase): """Tests that 'on' doesn't put sequence breaks in logic. This is also the test base for in-logic.""" options: typing.Dict[str, typing.Any] = {"sequence_breaks": "on"} - def test_sequence_breaks_access(self): + def test_sequence_breaks_access(self) -> None: in_logic = self.options["sequence_breaks"] == "logic" # some locations that just need any weapon + sequence break @@ -30,7 +30,7 @@ def test_sequence_breaks_access(self): self.collect_by_name("Bronze Spear") # Escape now just needs either Megataur or Rimsala dead self.assertEqual(self.can_reach_location("Escape"), in_logic) - def test_sequence_breaks_goal(self): + def test_sequence_breaks_goal(self) -> None: in_logic = self.options["sequence_breaks"] == "logic" # don't need Energy Core with sequence breaks in logic diff --git a/worlds/soe/test/test_traps.py b/worlds/soe/test/test_traps.py index f83a37be822..7babd4522b3 100644 --- a/worlds/soe/test/test_traps.py +++ b/worlds/soe/test/test_traps.py @@ -32,7 +32,8 @@ def test_dataclass(self) -> None: def test_trap_count(self) -> None: """Test that total trap count is correct""" - self.assertEqual(self.options["trap_count"], len(self.get_items_by_name(self.option_name_to_item_name.values()))) + self.assertEqual(self.options["trap_count"], + len(self.get_items_by_name(self.option_name_to_item_name.values()))) class TestTrapAllZeroChance(Bases.TrapTestBase):