 52e65e208e
			
		
	
	52e65e208e
	
	
	
		
			
			Major Content update for Stardew Valley, including the following features - Major performance improvements all across the Stardew Valley apworld, including a significant reduction in the test time - Randomized Farm Type - Bundles rework (Remixed Bundles and Missing Bundle!) - New Settings: * Shipsanity - Shipping individual items * Monstersanity - Slaying monsters * Cooksanity - Cooking individual recipes * Chefsanity - Learning individual recipes * Craftsanity - Crafting individual items - New Goals: * Protector of the Valley - Complete every monster slayer goal * Full Shipment - Ship every item * Craftmaster - Craft every item * Gourmet Chef - Cook every recipe * Legend - Earn 10 000 000g * Mystery of the Stardrops - Find every stardrop (Maguffin Hunt) * Allsanity - Complete every check in your slot - Building Shuffle: Cheaper options - Tool Shuffle: Cheaper options - Money rework - New traps - New isolated checks and items, including the farm cave, the movie theater, etc - Mod Support: SVE [Albrekka] - Mod Support: Distant Lands [Albrekka] - Mod Support: Hat Mouse Lacey [Albrekka] - Mod Support: Boarding House [Albrekka] Co-authored-by: Witchybun <elnendil@gmail.com> Co-authored-by: Witchybun <96719127+Witchybun@users.noreply.github.com> Co-authored-by: Jouramie <jouramie@hotmail.com> Co-authored-by: Alchav <59858495+Alchav@users.noreply.github.com>
		
			
				
	
	
		
			713 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			713 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from random import Random
 | |
| from typing import Iterable, Dict, Protocol, List, Tuple, Set
 | |
| 
 | |
| from BaseClasses import Region, Entrance
 | |
| from .options import EntranceRandomization, ExcludeGingerIsland, Museumsanity, StardewValleyOptions
 | |
| from .strings.entrance_names import Entrance
 | |
| from .strings.region_names import Region
 | |
| from .region_classes import RegionData, ConnectionData, RandomizationFlag, ModificationFlag
 | |
| from .mods.mod_regions import ModDataList, vanilla_connections_to_remove_by_mod
 | |
| 
 | |
| 
 | |
| class RegionFactory(Protocol):
 | |
|     def __call__(self, name: str, regions: Iterable[str]) -> Region:
 | |
|         raise NotImplementedError
 | |
| 
 | |
| 
 | |
