2021-12-11 13:16:55 +00:00
from typing import List , Set , Dict , Tuple , Optional , Callable
2021-09-24 02:07:32 +00:00
from BaseClasses import MultiWorld , Region , Entrance , Location , RegionType
from . Options import is_option_enabled
from . Locations import LocationData
2021-09-30 17:51:07 +00:00
def create_regions ( world : MultiWorld , player : int , locations : Tuple [ LocationData , . . . ] , location_cache : List [ Location ] , pyramid_keys_unlock : str ) :
2021-09-24 02:07:32 +00:00
locations_per_region = get_locations_per_region ( locations )
2021-12-11 13:16:55 +00:00
regions = [
2021-09-30 17:51:07 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Menu ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Tutorial ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Lake desolation ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Upper lake desolation ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Lower lake desolation ' ) ,
2021-10-15 22:51:18 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Library ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Library top ' ) ,
2021-09-30 17:51:07 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Varndagroth tower left ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Varndagroth tower right (upper) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Varndagroth tower right (lower) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Varndagroth tower right (elevator) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Sealed Caves (Sirens) ' ) ,
2021-11-29 21:21:56 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Military Fortress ' ) ,
2021-09-30 17:51:07 +00:00
create_region ( world , player , locations_per_region , location_cache , ' The lab ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' The lab (power off) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' The lab (upper) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Emperors tower ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Skeleton Shaft ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Sealed Caves (upper) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Sealed Caves (Xarion) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Refugee Camp ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Forest ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Left Side forest Caves ' ) ,
2021-10-15 22:51:18 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Upper Lake Serene ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Lower Lake Serene ' ) ,
2021-09-30 17:51:07 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Caves of Banishment (upper) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Caves of Banishment (Maw) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Caves of Banishment (Sirens) ' ) ,
2021-10-15 22:51:18 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Castle Ramparts ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Castle Keep ' ) ,
2021-09-30 17:51:07 +00:00
create_region ( world , player , locations_per_region , location_cache , ' Royal towers (lower) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Royal towers ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Royal towers (upper) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Ancient Pyramid (left) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Ancient Pyramid (right) ' ) ,
create_region ( world , player , locations_per_region , location_cache , ' Space time continuum ' )
2021-09-24 02:07:32 +00:00
]
2021-12-14 13:04:34 +00:00
if __debug__ :
throwIfAnyLocationIsNotAssignedToARegion ( regions , locations_per_region . keys ( ) )
2021-12-11 13:16:55 +00:00
world . regions + = regions
2021-09-24 02:07:32 +00:00
connectStartingRegion ( world , player )
2021-10-03 10:37:06 +00:00
names : Dict [ str , int ] = { }
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Lake desolation ' , ' Lower lake desolation ' , lambda state : state . _timespinner_has_timestop ( world , player or state . has ( ' Talaria Attachment ' , player ) ) )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Lake desolation ' , ' Upper lake desolation ' , lambda state : state . _timespinner_has_fire ( world , player ) and state . can_reach ( ' Upper Lake Serene ' , ' Region ' , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Lake desolation ' , ' Skeleton Shaft ' , lambda state : state . _timespinner_has_doublejump ( world , player ) )
connect ( world , player , names , ' Lake desolation ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Upper lake desolation ' , ' Lake desolation ' )
connect ( world , player , names , ' Upper lake desolation ' , ' Lower lake desolation ' )
connect ( world , player , names , ' Lower lake desolation ' , ' Lake desolation ' )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Lower lake desolation ' , ' Library ' )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Lower lake desolation ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Library ' , ' Lower lake desolation ' )
connect ( world , player , names , ' Library ' , ' Library top ' , lambda state : state . _timespinner_has_doublejump ( world , player ) or state . has ( ' Talaria Attachment ' , player ) )
connect ( world , player , names , ' Library ' , ' Varndagroth tower left ' , lambda state : state . _timespinner_has_keycard_D ( world , player ) )
connect ( world , player , names , ' Library ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Library top ' , ' Library ' )
connect ( world , player , names , ' Varndagroth tower left ' , ' Library ' )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Varndagroth tower left ' , ' Varndagroth tower right (upper) ' , lambda state : state . _timespinner_has_keycard_C ( world , player ) )
connect ( world , player , names , ' Varndagroth tower left ' , ' Varndagroth tower right (lower) ' , lambda state : state . _timespinner_has_keycard_B ( world , player ) )
connect ( world , player , names , ' Varndagroth tower left ' , ' Sealed Caves (Sirens) ' , lambda state : state . _timespinner_has_keycard_B ( world , player ) and state . has ( ' Elevator Keycard ' , player ) )
connect ( world , player , names , ' Varndagroth tower left ' , ' Refugee Camp ' , lambda state : state . has ( ' Timespinner Wheel ' , player ) and state . has ( ' Timespinner Spindle ' , player ) )
connect ( world , player , names , ' Varndagroth tower right (upper) ' , ' Varndagroth tower left ' )
connect ( world , player , names , ' Varndagroth tower right (upper) ' , ' Varndagroth tower right (elevator) ' , lambda state : state . has ( ' Elevator Keycard ' , player ) )
connect ( world , player , names , ' Varndagroth tower right (elevator) ' , ' Varndagroth tower right (upper) ' )
connect ( world , player , names , ' Varndagroth tower right (elevator) ' , ' Varndagroth tower right (lower) ' )
2021-11-14 12:19:53 +00:00
connect ( world , player , names , ' Varndagroth tower right (lower) ' , ' Varndagroth tower left ' , lambda state : state . _timespinner_has_keycard_B ( world , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Varndagroth tower right (lower) ' , ' Varndagroth tower right (elevator) ' , lambda state : state . has ( ' Elevator Keycard ' , player ) )
connect ( world , player , names , ' Varndagroth tower right (lower) ' , ' Sealed Caves (Sirens) ' , lambda state : state . _timespinner_has_keycard_B ( world , player ) and state . has ( ' Elevator Keycard ' , player ) )
2021-11-29 21:21:56 +00:00
connect ( world , player , names , ' Varndagroth tower right (lower) ' , ' Military Fortress ' , lambda state : state . _timespinner_can_kill_all_3_bosses ( world , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Varndagroth tower right (lower) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Sealed Caves (Sirens) ' , ' Varndagroth tower left ' , lambda state : state . has ( ' Elevator Keycard ' , player ) )
connect ( world , player , names , ' Sealed Caves (Sirens) ' , ' Varndagroth tower right (lower) ' , lambda state : state . has ( ' Elevator Keycard ' , player ) )
connect ( world , player , names , ' Sealed Caves (Sirens) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
2021-11-29 21:21:56 +00:00
connect ( world , player , names , ' Military Fortress ' , ' Varndagroth tower right (lower) ' , lambda state : state . _timespinner_can_kill_all_3_bosses ( world , player ) )
connect ( world , player , names , ' Military Fortress ' , ' The lab ' , lambda state : state . _timespinner_has_keycard_B ( world , player ) and state . _timespinner_has_doublejump ( world , player ) )
connect ( world , player , names , ' The lab ' , ' Military Fortress ' )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' The lab ' , ' The lab (power off) ' , lambda state : state . _timespinner_has_doublejump_of_npc ( world , player ) )
connect ( world , player , names , ' The lab (power off) ' , ' The lab ' )
connect ( world , player , names , ' The lab (power off) ' , ' The lab (upper) ' , lambda state : state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' The lab (upper) ' , ' The lab (power off) ' )
connect ( world , player , names , ' The lab (upper) ' , ' Emperors tower ' , lambda state : state . _timespinner_has_forwarddash_doublejump ( world , player ) )
2021-11-28 21:59:34 +00:00
connect ( world , player , names , ' The lab (upper) ' , ' Ancient Pyramid (left) ' , lambda state : state . has_all ( { ' Timespinner Wheel ' , ' Timespinner Spindle ' , ' Timespinner Gear 1 ' , ' Timespinner Gear 2 ' , ' Timespinner Gear 3 ' } , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Emperors tower ' , ' The lab (upper) ' )
connect ( world , player , names , ' Skeleton Shaft ' , ' Lake desolation ' )
connect ( world , player , names , ' Skeleton Shaft ' , ' Sealed Caves (upper) ' , lambda state : state . _timespinner_has_keycard_A ( world , player ) )
connect ( world , player , names , ' Skeleton Shaft ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Sealed Caves (upper) ' , ' Skeleton Shaft ' )
connect ( world , player , names , ' Sealed Caves (upper) ' , ' Sealed Caves (Xarion) ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) or state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' Sealed Caves (Xarion) ' , ' Sealed Caves (upper) ' , lambda state : state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' Sealed Caves (Xarion) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Refugee Camp ' , ' Forest ' )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Refugee Camp ' , ' Library ' , lambda state : not is_option_enabled ( world , player , " Inverted " ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Refugee Camp ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Forest ' , ' Refugee Camp ' )
connect ( world , player , names , ' Forest ' , ' Left Side forest Caves ' , lambda state : state . has ( ' Talaria Attachment ' , player ) or state . _timespinner_has_timestop ( world , player ) )
connect ( world , player , names , ' Forest ' , ' Caves of Banishment (Sirens) ' )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Forest ' , ' Castle Ramparts ' )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Left Side forest Caves ' , ' Forest ' )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Left Side forest Caves ' , ' Upper Lake Serene ' , lambda state : state . _timespinner_has_timestop ( world , player ) )
connect ( world , player , names , ' Left Side forest Caves ' , ' Lower Lake Serene ' , lambda state : state . has ( ' Water Mask ' , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Left Side forest Caves ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Upper Lake Serene ' , ' Left Side forest Caves ' )
connect ( world , player , names , ' Upper Lake Serene ' , ' Lower Lake Serene ' , lambda state : state . has ( ' Water Mask ' , player ) )
connect ( world , player , names , ' Lower Lake Serene ' , ' Upper Lake Serene ' )
connect ( world , player , names , ' Lower Lake Serene ' , ' Left Side forest Caves ' )
connect ( world , player , names , ' Lower Lake Serene ' , ' Caves of Banishment (upper) ' )
connect ( world , player , names , ' Caves of Banishment (upper) ' , ' Upper Lake Serene ' , lambda state : state . has ( ' Water Mask ' , player ) )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Caves of Banishment (upper) ' , ' Caves of Banishment (Maw) ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) or state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' Caves of Banishment (upper) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Caves of Banishment (Maw) ' , ' Caves of Banishment (upper) ' , lambda state : state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' Caves of Banishment (Maw) ' , ' Caves of Banishment (Sirens) ' , lambda state : state . has ( ' Gas Mask ' , player ) )
connect ( world , player , names , ' Caves of Banishment (Maw) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Caves of Banishment (Sirens) ' , ' Forest ' )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Castle Ramparts ' , ' Forest ' )
connect ( world , player , names , ' Castle Ramparts ' , ' Castle Keep ' )
connect ( world , player , names , ' Castle Ramparts ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Castle Keep ' , ' Castle Ramparts ' )
connect ( world , player , names , ' Castle Keep ' , ' Royal towers (lower) ' , lambda state : state . _timespinner_has_doublejump ( world , player ) )
connect ( world , player , names , ' Castle Keep ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Royal towers (lower) ' , ' Castle Keep ' )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Royal towers (lower) ' , ' Royal towers ' , lambda state : state . has ( ' Timespinner Wheel ' , player ) or state . _timespinner_has_forwarddash_doublejump ( world , player ) )
connect ( world , player , names , ' Royal towers (lower) ' , ' Space time continuum ' , lambda state : state . has ( ' Twin Pyramid Key ' , player ) )
connect ( world , player , names , ' Royal towers ' , ' Royal towers (lower) ' )
connect ( world , player , names , ' Royal towers ' , ' Royal towers (upper) ' , lambda state : state . _timespinner_has_doublejump ( world , player ) )
connect ( world , player , names , ' Royal towers (upper) ' , ' Royal towers ' )
connect ( world , player , names , ' Ancient Pyramid (left) ' , ' The lab (upper) ' )
connect ( world , player , names , ' Ancient Pyramid (left) ' , ' Ancient Pyramid (right) ' , lambda state : state . _timespinner_has_upwarddash ( world , player ) )
connect ( world , player , names , ' Ancient Pyramid (right) ' , ' Ancient Pyramid (left) ' , lambda state : state . _timespinner_has_upwarddash ( world , player ) )
connect ( world , player , names , ' Space time continuum ' , ' Lake desolation ' , lambda state : pyramid_keys_unlock == " GateLakeDesolation " )
connect ( world , player , names , ' Space time continuum ' , ' Lower lake desolation ' , lambda state : pyramid_keys_unlock == " GateKittyBoss " )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Library ' , lambda state : pyramid_keys_unlock == " GateLeftLibrary " )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Varndagroth tower right (lower) ' , lambda state : pyramid_keys_unlock == " GateMilitairyGate " )
connect ( world , player , names , ' Space time continuum ' , ' Skeleton Shaft ' , lambda state : pyramid_keys_unlock == " GateSealedCaves " )
connect ( world , player , names , ' Space time continuum ' , ' Sealed Caves (Sirens) ' , lambda state : pyramid_keys_unlock == " GateSealedSirensCave " )
2021-10-16 17:22:23 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Left Side forest Caves ' , lambda state : pyramid_keys_unlock == " GateLakeSirineRight " )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Refugee Camp ' , lambda state : pyramid_keys_unlock == " GateAccessToPast " )
2021-10-15 22:51:18 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Castle Ramparts ' , lambda state : pyramid_keys_unlock == " GateCastleRamparts " )
connect ( world , player , names , ' Space time continuum ' , ' Castle Keep ' , lambda state : pyramid_keys_unlock == " GateCastleKeep " )
2021-09-24 02:07:32 +00:00
connect ( world , player , names , ' Space time continuum ' , ' Royal towers (lower) ' , lambda state : pyramid_keys_unlock == " GateRoyalTowers " )
connect ( world , player , names , ' Space time continuum ' , ' Caves of Banishment (Maw) ' , lambda state : pyramid_keys_unlock == " GateMaw " )
connect ( world , player , names , ' Space time continuum ' , ' Caves of Banishment (upper) ' , lambda state : pyramid_keys_unlock == " GateCavesOfBanishment " )
2021-10-03 10:37:06 +00:00
2021-12-11 13:16:55 +00:00
def throwIfAnyLocationIsNotAssignedToARegion ( regions : List [ Region ] , regionNames : Set [ str ] ) :
existingRegions = set ( )
for region in regions :
existingRegions . add ( region . name )
if ( regionNames - existingRegions ) :
raise Exception ( " Tiemspinner: the following regions are used in locations: {} , but no such region exists " . format ( regionNames - existingRegions ) )
2021-10-09 09:58:38 +00:00
def create_location ( player : int , location_data : LocationData , region : Region , location_cache : List [ Location ] ) - > Location :
location = Location ( player , location_data . name , location_data . code , region )
location . access_rule = location_data . rule
2021-09-24 02:07:32 +00:00
if id is None :
location . event = True
location . locked = True
2021-09-30 17:51:07 +00:00
location_cache . append ( location )
2021-09-24 02:07:32 +00:00
return location
2021-09-30 17:51:07 +00:00
def create_region ( world : MultiWorld , player : int , locations_per_region : Dict [ str , List [ LocationData ] ] , location_cache : List [ Location ] , name : str ) - > Region :
2021-09-24 02:07:32 +00:00
region = Region ( name , RegionType . Generic , name , player )
region . world = world
if name in locations_per_region :
for location_data in locations_per_region [ name ] :
2021-10-09 09:58:38 +00:00
location = create_location ( player , location_data , region , location_cache )
2021-09-24 02:07:32 +00:00
region . locations . append ( location )
return region
2021-09-30 17:51:07 +00:00
2021-09-24 02:07:32 +00:00
def connectStartingRegion ( world : MultiWorld , player : int ) :
menu = world . get_region ( ' Menu ' , player )
tutorial = world . get_region ( ' Tutorial ' , player )
space_time_continuum = world . get_region ( ' Space time continuum ' , player )
if is_option_enabled ( world , player , " Inverted " ) :
starting_region = world . get_region ( ' Refugee Camp ' , player )
else :
starting_region = world . get_region ( ' Lake desolation ' , player )
menu_to_tutorial = Entrance ( player , ' Tutorial ' , menu )
menu_to_tutorial . connect ( tutorial )
menu . exits . append ( menu_to_tutorial )
tutorial_to_start = Entrance ( player , ' Start Game ' , tutorial )
tutorial_to_start . connect ( starting_region )
tutorial . exits . append ( tutorial_to_start )
teleport_back_to_start = Entrance ( player , ' Teleport back to start ' , space_time_continuum )
teleport_back_to_start . connect ( starting_region )
space_time_continuum . exits . append ( teleport_back_to_start )
2021-09-30 17:51:07 +00:00
2021-10-03 10:37:06 +00:00
def connect ( world : MultiWorld , player : int , used_names : Dict [ str , int ] , source : str , target : str , rule : Optional [ Callable ] = None ) :
2021-09-24 02:07:32 +00:00
sourceRegion = world . get_region ( source , player )
targetRegion = world . get_region ( target , player )
if target not in used_names :
used_names [ target ] = 1
name = target
else :
used_names [ target ] + = 1
name = target + ( ' ' * used_names [ target ] )
connection = Entrance ( player , name , sourceRegion )
if rule :
connection . access_rule = rule
sourceRegion . exits . append ( connection )
connection . connect ( targetRegion )
2021-09-30 17:51:07 +00:00
def get_locations_per_region ( locations : Tuple [ LocationData , . . . ] ) - > Dict [ str , List [ LocationData ] ] :
2021-09-24 02:07:32 +00:00
per_region : Dict [ str , List [ LocationData ] ] = { }
for location in locations :
2021-09-30 17:51:07 +00:00
per_region . setdefault ( location . region , [ ] ) . append ( location )
2021-09-24 02:07:32 +00:00
2021-10-01 12:15:45 +00:00
return per_region