Skip to content

Commit

Permalink
SoE: minor typing and style fixes (ArchipelagoMW#2724)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
black-sliver authored Jan 15, 2024
1 parent d10f8f6 commit 518b04c
Show file tree
Hide file tree
Showing 9 changed files with 28 additions and 24 deletions.
9 changes: 5 additions & 4 deletions worlds/soe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 5 additions & 3 deletions worlds/soe/options.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion worlds/soe/patch.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions worlds/soe/test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions worlds/soe/test/test_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,)
Expand All @@ -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)
12 changes: 6 additions & 6 deletions worlds/soe/test/test_goal.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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)

Expand All @@ -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)
4 changes: 2 additions & 2 deletions worlds/soe/test/test_oob.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions worlds/soe/test/test_sequence_breaks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion worlds/soe/test/test_traps.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit 518b04c

Please sign in to comment.