| vanilla_regions = [
 | |
|     RegionData(Region.menu, [Entrance.to_stardew_valley]),
 | |
|     RegionData(Region.stardew_valley, [Entrance.to_farmhouse]),
 | |
|     RegionData(Region.farm_house, [Entrance.farmhouse_to_farm, Entrance.downstairs_to_cellar, Entrance.farmhouse_cooking, Entrance.watch_queen_of_sauce]),
 | |
|     RegionData(Region.cellar),
 | |
|     RegionData(Region.kitchen),
 | |
|     RegionData(Region.queen_of_sauce),
 | |
|     RegionData(Region.farm,
 | |
|                [Entrance.farm_to_backwoods, Entrance.farm_to_bus_stop, Entrance.farm_to_forest,
 | |
|                 Entrance.farm_to_farmcave, Entrance.enter_greenhouse,
 | |
|                 Entrance.enter_coop, Entrance.enter_barn,
 | |
|                 Entrance.enter_shed, Entrance.enter_slime_hutch,
 | |
|                 Entrance.farming, Entrance.shipping]),
 | |
|     RegionData(Region.farming),
 | |
|     RegionData(Region.shipping),
 | |
|     RegionData(Region.backwoods, [Entrance.backwoods_to_mountain]),
 | |
|     RegionData(Region.bus_stop,
 | |
|                [Entrance.bus_stop_to_town, Entrance.take_bus_to_desert, Entrance.bus_stop_to_tunnel_entrance]),
 | |
|     RegionData(Region.forest,
 | |
|                [Entrance.forest_to_town, Entrance.enter_secret_woods, Entrance.forest_to_wizard_tower,
 | |
|                 Entrance.forest_to_marnie_ranch,
 | |
|                 Entrance.forest_to_leah_cottage, Entrance.forest_to_sewer,
 | |
|                 Entrance.buy_from_traveling_merchant,
 | |
|                 Entrance.attend_flower_dance, Entrance.attend_festival_of_ice]),
 | |
|     RegionData(Region.traveling_cart, [Entrance.buy_from_traveling_merchant_sunday,
 | |
|                                        Entrance.buy_from_traveling_merchant_monday,
 | |
|                                        Entrance.buy_from_traveling_merchant_tuesday,
 | |
|                                        Entrance.buy_from_traveling_merchant_wednesday,
 | |
|                                        Entrance.buy_from_traveling_merchant_thursday,
 | |
|                                        Entrance.buy_from_traveling_merchant_friday,
 | |
|                                        Entrance.buy_from_traveling_merchant_saturday]),
 | |
|     RegionData(Region.traveling_cart_sunday),
 | |
|     RegionData(Region.traveling_cart_monday),
 | |
|     RegionData(Region.traveling_cart_tuesday),
 | |
|     RegionData(Region.traveling_cart_wednesday),
 | |
|     RegionData(Region.traveling_cart_thursday),
 | |
|     RegionData(Region.traveling_cart_friday),
 | |
|     RegionData(Region.traveling_cart_saturday),
 | |
|     RegionData(Region.farm_cave),
 | |
|     RegionData(Region.greenhouse),
 | |
|     RegionData(Region.mountain,
 | |
|                [Entrance.mountain_to_railroad, Entrance.mountain_to_tent, Entrance.mountain_to_carpenter_shop,
 | |
|                 Entrance.mountain_to_the_mines, Entrance.enter_quarry, Entrance.mountain_to_adventurer_guild,
 | |
|                 Entrance.mountain_to_town, Entrance.mountain_to_maru_room,
 | |
|                 Entrance.mountain_to_leo_treehouse]),
 | |
|     RegionData(Region.leo_treehouse),
 | |
|     RegionData(Region.maru_room),
 | |
|     RegionData(Region.tunnel_entrance, [Entrance.tunnel_entrance_to_bus_tunnel]),
 | |
|     RegionData(Region.bus_tunnel),
 | |
|     RegionData(Region.town,
 | |
|                [Entrance.town_to_community_center, Entrance.town_to_beach, Entrance.town_to_hospital,
 | |
|                 Entrance.town_to_pierre_general_store, Entrance.town_to_saloon, Entrance.town_to_alex_house,
 | |
|                 Entrance.town_to_trailer,
 | |
|                 Entrance.town_to_mayor_manor,
 | |
|                 Entrance.town_to_sam_house, Entrance.town_to_haley_house, Entrance.town_to_sewer,
 | |
|                 Entrance.town_to_clint_blacksmith,
 | |
|                 Entrance.town_to_museum,
 | |
|                 Entrance.town_to_jojamart, Entrance.purchase_movie_ticket,
 | |
|                 Entrance.attend_egg_festival, Entrance.attend_fair, Entrance.attend_spirit_eve, Entrance.attend_winter_star]),
 | |
|     RegionData(Region.beach, [Entrance.beach_to_willy_fish_shop, Entrance.enter_elliott_house, Entrance.enter_tide_pools,
 | |
|                               Entrance.fishing,
 | |
|                               Entrance.attend_luau, Entrance.attend_moonlight_jellies, Entrance.attend_night_market]),
 | |
|     RegionData(Region.fishing),
 | |
|     RegionData(Region.railroad, [Entrance.enter_bathhouse_entrance, Entrance.enter_witch_warp_cave]),
 | |
|     RegionData(Region.ranch),
 | |
|     RegionData(Region.leah_house),
 | |
|     RegionData(Region.sewer, [Entrance.enter_mutant_bug_lair]),
 | |
|     RegionData(Region.mutant_bug_lair),
 | |
|     RegionData(Region.wizard_tower, [Entrance.enter_wizard_basement,
 | |
|                                      Entrance.use_desert_obelisk, Entrance.use_island_obelisk]),
 | |
|     RegionData(Region.wizard_basement),
 | |
|     RegionData(Region.tent),
 | |
|     RegionData(Region.carpenter, [Entrance.enter_sebastian_room]),
 | |
|     RegionData(Region.sebastian_room),
 | |
|     RegionData(Region.adventurer_guild),
 | |
|     RegionData(Region.community_center,
 | |
|                [Entrance.access_crafts_room, Entrance.access_pantry, Entrance.access_fish_tank,
 | |
|                 Entrance.access_boiler_room, Entrance.access_bulletin_board, Entrance.access_vault]),
 | |
|     RegionData(Region.crafts_room),
 | |
|     RegionData(Region.pantry),
 | |
|     RegionData(Region.fish_tank),
 | |
|     RegionData(Region.boiler_room),
 | |
|     RegionData(Region.bulletin_board),
 | |
|     RegionData(Region.vault),
 | |
|     RegionData(Region.hospital, [Entrance.enter_harvey_room]),
 | |
|     RegionData(Region.harvey_room),
 | |
|     RegionData(Region.pierre_store, [Entrance.enter_sunroom]),
 | |
|     RegionData(Region.sunroom),
 | |
|     RegionData(Region.saloon, [Entrance.play_journey_of_the_prairie_king, Entrance.play_junimo_kart]),
 | |
|     RegionData(Region.jotpk_world_1, [Entrance.reach_jotpk_world_2]),
 | |
|     RegionData(Region.jotpk_world_2, [Entrance.reach_jotpk_world_3]),
 | |
|     RegionData(Region.jotpk_world_3),
 | |
|     RegionData(Region.junimo_kart_1, [Entrance.reach_junimo_kart_2]),
 | |
|     RegionData(Region.junimo_kart_2, [Entrance.reach_junimo_kart_3]),
 | |
|     RegionData(Region.junimo_kart_3),
 | |
|     RegionData(Region.alex_house),
 | |
|     RegionData(Region.trailer),
 | |
|     RegionData(Region.mayor_house),
 | |
|     RegionData(Region.sam_house),
 | |
|     RegionData(Region.haley_house),
 | |
|     RegionData(Region.blacksmith, [Entrance.blacksmith_copper]),
 | |
|     RegionData(Region.blacksmith_copper, [Entrance.blacksmith_iron]),
 | |
|     RegionData(Region.blacksmith_iron, [Entrance.blacksmith_gold]),
 | |
|     RegionData(Region.blacksmith_gold, [Entrance.blacksmith_iridium]),
 | |
|     RegionData(Region.blacksmith_iridium),
 | |
|     RegionData(Region.museum),
 | |
|     RegionData(Region.jojamart, [Entrance.enter_abandoned_jojamart]),
 | |
|     RegionData(Region.abandoned_jojamart, [Entrance.enter_movie_theater]),
 | |
|     RegionData(Region.movie_ticket_stand),
 | |
|     RegionData(Region.movie_theater),
 | |
|     RegionData(Region.fish_shop, [Entrance.fish_shop_to_boat_tunnel]),
 | |
|     RegionData(Region.boat_tunnel, [Entrance.boat_to_ginger_island]),
 | |
|     RegionData(Region.elliott_house),
 | |
|     RegionData(Region.tide_pools),
 | |
|     RegionData(Region.bathhouse_entrance, [Entrance.enter_locker_room]),
 | |
|     RegionData(Region.locker_room, [Entrance.enter_public_bath]),
 | |
|     RegionData(Region.public_bath),
 | |
|     RegionData(Region.witch_warp_cave, [Entrance.enter_witch_swamp]),
 | |
|     RegionData(Region.witch_swamp, [Entrance.enter_witch_hut]),
 | |
|     RegionData(Region.witch_hut, [Entrance.witch_warp_to_wizard_basement]),
 | |
|     RegionData(Region.quarry, [Entrance.enter_quarry_mine_entrance]),
 | |
|     RegionData(Region.quarry_mine_entrance, [Entrance.enter_quarry_mine]),
 | |
|     RegionData(Region.quarry_mine),
 | |
|     RegionData(Region.secret_woods),
 | |
|     RegionData(Region.desert, [Entrance.enter_skull_cavern_entrance, Entrance.enter_oasis]),
 | |
|     RegionData(Region.oasis, [Entrance.enter_casino]),
 | |
|     RegionData(Region.casino),
 | |
|     RegionData(Region.skull_cavern_entrance, [Entrance.enter_skull_cavern]),
 | |
|     RegionData(Region.skull_cavern, [Entrance.mine_to_skull_cavern_floor_25]),
 | |
|     RegionData(Region.skull_cavern_25, [Entrance.mine_to_skull_cavern_floor_50]),
 | |
|     RegionData(Region.skull_cavern_50, [Entrance.mine_to_skull_cavern_floor_75]),
 | |
|     RegionData(Region.skull_cavern_75, [Entrance.mine_to_skull_cavern_floor_100]),
 | |
|     RegionData(Region.skull_cavern_100, [Entrance.mine_to_skull_cavern_floor_125]),
 | |
|     RegionData(Region.skull_cavern_125, [Entrance.mine_to_skull_cavern_floor_150]),
 | |
|     RegionData(Region.skull_cavern_150, [Entrance.mine_to_skull_cavern_floor_175]),
 | |
|     RegionData(Region.skull_cavern_175, [Entrance.mine_to_skull_cavern_floor_200]),
 | |
|     RegionData(Region.skull_cavern_200, [Entrance.enter_dangerous_skull_cavern]),
 | |
|     RegionData(Region.dangerous_skull_cavern),
 | |
|     RegionData(Region.island_south, [Entrance.island_south_to_west, Entrance.island_south_to_north,
 | |
|                                      Entrance.island_south_to_east, Entrance.island_south_to_southeast,
 | |
|                                      Entrance.use_island_resort,
 | |
|                                      Entrance.parrot_express_docks_to_volcano,
 | |
|                                      Entrance.parrot_express_docks_to_dig_site,
 | |
|                                      Entrance.parrot_express_docks_to_jungle]),
 | |
|     RegionData(Region.island_resort),
 | |
|     RegionData(Region.island_west,
 | |
|                [Entrance.island_west_to_islandfarmhouse, Entrance.island_west_to_gourmand_cave,
 | |
|                 Entrance.island_west_to_crystals_cave, Entrance.island_west_to_shipwreck,
 | |
|                 Entrance.island_west_to_qi_walnut_room, Entrance.use_farm_obelisk,
 | |
|                 Entrance.parrot_express_jungle_to_docks, Entrance.parrot_express_jungle_to_dig_site,
 | |
|                 Entrance.parrot_express_jungle_to_volcano]),
 | |
|     RegionData(Region.island_east, [Entrance.island_east_to_leo_hut, Entrance.island_east_to_island_shrine]),
 | |
|     RegionData(Region.island_shrine),
 | |
|     RegionData(Region.island_south_east, [Entrance.island_southeast_to_pirate_cove]),
 | |
|     RegionData(Region.island_north, [Entrance.talk_to_island_trader, Entrance.island_north_to_field_office,
 | |
|                                      Entrance.island_north_to_dig_site, Entrance.island_north_to_volcano,
 | |
|                                      Entrance.parrot_express_volcano_to_dig_site,
 | |
|                                      Entrance.parrot_express_volcano_to_jungle,
 | |
|                                      Entrance.parrot_express_volcano_to_docks]),
 | |
|     RegionData(Region.volcano, [Entrance.climb_to_volcano_5, Entrance.volcano_to_secret_beach]),
 | |
|     RegionData(Region.volcano_secret_beach),
 | |
|     RegionData(Region.volcano_floor_5, [Entrance.talk_to_volcano_dwarf, Entrance.climb_to_volcano_10]),
 | |
|     RegionData(Region.volcano_dwarf_shop),
 | |
|     RegionData(Region.volcano_floor_10),
 | |
|     RegionData(Region.island_trader),
 | |
|     RegionData(Region.island_farmhouse, [Entrance.island_cooking]),
 | |
|     RegionData(Region.gourmand_frog_cave),
 | |
|     RegionData(Region.colored_crystals_cave),
 | |
|     RegionData(Region.shipwreck),
 | |
|     RegionData(Region.qi_walnut_room),
 | |
|     RegionData(Region.leo_hut),
 | |
|     RegionData(Region.pirate_cove),
 | |
|     RegionData(Region.field_office),
 | |
|     RegionData(Region.dig_site,
 | |
|                [Entrance.dig_site_to_professor_snail_cave, Entrance.parrot_express_dig_site_to_volcano,
 | |
|                 Entrance.parrot_express_dig_site_to_docks, Entrance.parrot_express_dig_site_to_jungle]),
 | |
|     RegionData(Region.professor_snail_cave),
 | |
|     RegionData(Region.mines, [Entrance.talk_to_mines_dwarf,
 | |
|                               Entrance.dig_to_mines_floor_5]),
 | |
|     RegionData(Region.mines_dwarf_shop),
 | |
|     RegionData(Region.mines_floor_5, [Entrance.dig_to_mines_floor_10]),
 | |
|     RegionData(Region.mines_floor_10, [Entrance.dig_to_mines_floor_15]),
 | |
|     RegionData(Region.mines_floor_15, [Entrance.dig_to_mines_floor_20]),
 | |
|     RegionData(Region.mines_floor_20, [Entrance.dig_to_mines_floor_25]),
 | |
|     RegionData(Region.mines_floor_25, [Entrance.dig_to_mines_floor_30]),
 | |
|     RegionData(Region.mines_floor_30, [Entrance.dig_to_mines_floor_35]),
 | |
|     RegionData(Region.mines_floor_35, [Entrance.dig_to_mines_floor_40]),
 | |
|     RegionData(Region.mines_floor_40, [Entrance.dig_to_mines_floor_45]),
 | |
|     RegionData(Region.mines_floor_45, [Entrance.dig_to_mines_floor_50]),
 | |
|     RegionData(Region.mines_floor_50, [Entrance.dig_to_mines_floor_55]),
 | |
|     RegionData(Region.mines_floor_55, [Entrance.dig_to_mines_floor_60]),
 | |
|     RegionData(Region.mines_floor_60, [Entrance.dig_to_mines_floor_65]),
 | |
|     RegionData(Region.mines_floor_65, [Entrance.dig_to_mines_floor_70]),
 | |
|     RegionData(Region.mines_floor_70, [Entrance.dig_to_mines_floor_75]),
 | |
|     RegionData(Region.mines_floor_75, [Entrance.dig_to_mines_floor_80]),
 | |
|     RegionData(Region.mines_floor_80, [Entrance.dig_to_mines_floor_85]),
 | |
|     RegionData(Region.mines_floor_85, [Entrance.dig_to_mines_floor_90]),
 | |
|     RegionData(Region.mines_floor_90, [Entrance.dig_to_mines_floor_95]),
 | |
|     RegionData(Region.mines_floor_95, [Entrance.dig_to_mines_floor_100]),
 | |
|     RegionData(Region.mines_floor_100, [Entrance.dig_to_mines_floor_105]),
 | |
|     RegionData(Region.mines_floor_105, [Entrance.dig_to_mines_floor_110]),
 | |
|     RegionData(Region.mines_floor_110, [Entrance.dig_to_mines_floor_115]),
 | |
|     RegionData(Region.mines_floor_115, [Entrance.dig_to_mines_floor_120]),
 | |
|     RegionData(Region.mines_floor_120, [Entrance.dig_to_dangerous_mines_20, Entrance.dig_to_dangerous_mines_60, Entrance.dig_to_dangerous_mines_100]),
 | |
|     RegionData(Region.dangerous_mines_20),
 | |
|     RegionData(Region.dangerous_mines_60),
 | |
|     RegionData(Region.dangerous_mines_100),
 | |
|     RegionData(Region.coop),
 | |
|     RegionData(Region.barn),
 | |
|     RegionData(Region.shed),
 | |
|     RegionData(Region.slime_hutch),
 | |
|     RegionData(Region.egg_festival),
 | |
|     RegionData(Region.flower_dance),
 | |
|     RegionData(Region.luau),
 | |
|     RegionData(Region.moonlight_jellies),
 | |
|     RegionData(Region.fair),
 | |
|     RegionData(Region.spirit_eve),
 | |
|     RegionData(Region.festival_of_ice),
 | |
|     RegionData(Region.night_market),
 | |
|     RegionData(Region.winter_star),
 | |
| ]
 | |
