SoE: minor typing and style fixes (#2724)
* SoE: fix typing for tests * SoE: explicitly export pyevermizer To support loading the module from source (rather than module) we import pyevermizer from `__init__.py` in other files. This has been an implicit export and `mypy --strict` disables implicit exports, so we export it explicitly now. * SoE: fix style in patch.py * SoE: remove unused imports * SoE: fix format mistakes * SoE: cleaner typing in SoEOptions.flags as suggested by beauxq
This commit is contained in:
parent
d10f8f66c7
commit
518b04c08e
|
@ -13,12 +13,15 @@ from Utils import output_path
|
|||
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 SoESettings(settings.Group):
|
|||
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 @@ class SoEWorld(World):
|
|||
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:
|
||||
|
|
|
@ -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 @@ class SoEOptions(PerGameCommonOptions):
|
|||
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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 @@ class SoETestBase(WorldTestBase):
|
|||
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)
|
||||
|
|
|
@ -4,10 +4,10 @@ from . import SoETestBase
|
|||
|
||||
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 @@ class AccessTest(SoETestBase):
|
|||
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)
|
||||
|
|
|
@ -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 @@ class TestFragmentGoal(SoETestBase):
|
|||
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)
|
||||
|
|
|
@ -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 @@ class OoBTest(SoETestBase):
|
|||
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)
|
||||
|
|
|
@ -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 @@ class SequenceBreaksTest(SoETestBase):
|
|||
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
|
||||
|
|
|
@ -32,7 +32,8 @@ class Bases:
|
|||
|
||||
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):
|
||||
|
|
Loading…
Reference in New Issue