Files
dockipelago/worlds/grinch/Regions.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

252 lines
8.9 KiB
Python

from typing import TYPE_CHECKING, NamedTuple, Optional
from BaseClasses import Region, MultiWorld, Entrance
from .Rules import interpret_rule
from .Items import grinch_items
from ..generic.Rules import add_rule
if TYPE_CHECKING:
from . import GrinchWorld
mainareas_list = [
"Mount Crumpit"
"Whoville",
"Who Forest",
"Who Dump",
"Who Lake",
]
subareas_list = [
"Post Office",
"City Hall",
"Clock Tower",
"Ski Resort",
"Civic Center",
"Minefield",
"Power Plant",
"Generator Building",
"Submarine World",
"Scout's Hut",
"North Shore",
"Mayor's Villa",
"Sleigh Room",
"Sleigh Ride",
]
supadow_list = [
"Spin N' Win Supadow",
"Dankamania Supadow",
"The Copter Race Contest Supadow",
"Bike Race",
]
class GrinchRegionInfo(NamedTuple):
map_id: int
parent_region: str
allow_deathlink: bool = False
map_table_addr: Optional[int] = None
allow_music_rando: Optional[bool] = None
region_access: Optional[list[list[str]]] = None
advanced_region_access: Optional[list[list[str]]] = None
class GrinchRegion(Region):
region_data: GrinchRegionInfo
def __init__(self, region_name: str, region_data: GrinchRegionInfo, player: int, multiworld: MultiWorld):
super().__init__(region_name, player, multiworld)
self.region_data = region_data
ALL_REGIONS_INFO: dict[str, GrinchRegionInfo] = {
"Mount Crumpit": GrinchRegionInfo(0x05, "", False, 0x0FAAB4, True),
"Whoville": GrinchRegionInfo(0x07, "Mount Crumpit", True, 0x0E8FA0, True,
region_access=[
[grinch_items.keys.WHOVILLE],
["1:" + grinch_items.keys.PROGRESSIVE_VACUUM_TUBE],
],),
"Who Forest": GrinchRegionInfo(0x0B, "Mount Crumpit", True, 0x0E1C54, True,
region_access=[
[grinch_items.keys.WHO_FOREST],
["2:" + grinch_items.keys.PROGRESSIVE_VACUUM_TUBE],
],),
"Who Dump": GrinchRegionInfo(0x0E, "Mount Crumpit", True, 0x0DFF24, True,
region_access=[
[grinch_items.keys.WHO_DUMP],
["3:" + grinch_items.keys.PROGRESSIVE_VACUUM_TUBE],
],),
"Who Lake": GrinchRegionInfo(0x12, "Mount Crumpit", True, 0x0DD16C, True,
region_access=[
[grinch_items.keys.WHO_LAKE],
["4:" + grinch_items.keys.PROGRESSIVE_VACUUM_TUBE],
],),
"Sleigh Room": GrinchRegionInfo(0x05, "Mount Crumpit", False, 0x0FAAB4, True,
region_access=[
[grinch_items.keys.SLEIGH_ROOM_KEY],
],),
"Spin N' Win": GrinchRegionInfo(0x1A, "Mount Crumpit", False, allow_music_rando=True),
"Dankamania": GrinchRegionInfo(0x1B, "Mount Crumpit", False, allow_music_rando=True),
"The Copter Race Contest": GrinchRegionInfo(0X1C, "Mount Crumpit", False, allow_music_rando=True),
"Post Office": GrinchRegionInfo(0x0A, "Whoville", False, 0x0DFB64, True,
region_access=[
[grinch_items.level_items.WV_WHO_CLOAK],
],),
"City Hall": GrinchRegionInfo(0x08, "Whoville", False, 0x0E7090, True,
region_access=[
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER],
],),
"Clock Tower": GrinchRegionInfo(0x09, "Whoville", False, 0x0E70E8, True,
region_access=[
[grinch_items.moves.SNEAK],
[grinch_items.gadgets.SLIME_SHOOTER],
],),
"Ski Resort": GrinchRegionInfo(0x0C, "Who Forest", True, 0x0E98C0, True,
region_access=[
[grinch_items.level_items.WF_CABLE_CAR_ACCESS_CARD],
],),
"Civic Center": GrinchRegionInfo(0x0D, "Who Forest", True, 0x0DDEA0, True,
region_access=[
[grinch_items.gadgets.GRINCH_COPTER],
[grinch_items.gadgets.OCTOPUS_CLIMBING_DEVICE],
],),
"Minefield": GrinchRegionInfo(0x11, "Who Dump", True, 0x0E87C4, True,
region_access=[
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.ROCKET_SPRING,
grinch_items.moves.PANCAKE],
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.GRINCH_COPTER,
grinch_items.moves.PANCAKE],
],),
"Power Plant": GrinchRegionInfo(0x10, "Who Dump", True, 0x0E885C, True,
region_access=[
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.GRINCH_COPTER,
grinch_items.moves.PANCAKE],
[grinch_items.gadgets.SLIME_SHOOTER,
grinch_items.gadgets.GRINCH_COPTER,
grinch_items.moves.PANCAKE],
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.OCTOPUS_CLIMBING_DEVICE,
grinch_items.gadgets.SLIME_SHOOTER,
grinch_items.gadgets.ROCKET_SPRING,
grinch_items.moves.PANCAKE],
],),
"Generator Building": GrinchRegionInfo(0x0F, "Power Plant", True, 0x0E0ED4, True,
region_access=[
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.GRINCH_COPTER],
[grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
grinch_items.gadgets.OCTOPUS_CLIMBING_DEVICE,
grinch_items.gadgets.ROCKET_SPRING,
grinch_items.moves.MAX,
grinch_items.moves.BAD_BREATH],
],),
"Submarine World": GrinchRegionInfo(0x17, "Who Lake", True, 0x0E0368, True,
region_access=[
[grinch_items.gadgets.MARINE_MOBILE],
],),
"Scout's Hut": GrinchRegionInfo(0x13, "Who Lake", True, 0x0D5DFC, True,
region_access=[
[grinch_items.gadgets.GRINCH_COPTER,
grinch_items.moves.SNEAK],
[grinch_items.gadgets.ROCKET_SPRING,
grinch_items.moves.SNEAK],
],),
"North Shore": GrinchRegionInfo(0x14, "Who Lake", True, 0x0DD43C, True,
region_access=[
[grinch_items.level_items.WL_SCOUT_CLOTHES,
grinch_items.moves.SNEAK],
],),
"Mayor's Villa": GrinchRegionInfo(0x16, "North Shore", True, 0x0FA7C8, True,
region_access=[
[grinch_items.level_items.WL_SCOUT_CLOTHES],
],),
"Bike Race": GrinchRegionInfo(0x18, "Sleigh Room", False, allow_music_rando=True),
"Sleigh Ride": GrinchRegionInfo(0x19, "Sleigh Room", False, allow_music_rando=True,
region_access=[
[
grinch_items.sleigh_parts.EXHAUST_PIPES,
grinch_items.sleigh_parts.TWIN_END_TUBA,
grinch_items.sleigh_parts.SKIS,
grinch_items.sleigh_parts.TIRES,
],
# grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
# grinch_items.keys.WHOVILLE,
# grinch_items.keys.WHO_FOREST,
# grinch_items.keys.WHO_DUMP,
# grinch_items.keys.WHO_LAKE,
# grinch_items.gadgets.ROCKET_SPRING,
# grinch_items.gadgets.MARINE_MOBILE,
# grinch_items.moves.MAX,
# grinch_items.moves.SEIZE,
# grinch_items.moves.PANCAKE],
# [grinch_items.gadgets.ROTTEN_EGG_LAUNCHER,
# "4:" + grinch_items.keys.PROGRESSIVE_VACUUM_TUBE,
# grinch_items.gadgets.ROCKET_SPRING,
# grinch_items.gadgets.MARINE_MOBILE,
# grinch_items.moves.MAX,
# grinch_items.moves.SEIZE,
# grinch_items.moves.PANCAKE],
],),
}
def create_regions(world: "GrinchWorld"):
for area in [*mainareas_list, *subareas_list, *supadow_list]:
# Each area in mainarea, subarea, and supadow create a region for the given player
world.multiworld.regions.append(Region(area, world.player, world.multiworld))
# TODO Optimize this function
def grinchconnect(
world: "GrinchWorld",
current_region_name: str,
connected_region_name: str,
access_rules: list[list[str]]
):
current_region = world.get_region(current_region_name)
connected_region = world.get_region(connected_region_name)
rule_list = interpret_rule(access_rules, world.player)
# Goes from current to connected
curr_entr: Entrance = current_region.connect(connected_region)
# Goes from connected to current
connect_entr: Entrance = connected_region.connect(current_region)
for access_rule in rule_list:
if rule_list.index(access_rule) == 0:
add_rule(curr_entr, access_rule)
else:
add_rule(curr_entr, access_rule, combine="or")
if rule_list.index(access_rule) == 0:
add_rule(connect_entr, access_rule)
else:
add_rule(connect_entr, access_rule, combine="or")
# What regions are connected to each other
def connect_regions(world: "GrinchWorld", multiworld: MultiWorld):
for grinch_region, grinch_data in ALL_REGIONS_INFO.items():
multiworld.regions.append(GrinchRegion(grinch_region, grinch_data, world.player, multiworld))
if grinch_region == "Mount Crumpit":
continue
grinchconnect(world, grinch_region, grinch_data.parent_region, grinch_data.region_access)