| 
 | |
| # Exists and where they lead
 | |
| vanilla_connections = [
 | |
|     ConnectionData(Entrance.to_stardew_valley, Region.stardew_valley),
 | |
|     ConnectionData(Entrance.to_farmhouse, Region.farm_house),
 | |
|     ConnectionData(Entrance.farmhouse_to_farm, Region.farm),
 | |
|     ConnectionData(Entrance.downstairs_to_cellar, Region.cellar),
 | |
|     ConnectionData(Entrance.farmhouse_cooking, Region.kitchen),
 | |
|     ConnectionData(Entrance.watch_queen_of_sauce, Region.queen_of_sauce),
 | |
|     ConnectionData(Entrance.farm_to_backwoods, Region.backwoods),
 | |
|     ConnectionData(Entrance.farm_to_bus_stop, Region.bus_stop),
 | |
|     ConnectionData(Entrance.farm_to_forest, Region.forest),
 | |
|     ConnectionData(Entrance.farm_to_farmcave, Region.farm_cave, flag=RandomizationFlag.NON_PROGRESSION),
 | |
|     ConnectionData(Entrance.farming, Region.farming),
 | |
|     ConnectionData(Entrance.enter_greenhouse, Region.greenhouse),
 | |
|     ConnectionData(Entrance.enter_coop, Region.coop),
 | |
|     ConnectionData(Entrance.enter_barn, Region.barn),
 | |
|     ConnectionData(Entrance.enter_shed, Region.shed),
 | |
|     ConnectionData(Entrance.enter_slime_hutch, Region.slime_hutch),
 | |
|     ConnectionData(Entrance.shipping, Region.shipping),
 | |
|     ConnectionData(Entrance.use_desert_obelisk, Region.desert),
 | |
|     ConnectionData(Entrance.use_island_obelisk, Region.island_south, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.use_farm_obelisk, Region.farm),
 | |
|     ConnectionData(Entrance.backwoods_to_mountain, Region.mountain),
 | |
|     ConnectionData(Entrance.bus_stop_to_town, Region.town),
 | |
|     ConnectionData(Entrance.bus_stop_to_tunnel_entrance, Region.tunnel_entrance),
 | |
|     ConnectionData(Entrance.tunnel_entrance_to_bus_tunnel, Region.bus_tunnel, flag=RandomizationFlag.NON_PROGRESSION),
 | |
|     ConnectionData(Entrance.take_bus_to_desert, Region.desert),
 | |
|     ConnectionData(Entrance.forest_to_town, Region.town),
 | |
|     ConnectionData(Entrance.forest_to_wizard_tower, Region.wizard_tower,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_wizard_basement, Region.wizard_basement, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.forest_to_marnie_ranch, Region.ranch,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.forest_to_leah_cottage, Region.leah_house,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_secret_woods, Region.secret_woods),
 | |
|     ConnectionData(Entrance.forest_to_sewer, Region.sewer, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant, Region.traveling_cart),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_sunday, Region.traveling_cart_sunday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_monday, Region.traveling_cart_monday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_tuesday, Region.traveling_cart_tuesday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_wednesday, Region.traveling_cart_wednesday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_thursday, Region.traveling_cart_thursday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_friday, Region.traveling_cart_friday),
 | |
