mirror of
https://github.com/ArchipelagoMW/Archipelago.git
synced 2026-03-24 16:53:24 -07:00
Compare commits
2 Commits
NewSoupVi-
...
NewSoupVi-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9adca5b04b | ||
|
|
182d58e847 |
@@ -1719,10 +1719,9 @@ class Spoiler:
|
|||||||
logging.debug('The following items could not be reached: %s', ['%s (Player %d) at %s (Player %d)' % (
|
logging.debug('The following items could not be reached: %s', ['%s (Player %d) at %s (Player %d)' % (
|
||||||
location.item.name, location.item.player, location.name, location.player) for location in
|
location.item.name, location.item.player, location.name, location.player) for location in
|
||||||
sphere_candidates])
|
sphere_candidates])
|
||||||
if not multiworld.has_beaten_game(state):
|
if any([multiworld.worlds[location.item.player].options.accessibility != 'minimal' for location in sphere_candidates]):
|
||||||
raise RuntimeError("During playthrough generation, the game was determined to be unbeatable. "
|
raise RuntimeError(f'Not all progression items reachable ({sphere_candidates}). '
|
||||||
"Something went terribly wrong here. "
|
f'Something went terribly wrong here.')
|
||||||
f"Unreachable progression items: {sphere_candidates}")
|
|
||||||
else:
|
else:
|
||||||
self.unreachables = sphere_candidates
|
self.unreachables = sphere_candidates
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -82,10 +82,10 @@ overridden. For more information on what methods are available to your class, ch
|
|||||||
|
|
||||||
#### Alternatives to WorldTestBase
|
#### Alternatives to WorldTestBase
|
||||||
|
|
||||||
Unit tests can also be created using
|
Unit tests can also be created using [TestBase](/test/bases.py#L16) or
|
||||||
[unittest.TestCase](https://docs.python.org/3/library/unittest.html#unittest.TestCase) directly. These may be useful
|
[unittest.TestCase](https://docs.python.org/3/library/unittest.html#unittest.TestCase) depending on your use case. These
|
||||||
for generating a multiworld under very specific constraints without using the generic world setup, or for testing
|
may be useful for generating a multiworld under very specific constraints without using the generic world setup, or for
|
||||||
portions of your code that can be tested without relying on a multiworld to be created first.
|
testing portions of your code that can be tested without relying on a multiworld to be created first.
|
||||||
|
|
||||||
#### Parametrization
|
#### Parametrization
|
||||||
|
|
||||||
@@ -102,7 +102,8 @@ for multiple inputs) the base test. Some important things to consider when attem
|
|||||||
|
|
||||||
* Classes inheriting from `WorldTestBase`, including those created by the helpers in `test.param`, will run all
|
* Classes inheriting from `WorldTestBase`, including those created by the helpers in `test.param`, will run all
|
||||||
base tests by default, make sure the produced tests actually do what you aim for and do not waste a lot of
|
base tests by default, make sure the produced tests actually do what you aim for and do not waste a lot of
|
||||||
extra CPU time. Consider using `unittest.TestCase` directly or setting `WorldTestBase.run_default_tests` to False.
|
extra CPU time. Consider using `TestBase` or `unittest.TestCase` directly
|
||||||
|
or setting `WorldTestBase.run_default_tests` to False.
|
||||||
|
|
||||||
#### Performance Considerations
|
#### Performance Considerations
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,98 @@ from test.general import gen_steps
|
|||||||
from worlds import AutoWorld
|
from worlds import AutoWorld
|
||||||
from worlds.AutoWorld import World, call_all
|
from worlds.AutoWorld import World, call_all
|
||||||
|
|
||||||
from BaseClasses import Location, MultiWorld, CollectionState, Item
|
from BaseClasses import Location, MultiWorld, CollectionState, ItemClassification, Item
|
||||||
|
from worlds.alttp.Items import item_factory
|
||||||
|
|
||||||
|
|
||||||
|
class TestBase(unittest.TestCase):
|
||||||
|
multiworld: MultiWorld
|
||||||
|
_state_cache = {}
|
||||||
|
|
||||||
|
def get_state(self, items):
|
||||||
|
if (self.multiworld, tuple(items)) in self._state_cache:
|
||||||
|
return self._state_cache[self.multiworld, tuple(items)]
|
||||||
|
state = CollectionState(self.multiworld)
|
||||||
|
for item in items:
|
||||||
|
item.classification = ItemClassification.progression
|
||||||
|
state.collect(item, prevent_sweep=True)
|
||||||
|
state.sweep_for_advancements()
|
||||||
|
state.update_reachable_regions(1)
|
||||||
|
self._state_cache[self.multiworld, tuple(items)] = state
|
||||||
|
return state
|
||||||
|
|
||||||
|
def get_path(self, state, region):
|
||||||
|
def flist_to_iter(node):
|
||||||
|
while node:
|
||||||
|
value, node = node
|
||||||
|
yield value
|
||||||
|
|
||||||
|
from itertools import zip_longest
|
||||||
|
reversed_path_as_flist = state.path.get(region, (region, None))
|
||||||
|
string_path_flat = reversed(list(map(str, flist_to_iter(reversed_path_as_flist))))
|
||||||
|
# Now we combine the flat string list into (region, exit) pairs
|
||||||
|
pathsiter = iter(string_path_flat)
|
||||||
|
pathpairs = zip_longest(pathsiter, pathsiter)
|
||||||
|
return list(pathpairs)
|
||||||
|
|
||||||
|
def run_location_tests(self, access_pool):
|
||||||
|
for i, (location, access, *item_pool) in enumerate(access_pool):
|
||||||
|
items = item_pool[0]
|
||||||
|
all_except = item_pool[1] if len(item_pool) > 1 else None
|
||||||
|
state = self._get_items(item_pool, all_except)
|
||||||
|
path = self.get_path(state, self.multiworld.get_location(location, 1).parent_region)
|
||||||
|
with self.subTest(msg="Reach Location", location=location, access=access, items=items,
|
||||||
|
all_except=all_except, path=path, entry=i):
|
||||||
|
|
||||||
|
self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), access,
|
||||||
|
f"failed {self.multiworld.get_location(location, 1)} with: {item_pool}")
|
||||||
|
|
||||||
|
# check for partial solution
|
||||||
|
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
||||||
|
for missing_item in item_pool[0]:
|
||||||
|
with self.subTest(msg="Location reachable without required item", location=location,
|
||||||
|
items=item_pool[0], missing_item=missing_item, entry=i):
|
||||||
|
state = self._get_items_partial(item_pool, missing_item)
|
||||||
|
|
||||||
|
self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), False,
|
||||||
|
f"failed {self.multiworld.get_location(location, 1)}: succeeded with "
|
||||||
|
f"{missing_item} removed from: {item_pool}")
|
||||||
|
|
||||||
|
def run_entrance_tests(self, access_pool):
|
||||||
|
for i, (entrance, access, *item_pool) in enumerate(access_pool):
|
||||||
|
items = item_pool[0]
|
||||||
|
all_except = item_pool[1] if len(item_pool) > 1 else None
|
||||||
|
state = self._get_items(item_pool, all_except)
|
||||||
|
path = self.get_path(state, self.multiworld.get_entrance(entrance, 1).parent_region)
|
||||||
|
with self.subTest(msg="Reach Entrance", entrance=entrance, access=access, items=items,
|
||||||
|
all_except=all_except, path=path, entry=i):
|
||||||
|
|
||||||
|
self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), access)
|
||||||
|
|
||||||
|
# check for partial solution
|
||||||
|
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
||||||
|
for missing_item in item_pool[0]:
|
||||||
|
with self.subTest(msg="Entrance reachable without required item", entrance=entrance,
|
||||||
|
items=item_pool[0], missing_item=missing_item, entry=i):
|
||||||
|
state = self._get_items_partial(item_pool, missing_item)
|
||||||
|
self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), False,
|
||||||
|
f"failed {self.multiworld.get_entrance(entrance, 1)} with: {item_pool}")
|
||||||
|
|
||||||
|
def _get_items(self, item_pool, all_except):
|
||||||
|
if all_except and len(all_except) > 0:
|
||||||
|
items = self.multiworld.itempool[:]
|
||||||
|
items = [item for item in items if
|
||||||
|
item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)]
|
||||||
|
items.extend(item_factory(item_pool[0], self.multiworld.worlds[1]))
|
||||||
|
else:
|
||||||
|
items = item_factory(item_pool[0], self.multiworld.worlds[1])
|
||||||
|
return self.get_state(items)
|
||||||
|
|
||||||
|
def _get_items_partial(self, item_pool, missing_item):
|
||||||
|
new_items = item_pool[0].copy()
|
||||||
|
new_items.remove(missing_item)
|
||||||
|
items = item_factory(new_items, self.multiworld.worlds[1])
|
||||||
|
return self.get_state(items)
|
||||||
|
|
||||||
|
|
||||||
class WorldTestBase(unittest.TestCase):
|
class WorldTestBase(unittest.TestCase):
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import unittest
|
||||||
|
from argparse import Namespace
|
||||||
|
|
||||||
|
from BaseClasses import MultiWorld, CollectionState
|
||||||
|
from worlds import AutoWorldRegister
|
||||||
|
|
||||||
|
|
||||||
|
class LTTPTestBase(unittest.TestCase):
|
||||||
|
def world_setup(self):
|
||||||
|
from worlds.alttp.Options import Medallion
|
||||||
|
self.multiworld = MultiWorld(1)
|
||||||
|
self.multiworld.game[1] = "A Link to the Past"
|
||||||
|
self.multiworld.set_seed(None)
|
||||||
|
args = Namespace()
|
||||||
|
for name, option in AutoWorldRegister.world_types["A Link to the Past"].options_dataclass.type_hints.items():
|
||||||
|
setattr(args, name, {1: option.from_any(getattr(option, "default"))})
|
||||||
|
self.multiworld.set_options(args)
|
||||||
|
self.multiworld.state = CollectionState(self.multiworld)
|
||||||
|
self.world = self.multiworld.worlds[1]
|
||||||
|
# by default medallion access is randomized, for unittests we set it to vanilla
|
||||||
|
self.world.options.misery_mire_medallion.value = Medallion.option_ether
|
||||||
|
self.world.options.turtle_rock_medallion.value = Medallion.option_quake
|
||||||
|
|||||||
@@ -1,113 +0,0 @@
|
|||||||
import unittest
|
|
||||||
from argparse import Namespace
|
|
||||||
|
|
||||||
from BaseClasses import MultiWorld, CollectionState, ItemClassification
|
|
||||||
from worlds import AutoWorldRegister
|
|
||||||
from ..Items import item_factory
|
|
||||||
|
|
||||||
|
|
||||||
class TestBase(unittest.TestCase):
|
|
||||||
multiworld: MultiWorld
|
|
||||||
_state_cache = {}
|
|
||||||
|
|
||||||
def get_state(self, items):
|
|
||||||
if (self.multiworld, tuple(items)) in self._state_cache:
|
|
||||||
return self._state_cache[self.multiworld, tuple(items)]
|
|
||||||
state = CollectionState(self.multiworld)
|
|
||||||
for item in items:
|
|
||||||
item.classification = ItemClassification.progression
|
|
||||||
state.collect(item, prevent_sweep=True)
|
|
||||||
state.sweep_for_advancements()
|
|
||||||
state.update_reachable_regions(1)
|
|
||||||
self._state_cache[self.multiworld, tuple(items)] = state
|
|
||||||
return state
|
|
||||||
|
|
||||||
def get_path(self, state, region):
|
|
||||||
def flist_to_iter(node):
|
|
||||||
while node:
|
|
||||||
value, node = node
|
|
||||||
yield value
|
|
||||||
|
|
||||||
from itertools import zip_longest
|
|
||||||
reversed_path_as_flist = state.path.get(region, (region, None))
|
|
||||||
string_path_flat = reversed(list(map(str, flist_to_iter(reversed_path_as_flist))))
|
|
||||||
# Now we combine the flat string list into (region, exit) pairs
|
|
||||||
pathsiter = iter(string_path_flat)
|
|
||||||
pathpairs = zip_longest(pathsiter, pathsiter)
|
|
||||||
return list(pathpairs)
|
|
||||||
|
|
||||||
def run_location_tests(self, access_pool):
|
|
||||||
for i, (location, access, *item_pool) in enumerate(access_pool):
|
|
||||||
items = item_pool[0]
|
|
||||||
all_except = item_pool[1] if len(item_pool) > 1 else None
|
|
||||||
state = self._get_items(item_pool, all_except)
|
|
||||||
path = self.get_path(state, self.multiworld.get_location(location, 1).parent_region)
|
|
||||||
with self.subTest(msg="Reach Location", location=location, access=access, items=items,
|
|
||||||
all_except=all_except, path=path, entry=i):
|
|
||||||
|
|
||||||
self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), access,
|
|
||||||
f"failed {self.multiworld.get_location(location, 1)} with: {item_pool}")
|
|
||||||
|
|
||||||
# check for partial solution
|
|
||||||
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
|
||||||
for missing_item in item_pool[0]:
|
|
||||||
with self.subTest(msg="Location reachable without required item", location=location,
|
|
||||||
items=item_pool[0], missing_item=missing_item, entry=i):
|
|
||||||
state = self._get_items_partial(item_pool, missing_item)
|
|
||||||
|
|
||||||
self.assertEqual(self.multiworld.get_location(location, 1).can_reach(state), False,
|
|
||||||
f"failed {self.multiworld.get_location(location, 1)}: succeeded with "
|
|
||||||
f"{missing_item} removed from: {item_pool}")
|
|
||||||
|
|
||||||
def run_entrance_tests(self, access_pool):
|
|
||||||
for i, (entrance, access, *item_pool) in enumerate(access_pool):
|
|
||||||
items = item_pool[0]
|
|
||||||
all_except = item_pool[1] if len(item_pool) > 1 else None
|
|
||||||
state = self._get_items(item_pool, all_except)
|
|
||||||
path = self.get_path(state, self.multiworld.get_entrance(entrance, 1).parent_region)
|
|
||||||
with self.subTest(msg="Reach Entrance", entrance=entrance, access=access, items=items,
|
|
||||||
all_except=all_except, path=path, entry=i):
|
|
||||||
|
|
||||||
self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), access)
|
|
||||||
|
|
||||||
# check for partial solution
|
|
||||||
if not all_except and access: # we are not supposed to be able to reach location with partial inventory
|
|
||||||
for missing_item in item_pool[0]:
|
|
||||||
with self.subTest(msg="Entrance reachable without required item", entrance=entrance,
|
|
||||||
items=item_pool[0], missing_item=missing_item, entry=i):
|
|
||||||
state = self._get_items_partial(item_pool, missing_item)
|
|
||||||
self.assertEqual(self.multiworld.get_entrance(entrance, 1).can_reach(state), False,
|
|
||||||
f"failed {self.multiworld.get_entrance(entrance, 1)} with: {item_pool}")
|
|
||||||
|
|
||||||
def _get_items(self, item_pool, all_except):
|
|
||||||
if all_except and len(all_except) > 0:
|
|
||||||
items = self.multiworld.itempool[:]
|
|
||||||
items = [item for item in items if
|
|
||||||
item.name not in all_except and not ("Bottle" in item.name and "AnyBottle" in all_except)]
|
|
||||||
items.extend(item_factory(item_pool[0], self.multiworld.worlds[1]))
|
|
||||||
else:
|
|
||||||
items = item_factory(item_pool[0], self.multiworld.worlds[1])
|
|
||||||
return self.get_state(items)
|
|
||||||
|
|
||||||
def _get_items_partial(self, item_pool, missing_item):
|
|
||||||
new_items = item_pool[0].copy()
|
|
||||||
new_items.remove(missing_item)
|
|
||||||
items = item_factory(new_items, self.multiworld.worlds[1])
|
|
||||||
return self.get_state(items)
|
|
||||||
|
|
||||||
|
|
||||||
class LTTPTestBase(unittest.TestCase):
|
|
||||||
def world_setup(self):
|
|
||||||
from worlds.alttp.Options import Medallion
|
|
||||||
self.multiworld = MultiWorld(1)
|
|
||||||
self.multiworld.game[1] = "A Link to the Past"
|
|
||||||
self.multiworld.set_seed(None)
|
|
||||||
args = Namespace()
|
|
||||||
for name, option in AutoWorldRegister.world_types["A Link to the Past"].options_dataclass.type_hints.items():
|
|
||||||
setattr(args, name, {1: option.from_any(getattr(option, "default"))})
|
|
||||||
self.multiworld.set_options(args)
|
|
||||||
self.multiworld.state = CollectionState(self.multiworld)
|
|
||||||
self.world = self.multiworld.worlds[1]
|
|
||||||
# by default medallion access is randomized, for unittests we set it to vanilla
|
|
||||||
self.world.options.misery_mire_medallion.value = Medallion.option_ether
|
|
||||||
self.world.options.turtle_rock_medallion.value = Medallion.option_quake
|
|
||||||
@@ -5,7 +5,7 @@ from worlds.alttp.ItemPool import difficulties
|
|||||||
from worlds.alttp.Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from worlds.alttp.Regions import create_regions
|
from worlds.alttp.Regions import create_regions
|
||||||
from worlds.alttp.Shops import create_shops
|
from worlds.alttp.Shops import create_shops
|
||||||
from worlds.alttp.test.bases import LTTPTestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestDungeon(LTTPTestBase):
|
class TestDungeon(LTTPTestBase):
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...EntranceShuffle import link_inverted_entrances
|
from worlds.alttp.EntranceShuffle import link_inverted_entrances
|
||||||
from ...InvertedRegions import create_inverted_regions
|
from worlds.alttp.InvertedRegions import create_inverted_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Regions import mark_light_world_regions
|
from worlds.alttp.Regions import mark_light_world_regions
|
||||||
from ...Shops import create_shops
|
from worlds.alttp.Shops import create_shops
|
||||||
|
from test.bases import TestBase
|
||||||
|
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestInverted(TestBase, LTTPTestBase):
|
class TestInverted(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from worlds.alttp.EntranceShuffle import connect_entrance, Inverted_LW_Entrances
|
|||||||
from worlds.alttp.InvertedRegions import create_inverted_regions
|
from worlds.alttp.InvertedRegions import create_inverted_regions
|
||||||
from worlds.alttp.ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from worlds.alttp.Rules import set_inverted_big_bomb_rules
|
from worlds.alttp.Rules import set_inverted_big_bomb_rules
|
||||||
from worlds.alttp.test.bases import LTTPTestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestInvertedBombRules(LTTPTestBase):
|
class TestInvertedBombRules(LTTPTestBase):
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...EntranceShuffle import link_inverted_entrances
|
from worlds.alttp.EntranceShuffle import link_inverted_entrances
|
||||||
from ...InvertedRegions import create_inverted_regions
|
from worlds.alttp.InvertedRegions import create_inverted_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Options import GlitchesRequired
|
from worlds.alttp.Options import GlitchesRequired
|
||||||
from ...Regions import mark_light_world_regions
|
from worlds.alttp.Regions import mark_light_world_regions
|
||||||
from ...Shops import create_shops
|
from worlds.alttp.Shops import create_shops
|
||||||
|
from test.bases import TestBase
|
||||||
|
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestInvertedMinor(TestBase, LTTPTestBase):
|
class TestInvertedMinor(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...EntranceShuffle import link_inverted_entrances
|
from worlds.alttp.EntranceShuffle import link_inverted_entrances
|
||||||
from ...InvertedRegions import create_inverted_regions
|
from worlds.alttp.InvertedRegions import create_inverted_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Options import GlitchesRequired
|
from worlds.alttp.Options import GlitchesRequired
|
||||||
from ...Regions import mark_light_world_regions
|
from worlds.alttp.Regions import mark_light_world_regions
|
||||||
from ...Shops import create_shops
|
from worlds.alttp.Shops import create_shops
|
||||||
|
from test.bases import TestBase
|
||||||
|
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestInvertedOWG(TestBase, LTTPTestBase):
|
class TestInvertedOWG(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ..bases import TestBase
|
from test.bases import TestBase
|
||||||
|
|
||||||
base_items = 41
|
base_items = 41
|
||||||
extra_counts = (15, 15, 10, 5, 25)
|
extra_counts = (15, 15, 10, 5, 25)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...InvertedRegions import mark_dark_world_regions
|
from worlds.alttp.InvertedRegions import mark_dark_world_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Options import GlitchesRequired
|
from test.bases import TestBase
|
||||||
|
from worlds.alttp.Options import GlitchesRequired
|
||||||
|
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestMinor(TestBase, LTTPTestBase):
|
class TestMinor(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...InvertedRegions import mark_dark_world_regions
|
from worlds.alttp.InvertedRegions import mark_dark_world_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Options import GlitchesRequired
|
from test.bases import TestBase
|
||||||
|
from worlds.alttp.Options import GlitchesRequired
|
||||||
|
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestVanillaOWG(TestBase, LTTPTestBase):
|
class TestVanillaOWG(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from ...Shops import shop_table
|
from worlds.alttp.Shops import shop_table
|
||||||
from ..bases import TestBase
|
from test.bases import TestBase
|
||||||
|
|
||||||
|
|
||||||
class TestSram(TestBase):
|
class TestSram(TestBase):
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from ...Dungeons import get_dungeon_item_pool
|
from worlds.alttp.Dungeons import get_dungeon_item_pool
|
||||||
from ...InvertedRegions import mark_dark_world_regions
|
from worlds.alttp.InvertedRegions import mark_dark_world_regions
|
||||||
from ...ItemPool import difficulties
|
from worlds.alttp.ItemPool import difficulties
|
||||||
from ...Items import item_factory
|
from worlds.alttp.Items import item_factory
|
||||||
from ...Options import GlitchesRequired
|
from test.bases import TestBase
|
||||||
|
from worlds.alttp.Options import GlitchesRequired
|
||||||
from ..bases import LTTPTestBase, TestBase
|
from worlds.alttp.test import LTTPTestBase
|
||||||
|
|
||||||
|
|
||||||
class TestVanilla(TestBase, LTTPTestBase):
|
class TestVanilla(TestBase, LTTPTestBase):
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from .Options import CCCharlesOptions
|
|||||||
from .Rules import set_rules
|
from .Rules import set_rules
|
||||||
from .Regions import create_regions
|
from .Regions import create_regions
|
||||||
from BaseClasses import Tutorial, ItemClassification
|
from BaseClasses import Tutorial, ItemClassification
|
||||||
from worlds.AutoWorld import World, WebWorld
|
from worlds.AutoWorld import InvalidItemError, World, WebWorld
|
||||||
|
|
||||||
|
|
||||||
class CCCharlesWeb(WebWorld):
|
class CCCharlesWeb(WebWorld):
|
||||||
@@ -157,7 +157,7 @@ class CCCharlesWorld(World):
|
|||||||
case "Bug Spray":
|
case "Bug Spray":
|
||||||
classification = ItemClassification.progression
|
classification = ItemClassification.progression
|
||||||
case _: # Should not occur
|
case _: # Should not occur
|
||||||
raise Exception("Unexpected case met: classification cannot be set for unknown item \"" + name + "\"")
|
raise InvalidItemError("Unexpected case met: classification cannot be set for unknown item \"" + name + "\"")
|
||||||
|
|
||||||
return CCCharlesItem(name, classification, item_id, self.player)
|
return CCCharlesItem(name, classification, item_id, self.player)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
from unittest import TestCase
|
from test.bases import TestBase
|
||||||
from ..data import Warp
|
from ..data import Warp
|
||||||
|
|
||||||
|
|
||||||
class TestWarps(TestCase):
|
class TestWarps(TestBase):
|
||||||
def test_warps_connect_ltr(self) -> None:
|
def test_warps_connect_ltr(self) -> None:
|
||||||
# 2-way
|
# 2-way
|
||||||
self.assertTrue(Warp("FAKE_MAP_A:0/FAKE_MAP_B:0").connects_to(Warp("FAKE_MAP_B:0/FAKE_MAP_A:0")))
|
self.assertTrue(Warp("FAKE_MAP_A:0/FAKE_MAP_B:0").connects_to(Warp("FAKE_MAP_B:0/FAKE_MAP_A:0")))
|
||||||
|
|||||||
Reference in New Issue
Block a user