@@ -551,36 +551,61 @@ def GetAccessibleLocations(
551551
552552def VerifyMinimalLogic (spoiler : Spoiler ) -> bool :
553553 """Verify a world in the context of minimal logic."""
554- # Key 5 not in Level 7 with non-LZR
555554 level_7 = None
555+ level_7_lobby_map = None
556556 if spoiler .settings .shuffle_loading_zones != ShuffleLoadingZones .all : # Non-LZR
557- level_7 = Levels .CreepyCastle
558557 if spoiler .settings .shuffle_loading_zones == ShuffleLoadingZones .levels :
559- level_7 = spoiler .settings .level_order [6 ]
560-
561- # Kongs not in shops tied to them
562- kong_shop_locations = [
563- [], # DK
564- [], # Diddy
565- [], # Lanky
566- [], # Tiny
567- [], # Chunky
568- ]
569- for level , shop_level_data in ShopLocationReference .items ():
570- for vendor , shop_vendor_data in shop_level_data .items ():
571- for kong_idx , kong_loc in enumerate (shop_vendor_data ):
572- if kong_idx < 5 :
573- kong_shop_locations [kong_idx ].append (kong_loc )
558+ # In level shuffle, check level 7
559+ level_7 = spoiler .settings .level_order [7 ]
560+ else :
561+ # Vanilla Order
562+ level_7 = Levels .CreepyCastle
563+
564+ # Map the level to its lobby map
565+ lobby_map_dict = {
566+ Levels .JungleJapes : Maps .JungleJapesLobby ,
567+ Levels .AngryAztec : Maps .AngryAztecLobby ,
568+ Levels .FranticFactory : Maps .FranticFactoryLobby ,
569+ Levels .GloomyGalleon : Maps .GloomyGalleonLobby ,
570+ Levels .FungiForest : Maps .FungiForestLobby ,
571+ Levels .CrystalCaves : Maps .CrystalCavesLobby ,
572+ Levels .CreepyCastle : Maps .CreepyCastleLobby ,
573+ }
574+ level_7_lobby_map = lobby_map_dict .get (level_7 )
575+ level_7_items = []
576+
574577 kong_items = [Items .Donkey , Items .Diddy , Items .Lanky , Items .Tiny , Items .Chunky ]
575578 for loc , data in spoiler .LocationList .items ():
576- if level_7 is not None :
577- if data .level == level_7 and data .item == Items .FungiForestKey :
578- print ("Placement invalid because of Key 5 being in Level 7" )
579+
580+ # Track items in Level 7
581+ if level_7 is not None and data .level == level_7 and data .item is not None :
582+ level_7_items .append (data .item )
583+
584+ # Key 5 cannot be in Level 7 or its lobby
585+ if level_7 is not None and data .item == Items .FungiForestKey :
586+ # Check if in the level itself
587+ if data .level == level_7 :
588+ print (f"Placement invalid because of Key 5 being in Level 7 at { data .name } " )
579589 return False
580- for kong_index , kong_locs in enumerate (kong_shop_locations ):
581- if loc in kong_locs and data .item == kong_items [kong_index ]:
582- print ("Placement invalid due to shop in shop location" )
590+ # Check if in the level's lobby
591+ if level_7_lobby_map is not None and data .default_mapid_data is not None :
592+ for map_data in data .default_mapid_data :
593+ if map_data .map == level_7_lobby_map :
594+ print (f"Placement invalid because of Key 5 being in Level 7 lobby at { data .name } " )
595+ return False
596+
597+ # Kongs cannot be locked behind shops that require that specific Kong to access
598+ if data .type == Types .Shop and data .kong < 5 :
599+ if data .item == kong_items [data .kong ]:
600+ print (f"Placement invalid: { kong_items [data .kong ].name } is locked behind their own shop at { data .name } " )
583601 return False
602+
603+ # Kongs cannot be on their own banana medal or half-medal locations
604+ if data .type in (Types .Medal , Types .HalfMedal ) and data .kong < 5 :
605+ if data .item == kong_items [data .kong ]:
606+ print (f"Placement invalid: { kong_items [data .kong ].name } is on their own medal location at { data .name } " )
607+ return False
608+
584609 # Blasts/Arcade R2 can't contain DK
585610 non_dk_locations = [
586611 Locations .JapesDonkeyBaboonBlast ,
@@ -1466,6 +1491,15 @@ def RandomFill(spoiler: Spoiler, itemsToPlace: List[Items], inOrder: bool = Fals
14661491 spoiler .settings .random .shuffle (itemEmpty )
14671492 locationId = itemEmpty .pop ()
14681493 spoiler .LocationList [locationId ].PlaceItem (spoiler , item )
1494+
1495+ # In minimal logic, verify placement doesn't violate minimal logic rules
1496+ if settings .logic_type == LogicType .minimal :
1497+ if not VerifyMinimalLogic (spoiler ):
1498+ # Placement violated minimal logic, unplace and try another location
1499+ spoiler .LocationList [locationId ].UnplaceItem (spoiler )
1500+ itemsToPlace .append (item )
1501+ continue
1502+
14691503 empty .remove (locationId )
14701504 if locationId in SharedShopLocations :
14711505 settings .placed_shared_shops += 1
0 commit comments