|     ConnectionData(Entrance.buy_from_traveling_merchant_saturday, Region.traveling_cart_saturday),
 | |
|     ConnectionData(Entrance.town_to_sewer, Region.sewer, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_mutant_bug_lair, Region.mutant_bug_lair, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.mountain_to_railroad, Region.railroad),
 | |
|     ConnectionData(Entrance.mountain_to_tent, Region.tent,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.mountain_to_leo_treehouse, Region.leo_treehouse,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.mountain_to_carpenter_shop, Region.carpenter,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.mountain_to_maru_room, Region.maru_room,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_sebastian_room, Region.sebastian_room, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.mountain_to_adventurer_guild, Region.adventurer_guild,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_quarry, Region.quarry),
 | |
|     ConnectionData(Entrance.enter_quarry_mine_entrance, Region.quarry_mine_entrance,
 | |
|                    flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_quarry_mine, Region.quarry_mine),
 | |
|     ConnectionData(Entrance.mountain_to_town, Region.town),
 | |
|     ConnectionData(Entrance.town_to_community_center, Region.community_center,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.access_crafts_room, Region.crafts_room),
 | |
|     ConnectionData(Entrance.access_pantry, Region.pantry),
 | |
|     ConnectionData(Entrance.access_fish_tank, Region.fish_tank),
 | |
