From 097ac189e428d38b47cb876393731fa4d488d384 Mon Sep 17 00:00:00 2001 From: black-sliver <59490463+black-sliver@users.noreply.github.com> Date: Fri, 14 Oct 2022 19:35:53 +0200 Subject: [PATCH] SoE: add tests ... (#1097) * SoE: add tests ... ... for goals, bronze axe and bronze spear+ * SoE: fix tests --- test/soe/TestAccess.py | 22 +++++++++++ test/soe/TestGoal.py | 53 ++++++++++++++++++++++++++ test/soe/__init__.py | 84 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 test/soe/TestAccess.py create mode 100644 test/soe/TestGoal.py create mode 100644 test/soe/__init__.py diff --git a/test/soe/TestAccess.py b/test/soe/TestAccess.py new file mode 100644 index 00000000..c7da7b88 --- /dev/null +++ b/test/soe/TestAccess.py @@ -0,0 +1,22 @@ +import typing +from . import SoETestBase + + +class AccessTest(SoETestBase): + @staticmethod + def _resolveGourds(gourds: typing.Dict[str, typing.Iterable[int]]): + return [f"{name} #{number}" for name, numbers in gourds.items() for number in numbers] + + def testBronzeAxe(self): + gourds = { + "Pyramid bottom": (118, 121, 122, 123, 124, 125), + "Pyramid top": (140,) + } + locations = ["Rimsala"] + self._resolveGourds(gourds) + items = [["Bronze Axe"]] + self.assertAccessDependency(locations, items) + + def testBronzeSpearPlus(self): + locations = ["Megataur"] + items = [["Bronze Spear"], ["Lance (Weapon)"], ["Laser Lance"]] + self.assertAccessDependency(locations, items) diff --git a/test/soe/TestGoal.py b/test/soe/TestGoal.py new file mode 100644 index 00000000..d127d389 --- /dev/null +++ b/test/soe/TestGoal.py @@ -0,0 +1,53 @@ +from . import SoETestBase + + +class TestFragmentGoal(SoETestBase): + options = { + "energy_core": "fragments", + "available_fragments": 21, + "required_fragments": 20, + } + + def testFragments(self): + self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Gauge"]) + self.assertBeatable(False) # 0 fragments + fragments = self.get_items_by_name("Energy Core Fragment") + victory = self.get_item_by_name("Victory") + self.collect(fragments[:-2]) # 1 too few + self.assertEqual(self.count("Energy Core Fragment"), 19) + self.assertBeatable(False) + self.collect(fragments[-2:-1]) # exact + self.assertEqual(self.count("Energy Core Fragment"), 20) + self.assertBeatable(True) + self.remove([victory]) # reset + self.collect(fragments[-1:]) # 1 extra + self.assertEqual(self.count("Energy Core Fragment"), 21) + self.assertBeatable(True) + + def testNoWeapon(self): + self.collect_by_name(["Diamond Eye", "Wheel", "Gauge", "Energy Core Fragment"]) + self.assertBeatable(False) + + def testNoRocket(self): + self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Energy Core Fragment"]) + self.assertBeatable(False) + + +class TestShuffleGoal(SoETestBase): + options = { + "energy_core": "shuffle", + } + + def testCore(self): + self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Gauge"]) + self.assertBeatable(False) + self.collect_by_name(["Energy Core"]) + self.assertBeatable(True) + + def testNoWeapon(self): + self.collect_by_name(["Diamond Eye", "Wheel", "Gauge", "Energy Core"]) + self.assertBeatable(False) + + def testNoRocket(self): + self.collect_by_name(["Gladiator Sword", "Diamond Eye", "Wheel", "Energy Core"]) + self.assertBeatable(False) diff --git a/test/soe/__init__.py b/test/soe/__init__.py new file mode 100644 index 00000000..0161a6c3 --- /dev/null +++ b/test/soe/__init__.py @@ -0,0 +1,84 @@ +import typing +import unittest +from argparse import Namespace +from test.general import gen_steps +from BaseClasses import MultiWorld, Item +from worlds import AutoWorld +from worlds.AutoWorld import call_all + + +class SoETestBase(unittest.TestCase): + options: typing.Dict[str, typing.Any] = {} + world: MultiWorld + game = "Secret of Evermore" + + def setUp(self): + self.world = MultiWorld(1) + self.world.game[1] = self.game + self.world.player_name = {1: "Tester"} + self.world.set_seed() + args = Namespace() + for name, option in AutoWorld.AutoWorldRegister.world_types[self.game].option_definitions.items(): + setattr(args, name, {1: option.from_any(self.options.get(name, option.default))}) + self.world.set_options(args) + self.world.set_default_common_options() + for step in gen_steps: + call_all(self.world, step) + + def collect_all_but(self, item_names: typing.Union[str, typing.Iterable[str]]): + if isinstance(item_names, str): + item_names = (item_names,) + for item in self.world.get_items(): + if item.name not in item_names: + self.world.state.collect(item) + + def get_item_by_name(self, item_name: str): + for item in self.world.get_items(): + if item.name == item_name: + return item + raise ValueError("No such item") + + def get_items_by_name(self, item_names: typing.Union[str, typing.Iterable[str]]): + if isinstance(item_names, str): + item_names = (item_names,) + return [item for item in self.world.itempool if item.name in item_names] + + def collect_by_name(self, item_names: typing.Union[str, typing.Iterable[str]]): + items = self.get_items_by_name(item_names) + self.collect(items) + return items + + def collect(self, items: typing.Union[Item, typing.Iterable[Item]]): + if isinstance(items, Item): + items = (items,) + for item in items: + self.world.state.collect(item) + + def remove(self, items: typing.Union[Item, typing.Iterable[Item]]): + if isinstance(items, Item): + items = (items,) + for item in items: + if item.location and item.location.event and item.location in self.world.state.events: + self.world.state.events.remove(item.location) + self.world.state.remove(item) + + def can_reach_location(self, location): + return self.world.state.can_reach(location, "Location", 1) + + def count(self, item_name): + return self.world.state.count(item_name, 1) + + def assertAccessDependency(self, locations, possible_items): + all_items = [item_name for item_names in possible_items for item_name in item_names] + + self.collect_all_but(all_items) + for location in self.world.get_locations(): + self.assertEqual(self.world.state.can_reach(location), location.name not in locations) + for item_names in possible_items: + items = self.collect_by_name(item_names) + for location in locations: + self.assertTrue(self.can_reach_location(location)) + self.remove(items) + + def assertBeatable(self, beatable: bool): + self.assertEqual(self.world.can_beat_game(self.world.state), beatable)