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-08-06 00:49:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  typing  import  Set ,  TextIO  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-14 03:37:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  worlds . sm . variaRandomizer . graph . graph_utils  import  GraphUtils  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								logger  =  logging . getLogger ( " Super Metroid " )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Regions  import  create_regions  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Rules  import  set_rules ,  add_entrance_rule  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Options  import  sm_options  
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . Rom  import  get_base_rom_path ,  ROM_PLAYER_LIMIT ,  SMDeltaPatch ,  get_sm_symbols  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  Utils  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-06-17 03:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  BaseClasses  import  Region ,  Entrance ,  Location ,  MultiWorld ,  Item ,  ItemClassification ,  RegionType ,  CollectionState ,  Tutorial  
						 
					
						
							
								
									
										
										
										
											2022-05-11 13:05:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  . . AutoWorld  import  World ,  AutoLogicRegister ,  WebWorld  
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  logic . smboolmanager  import  SMBoolManager  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  graph . vanilla . graph_locations  import  locationsDict  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  graph . graph_utils  import  getAccessPoint  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  rando . ItemLocContainer  import  ItemLocation  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  rando . Items  import  ItemManager  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  utils . parameters  import  *  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  logic . logic  import  Logic  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  randomizer  import  VariaRandomizer  
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  utils . doorsmanager  import  DoorsManager  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  rom . rom_patches  import  RomPatches  
						 
					
						
							
								
									
										
										
										
											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 , 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:11 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    parent . state . smbm [ player ] . onlyBossLeft )  for  player  in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        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-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 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-31 00:14:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    data_version  =  2 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    remote_items :  bool  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    remote_start_inventory :  bool  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        super ( ) . __init__ ( world ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-04-29 20:37:28 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    @classmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  stage_assert_generate ( cls ,  world ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        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 ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . variaRando  =  VariaRandomizer ( self . world ,  get_base_rom_path ( ) ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . world . state . smbm [ self . player ]  =  SMBoolManager ( self . player ,  self . variaRando . maxDifficulty ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # 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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . world . local_items [ self . player ] . value . add ( ' Nothing ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-10 14:51:09 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . world . local_items [ self . player ] . value . add ( ' No Energy ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( self . variaRando . args . morphPlacement  ==  " early " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . local_items [ self . player ] . value . add ( ' Morph ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-21 00:34:47 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . remote_items  =  self . world . remote_items [ self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  ( len ( self . variaRando . randoExec . setup . restrictedLocs )  >  0 ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-22 03:44:58 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            self . world . accessibility [ self . player ]  =  self . world . accessibility [ self . player ] . from_text ( " minimal " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logger . warning ( f " accessibility forced to  ' minimal '  for player  { self . world . get_player_name ( self . player ) }  because of  ' fun '  settings " ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  generate_basic ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itemPool  =  self . variaRando . container . itemPool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . startItems  =  [ variaItem  for  item  in  self . world . precollected_items [ self . player ]  for  variaItem  in  ItemManager . Items . values ( )  if  variaItem . Name  ==  item . name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . world . start_inventory_removes_from_pool [ self . player ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  item  in  self . startItems : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( item  in  itemPool ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    itemPool . remove ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        missingPool  =  105  -  len ( itemPool )  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  i  in  range ( 1 ,  missingPool ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            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 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-17 03:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            smitem  =  SMItem ( item . Name ,  ItemClassification . progression  if  isAdvancement  else  ItemClassification . filler , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            item . Type ,  None  if  itemClass  ==  ' Boss '  else  self . item_name_to_id [ item . Name ] ,  player = self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . world . itempool  + =  pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  ( location ,  item )  in  self . locked_items . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . get_location ( location ,  self . player ) . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . get_location ( location ,  self . player ) . address  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        startAP  =  self . world . get_entrance ( ' StartAP ' ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        startAP . connect ( self . world . get_region ( self . variaRando . args . startLocation ,  self . player ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            src_region  =  self . world . get_region ( src . Name ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            dest_region  =  self . world . get_region ( dest . Name ,  self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( ( src . Name  +  " -> "  +  dest . Name ,  self . player )  not  in  self . world . _entrance_cache ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                src_region . exits . append ( Entrance ( self . player ,  src . Name  +  " -> "  +  dest . Name ,  src_region ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								            srcDestEntrance  =  self . world . get_entrance ( src . Name  +  " -> "  +  dest . Name ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            srcDestEntrance . connect ( dest_region ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            add_entrance_rule ( self . world . get_entrance ( src . Name  +  " -> "  +  dest . Name ,  self . player ) ,  self . player ,  getAccessPoint ( src . Name ) . traverse ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  set_rules ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        set_rules ( self . world ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_regions ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        create_locations ( self ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        create_regions ( self ,  self . world ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  getWordArray ( self ,  w ) :  # 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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # used for remote location Credits Spoiler of local items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    class  DummyLocation : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  __init__ ( self ,  name ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . Name  =  name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( os . path . join ( os . path . dirname ( __file__ ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " multiworld-basepatch.ips " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . applyIPSPatch ( os . path . join ( os . path . dirname ( __file__ ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " variapatches.ips " ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-30 12:42:02 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  APPostPatchRom ( self ,  romPatcher ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        symbols  =  get_sm_symbols ( os . path . join ( os . path . dirname ( __file__ ) ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              " data " ,  " SMBasepatch_prebuilt " ,  " sm-basepatch-symbols.json " ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        multiWorldLocations  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        multiWorldItems  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        idx  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . playerIDMap  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        playerIDCount  =  0  # 0 is for "Archipelago" server; highest possible = 200 (201 entries) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        vanillaItemTypesCount  =  21 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        for  itemLoc  in  self . world . get_locations ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  itemLoc . player  ==  self . player  and  locationsDict [ itemLoc . name ] . Id  !=  None : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # this SM world can find this item: write full item data to tables and assign player data for writing 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                romPlayerID  =  itemLoc . item . player  if  itemLoc . item . player  < =  ROM_PLAYER_LIMIT  else  0 
							 
						 
					
						
							
								
									
										
										
										
											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 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    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 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  ( romPlayerID  >  0  and  romPlayerID  not  in  self . playerIDMap . keys ( ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    playerIDCount  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . playerIDMap [ romPlayerID ]  =  playerIDCount 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                [ w0 ,  w1 ]  =  self . getWordArray ( 0  if  itemLoc . item . player  ==  self . player  else  1 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ w2 ,  w3 ]  =  self . getWordArray ( itemId ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ w4 ,  w5 ]  =  self . getWordArray ( romPlayerID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                [ 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 ] } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  itemLoc . item . player  ==  self . player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # this SM world owns the item: so in case the sending player might not have anything placed in this 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # world to receive from it, assign them space in playerIDMap so that the ROM can display their name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # (SM item name not needed, as SM item type id will be in the message they send to this world live) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                romPlayerID  =  itemLoc . player  if  itemLoc . player  < =  ROM_PLAYER_LIMIT  else  0 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  ( romPlayerID  >  0  and  romPlayerID  not  in  self . playerIDMap . keys ( ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    playerIDCount  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    self . playerIDMap [ romPlayerID ]  =  playerIDCount 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        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-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        offworldSprites  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  itemSprite  in  itemSprites : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            with  open ( os . path . join ( os . path . dirname ( __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-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        deathLink  =  [ { " sym " :  symbols [ " config_deathlink " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                      " values " :  [ self . world . death_link [ self . player ] . value ] } ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        remoteItem  =  [ { " sym " :  symbols [ " config_remote_items " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                       " values " :  self . getWordArray ( 0b001  +  ( 0b010  if  self . remote_items  else  0b000 ) ) } ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ownPlayerId  =  [ { " sym " :  symbols [ " config_player_id " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        " values " :  self . getWordArray ( self . player ) } ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerNames  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerNameIDMap  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerNames . append ( { " sym " :  symbols [ " rando_player_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            " values " :  " Archipelago " . upper ( ) . center ( 16 ) . encode ( ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        playerNameIDMap . append ( { " sym " :  symbols [ " rando_player_id_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                " offset " :  0 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                " values " :  self . getWordArray ( 0 ) } ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  key , value  in  self . playerIDMap . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            playerNames . append ( { " sym " :  symbols [ " rando_player_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                " offset " :  value  *  16 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                " values " :  self . world . player_name [ key ] [ : 16 ] . upper ( ) . center ( 16 ) . encode ( ) } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            playerNameIDMap . append ( { " sym " :  symbols [ " rando_player_id_table " ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    " offset " :  value  *  2 , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    " values " :  self . getWordArray ( key ) } ) 
							 
						 
					
						
							
								
									
										
										
										
											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 , 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-16 20:31:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        ' PlayerName ' :   playerNames , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        ' PlayerNameIDMap ' :   playerNameIDMap } 
							 
						 
					
						
							
								
									
										
										
										
											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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        def  resolve_symbols_to_file_offset_based_dict ( byte_edits_arr )  - >  dict : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            this_patch_as_dict  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  byte_edit  in  byte_edits_arr : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                offset_within_rom_file  =  byte_edit [ " sym " ] [ " offset_within_rom_file " ]  +  byte_edit [ " offset " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                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-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        self . romName  =  bytearray ( f ' SM { __version__ . replace ( " . " ,  " " ) [ 0 : 3 ] } _ { self . player } _ { self . world . 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-08-13 02:58:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        itemLocs  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ItemLocation ( ItemManager . Items [ itemLoc . item . type 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         if  isinstance ( itemLoc . item ,  SMItem )  and  itemLoc . item . type  in  ItemManager . Items  else 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         ' ArchipelagoItem ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                         locationsDict [ itemLoc . name ] ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  itemLoc  in  self . world . get_locations ( )  if  itemLoc . player  ==  self . player 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-26 00:43:39 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        romPatcher . writeItemsLocs ( itemLocs ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -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 . world . get_player_name ( itemLoc . player )  +  "   "  +  itemLoc . name ) ,  True )  for  itemLoc  in  self . world . 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 . world . get_player_name ( itemLoc . player )  +  "   "  +  itemLoc . name ) ,  True )  for  itemLoc  in  self . world . get_locations ( )  if  itemLoc . item . player  ==  self . player  and  itemLoc . item . advancement  ==  True ]  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # progItemLocs = [ItemLocation(ItemManager.Items[itemLoc.item.type if itemLoc.item.type in ItemManager.Items else 'ArchipelagoItem'], locationsDict[itemLoc.name], True) for itemLoc in self.world.get_locations() if itemLoc.player == self.player and itemLoc.item.player == self.player and itemLoc.item.advancement == True] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # romPatcher.writeSplitLocs(self.variaRando.args.majorsSplit, itemLocs, progItemLocs) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeSpoiler ( itemLocs ,  progItemLocs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        romPatcher . writeRandoSettings ( self . variaRando . randoExec . randoSettings ,  itemLocs ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  generate_output ( self ,  output_directory :  str ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        outfilebase  =  ' AP_ '  +  self . world . seed_name 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        outfilepname  =  f ' _P { self . player } ' 
							 
						 
					
						
							
								
									
										
										
										
											2022-04-02 22:47:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        outfilepname  + =  f " _ { self . world . get_file_safe_player_name ( self . player ) . replace ( '   ' ,  ' _ ' ) } " 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        outputFilename  =  os . path . join ( output_directory ,  f ' { outfilebase } { outfilepname } .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 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            patch  =  SMDeltaPatch ( os . path . splitext ( outputFilename ) [ 0 ] + SMDeltaPatch . patch_file_ending ,  player = self . player , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                 player_name = self . world . player_name [ self . player ] ,  patched_path = outputFilename ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            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-02-09 21:06:34 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            multidata [ " connect_names " ] [ new_name ]  =  multidata [ " connect_names " ] [ self . world . player_name [ self . player ] ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  fill_slot_data ( self ) :  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  not  self . world . is_race : 
							 
						 
					
						
							
								
									
										
										
										
											2022-08-15 16:46:59 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  option_name  in  self . option_definitions : 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-01 18:37:52 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                option  =  getattr ( self . world ,  option_name ) [ self . player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  collect ( self ,  state :  CollectionState ,  item :  Item )  - >  bool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-05 15:49:19 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        state . smbm [ self . player ] . addItem ( item . type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  super ( SMWorld ,  self ) . collect ( state ,  item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  remove ( self ,  state :  CollectionState ,  item :  Item )  - >  bool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        state . smbm [ self . player ] . removeItem ( item . type ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  super ( SMWorld ,  self ) . remove ( state ,  item ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_item ( self ,  name :  str )  - >  Item : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item  =  next ( x  for  x  in  ItemManager . Items . values ( )  if  x . Name  ==  name ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-31 05:08:41 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  SMItem ( item . Name ,  ItemClassification . progression  if  item . Class  !=  ' Minor '  else  ItemClassification . filler ,  item . Type ,  self . item_name_to_id [ item . Name ] , 
							 
						 
					
						
							
								
									
										
										
										
											2022-06-17 03:23:27 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                      player = self . player ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-19 09:37:26 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  get_filler_item_name ( self )  - >  str : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . world . random . randint ( 0 ,  100 )  <  self . world . minor_qty [ self . player ] . value : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            power_bombs  =  self . world . power_bomb_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            missiles  =  self . world . missile_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            super_missiles  =  self . world . super_qty [ self . player ] . value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            roll  =  self . world . 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 " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    def  pre_fill ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ( self . variaRando . args . morphPlacement  ==  " early " )  and  next ( ( item  for  item  in  self . world . itempool  if  item . player  ==  self . player  and  item . name  ==  " Morph Ball " ) ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            viable  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  location  in  self . world . get_locations ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  location . player  ==  self . player  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        and  location . item  is  None  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        and  location . can_reach ( self . world . state ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    viable . append ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . random . shuffle ( viable ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            key  =  self . world . create_item ( " Morph Ball " ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            loc  =  viable . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            loc . place_locked_item ( key ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . itempool [ : ]  =  [ item  for  item  in  self . world . itempool  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        item . player  !=  self . player  or 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        item . name  !=  " Morph Ball " ]  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . random . shuffle ( nonChozoLoc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self . world . 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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    @classmethod 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-16 20:06:25 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  stage_fill_hook ( cls ,  world ,  progitempool ,  usefulitempool ,  filleritempool ,  fill_locations ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        if  world . get_game_players ( " Super Metroid " ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            progitempool . sort ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                key = lambda  item :  1  if  ( item . name  ==  ' Morph Ball ' )  else  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-28 01:50:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    @classmethod 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  stage_post_fill ( cls ,  world ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        new_state  =  CollectionState ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        progitempool  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-28 01:50:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  item  in  world . itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . game  ==  " Super Metroid "  and  item . advancement : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                progitempool . append ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  progitempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_state . collect ( item ,  True ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-28 01:50:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        bossesLoc  =  [ ' Draygon ' ,  ' Kraid ' ,  ' Ridley ' ,  ' Phantoon ' ,  ' Mother Brain ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-28 01:50:58 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        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 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-02 00:11:42 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-15 10:29:56 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  write_spoiler ( self ,  spoiler_handle :  TextIO ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . world . area_randomization [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n \n Area Transitions: \n \n ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n ' . join ( [ ' %s %s   %s   %s '  %  ( f ' { self . world . get_player_name ( self . player ) } :  ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            if  self . world . players  >  1  else  ' ' ,  src . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            ' <=> ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            dest . Name )  for  src ,  dest  in  self . variaRando . randoExec . areaGraph . InterAreaTransitions  if  not  src . Boss ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  self . world . boss_randomization [ self . player ] . value  !=  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n \n Boss Transitions: \n \n ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spoiler_handle . write ( ' \n ' . join ( [ ' %s %s   %s   %s '  %  ( f ' { self . world . get_player_name ( self . player ) } :  ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            if  self . world . players  >  1  else  ' ' ,  src . Name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            ' <=> ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  create_locations ( self ,  player :  int ) :  
						 
					
						
							
								
									
										
										
										
											2022-08-31 00:14:17 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  name  in  locationsDict : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . locations [ name ]  =  SMLocation ( player ,  name ,  self . location_name_to_id . get ( name ,  None ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-18 04:53:09 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  create_region ( self ,  world :  MultiWorld ,  player :  int ,  name :  str ,  locations = None ,  exits = None ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret  =  Region ( name ,  RegionType . LightWorld ,  name ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ret . world  =  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 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  can_fill ( self ,  state :  CollectionState ,  item :  Item ,  check_access = True )  - >  bool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        return  self . always_allow ( state ,  item )  or  ( self . item_rule ( item )  and  ( not  check_access  or  ( self . can_reach ( state )  and  self . can_comeback ( state ,  item ) ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  can_comeback ( self ,  state :  CollectionState ,  item :  Item ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        randoExec  =  state . world . worlds [ self . player ] . variaRando . randoExec 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  key  in  locationsDict [ self . name ] . AccessFrom . keys ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-07-14 03:37:45 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ( randoExec . areaGraph . canAccessList (   state . smbm [ self . player ] ,  
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    key , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    [ randoExec . graphSettings . startAP ,  ' Landing Site ' ]  if  not  GraphUtils . isStandardStart ( randoExec . graphSettings . startAP )  else  [ ' Landing Site ' ] , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                    state . smbm [ self . player ] . maxDiff ) ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-25 02:50:32 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                return  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  False 
							 
						 
					
						
							
								
									
										
										
										
											2021-11-12 08:00:11 -05:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											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