|     ConnectionData(Entrance.access_boiler_room, Region.boiler_room),
 | |
|     ConnectionData(Entrance.access_bulletin_board, Region.bulletin_board),
 | |
|     ConnectionData(Entrance.access_vault, Region.vault),
 | |
|     ConnectionData(Entrance.town_to_hospital, Region.hospital,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_harvey_room, Region.harvey_room, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.town_to_pierre_general_store, Region.pierre_store,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_sunroom, Region.sunroom, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.town_to_clint_blacksmith, Region.blacksmith,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.blacksmith_copper, Region.blacksmith_copper),
 | |
|     ConnectionData(Entrance.blacksmith_iron, Region.blacksmith_iron),
 | |
|     ConnectionData(Entrance.blacksmith_gold, Region.blacksmith_gold),
 | |
|     ConnectionData(Entrance.blacksmith_iridium, Region.blacksmith_iridium),
 | |
|     ConnectionData(Entrance.town_to_saloon, Region.saloon,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.play_journey_of_the_prairie_king, Region.jotpk_world_1),
 | |
|     ConnectionData(Entrance.reach_jotpk_world_2, Region.jotpk_world_2),
 | |
|     ConnectionData(Entrance.reach_jotpk_world_3, Region.jotpk_world_3),
 | |
|     ConnectionData(Entrance.play_junimo_kart, Region.junimo_kart_1),
 | |
|     ConnectionData(Entrance.reach_junimo_kart_2, Region.junimo_kart_2),
 | |
|     ConnectionData(Entrance.reach_junimo_kart_3, Region.junimo_kart_3),
 | |
|     ConnectionData(Entrance.town_to_sam_house, Region.sam_house,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_haley_house, Region.haley_house,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_mayor_manor, Region.mayor_house,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_alex_house, Region.alex_house,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_trailer, Region.trailer,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_museum, Region.museum,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.town_to_jojamart, Region.jojamart,
 | |
|                    flag=RandomizationFlag.PELICAN_TOWN | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.purchase_movie_ticket, Region.movie_ticket_stand),
 | |
|     ConnectionData(Entrance.enter_abandoned_jojamart, Region.abandoned_jojamart),
 | |
|     ConnectionData(Entrance.enter_movie_theater, Region.movie_theater),
 | |
|     ConnectionData(Entrance.town_to_beach, Region.beach),
 | |
|     ConnectionData(Entrance.enter_elliott_house, Region.elliott_house,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.beach_to_willy_fish_shop, Region.fish_shop,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.fish_shop_to_boat_tunnel, Region.boat_tunnel,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.boat_to_ginger_island, Region.island_south, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.enter_tide_pools, Region.tide_pools),
 | |
|     ConnectionData(Entrance.fishing, Region.fishing),
 | |
|     ConnectionData(Entrance.mountain_to_the_mines, Region.mines,
 | |
|                    flag=RandomizationFlag.NON_PROGRESSION | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.talk_to_mines_dwarf, Region.mines_dwarf_shop),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_5, Region.mines_floor_5),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_10, Region.mines_floor_10),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_15, Region.mines_floor_15),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_20, Region.mines_floor_20),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_25, Region.mines_floor_25),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_30, Region.mines_floor_30),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_35, Region.mines_floor_35),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_40, Region.mines_floor_40),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_45, Region.mines_floor_45),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_50, Region.mines_floor_50),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_55, Region.mines_floor_55),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_60, Region.mines_floor_60),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_65, Region.mines_floor_65),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_70, Region.mines_floor_70),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_75, Region.mines_floor_75),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_80, Region.mines_floor_80),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_85, Region.mines_floor_85),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_90, Region.mines_floor_90),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_95, Region.mines_floor_95),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_100, Region.mines_floor_100),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_105, Region.mines_floor_105),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_110, Region.mines_floor_110),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_115, Region.mines_floor_115),
 | |
|     ConnectionData(Entrance.dig_to_mines_floor_120, Region.mines_floor_120),
 | |
|     ConnectionData(Entrance.dig_to_dangerous_mines_20, Region.dangerous_mines_20, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.dig_to_dangerous_mines_60, Region.dangerous_mines_60, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.dig_to_dangerous_mines_100, Region.dangerous_mines_100, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.enter_skull_cavern_entrance, Region.skull_cavern_entrance,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_oasis, Region.oasis,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_casino, Region.casino, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_skull_cavern, Region.skull_cavern),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_25, Region.skull_cavern_25),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_50, Region.skull_cavern_50),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_75, Region.skull_cavern_75),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_100, Region.skull_cavern_100),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_125, Region.skull_cavern_125),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_150, Region.skull_cavern_150),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_175, Region.skull_cavern_175),
 | |
|     ConnectionData(Entrance.mine_to_skull_cavern_floor_200, Region.skull_cavern_200),
 | |
|     ConnectionData(Entrance.enter_dangerous_skull_cavern, Region.dangerous_skull_cavern, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.enter_witch_warp_cave, Region.witch_warp_cave, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_witch_swamp, Region.witch_swamp, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_witch_hut, Region.witch_hut, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.witch_warp_to_wizard_basement, Region.wizard_basement, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_bathhouse_entrance, Region.bathhouse_entrance,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.LEAD_TO_OPEN_AREA),
 | |
