2022-03-31 03:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  __future__  import  annotations  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  copy  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  os  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  threading  
						 
					
						
							
								
									
										
										
										
											2022-03-31 03:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  base64  
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  typing  import  Any ,  Dict ,  Iterable ,  List ,  Set ,  TextIO ,  TypedDict  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  BaseClasses  import  Region ,  Entrance ,  Location ,  MultiWorld ,  Item ,  ItemClassification ,  CollectionState ,  Tutorial  
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  Fill  import  fill_restrictive  
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  worlds . AutoWorld  import  World ,  AutoLogicRegister ,  WebWorld  
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  worlds . generic . Rules  import  set_rule ,  add_rule ,  add_item_rule  
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								logger  =  logging . getLogger ( " Super Metroid " )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Options  import  sm_options  
						 
					
						
							
								
									
										
										
										
											2022-10-25 13:54:43 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . Client  import  SMSNIClient  
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . Rom  import  get_base_rom_path ,  SM_ROM_MAX_PLAYERID ,  SM_ROM_PLAYERDATA_COUNT ,  SMDeltaPatch ,  get_sm_symbols  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  Utils  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . variaRandomizer . logic . smboolmanager  import  SMBoolManager  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . graph . vanilla . graph_locations  import  locationsDict  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . graph . graph_utils  import  getAccessPoint  
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . variaRandomizer . rando . ItemLocContainer  import  ItemLocation ,  ItemLocContainer  
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . variaRandomizer . rando . Items  import  ItemManager  
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . variaRandomizer . rando . RandoServices  import  ComebackCheckType  
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . variaRandomizer . utils . parameters  import  *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . utils . utils  import  openFile  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . logic . logic  import  Logic  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . randomizer  import  VariaRandomizer  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . utils . doorsmanager  import  DoorsManager  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . rom . rom_patches  import  RomPatches  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . variaRandomizer . graph . graph_utils  import  GraphUtils  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  SMCollectionState ( metaclass = AutoLogicRegister ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  init_mixin ( self ,  parent :  MultiWorld ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 08:21:26 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # for unit tests where MultiWorld is instantiated before worlds 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  hasattr ( parent ,  " state " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . smbm  =  { player :  SMBoolManager ( player ,  parent . state . smbm [ player ] . maxDiff , 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-22 18:36:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    parent . state . smbm [ player ] . onlyBossLeft ,  parent . state . smbm [ player ] . lastAP )  for  player  in 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                        parent . get_game_players ( " Super Metroid " ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  player ,  group  in  parent . groups . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( group [ " game " ]  ==  " Super Metroid " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . smbm [ player ]  =  SMBoolManager ( player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  player  not  in  parent . state . smbm : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        parent . state . smbm [ player ]  =  SMBoolManager ( player ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . smbm  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  copy_mixin ( self ,  ret )  - >  CollectionState : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        ret . smbm  =  { player :  copy . deepcopy ( self . smbm [ player ] )  for  player  in  self . smbm } 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  get_game_players ( self ,  multiword :  MultiWorld ,  game_name :  str ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  tuple ( player  for  player  in  multiword . get_all_ids ( )  if  multiword . game [ player ]  ==  game_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 07:07:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  SMWeb ( WebWorld ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    tutorials  =  [ Tutorial ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " Multiworld Setup Guide " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " A guide to setting up the Super Metroid Client on your computer. This guide covers single-player, multiworld, and related software. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " English " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " multiworld_en.md " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " multiworld/en " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        [ " Farrak Kilhn " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  ByteEdit ( TypedDict ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sym :  Dict [ str ,  Any ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    offset :  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    values :  Iterable [ int ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-31 00:14:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								locations_start_id  =  82000  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								items_start_id  =  83000  
						 
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  SMWorld ( World ) :  
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     This  is  Very  Adaptive  Randomizer  of  Items  and  Areas  for  Super  Metroid  ( VARIA  SM ) .  It  supports 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     a  wide  range  of  options  to  randomize  Item  locations ,  required  skills  and  even  the  connections  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								     between  the  main  Areas ! 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    game :  str  =  " Super Metroid " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    topology_present  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    data_version  =  3 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 16:46:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    option_definitions  =  sm_options 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-31 00:14:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_name_to_id  =  { value . Name :  items_start_id  +  value . Id  for  key ,  value  in  ItemManager . Items . items ( )  if  value . Id  !=  None } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_name_to_id  =  { key :  locations_start_id  +  value . Id  for  key ,  value  in  locationsDict . items ( )  if  value . Id  !=  None } 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    web  =  SMWeb ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-08 11:16:36 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # changes to client DeathLink handling for 0.2.1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # changes to client Remote Item handling for 0.2.6 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    required_client_version  =  ( 0 ,  2 ,  6 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    itemManager :  ItemManager 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Logic . factory ( ' vanilla ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  world :  MultiWorld ,  player :  int ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . rom_name_available_event  =  threading . Event ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . locations  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . need_comeback_check  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        super ( ) . __init__ ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    @classmethod 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-16 00:28:02 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  stage_assert_generate ( cls ,  multiworld :  MultiWorld ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        rom_file  =  get_base_rom_path ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  os . path . exists ( rom_file ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FileNotFoundError ( rom_file ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  generate_early ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        Logic . factory ( ' vanilla ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . variaRando  =  VariaRandomizer ( self . multiworld ,  get_base_rom_path ( ) ,  self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-22 18:36:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . multiworld . state . smbm [ self . player ]  =  SMBoolManager ( self . player ,  self . variaRando . maxDifficulty ,  lastAP  =  self . variaRando . args . startLocation ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # keeps Nothing items local so no player will ever pickup Nothing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # doing so reduces contribution of this world to the Multiworld the more Nothing there is though 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . multiworld . local_items [ self . player ] . value . add ( ' Nothing ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . local_items [ self . player ] . value . add ( ' No Energy ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( self . variaRando . args . morphPlacement  ==  " early " ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-11-16 10:32:33 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . multiworld . local_early_items [ self . player ] [ ' Morph Ball ' ]  =  1 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . remote_items  =  self . multiworld . remote_items [ self . player ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-21 00:34:47 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( len ( self . variaRando . randoExec . setup . restrictedLocs )  >  0 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . multiworld . accessibility [ self . player ]  =  self . multiworld . accessibility [ self . player ] . from_text ( " minimal " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logger . warning ( f " accessibility forced to  ' minimal '  for player  { self . multiworld . get_player_name ( self . player ) }  because of  ' fun '  settings " ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  create_items ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        itemPool  =  self . variaRando . container . itemPool 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . startItems  =  [ variaItem  for  item  in  self . multiworld . precollected_items [ self . player ]  for  variaItem  in  ItemManager . Items . values ( )  if  variaItem . Name  ==  item . name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . multiworld . start_inventory_removes_from_pool [ self . player ] : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            for  item  in  self . startItems : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( item  in  itemPool ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemPool . remove ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        missingPool  =  109  -  len ( itemPool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i  in  range ( missingPool ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            itemPool . append ( ItemManager . Items [ ' Nothing ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Generate item pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pool  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . locked_items  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . NothingPool  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        weaponCount  =  [ 0 ,  0 ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  itemPool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            isAdvancement  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . Type  ==  ' Missile ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  weaponCount [ 0 ]  <  3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    weaponCount [ 0 ]  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    isAdvancement  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  item . Type  ==  ' Super ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  weaponCount [ 1 ]  <  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    weaponCount [ 1 ]  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    isAdvancement  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  item . Type  ==  ' PowerBomb ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  weaponCount [ 2 ]  <  3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    weaponCount [ 2 ]  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    isAdvancement  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-05 14:15:19 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  item . Category  ==  ' Nothing ' : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                isAdvancement  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            itemClass  =  ItemManager . Items [ item . Type ] . Class 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            smitem  =  SMItem ( item . Name ,  
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            ItemClassification . progression  if  isAdvancement  else  ItemClassification . filler ,  
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            item . Type , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            None  if  itemClass  ==  ' Boss '  else  self . item_name_to_id [ item . Name ] ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            player = self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            beamItems  =  [ ' Spazer ' ,  ' Ice ' ,  ' Wave '  , ' Plasma ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  self . multiworld . doors_colors_rando [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  item . Type  in  beamItems : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . multiworld . local_items [ self . player ] . value . add ( item . Name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            if  itemClass  ==  ' Boss ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . locked_items [ item . Name ]  =  smitem 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  item . Category  ==  ' Nothing ' : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . NothingPool . append ( smitem ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pool . append ( smitem ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . multiworld . itempool  + =  pool 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( location ,  item )  in  self . locked_items . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . multiworld . get_location ( location ,  self . player ) . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . multiworld . get_location ( location ,  self . player ) . address  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  evalSMBool ( self ,  smbool ,  maxDiff ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  smbool . bool  ==  True  and  smbool . difficulty  < =  maxDiff 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  add_entrance_rule ( self ,  entrance ,  player ,  func ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        add_rule ( entrance ,  lambda  state :  self . evalSMBool ( func ( state . smbm [ player ] ) ,  state . smbm [ player ] . maxDiff ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  set_rules ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  add_accessFrom_rule ( location ,  player ,  accessFrom ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            add_rule ( location ,  lambda  state :  any ( ( state . can_reach ( accessName ,  player = player )  and  self . evalSMBool ( rule ( state . smbm [ player ] ) ,  state . smbm [ player ] . maxDiff ) )  for  accessName ,  rule  in  accessFrom . items ( ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  add_postAvailable_rule ( location ,  player ,  func ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            add_rule ( location ,  lambda  state :  self . evalSMBool ( func ( state . smbm [ player ] ) ,  state . smbm [ player ] . maxDiff ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  set_available_rule ( location ,  player ,  func ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            set_rule ( location ,  lambda  state :  self . evalSMBool ( func ( state . smbm [ player ] ) ,  state . smbm [ player ] . maxDiff ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  set_entrance_rule ( entrance ,  player ,  func ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            set_rule ( entrance ,  lambda  state :  self . evalSMBool ( func ( state . smbm [ player ] ) ,  state . smbm [ player ] . maxDiff ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . completion_condition [ self . player ]  =  lambda  state :  state . has ( ' Mother Brain ' ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ammoItems  =  [ ' Missile ' ,  ' Super ' ,  ' PowerBomb ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  key ,  value  in  locationsDict . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            location  =  self . multiworld . get_location ( key ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            set_available_rule ( location ,  self . player ,  value . Available ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  value . AccessFrom  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                add_accessFrom_rule ( location ,  self . player ,  value . AccessFrom ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  value . PostAvailable  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                add_postAvailable_rule ( location ,  self . player ,  value . PostAvailable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  self . multiworld . doors_colors_rando [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                add_item_rule ( location ,  lambda  item :     item . type  not  in  ammoItems  or  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        ( item . type  in  ammoItems  and  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        ( not  item . advancement  or  ( item . advancement  and  item . player  ==  self . player ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  accessPoint  in  Logic . accessPoints : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  accessPoint . Escape : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  key ,  value1  in  accessPoint . intraTransitions . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    set_entrance_rule ( self . multiworld . get_entrance ( accessPoint . Name  +  " -> "  +  key ,  self . player ) ,  self . player ,  value1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_region ( self ,  world :  MultiWorld ,  player :  int ,  name :  str ,  locations = None ,  exits = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ret  =  Region ( name ,  player ,  world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  loc  in  locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location  =  self . locations [ loc ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . parent_region  =  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ret . locations . append ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  exits : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  exit  in  exits : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ret . exits . append ( Entrance ( player ,  exit ,  ret ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ret 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_regions ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # create locations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  name  in  locationsDict : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . locations [ name ]  =  SMLocation ( self . player ,  name ,  self . location_name_to_id . get ( name ,  None ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # create regions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        regions  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  accessPoint  in  Logic . accessPoints : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  accessPoint . Escape : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                regions . append ( self . create_region (   self . multiworld ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    self . player ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    accessPoint . Name ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    None , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    [ accessPoint . Name  +  " -> "  +  key  for  key  in  accessPoint . intraTransitions . keys ( ) ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . regions  + =  regions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # create a region for each location and link each to what the location has access 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # we make them one way so that the filler (and spoiler log) doesnt try to use those region as intermediary path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # this is required in AP because a location cant have multiple parent regions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        locationRegions  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  locationName ,  value  in  locationsDict . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locationRegions . append ( self . create_region (   self . multiworld ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        self . player ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        locationName ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                        [ locationName ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  key  in  value . AccessFrom . keys ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                currentRegion  =  self . multiworld . get_region ( key ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                currentRegion . exits . append ( Entrance ( self . player ,  key  +  " -> " +  locationName ,  currentRegion ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . regions  + =  locationRegions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #create entrances 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        regionConcat  =  regions  +  locationRegions 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  region  in  regionConcat : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  exit  in  region . exits : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                exit . connect ( self . multiworld . get_region ( exit . name [ exit . name . find ( " -> " )  +  2 : ] ,  self . player ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            src_region  =  self . multiworld . get_region ( src . Name ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dest_region  =  self . multiworld . get_region ( dest . Name ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( ( src . Name  +  " -> "  +  dest . Name ,  self . player )  not  in  self . multiworld . _entrance_cache ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                src_region . exits . append ( Entrance ( self . player ,  src . Name  +  " -> "  +  dest . Name ,  src_region ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            srcDestEntrance  =  self . multiworld . get_entrance ( src . Name  +  " -> "  +  dest . Name ,  self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            srcDestEntrance . connect ( dest_region ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . add_entrance_rule ( self . multiworld . get_entrance ( src . Name  +  " -> "  +  dest . Name ,  self . player ) ,  self . player ,  getAccessPoint ( src . Name ) . traverse ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . multiworld . regions  + =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . create_region ( self . multiworld ,  self . player ,  ' Menu ' ,  None ,  [ ' StartAP ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        startAP  =  self . multiworld . get_entrance ( ' StartAP ' ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        startAP . connect ( self . multiworld . get_region ( self . variaRando . args . startLocation ,  self . player ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  collect ( self ,  state :  CollectionState ,  item :  Item )  - >  bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        state . smbm [ self . player ] . addItem ( item . type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  item . location  !=  None  and  item . location . game  ==  self . game : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  entrance  in  self . multiworld . get_region ( item . location . parent_region . name ,  item . location . player ) . entrances : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( entrance . parent_region . can_reach ( state ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    state . smbm [ item . location . player ] . lastAP  =  entrance . parent_region . name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  super ( SMWorld ,  self ) . collect ( state ,  item ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  remove ( self ,  state :  CollectionState ,  item :  Item )  - >  bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        state . smbm [ self . player ] . removeItem ( item . type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  super ( SMWorld ,  self ) . remove ( state ,  item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_item ( self ,  name :  str )  - >  Item : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item  =  next ( x  for  x  in  ItemManager . Items . values ( )  if  x . Name  ==  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  SMItem ( item . Name ,  ItemClassification . progression  if  item . Class  !=  ' Minor '  else  ItemClassification . filler ,  item . Type ,  self . item_name_to_id [ item . Name ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      player = self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_filler_item_name ( self )  - >  str : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . multiworld . random . randint ( 0 ,  100 )  <  self . multiworld . minor_qty [ self . player ] . value : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            power_bombs  =  self . multiworld . power_bomb_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            missiles  =  self . multiworld . missile_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            super_missiles  =  self . multiworld . super_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            roll  =  self . multiworld . random . randint ( 1 ,  power_bombs  +  missiles  +  super_missiles ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  roll  < =  power_bombs : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  " Power Bomb " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  roll  < =  power_bombs  +  missiles : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  " Missile " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                return  " Super Missile " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  " Nothing " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  pre_fill ( self ) : 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  len ( self . NothingPool )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            nonChozoLoc  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            chozoLoc  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  loc  in  self . locations . values ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  loc . item  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  locationsDict [ loc . name ] . isChozo ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        chozoLoc . append ( loc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        nonChozoLoc . append ( loc ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . multiworld . random . shuffle ( nonChozoLoc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . multiworld . random . shuffle ( chozoLoc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            missingCount  =  len ( self . NothingPool )  -  len ( nonChozoLoc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locations  =  nonChozoLoc 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( missingCount  >  0 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  + =  chozoLoc [ : missingCount ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locations  =  locations [ : len ( self . NothingPool ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  item ,  loc  in  zip ( self . NothingPool ,  locations ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                loc . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                loc . address  =  loc . item . code  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  post_fill ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . itemLocs  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ItemLocation ( ItemManager . Items [ itemLoc . item . type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         if  isinstance ( itemLoc . item ,  SMItem )  and  itemLoc . item . type  in  ItemManager . Items  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         ' ArchipelagoItem ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         locationsDict [ itemLoc . name ] ,  itemLoc . item . player ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  itemLoc  in  self . multiworld . get_locations ( self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . progItemLocs  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ItemLocation ( ItemManager . Items [ itemLoc . item . type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         if  isinstance ( itemLoc . item ,  SMItem )  and  itemLoc . item . type  in  ItemManager . Items  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         ' ArchipelagoItem ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         locationsDict [ itemLoc . name ] ,  itemLoc . item . player ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  itemLoc  in  self . multiworld . get_locations ( self . player )  if  itemLoc . item . advancement 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  itemLoc  in  self . itemLocs : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  itemLoc . Item . Class  ==  " Boss " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                itemLoc . Item . Class  =  " Minor " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  itemLoc  in  self . progItemLocs : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  itemLoc . Item . Class  ==  " Boss " : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                itemLoc . Item . Class  =  " Minor " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        localItemLocs  =  [ il  for  il  in  self . itemLocs  if  il . player  ==  self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        localprogItemLocs  =  [ il  for  il  in  self . progItemLocs  if  il . player  ==  self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        escapeTrigger  =  ( localItemLocs ,  localprogItemLocs ,  ' Full ' )  if  self . variaRando . randoExec . randoSettings . restrictions [ " EscapeTrigger " ]  else  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        escapeOk  =  self . variaRando . randoExec . graphBuilder . escapeGraph ( self . variaRando . container ,  self . variaRando . randoExec . areaGraph ,  self . variaRando . randoExec . randoSettings . maxDiff ,  escapeTrigger ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        assert  escapeOk ,  " Could not find a solution for escape " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . variaRando . doors  =  GraphUtils . getDoorConnections ( self . variaRando . randoExec . areaGraph , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    self . variaRando . args . area ,  self . variaRando . args . bosses , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    self . variaRando . args . escapeRando ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . variaRando . randoExec . postProcessItemLocs ( self . itemLocs ,  self . variaRando . args . hideItems ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . need_comeback_check  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    @classmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  stage_post_fill ( cls ,  world ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        new_state  =  CollectionState ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        progitempool  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  world . itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . game  ==  " Super Metroid "  and  item . advancement : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                progitempool . append ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  progitempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_state . collect ( item ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        bossesLoc  =  [ ' Draygon ' ,  ' Kraid ' ,  ' Ridley ' ,  ' Phantoon ' ,  ' Mother Brain ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  player  in  world . get_game_players ( " Super Metroid " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  bossLoc  in  bossesLoc : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  not  world . get_location ( bossLoc ,  player ) . can_reach ( new_state ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    world . state . smbm [ player ] . onlyBossLeft  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  getWordArray ( self ,  w :  int )  - >  List [ int ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        """  little-endian convert a 16-bit number to an array of numbers <= 255 each  """ 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  [ w  &  0x00FF ,  ( w  &  0xFF00 )  >>  8 ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # used for remote location Credits Spoiler of local items and Objectives' writeItemsMasks 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    class  DummyLocation : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  __init__ ( self ,  name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . Name  =  name 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . restricted  =  False 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  isBoss ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  convertToROMItemName ( self ,  itemName ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        charMap  =  {  " A "  :  0x3CE0 ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " B "  :  0x3CE1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " C "  :  0x3CE2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " D "  :  0x3CE3 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " E "  :  0x3CE4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " F "  :  0x3CE5 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " G "  :  0x3CE6 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " H "  :  0x3CE7 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " I "  :  0x3CE8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " J "  :  0x3CE9 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " K "  :  0x3CEA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " L "  :  0x3CEB , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " M "  :  0x3CEC , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " N "  :  0x3CED , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " O "  :  0x3CEE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " P "  :  0x3CEF , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " Q "  :  0x3CF0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " R "  :  0x3CF1 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " S "  :  0x3CF2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " T "  :  0x3CF3 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " U "  :  0x3CF4 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " V "  :  0x3CF5 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " W "  :  0x3CF6 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " X "  :  0x3CF7 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " Y "  :  0x3CF8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " Z "  :  0x3CF9 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    "   "  :  0x3C4E , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " ! "  :  0x3CFF , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " ? "  :  0x3CFE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " ' "  :  0x3CFD , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " , "  :  0x3CFB , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " . "  :  0x3CFA , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " - "  :  0x3CCF , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " _ "  :  0x000E , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 1 "  :  0x3C00 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 2 "  :  0x3C01 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 3 "  :  0x3C02 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 4 "  :  0x3C03 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 5 "  :  0x3C04 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 6 "  :  0x3C05 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 7 "  :  0x3C06 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 8 "  :  0x3C07 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 9 "  :  0x3C08 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " 0 "  :  0x3C09 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    " % "  :  0x3C0A } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        data  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemName  =  itemName . upper ( ) [ : 26 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemName  =  itemName . strip ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemName  =  itemName . center ( 26 ,  "   " )     
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemName  =  " ___ "  +  itemName  +  " ___ " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  char  in  itemName : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            [ w0 ,  w1 ]  =  self . getWordArray ( charMap . get ( char ,  0x3C4E ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            data . append ( w0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            data . append ( w1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-30 12:42:02 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  APPrePatchRom ( self ,  romPatcher ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # first apply the sm multiworld code patch named 'basepatch' (also has empty tables that we'll overwrite), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #  + apply some patches from varia that we want to be always-on. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # basepatch and variapatches are both generated from https://github.com/lordlou/SMBasepatch 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( " / " . join ( ( os . path . dirname ( self . __file__ ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " multiworld-basepatch.ips " ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( " / " . join ( ( os . path . dirname ( self . __file__ ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " variapatches.ips " ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-30 12:42:02 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  APPostPatchRom ( self ,  romPatcher ) : 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        symbols  =  get_sm_symbols ( " / " . join ( ( os . path . dirname ( self . __file__ ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " sm-basepatch-symbols.json " ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # gather all player ids and names relevant to this rom, then write player name and player id data tables 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerIdSet :  Set [ int ]  =  { 0 }   # 0 is for "Archipelago" server 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  itemLoc  in  self . multiworld . get_locations ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            assert  itemLoc . item ,  f " World of player  ' { self . multiworld . player_name [ itemLoc . player ] } '  has a loc.item  "  +  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 f " that is  { itemLoc . item }  during generate_output " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # add each playerid who has a location containing an item to send to us *or* to an item_link we're part of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  itemLoc . item . player  ==  self . player  or  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    ( itemLoc . item . player  in  self . multiworld . groups  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     self . player  in  self . multiworld . groups [ itemLoc . item . player ] [ ' players ' ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                playerIdSet  | =  { itemLoc . player } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # add each playerid, including item link ids, that we'll be sending items to 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  itemLoc . player  ==  self . player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                playerIdSet  | =  { itemLoc . item . player } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( playerIdSet )  >  SM_ROM_PLAYERDATA_COUNT : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # max 202 entries, but it's possible for item links to add enough replacement items for us, that are placed 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # in worlds that otherwise have no relation to us, that the 2*location count limit is exceeded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logger . warning ( " SM is interacting with too many players to fit in ROM.  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           f " Removing the highest  { len ( playerIdSet )  -  SM_ROM_PLAYERDATA_COUNT }  ids to fit " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playerIdSet  =  set ( sorted ( playerIdSet ) [ : SM_ROM_PLAYERDATA_COUNT ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        otherPlayerIndex :  Dict [ int ,  int ]  =  { }   # ap player id -> rom-local player index 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerNameData :  List [ ByteEdit ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerIdData :  List [ ByteEdit ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # sort all player data by player id so that the game can look up a player's data reasonably quickly when 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # the client sends an ap playerid to the game 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i ,  playerid  in  enumerate ( sorted ( playerIdSet ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playername  =  self . multiworld . player_name [ playerid ]  if  playerid  !=  0  else  " Archipelago " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playerIdForRom  =  playerid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  playerid  >  SM_ROM_MAX_PLAYERID : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # note, playerIdForRom = 0 is not unique so the game cannot look it up. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # instead it will display the player received-from as "Archipelago" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                playerIdForRom  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  playerid  ==  self . player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  Exception ( f " SM rom cannot fit enough bits to represent self player id  { playerid } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    logger . warning ( f " SM rom cannot fit enough bits to represent player id  { playerid } , setting to 0 in rom " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            otherPlayerIndex [ playerid ]  =  i 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playerNameData . append ( { " sym " :  symbols [ " rando_player_name_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   " offset " :  i  *  16 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                   " values " :  playername [ : 16 ] . upper ( ) . center ( 16 ) . encode ( ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playerIdData . append ( { " sym " :  symbols [ " rando_player_id_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 " offset " :  i  *  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 " values " :  self . getWordArray ( playerIdForRom ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        multiWorldLocations :  List [ ByteEdit ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        multiWorldItems :  List [ ByteEdit ]  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        idx  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        vanillaItemTypesCount  =  21 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  itemLoc  in  self . multiworld . get_locations ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  itemLoc . player  ==  self . player  and  " Boss "  not  in  locationsDict [ itemLoc . name ] . Class : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # item to place in this SM world: write full item data to tables 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-13 02:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  isinstance ( itemLoc . item ,  SMItem )  and  itemLoc . item . type  in  ItemManager . Items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemId  =  ItemManager . Items [ itemLoc . item . type ] . Id 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    itemId  =  ItemManager . Items [ " ArchipelagoItem " ] . Id  +  idx 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    multiWorldItems . append ( { " sym " :  symbols [ " message_item_names " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            " offset " :  ( vanillaItemTypesCount  +  idx ) * 64 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            " values " :  self . convertToROMItemName ( itemLoc . item . name ) } ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    idx  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-13 02:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  itemLoc . item . player  ==  self . player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemDestinationType  =  0   # dest type 0 means 'regular old SM item' per itemtable.asm 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  itemLoc . item . player  in  self . multiworld . groups  and  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        self . player  in  self . multiworld . groups [ itemLoc . item . player ] [ ' players ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # dest type 2 means 'SM item link item that sends to the current player and others' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # per itemtable.asm (groups are synonymous with item_links, currently) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemDestinationType  =  2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemDestinationType  =  1   # dest type 1 means 'item for entirely someone else' per itemtable.asm 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w0 ,  w1 ]  =  self . getWordArray ( itemDestinationType ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w2 ,  w3 ]  =  self . getWordArray ( itemId ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w4 ,  w5 ]  =  self . getWordArray ( otherPlayerIndex [ itemLoc . item . player ]  if  itemLoc . item . player  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                             otherPlayerIndex  else  0 ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w6 ,  w7 ]  =  self . getWordArray ( 0  if  itemLoc . item . advancement  else  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                multiWorldLocations . append ( { " sym " :  symbols [ " rando_item_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            " offset " :  locationsDict [ itemLoc . name ] . Id * 8 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                            " values " :  [ w0 ,  w1 ,  w2 ,  w3 ,  w4 ,  w5 ,  w6 ,  w7 ] } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemSprites  =  [ { " fileName " :           " off_world_prog_item.bin " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " paletteSymbolName " :  " prog_item_eight_palette_indices " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " dataSymbolName " :     " offworld_graphics_data_progression_item " } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       { " fileName " :           " off_world_item.bin " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " paletteSymbolName " :  " nonprog_item_eight_palette_indices " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " dataSymbolName " :     " offworld_graphics_data_item " } ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        idx  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        offworldSprites :  List [ ByteEdit ]  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  itemSprite  in  itemSprites : 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-08 16:52:34 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            with  openFile ( " / " . join ( ( os . path . dirname ( self . __file__ ) ,  " data " ,  " custom_sprite " ,  itemSprite [ " fileName " ] ) ) ,  ' rb ' )  as  stream : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                buffer  =  bytearray ( stream . read ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                offworldSprites . append ( { " sym " :  symbols [ itemSprite [ " paletteSymbolName " ] ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        " values " :  buffer [ 0 : 8 ] } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                offworldSprites . append ( { " sym " :  symbols [ itemSprite [ " dataSymbolName " ] ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        " values " :  buffer [ 8 : 264 ] } ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                idx  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        deathLink :  List [ ByteEdit ]  =  [ { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " sym " :  symbols [ " config_deathlink " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " values " :  [ self . multiworld . death_link [ self . player ] . value ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        remoteItem :  List [ ByteEdit ]  =  [ { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " sym " :  symbols [ " config_remote_items " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " values " :  self . getWordArray ( 0b001  +  ( 0b010  if  self . remote_items  else  0b000 ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ownPlayerId :  List [ ByteEdit ]  =  [ { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " sym " :  symbols [ " config_player_id " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            " values " :  self . getWordArray ( self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        } ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        patchDict  =  {    ' MultiWorldLocations ' :  multiWorldLocations , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ' MultiWorldItems ' :  multiWorldItems , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ' offworldSprites ' :  offworldSprites , 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ' deathLink ' :  deathLink , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-21 00:34:47 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ' remoteItem ' :  remoteItem , 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ' ownPlayerId ' :  ownPlayerId , 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ' playerNameData ' :   playerNameData , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ' playerIdData ' :   playerIdData } 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # convert an array of symbolic byte_edit dicts like {"sym": symobj, "offset": 0, "values": [1, 0]} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # to a single rom patch dict like {0x438c: [1, 0], 0xa4a5: [0, 0, 0]} which varia will understand and apply 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        def  resolve_symbols_to_file_offset_based_dict ( byte_edits_arr :  List [ ByteEdit ] )  - >  Dict [ int ,  Iterable [ int ] ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this_patch_as_dict :  Dict [ int ,  Iterable [ int ] ]  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  byte_edit  in  byte_edits_arr : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 22:42:11 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                offset_within_rom_file :  int  =  byte_edit [ " sym " ] [ " offset_within_rom_file " ]  +  byte_edit [ " offset " ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                this_patch_as_dict [ offset_within_rom_file ]  =  byte_edit [ " values " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  this_patch_as_dict 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  patchname ,  byte_edits_arr  in  patchDict . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            patchDict [ patchname ]  =  resolve_symbols_to_file_offset_based_dict ( byte_edits_arr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatchDict ( patchDict ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        openTourianGreyDoors  =  { 0x07C823  +  5 :  [ 0x0C ] ,  0x07C831  +  5 :  [ 0x0C ] } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatchDict ( { ' openTourianGreyDoors ' :  openTourianGreyDoors } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        # set rom name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # 21 bytes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        from  Main  import  __version__ 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . romName  =  bytearray ( f ' SM { __version__ . replace ( " . " ,  " " ) [ 0 : 3 ] } _ { self . player } _ { self . multiworld . seed : 11 } ' ,  ' utf8 ' ) [ : 21 ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . romName . extend ( [ 0 ]  *  ( 21  -  len ( self . romName ) ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-24 08:40:02 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # clients should read from 0x7FC0, the location of the rom title in the SNES header. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # duplicative ROM name at 0x1C4F00 is still written here for now, since people with archipelago pre-0.3.0 client installed will still be depending on this location for connecting to SM 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( ' ROMName ' ,  {  ' ROMName ' :   { 0x1C4F00  :  self . romName ,  0x007FC0  :  self . romName }  } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-21 00:34:47 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        startItemROMAddressBase  =  symbols [ " start_item_data_major " ] [ " offset_within_rom_file " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # array for each item: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #  offset within ROM table "start_item_data_major" of this item"s info (starting status) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #  item bitmask or amount per pickup (BVOB = base value or bitmask), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #  offset within ROM table "start_item_data_major" of this item"s info (starting maximum/starting collected items) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #                                 current  BVOB   max 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #                                 -------  ----   --- 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        startItemROMDict  =  { " ETank " :         [  0x8 ,  0x64 ,   0xA ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Missile " :       [  0xC ,   0x5 ,   0xE ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Super " :         [ 0x10 ,   0x5 ,  0x12 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " PowerBomb " :     [ 0x14 ,   0x5 ,  0x16 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Reserve " :       [ 0x1A ,  0x64 ,  0x18 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Morph " :         [  0x2 ,   0x4 ,   0x0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Bomb " :          [  0x3 ,  0x10 ,   0x1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " SpringBall " :    [  0x2 ,   0x2 ,   0x0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " HiJump " :        [  0x3 ,   0x1 ,   0x1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Varia " :         [  0x2 ,   0x1 ,   0x0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Gravity " :       [  0x2 ,  0x20 ,   0x0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " SpeedBooster " :  [  0x3 ,  0x20 ,   0x1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " SpaceJump " :     [  0x3 ,   0x2 ,   0x1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " ScrewAttack " :   [  0x2 ,   0x8 ,   0x0 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Charge " :        [  0x7 ,  0x10 ,   0x5 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Ice " :           [  0x6 ,   0x2 ,   0x4 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Wave " :          [  0x6 ,   0x1 ,   0x4 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Spazer " :        [  0x6 ,   0x4 ,   0x4 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Plasma " :        [  0x6 ,   0x8 ,   0x4 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " Grapple " :       [  0x3 ,  0x40 ,   0x1 ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " XRayScope " :     [  0x3 ,  0x80 ,   0x1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # BVOB = base value or bitmask 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        mergedData  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        hasETank  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        hasSpazer  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        hasPlasma  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  startItem  in  self . startItems : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item  =  startItem . Type 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  item  ==  " ETank " :  hasETank  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item  ==  " Spazer " :  hasSpazer  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item  ==  " Plasma " :  hasPlasma  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( item  in  [ " ETank " ,  " Missile " ,  " Super " ,  " PowerBomb " ,  " Reserve " ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ( currentValue ,  amountPerItem ,  maxValue )  =  startItemROMDict [ item ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                if  ( startItemROMAddressBase  +  currentValue )  in  mergedData : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  currentValue ]  + =  amountPerItem 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  maxValue ]  + =  amountPerItem 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  currentValue ]  =  amountPerItem 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  maxValue ]  =  amountPerItem 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                ( collected ,  bitmask ,  equipped )  =  startItemROMDict [ item ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                if  ( startItemROMAddressBase  +  collected )  in  mergedData : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  collected ]  | =  bitmask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  equipped ]  | =  bitmask 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  collected ]  =  bitmask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    mergedData [ startItemROMAddressBase  +  equipped ]  =  bitmask 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  hasETank : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # we are overwriting the starting energy, so add up the E from 99 (normal starting energy) rather than from 0 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            mergedData [ startItemROMAddressBase  +  0x8 ]  + =  99 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            mergedData [ startItemROMAddressBase  +  0xA ]  + =  99 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  hasSpazer  and  hasPlasma : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            # de-equip spazer. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # otherwise, firing the unintended spazer+plasma combo would cause massive game glitches and crashes 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            mergedData [ startItemROMAddressBase  +  0x4 ]  & =  ~ 0x4 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  key ,  value  in  mergedData . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ( key  -  startItemROMAddressBase  >  7 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w0 ,  w1 ]  =  self . getWordArray ( value ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                mergedData [ key ]  =  [ w0 ,  w1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                mergedData [ key ]  =  [ value ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        startItemPatch  =  {  " startItemPatch " :   mergedData  } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( " startItemPatch " ,  startItemPatch ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # commit all the changes we've made here to the ROM 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        romPatcher . commitIPS ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        itemLocs  =  [ ItemLocation ( ItemManager . Items [ itemLoc . item . type ] ,  locationsDict [ itemLoc . name ]  if  itemLoc . name  in  locationsDict  and  itemLoc . player  ==  self . player  else  self . DummyLocation ( self . multiworld . get_player_name ( itemLoc . player )  +  "   "  +  itemLoc . name ) ,  True )  for  itemLoc  in  self . multiworld . get_locations ( )  if  itemLoc . item . player  ==  self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        progItemLocs  =  [ ItemLocation ( ItemManager . Items [ itemLoc . item . type ] ,  locationsDict [ itemLoc . name ]  if  itemLoc . name  in  locationsDict  and  itemLoc . player  ==  self . player  else  self . DummyLocation ( self . multiworld . get_player_name ( itemLoc . player )  +  "   "  +  itemLoc . name ) ,  True )  for  itemLoc  in  self . multiworld . get_locations ( )  if  itemLoc . item . player  ==  self . player  and  itemLoc . item . advancement  ==  True ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeObjectives ( itemLocs ,  romPatcher . settings [ " tourian " ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeItemsLocs ( self . itemLocs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        # romPatcher.writeSplitLocs(self.variaRando.args.majorsSplit, itemLocs, progItemLocs) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        romPatcher . writeItemsNumber ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  romPatcher . settings [ " isPlando " ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            romPatcher . writeSeed ( romPatcher . settings [ " seed " ] )  # lol if race mode 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeSpoiler ( itemLocs ,  progItemLocs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeRandoSettings ( self . variaRando . randoExec . randoSettings ,  itemLocs ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-09 18:35:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        romPatcher . writeDoorConnections ( romPatcher . settings [ " doors " ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeVersion ( romPatcher . settings [ " displayedVersion " ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  romPatcher . settings [ " ctrlDict " ]  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            romPatcher . writeControls ( romPatcher . settings [ " ctrlDict " ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  romPatcher . settings [ " moonWalk " ]  ==  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            romPatcher . enableMoonWalk ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeMagic ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeMajorsSplit ( romPatcher . settings [ " majorsSplit " ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #if self.settings["isPlando"] and self.race is None: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #    doorsPtrs = GraphUtils.getAps2DoorsPtrs() 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #    self.writePlandoTransitions(self.settings["plando"]["graphTrans"], doorsPtrs, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #                                self.settings["plando"]["maxTransitions"]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #    self.writePlandoAddresses(self.settings["plando"]["visitedLocations"]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #if self.settings["isPlando"] and self.settings["plando"]["additionalETanks"] != 0: 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        #    self.writeAdditionalETanks(self.settings["plando"]["additionalETanks"]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . end ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  generate_output ( self ,  output_directory :  str ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        outfilebase  =  self . multiworld . get_out_file_name_base ( self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-02 07:53:18 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        outputFilename  =  os . path . join ( output_directory ,  f " { outfilebase } .sfc " ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-30 12:42:02 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . variaRando . PatchRom ( outputFilename ,  self . APPrePatchRom ,  self . APPostPatchRom ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            self . write_crc ( outputFilename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . rom_name  =  self . romName 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        except : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            patch  =  SMDeltaPatch ( os . path . splitext ( outputFilename ) [ 0 ]  +  SMDeltaPatch . patch_file_ending ,  player = self . player , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 player_name = self . multiworld . player_name [ self . player ] ,  patched_path = outputFilename ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            patch . write ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        finally : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  os . path . exists ( outputFilename ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                os . unlink ( outputFilename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . rom_name_available_event . set ( )   # make sure threading continues and errors are collected 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  checksum_mirror_sum ( self ,  start ,  length ,  mask  =  0x800000 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-31 03:29:08 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        while  not ( length  &  mask )  and  mask : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            mask  >> =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        part1  =  sum ( start [ : mask ] )  &  0xFFFF 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        part2  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        next_length  =  length  -  mask 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  next_length : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            part2  =  self . checksum_mirror_sum ( start [ mask : ] ,  next_length ,  mask  >>  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            while  ( next_length  <  mask ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                next_length  + =  next_length 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                part2  + =  part2 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  ( part1  +  part2 )  &  0xFFFF 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write_bytes ( self ,  buffer ,  startaddress :  int ,  values ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        buffer [ startaddress : startaddress  +  len ( values ) ]  =  values 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  write_crc ( self ,  romName ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( romName ,  ' rb ' )  as  stream : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            buffer  =  bytearray ( stream . read ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            crc  =  self . checksum_mirror_sum ( buffer ,  len ( buffer ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            inv  =  crc  ^  0xFFFF 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . write_bytes ( buffer ,  0x7FDC ,  [ inv  &  0xFF ,  ( inv  >>  8 )  &  0xFF ,  crc  &  0xFF ,  ( crc  >>  8 )  &  0xFF ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        with  open ( romName ,  ' wb ' )  as  outfile : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            outfile . write ( buffer ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  modify_multidata ( self ,  multidata :  dict ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # wait for self.rom_name to be available. 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . rom_name_available_event . wait ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        rom_name  =  getattr ( self ,  " rom_name " ,  None ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # we skip in case of error, so that the original error in the output thread is the one that gets raised 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  rom_name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_name  =  base64 . b64encode ( bytes ( self . rom_name ) ) . decode ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            multidata [ " connect_names " ] [ new_name ]  =  multidata [ " connect_names " ] [ self . multiworld . player_name [ self . player ] ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  fill_slot_data ( self ) :  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  self . multiworld . is_race : 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 16:46:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  option_name  in  self . option_definitions : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                option  =  getattr ( self . multiworld ,  option_name ) [ self . player ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                slot_data [ option_name ]  =  option . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_data [ " Preset " ]  =  {  " Knows " :  { } , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    " Settings " :  { " hardRooms " :  Settings . SettingsDict [ self . player ] . hardRooms , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-02 13:41:03 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                                 " bossesDifficulty " :  Settings . SettingsDict [ self . player ] . bossesDifficulty , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                 " hellRuns " :  Settings . SettingsDict [ self . player ] . hellRuns } , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    " Controller " :  Controller . ControllerDict [ self . player ] . __dict__ } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  knows  in  Knows . __dict__ : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  isKnows ( knows ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    slot_data [ " Preset " ] [ " Knows " ] [ knows ]  =  [  getattr ( Knows . knowsDict [ self . player ] ,  knows ) . bool ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            getattr ( Knows . knowsDict [ self . player ] ,  knows ) . difficulty ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_data [ " InterAreaTransitions " ]  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                slot_data [ " InterAreaTransitions " ] [ src . Name ]  =  dest . Name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_data [ " Doors " ]  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  door  in  DoorsManager . doorsDict [ self . player ] . values ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                slot_data [ " Doors " ] [ door . name ]  =  door . getColor ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_data [ " RomPatches " ]  =  RomPatches . ActivePatches [ self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        return  slot_data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  write_spoiler ( self ,  spoiler_handle :  TextIO ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  self . multiworld . area_randomization [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n \n Area Transitions: \n \n ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n ' . join ( [ ' %s %s   %s   %s '  %  ( f ' { self . multiworld . get_player_name ( self . player ) } :  ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            if  self . multiworld . players  >  1  else  ' ' ,  src . Name , 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                                            ' <=> ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            dest . Name )  for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions  if  not  src . Boss ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  self . multiworld . boss_randomization [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n \n Boss Transitions: \n \n ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n ' . join ( [ ' %s %s   %s   %s '  %  ( f ' { self . multiworld . get_player_name ( self . player ) } :  ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            if  self . multiworld . players  >  1  else  ' ' ,  src . Name , 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                                            ' <=> ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            dest . Name )  for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions  if  src . Boss ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  SMLocation ( Location ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    game :  str  =  " Super Metroid " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  player :  int ,  name :  str ,  address = None ,  parent = None ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( SMLocation ,  self ) . __init__ ( player ,  name ,  address ,  parent ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-01-22 18:36:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  can_reach ( self ,  state :  CollectionState )  - >  bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # self.access_rule computes faster on average, so placing it first for faster abort 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        assert  self . parent_region ,  " Can ' t reach location without region " 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-23 16:16:01 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  super ( SMLocation ,  self ) . can_reach ( state )  and  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ( not  state . multiworld . worlds [ self . player ] . need_comeback_check  or  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                self . can_comeback ( state ,  self . item ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-01-22 18:36:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  can_comeback ( self ,  state :  CollectionState ,  item ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-31 21:41:21 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        randoExec  =  state . multiworld . worlds [ self . player ] . variaRando . randoExec 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        randoService  =  randoExec . setup . services 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        comebackCheck  =  ComebackCheckType . JustComeback         
							 
						 
					
						
							
								
									
										
										
										
											2023-01-22 18:36:18 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        n  =  2  if  GraphUtils . isStandardStart ( randoExec . graphSettings . startAP )  else  3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # is early game 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 03:10:21 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( len ( [ loc  for  loc  in  state . locations_checked  if  loc . player  ==  self . player ] )  < =  n  or  randoExec . graphSettings . startAP  ==  state . smbm [ self . player ] . lastAP ) : 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-16 23:46:19 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            comebackCheck  =  ComebackCheckType . NoCheck 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        container  =  ItemLocContainer ( state . smbm [ self . player ] ,  [ ] ,  [ ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  randoService . fullComebackCheck (   container ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                state . smbm [ self . player ] . lastAP ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                ItemManager . Items [ item . type ]  if  item  is  not  None  and  item . player  ==  self . player  else  None , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                locationsDict [ self . name ] ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                comebackCheck )  
							 
						 
					
						
							
								
									
										
										
										
											2022-06-17 03:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								class  SMItem ( Item ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    game  =  " Super Metroid " 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-06 00:49:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    type :  str 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-08-06 00:49:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  __init__ ( self ,  name ,  classification ,  type :  str ,  code ,  player :  int ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-17 03:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        super ( SMItem ,  self ) . __init__ ( name ,  classification ,  code ,  player ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        self . type  =  type