Skip to content

Commit

Permalink
core: Region management helpers (ArchipelagoMW#761)
Browse files Browse the repository at this point in the history
  • Loading branch information
alwaysintreble authored Apr 10, 2023
1 parent 9d73988 commit 94a0251
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 0 deletions.
23 changes: 23 additions & 0 deletions BaseClasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,29 @@ def get_connecting_entrance(self, is_main_entrance: typing.Callable[[Entrance],
for entrance in self.entrances: # BFS might be better here, trying DFS for now.
return entrance.parent_region.get_connecting_entrance(is_main_entrance)

def add_locations(self, locations: Dict[str, Optional[int]], location_type: Optional[typing.Type[Location]] = None) -> None:
"""Adds locations to the Region object, where location_type is your Location class and locations is a dict of
location names to address."""
if location_type is None:
location_type = Location
for location, address in locations.items():
self.locations.append(location_type(self.player, location, address, self))

def add_exits(self, exits: Dict[str, Optional[str]], rules: Dict[str, Callable[[CollectionState], bool]] = None) -> None:
"""
Connects current region to regions in exit dictionary. Passed region names must exist first.
:param exits: exits from the region. format is {"connecting_region", "exit_name"}
:param rules: rules for the exits from this region. format is {"connecting_region", rule}
"""
for exiting_region, name in exits.items():
ret = Entrance(self.player, name, self) if name \
else Entrance(self.player, f"{self.name} -> {exiting_region}", self)
if rules and exiting_region in rules:
ret.access_rule = rules[exiting_region]
self.exits.append(ret)
ret.connect(self.multiworld.get_region(exiting_region, self.player))

def __repr__(self):
return self.__str__()

Expand Down
71 changes: 71 additions & 0 deletions test/general/TestHelpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from random import seed
from typing import Dict, Optional, Callable, Tuple, List

from BaseClasses import MultiWorld, CollectionState, Region
import unittest


class TestHelpers(unittest.TestCase):
multiworld: MultiWorld
player: int = 1

def setUp(self) -> None:
self.multiworld = MultiWorld(self.player)
self.multiworld.game[self.player] = "helper_test_game"
self.multiworld.player_name = {1: "Tester"}
self.multiworld.set_seed(seed)
self.multiworld.set_default_common_options()

def testRegionHelpers(self) -> None:
regions: Dict[str, str] = {
"TestRegion1": "I'm an apple",
"TestRegion2": "I'm a banana",
}

locations: Dict[str, Dict[str, Optional[int]]] = {
"TestRegion1": {
"loc_1": 123,
"loc_2": 456,
"event_loc": None,
},
"TestRegion2": {
"loc_1": 321,
"loc_2": 654,
}
}

reg_exits: Dict[str, Dict[str, Optional[str]]] = {
"TestRegion1": {"TestRegion2": "connection"},
"TestRegion2": {"TestRegion1": None},
}

exit_rules: Dict[str, Callable[[CollectionState], bool]] = {
"TestRegion1": lambda state: state.has("test_item", self.player)
}

self.multiworld.regions += [Region(region, self.player, self.multiworld, regions[region]) for region in regions]

with self.subTest("Test Location Creation Helper"):
for region, loc_pair in locations.items():
self.multiworld.get_region(region, self.player).add_locations(loc_pair)

created_location_names = [loc.name for loc in self.multiworld.get_locations()]
for loc_pair in locations.values():
for loc_name in loc_pair:
self.assertTrue(loc_name in created_location_names)

with self.subTest("Test Exit Creation Helper"):
for region, exit_dict in reg_exits.items():
self.multiworld.get_region(region, self.player).add_exits(exit_dict, exit_rules)

created_exit_names = [exit.name for region in self.multiworld.get_regions() for exit in region.exits]
for parent, exit_pair in reg_exits.items():
for exit_reg, exit_name in exit_pair.items():
if exit_name:
self.assertTrue(exit_name in created_exit_names)
else:
self.assertTrue(f"{parent} -> {exit_reg}" in created_exit_names)
if exit_reg in exit_rules:
entrance_name = exit_name if exit_name else f"{parent} -> {exit_reg}"
self.assertEqual(exit_rules[exit_reg],
self.multiworld.get_entrance(entrance_name, self.player).access_rule)

0 comments on commit 94a0251

Please sign in to comment.