|     ConnectionData(Entrance.enter_locker_room, Region.locker_room, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.enter_public_bath, Region.public_bath, flag=RandomizationFlag.BUILDINGS),
 | |
|     ConnectionData(Entrance.island_south_to_west, Region.island_west, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_south_to_north, Region.island_north, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_south_to_east, Region.island_east, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_south_to_southeast, Region.island_south_east,
 | |
|                    flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.use_island_resort, Region.island_resort, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_west_to_islandfarmhouse, Region.island_farmhouse,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_cooking, Region.kitchen),
 | |
|     ConnectionData(Entrance.island_west_to_gourmand_cave, Region.gourmand_frog_cave,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_west_to_crystals_cave, Region.colored_crystals_cave,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_west_to_shipwreck, Region.shipwreck,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_west_to_qi_walnut_room, Region.qi_walnut_room, flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_east_to_leo_hut, Region.leo_hut,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_east_to_island_shrine, Region.island_shrine,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_southeast_to_pirate_cove, Region.pirate_cove,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_north_to_field_office, Region.field_office,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_north_to_dig_site, Region.dig_site, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.dig_site_to_professor_snail_cave, Region.professor_snail_cave, flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.island_north_to_volcano, Region.volcano,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.volcano_to_secret_beach, Region.volcano_secret_beach,
 | |
|                    flag=RandomizationFlag.BUILDINGS | RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.talk_to_island_trader, Region.island_trader, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.climb_to_volcano_5, Region.volcano_floor_5, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.talk_to_volcano_dwarf, Region.volcano_dwarf_shop, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.climb_to_volcano_10, Region.volcano_floor_10, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_jungle_to_docks, Region.island_south, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_dig_site_to_docks, Region.island_south, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_volcano_to_docks, Region.island_south, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_volcano_to_jungle, Region.island_west, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_docks_to_jungle, Region.island_west, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_dig_site_to_jungle, Region.island_west, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_docks_to_dig_site, Region.dig_site, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_volcano_to_dig_site, Region.dig_site, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_jungle_to_dig_site, Region.dig_site, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_dig_site_to_volcano, Region.island_north, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_docks_to_volcano, Region.island_north, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.parrot_express_jungle_to_volcano, Region.island_north, flag=RandomizationFlag.GINGER_ISLAND),
 | |
|     ConnectionData(Entrance.attend_egg_festival, Region.egg_festival),
 | |
|     ConnectionData(Entrance.attend_flower_dance, Region.flower_dance),
 | |
|     ConnectionData(Entrance.attend_luau, Region.luau),
 | |
|     ConnectionData(Entrance.attend_moonlight_jellies, Region.moonlight_jellies),
 | |
|     ConnectionData(Entrance.attend_fair, Region.fair),
 | |
|     ConnectionData(Entrance.attend_spirit_eve, Region.spirit_eve),
 | |
|     ConnectionData(Entrance.attend_festival_of_ice, Region.festival_of_ice),
 | |
|     ConnectionData(Entrance.attend_night_market, Region.night_market),
 | |
|     ConnectionData(Entrance.attend_winter_star, Region.winter_star),
 | |
| ]
 | |
| 
 | |
| 
 | |
| def create_final_regions(world_options) -> List[RegionData]:
 | |
|     final_regions = []
 | |
|     final_regions.extend(vanilla_regions)
 | |
|     if world_options.mods is None:
 | |
|         return final_regions
 | |
|     for mod in world_options.mods.value:
 | |
|         if mod not in ModDataList:
 | |
|             continue
 | |
|         for mod_region in ModDataList[mod].regions:
 | |
|             existing_region = next(
 | |
|                 (region for region in final_regions if region.name == mod_region.name), None)
 | |
|             if existing_region:
 | |
|                 final_regions.remove(existing_region)
 | |
|                 if ModificationFlag.MODIFIED in mod_region.flag:
 | |
|                     mod_region = modify_vanilla_regions(existing_region, mod_region)
 | |
|                 final_regions.append(existing_region.get_merged_with(mod_region.exits))
 | |
|                 continue
 | |
|             final_regions.append(mod_region.get_clone())
 | |
| 
 | |
|     return final_regions
 | |
| 
 | |
| 
 | |
| def create_final_connections_and_regions(world_options) -> Tuple[Dict[str, ConnectionData], Dict[str, RegionData]]:
 | |
|     regions_data: Dict[str, RegionData] = {region.name: region for region in create_final_regions(world_options)}
 | |
|     connections = {connection.name: connection for connection in vanilla_connections}
 | |
|     connections = modify_connections_for_mods(connections, world_options.mods)
 | |
|     include_island = world_options.exclude_ginger_island == ExcludeGingerIsland.option_false
 | |
|     return remove_ginger_island_regions_and_connections(regions_data, connections, include_island)
 | |
| 
 | |
| 
 | |
| def remove_ginger_island_regions_and_connections(regions_by_name: Dict[str, RegionData], connections: Dict[str, ConnectionData], include_island: bool):
 | |
|     if include_island:
 | |
|         return connections, regions_by_name
 | |
|     for connection_name in list(connections):
 | |
|         connection = connections[connection_name]
 | |
|         if connection.flag & RandomizationFlag.GINGER_ISLAND:
 | |
|             regions_by_name.pop(connection.destination, None)
 | |
|             connections.pop(connection_name)
 | |
|             regions_by_name = {name: regions_by_name[name].get_without_exit(connection_name) for name in regions_by_name}
 | |
|     return connections, regions_by_name
 | |
| 
 | |
| 
 | |
| def modify_connections_for_mods(connections: Dict[str, ConnectionData], mods) -> Dict[str, ConnectionData]:
 | |
|     if mods is None:
 | |
|         return connections
 | |
|     for mod in mods.value:
 | |
|         if mod not in ModDataList:
 | |
|             continue
 | |
|         if mod in vanilla_connections_to_remove_by_mod:
 | |
|             for connection_data in vanilla_connections_to_remove_by_mod[mod]:
 | |
|                 connections.pop(connection_data.name)
 | |
|         connections.update({connection.name: connection for connection in ModDataList[mod].connections})
 | |
|     return connections
 | |
| 
 | |
| 
 | |
| def modify_vanilla_regions(existing_region: RegionData, modified_region: RegionData) -> RegionData:
 | |
| 
 | |
|     updated_region = existing_region
 | |
|     region_exits = updated_region.exits
 | |
|     modified_exits = modified_region.exits
 | |
|     for exits in modified_exits:
 | |
|         region_exits.remove(exits)
 | |
| 
 | |
|     return updated_region
 | |
| 
 | |
| 
 | |
| def create_regions(region_factory: RegionFactory, random: Random, world_options: StardewValleyOptions) -> Tuple[
 | |
|     Dict[str, Region], Dict[str, Entrance], Dict[str, str]]:
 | |
|     entrances_data, regions_data = create_final_connections_and_regions(world_options)
 | |
|     regions_by_name: Dict[str: Region] = {region_name: region_factory(region_name, regions_data[region_name].exits) for region_name in regions_data}
 | |
|     entrances_by_name: Dict[str: Entrance] = {entrance.name: entrance for region in regions_by_name.values() for entrance in region.exits
 | |
|                                               if entrance.name in entrances_data}
 | |
| 
 | |
|     connections, randomized_data = randomize_connections(random, world_options, regions_data, entrances_data)
 | |
| 
 | |
|     for connection in connections:
 | |
|         if connection.name in entrances_by_name:
 | |
|             entrances_by_name[connection.name].connect(regions_by_name[connection.destination])
 | |
|     return regions_by_name, entrances_by_name, randomized_data
 | |
| 
 | |
| 
 | |
| def randomize_connections(random: Random, world_options: StardewValleyOptions, regions_by_name: Dict[str, RegionData],
 | |
|                           connections_by_name: Dict[str, ConnectionData]) -> Tuple[List[ConnectionData], Dict[str, str]]:
 | |
|     connections_to_randomize: List[ConnectionData] = []
 | |
|     if world_options.entrance_randomization == EntranceRandomization.option_pelican_town:
 | |
|         connections_to_randomize = [connections_by_name[connection] for connection in connections_by_name if
 | |
|                                     RandomizationFlag.PELICAN_TOWN in connections_by_name[connection].flag]
 | |
|     elif world_options.entrance_randomization == EntranceRandomization.option_non_progression:
 | |
|         connections_to_randomize = [connections_by_name[connection] for connection in connections_by_name if
 | |
|                                     RandomizationFlag.NON_PROGRESSION in connections_by_name[connection].flag]
 | |
|     elif world_options.entrance_randomization == EntranceRandomization.option_buildings:
 | |
|         connections_to_randomize = [connections_by_name[connection] for connection in connections_by_name if
 | |
|                                     RandomizationFlag.BUILDINGS in connections_by_name[connection].flag]
 | |
|     elif world_options.entrance_randomization == EntranceRandomization.option_chaos:
 | |
|         connections_to_randomize = [connections_by_name[connection] for connection in connections_by_name if
 | |
|                                     RandomizationFlag.BUILDINGS in connections_by_name[connection].flag]
 | |
|         connections_to_randomize = remove_excluded_entrances(connections_to_randomize, world_options)
 | |
| 
 | |
|         # On Chaos, we just add the connections to randomize, unshuffled, and the client does it every day
 | |
|         randomized_data_for_mod = {}
 | |
|         for connection in connections_to_randomize:
 | |
|             randomized_data_for_mod[connection.name] = connection.name
 | |
|             randomized_data_for_mod[connection.reverse] = connection.reverse
 | |
|         return list(connections_by_name.values()), randomized_data_for_mod
 | |
| 
 | |
|     connections_to_randomize = remove_excluded_entrances(connections_to_randomize, world_options)
 | |
|     random.shuffle(connections_to_randomize)
 | |
|     destination_pool = list(connections_to_randomize)
 | |
|     random.shuffle(destination_pool)
 | |
| 
 | |
|     randomized_connections = randomize_chosen_connections(connections_to_randomize, destination_pool)
 | |
|     add_non_randomized_connections(list(connections_by_name.values()), connections_to_randomize, randomized_connections)
 | |
| 
 | |
|     swap_connections_until_valid(regions_by_name, connections_by_name, randomized_connections, connections_to_randomize, random)
 | |
|     randomized_connections_for_generation = create_connections_for_generation(randomized_connections)
 | |
|     randomized_data_for_mod = create_data_for_mod(randomized_connections, connections_to_randomize)
 | |
| 
 | |
|     return randomized_connections_for_generation, randomized_data_for_mod
 | |
| 
 | |
| 
 | |
| def remove_excluded_entrances(connections_to_randomize: List[ConnectionData], world_options: StardewValleyOptions) -> List[ConnectionData]:
 | |
|     exclude_island = world_options.exclude_ginger_island == ExcludeGingerIsland.option_true
 | |
|     if exclude_island:
 | |
|         connections_to_randomize = [connection for connection in connections_to_randomize if RandomizationFlag.GINGER_ISLAND not in connection.flag]
 | |
| 
 | |
|     return connections_to_randomize
 | |
| 
 | |
| 
 | |
| def randomize_chosen_connections(connections_to_randomize: List[ConnectionData],
 | |
|                                  destination_pool: List[ConnectionData]) -> Dict[ConnectionData, ConnectionData]:
 | |
|     randomized_connections = {}
 | |
|     for connection in connections_to_randomize:
 | |
|         destination = destination_pool.pop()
 | |
|         randomized_connections[connection] = destination
 | |
|     return randomized_connections
 | |
| 
 | |
| 
 | |
| def create_connections_for_generation(randomized_connections: Dict[ConnectionData, ConnectionData]) -> List[ConnectionData]:
 | |
|     connections = []
 | |
|     for connection in randomized_connections:
 | |
|         destination = randomized_connections[connection]
 | |
|         connections.append(ConnectionData(connection.name, destination.destination, destination.reverse))
 | |
|     return connections
 | |
| 
 | |
| 
 | |
| def create_data_for_mod(randomized_connections: Dict[ConnectionData, ConnectionData],
 | |
|                         connections_to_randomize: List[ConnectionData]) -> Dict[str, str]:
 | |
|     randomized_data_for_mod = {}
 | |
|     for connection in randomized_connections:
 | |
|         if connection not in connections_to_randomize:
 | |
|             continue
 | |
|         destination = randomized_connections[connection]
 | |
|         add_to_mod_data(connection, destination, randomized_data_for_mod)
 | |
|     return randomized_data_for_mod
 | |
| 
 | |
| 
 | |
| def add_to_mod_data(connection: ConnectionData, destination: ConnectionData, randomized_data_for_mod: Dict[str, str]):
 | |
|     randomized_data_for_mod[connection.name] = destination.name
 | |
|     randomized_data_for_mod[destination.reverse] = connection.reverse
 | |
| 
 | |
| 
 | |
| def add_non_randomized_connections(all_connections: List[ConnectionData], connections_to_randomize: List[ConnectionData],
 | |
|                                    randomized_connections: Dict[ConnectionData, ConnectionData]):
 | |
|     for connection in all_connections:
 | |
|         if connection in connections_to_randomize:
 | |
|             continue
 | |
|         randomized_connections[connection] = connection
 | |
| 
 | |
| 
 | |
| def swap_connections_until_valid(regions_by_name, connections_by_name: Dict[str, ConnectionData], randomized_connections: Dict[ConnectionData, ConnectionData],
 | |
|                                  connections_to_randomize: List[ConnectionData], random: Random):
 | |
|     while True:
 | |
|         reachable_regions, unreachable_regions = find_reachable_regions(regions_by_name, connections_by_name, randomized_connections)
 | |
|         if not unreachable_regions:
 | |
|             return randomized_connections
 | |
|         swap_one_random_connection(regions_by_name, connections_by_name, randomized_connections, reachable_regions,
 | |
|                                    unreachable_regions, connections_to_randomize, random)
 | |
| 
 | |
| 
 | |
| def region_should_be_reachable(region_name: str, connections_in_slot: Iterable[ConnectionData]) -> bool:
 | |
|     if region_name == Region.menu:
 | |
|         return True
 | |
|     for connection in connections_in_slot:
 | |
|         if region_name == connection.destination:
 | |
|             return True
 | |
|     return False
 | |
| 
 | |
| 
 | |
| def find_reachable_regions(regions_by_name, connections_by_name,
 | |
|                            randomized_connections: Dict[ConnectionData, ConnectionData]):
 | |
|     reachable_regions = {Region.menu}
 | |
|     unreachable_regions = {region for region in regions_by_name.keys()}
 | |
|     # unreachable_regions = {region for region in regions_by_name.keys() if region_should_be_reachable(region, connections_by_name.values())}
 | |
|     unreachable_regions.remove(Region.menu)
 | |
|     exits_to_explore = list(regions_by_name[Region.menu].exits)
 | |
|     while exits_to_explore:
 | |
|         exit_name = exits_to_explore.pop()
 | |
|         # if exit_name not in connections_by_name:
 | |
|         #     continue
 | |
|         exit_connection = connections_by_name[exit_name]
 | |
|         replaced_connection = randomized_connections[exit_connection]
 | |
|         target_region_name = replaced_connection.destination
 | |
|         if target_region_name in reachable_regions:
 | |
|             continue
 | |
| 
 | |
|         target_region = regions_by_name[target_region_name]
 | |
|         reachable_regions.add(target_region_name)
 | |
|         unreachable_regions.remove(target_region_name)
 | |
|         exits_to_explore.extend(target_region.exits)
 | |
|     return reachable_regions, unreachable_regions
 | |
| 
 | |
| 
 | |
| def swap_one_random_connection(regions_by_name, connections_by_name, randomized_connections: Dict[ConnectionData, ConnectionData],
 | |
|                                reachable_regions: Set[str], unreachable_regions: Set[str],
 | |
|                                connections_to_randomize: List[ConnectionData], random: Random):
 | |
|     randomized_connections_already_shuffled = {connection: randomized_connections[connection]
 | |
|                                                for connection in randomized_connections
 | |
|                                                if connection != randomized_connections[connection]}
 | |
|     unreachable_regions_names_leading_somewhere = tuple([region for region in unreachable_regions
 | |
|                                                    if len(regions_by_name[region].exits) > 0])
 | |
|     unreachable_regions_leading_somewhere = [regions_by_name[region_name] for region_name in unreachable_regions_names_leading_somewhere]
 | |
|     unreachable_regions_exits_names = [exit_name for region in unreachable_regions_leading_somewhere for exit_name in region.exits]
 | |
|     unreachable_connections = [connections_by_name[exit_name] for exit_name in unreachable_regions_exits_names]
 | |
|     unreachable_connections_that_can_be_randomized = [connection for connection in unreachable_connections if connection in connections_to_randomize]
 | |
| 
 | |
|     chosen_unreachable_entrance = random.choice(unreachable_connections_that_can_be_randomized)
 | |
| 
 | |
|     chosen_reachable_entrance = None
 | |
|     while chosen_reachable_entrance is None or chosen_reachable_entrance not in randomized_connections_already_shuffled:
 | |
|         chosen_reachable_region_name = random.choice(sorted(reachable_regions))
 | |
|         chosen_reachable_region = regions_by_name[chosen_reachable_region_name]
 | |
|         if not any(chosen_reachable_region.exits):
 | |
|             continue
 | |
|         chosen_reachable_entrance_name = random.choice(chosen_reachable_region.exits)
 | |
|         chosen_reachable_entrance = connections_by_name[chosen_reachable_entrance_name]
 | |
| 
 | |
|     swap_two_connections(chosen_reachable_entrance, chosen_unreachable_entrance, randomized_connections)
 | |
| 
 | |
| 
 | |
| def swap_two_connections(entrance_1, entrance_2, randomized_connections):
 | |
|     reachable_destination = randomized_connections[entrance_1]
 | |
|     unreachable_destination = randomized_connections[entrance_2]
 | |
|     randomized_connections[entrance_1] = unreachable_destination
 | |
|     randomized_connections[entrance_2] = reachable_destination
 |