2024-03-15 17:33:03 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  typing  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  dataclasses  import  fields  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  typing  import  List ,  Set ,  Iterable ,  Sequence ,  Dict ,  Callable ,  Union  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  math  import  floor ,  ceil  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  BaseClasses  import  Item ,  MultiWorld ,  Location ,  Tutorial ,  ItemClassification  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  worlds . AutoWorld  import  WebWorld ,  World  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  .  import  ItemNames  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Items  import  StarcraftItem ,  filler_items ,  get_item_table ,  get_full_item_list ,  \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get_basic_units ,  ItemData ,  upgrade_included_names ,  progressive_if_nco ,  kerrigan_actives ,  kerrigan_passives ,  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    kerrigan_only_passives ,  progressive_if_ext ,  not_balanced_starting_units ,  spear_of_adun_calldowns ,  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    spear_of_adun_castable_passives ,  nova_equipment 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . ItemGroups  import  item_name_groups  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Locations  import  get_locations ,  LocationType ,  get_location_types ,  get_plando_locations  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Regions  import  create_regions  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . Options  import  get_option_value ,  LocationInclusion ,  KerriganLevelItemDistribution ,  \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    KerriganPresence ,  KerriganPrimalStatus ,  RequiredTactics ,  kerrigan_unit_available ,  StarterUnit ,  SpearOfAdunPresence ,  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    get_enabled_campaigns ,  SpearOfAdunAutonomouslyCastAbilityPresence ,  Starcraft2Options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . PoolFilter  import  filter_items ,  get_item_upgrades ,  UPGRADABLE_ITEMS ,  missions_in_mission_table ,  get_used_races  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								from  . MissionTables  import  MissionInfo ,  SC2Campaign ,  lookup_name_to_mission ,  SC2Mission ,  \ 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    SC2Race 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  Starcraft2WebWorld ( WebWorld ) :  
						 
					
						
							
								
									
										
											 
										
											
												Docs, Starcraft 2: Add French documentation for setup and game page (#3031)
* Started to create the french doc
* First version of sc2 setup in french finish, created the file for the introduction of the game in french
* French-fy upgrade in setup, continue translation of game description
* Finish writing FR game page, added a link to it on the english game page. Re-read and corrected both the game page and setup page.
* Corrected a sentence in the SC2 English setup guide.
* Applied 120 carac limits for french part, applied modification for consistency.
* Added reference to website yaml checker, applied several wording correction/suggestions
* Modified link to AP page to be in relative (fr/en), uniformed SC2 and random writing (fr), applied some suggestons in writing quality(fr), added a mention to the datapackage (fr/en), enhanced prog balancing recommendation (fr)
* Correction of some grammar issues
* Removed name correction for english part since done in other PR; added mention to hotkey and language restriction
* Applied suggestions of peer review
* Applied mofications proposed by reviewer about the external website
---------
Co-authored-by: neocerber <neorcerber@gmail.com>
											 
										 
										
											2024-05-28 18:48:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    setup_en  =  Tutorial ( 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-15 17:33:03 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        " Multiworld Setup Guide " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " A guide to setting up the Starcraft 2 randomizer connected to an Archipelago Multiworld " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " English " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " setup_en.md " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " setup/en " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        [ " TheCondor " ,  " Phaneros " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
											 
										
											
												Docs, Starcraft 2: Add French documentation for setup and game page (#3031)
* Started to create the french doc
* First version of sc2 setup in french finish, created the file for the introduction of the game in french
* French-fy upgrade in setup, continue translation of game description
* Finish writing FR game page, added a link to it on the english game page. Re-read and corrected both the game page and setup page.
* Corrected a sentence in the SC2 English setup guide.
* Applied 120 carac limits for french part, applied modification for consistency.
* Added reference to website yaml checker, applied several wording correction/suggestions
* Modified link to AP page to be in relative (fr/en), uniformed SC2 and random writing (fr), applied some suggestons in writing quality(fr), added a mention to the datapackage (fr/en), enhanced prog balancing recommendation (fr)
* Correction of some grammar issues
* Removed name correction for english part since done in other PR; added mention to hotkey and language restriction
* Applied suggestions of peer review
* Applied mofications proposed by reviewer about the external website
---------
Co-authored-by: neocerber <neorcerber@gmail.com>
											 
										 
										
											2024-05-28 18:48:52 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    setup_fr  =  Tutorial ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        setup_en . tutorial_name , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        setup_en . description , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " Français " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " setup_fr.md " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        " setup/fr " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        [ " Neocerber " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    tutorials  =  [ setup_en ,  setup_fr ] 
							 
						 
					
						
							
								
									
										
										
										
											2024-03-15 17:33:03 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								class  SC2World ( World ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    StarCraft  II  is  a  science  fiction  real - time  strategy  video  game  developed  and  published  by  Blizzard  Entertainment . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Play  as  one  of  three  factions  across  four  campaigns  in  a  battle  for  supremacy  of  the  Koprulu  Sector . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    game  =  " Starcraft 2 " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    web  =  Starcraft2WebWorld ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_name_to_id  =  { name :  data . code  for  name ,  data  in  get_full_item_list ( ) . items ( ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_name_to_id  =  { location . name :  location . code  for  location  in  get_locations ( None ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    options_dataclass  =  Starcraft2Options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    options :  Starcraft2Options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_name_groups  =  item_name_groups 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    locked_locations :  typing . List [ str ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_cache :  typing . List [ Location ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    mission_req_table :  Dict [ SC2Campaign ,  Dict [ str ,  MissionInfo ] ]  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    final_mission_id :  int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    victory_item :  str 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    required_client_version  =  0 ,  4 ,  5 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  __init__ ( self ,  multiworld :  MultiWorld ,  player :  int ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        super ( SC2World ,  self ) . __init__ ( multiworld ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . location_cache  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . locked_locations  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_item ( self ,  name :  str )  - >  Item : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        data  =  get_full_item_list ( ) [ name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  StarcraftItem ( name ,  data . classification ,  data . code ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_regions ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . mission_req_table ,  self . final_mission_id ,  self . victory_item  =  create_regions ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            self ,  get_locations ( self ) ,  self . location_cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  create_items ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        setup_events ( self . player ,  self . locked_locations ,  self . location_cache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items  =  get_excluded_items ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        starter_items  =  assign_starter_items ( self ,  excluded_items ,  self . locked_locations ,  self . location_cache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_resource_locations ( self ,  self . locked_locations ,  self . location_cache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pool  =  get_item_pool ( self ,  self . mission_req_table ,  starter_items ,  excluded_items ,  self . location_cache ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_item_pool_with_dummy_items ( self ,  self . locked_locations ,  self . location_cache ,  pool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . itempool  + =  pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  set_rules ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        self . multiworld . completion_condition [ self . player ]  =  lambda  state :  state . has ( self . victory_item ,  self . player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  get_filler_item_name ( self )  - >  str : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  self . random . choice ( filler_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  fill_slot_data ( self ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  option_name  in  [ field . name  for  field  in  fields ( Starcraft2Options ) ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            option  =  get_option_value ( self ,  option_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  type ( option )  in  { str ,  int } : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                slot_data [ option_name ]  =  int ( option ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_req_table  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Serialize data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  campaign  in  self . mission_req_table : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_req_table [ campaign . id ]  =  { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  mission  in  self . mission_req_table [ campaign ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                slot_req_table [ campaign . id ] [ mission ]  =  self . mission_req_table [ campaign ] [ mission ] . _asdict ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Replace mission objects with mission IDs 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                slot_req_table [ campaign . id ] [ mission ] [ " mission " ]  =  slot_req_table [ campaign . id ] [ mission ] [ " mission " ] . id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  index  in  range ( len ( slot_req_table [ campaign . id ] [ mission ] [ " required_world " ] ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # TODO this is a band-aid, sometimes the mission_req_table already contains dicts 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # as far as I can tell it's related to having multiple vanilla mission orders 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  not  isinstance ( slot_req_table [ campaign . id ] [ mission ] [ " required_world " ] [ index ] ,  dict ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        slot_req_table [ campaign . id ] [ mission ] [ " required_world " ] [ index ]  =  slot_req_table [ campaign . id ] [ mission ] [ " required_world " ] [ index ] . _asdict ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        enabled_campaigns  =  get_enabled_campaigns ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data [ " plando_locations " ]  =  get_plando_locations ( self ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data [ " nova_covert_ops_only " ]  =  ( enabled_campaigns  ==  { SC2Campaign . NCO } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data [ " mission_req " ]  =  slot_req_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data [ " final_mission " ]  =  self . final_mission_id 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        slot_data [ " version " ]  =  3 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  SC2Campaign . HOTS  not  in  enabled_campaigns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            slot_data [ " kerrigan_presence " ]  =  KerriganPresence . option_not_present 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  slot_data 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  setup_events ( player :  int ,  locked_locations :  typing . List [ str ] ,  location_cache :  typing . List [ Location ] ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  location  in  location_cache : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  location . address  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item  =  Item ( location . name ,  ItemClassification . progression ,  None ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locked_locations . append ( location . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            location . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_excluded_items ( world :  World )  - >  Set [ str ] :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    excluded_items :  Set [ str ]  =  set ( get_option_value ( world ,  ' excluded_items ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  item  in  world . multiworld . precollected_items [ world . player ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items . add ( item . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    locked_items :  Set [ str ]  =  set ( get_option_value ( world ,  ' locked_items ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Starter items are also excluded items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    starter_items :  Set [ str ]  =  set ( get_option_value ( world ,  ' start_inventory ' ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_table  =  get_full_item_list ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    soa_presence  =  get_option_value ( world ,  " spear_of_adun_presence " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    soa_autocast_presence  =  get_option_value ( world ,  " spear_of_adun_autonomously_cast_ability_presence " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    enabled_campaigns  =  get_enabled_campaigns ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Ensure no item is both guaranteed and excluded 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalid_items  =  excluded_items . intersection ( locked_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalid_count  =  len ( invalid_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Don't count starter items that can appear multiple times 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    invalid_count  - =  len ( [ item  for  item  in  starter_items . intersection ( locked_items )  if  item_table [ item ] . quantity  !=  1 ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  invalid_count  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        raise  Exception ( f " { invalid_count }  item { ' s are '  if  invalid_count  >  1  else  '  is ' }  both locked and excluded from generation.  Please adjust your excluded items and locked items. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  smart_exclude ( item_choices :  Set [ str ] ,  choices_to_keep :  int ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        expected_choices  =  len ( item_choices ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  expected_choices  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_choices  =  set ( item_choices ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        starter_choices  =  item_choices . intersection ( starter_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_choices  =  item_choices . intersection ( excluded_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_choices . difference_update ( excluded_choices ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_choices . difference_update ( locked_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        candidates  =  sorted ( item_choices ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        exclude_amount  =  min ( expected_choices  -  choices_to_keep  -  len ( excluded_choices )  +  len ( starter_choices ) ,  len ( candidates ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  exclude_amount  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            excluded_items . update ( world . random . sample ( candidates ,  exclude_amount ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Nova gear exclusion if NCO not in campaigns 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  SC2Campaign . NCO  not  in  enabled_campaigns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items  =  excluded_items . union ( nova_equipment ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    kerrigan_presence  =  get_option_value ( world ,  " kerrigan_presence " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Exclude Primal Form item if option is not set or Kerrigan is unavailable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  get_option_value ( world ,  " kerrigan_primal_status " )  !=  KerriganPrimalStatus . option_item  or  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ( kerrigan_presence  in  { KerriganPresence . option_not_present ,  KerriganPresence . option_not_present_and_no_passives } ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items . add ( ItemNames . KERRIGAN_PRIMAL_FORM ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # no Kerrigan & remove all passives => remove all abilities 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  kerrigan_presence  ==  KerriganPresence . option_not_present_and_no_passives : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  tier  in  range ( 7 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            smart_exclude ( kerrigan_actives [ tier ] . union ( kerrigan_passives [ tier ] ) ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # no Kerrigan, but keep non-Kerrigan passives 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  kerrigan_presence  ==  KerriganPresence . option_not_present : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            smart_exclude ( kerrigan_only_passives ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  tier  in  range ( 7 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                smart_exclude ( kerrigan_actives [ tier ] ,  0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # SOA exclusion, other cases are handled by generic race logic 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( soa_presence  ==  SpearOfAdunPresence . option_lotv_protoss  and  SC2Campaign . LOTV  not  in  enabled_campaigns )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  soa_presence  ==  SpearOfAdunPresence . option_not_present : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items . update ( spear_of_adun_calldowns ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  ( soa_autocast_presence  ==  SpearOfAdunAutonomouslyCastAbilityPresence . option_lotv_protoss  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            and  SC2Campaign . LOTV  not  in  enabled_campaigns )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  soa_autocast_presence  ==  SpearOfAdunAutonomouslyCastAbilityPresence . option_not_present : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        excluded_items . update ( spear_of_adun_castable_passives ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  excluded_items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  assign_starter_items ( world :  World ,  excluded_items :  Set [ str ] ,  locked_locations :  List [ str ] ,  location_cache :  typing . List [ Location ] )  - >  List [ Item ] :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    starter_items :  List [ Item ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    non_local_items  =  get_option_value ( world ,  " non_local_items " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    starter_unit  =  get_option_value ( world ,  " starter_unit " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    enabled_campaigns  =  get_enabled_campaigns ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    first_mission  =  get_first_mission ( world . mission_req_table ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Ensuring that first mission is completable 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  starter_unit  ==  StarterUnit . option_off : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        starter_mission_locations  =  [ location . name  for  location  in  location_cache 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     if  location . parent_region . name  ==  first_mission 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     and  location . access_rule  ==  Location . access_rule ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  not  starter_mission_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # Force early unit if first mission is impossible without one 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            starter_unit  =  StarterUnit . option_any_starter_unit 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  starter_unit  !=  StarterUnit . option_off : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        first_race  =  lookup_name_to_mission [ first_mission ] . race 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  first_race  ==  SC2Race . ANY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # If the first mission is a logic-less no-build 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            mission_req_table :  Dict [ SC2Campaign ,  Dict [ str ,  MissionInfo ] ]  =  world . mission_req_table 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            races  =  get_used_races ( mission_req_table ,  world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            races . remove ( SC2Race . ANY ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  lookup_name_to_mission [ first_mission ] . race  in  races : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # The campaign's race is in (At least one mission that's not logic-less no-build exists) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                first_race  =  lookup_name_to_mission [ first_mission ] . campaign . race 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  len ( races )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # The campaign only has logic-less no-build missions. Find any other valid race 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                first_race  =  world . random . choice ( list ( races ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  first_race  !=  SC2Race . ANY : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # The race of the early unit has been chosen 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            basic_units  =  get_basic_units ( world ,  first_race ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  starter_unit  ==  StarterUnit . option_balanced : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                basic_units  =  basic_units . difference ( not_balanced_starting_units ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_mission  ==  SC2Mission . DARK_WHISPERS . mission_name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Special case - you don't have a logicless location but need an AA 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                basic_units  =  basic_units . difference ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    { ItemNames . ZEALOT ,  ItemNames . CENTURION ,  ItemNames . SENTINEL ,  ItemNames . BLOOD_HUNTER , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     ItemNames . AVENGER ,  ItemNames . IMMORTAL ,  ItemNames . ANNIHILATOR ,  ItemNames . VANGUARD } ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_mission  ==  SC2Mission . SUDDEN_STRIKE . mission_name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Special case - cliffjumpers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                basic_units  =  { ItemNames . REAPER ,  ItemNames . GOLIATH ,  ItemNames . SIEGE_TANK ,  ItemNames . VIKING ,  ItemNames . BANSHEE } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            local_basic_unit  =  sorted ( item  for  item  in  basic_units  if  item  not  in  non_local_items  and  item  not  in  excluded_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  local_basic_unit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # Drop non_local_items constraint 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                local_basic_unit  =  sorted ( item  for  item  in  basic_units  if  item  not  in  excluded_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  not  local_basic_unit : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    raise  Exception ( " Early Unit: At least one basic unit must be included " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            unit :  Item  =  add_starter_item ( world ,  excluded_items ,  local_basic_unit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            starter_items . append ( unit ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # NCO-only specific rules 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  first_mission  ==  SC2Mission . SUDDEN_STRIKE . mission_name : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                support_item :  Union [ str ,  None ]  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  unit . name  ==  ItemNames . REAPER : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    support_item  =  ItemNames . REAPER_SPIDER_MINES 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  unit . name  ==  ItemNames . GOLIATH : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    support_item  =  ItemNames . GOLIATH_JUMP_JETS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  unit . name  ==  ItemNames . SIEGE_TANK : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    support_item  =  ItemNames . SIEGE_TANK_JUMP_JETS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                elif  unit . name  ==  ItemNames . VIKING : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    support_item  =  ItemNames . VIKING_SMART_SERVOS 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  support_item  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    starter_items . append ( add_starter_item ( world ,  excluded_items ,  [ support_item ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                starter_items . append ( add_starter_item ( world ,  excluded_items ,  [ ItemNames . NOVA_JUMP_SUIT_MODULE ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                starter_items . append ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    add_starter_item ( world ,  excluded_items , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                         ItemNames . NOVA_HELLFIRE_SHOTGUN , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                         ItemNames . NOVA_PLASMA_RIFLE , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                         ItemNames . NOVA_PULSE_GRENADES 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  enabled_campaigns  ==  { SC2Campaign . NCO } : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                starter_items . append ( add_starter_item ( world ,  excluded_items ,  [ ItemNames . LIBERATOR_RAID_ARTILLERY ] ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    starter_abilities  =  get_option_value ( world ,  ' start_primary_abilities ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  isinstance ( starter_abilities ,  int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  starter_abilities : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ability_count  =  starter_abilities 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        ability_tiers  =  [ 0 ,  1 ,  3 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . random . shuffle ( ability_tiers ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  ability_count  >  3 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            ability_tiers . append ( 6 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  tier  in  ability_tiers : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            abilities  =  kerrigan_actives [ tier ] . union ( kerrigan_passives [ tier ] ) . difference ( excluded_items ,  non_local_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  abilities : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                abilities  =  kerrigan_actives [ tier ] . union ( kerrigan_passives [ tier ] ) . difference ( excluded_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  abilities : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                ability_count  - =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                starter_items . append ( add_starter_item ( world ,  excluded_items ,  list ( abilities ) ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ability_count  ==  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  starter_items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_first_mission ( mission_req_table :  Dict [ SC2Campaign ,  Dict [ str ,  MissionInfo ] ] )  - >  str :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # The first world should also be the starting world 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    campaigns  =  mission_req_table . keys ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    lowest_id  =  min ( [ campaign . id  for  campaign  in  campaigns ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    first_campaign  =  [ campaign  for  campaign  in  campaigns  if  campaign . id  ==  lowest_id ] [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    first_mission  =  list ( mission_req_table [ first_campaign ] ) [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  first_mission 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  add_starter_item ( world :  World ,  excluded_items :  Set [ str ] ,  item_list :  Sequence [ str ] )  - >  Item :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_name  =  world . random . choice ( sorted ( item_list ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    excluded_items . add ( item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item  =  create_item_with_correct_settings ( world . player ,  item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . multiworld . push_precollected ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  get_item_pool ( world :  World ,  mission_req_table :  Dict [ SC2Campaign ,  Dict [ str ,  MissionInfo ] ] ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                  starter_items :  List [ Item ] ,  excluded_items :  Set [ str ] ,  location_cache :  List [ Location ] )  - >  List [ Item ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pool :  List [ Item ]  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # For the future: goal items like Artifact Shards go here 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    locked_items  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # YAML items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    yaml_locked_items  =  get_option_value ( world ,  ' locked_items ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  not  isinstance ( yaml_locked_items ,  int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Adjust generic upgrade availability based on options 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    include_upgrades  =  get_option_value ( world ,  ' generic_upgrade_missions ' )  ==  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    upgrade_items  =  get_option_value ( world ,  ' generic_upgrade_items ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  isinstance ( upgrade_items ,  int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Include items from outside main campaigns 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_sets  =  { ' wol ' ,  ' hots ' ,  ' lotv ' } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  get_option_value ( world ,  ' nco_items ' )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  SC2Campaign . NCO  in  get_enabled_campaigns ( world ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_sets . add ( ' nco ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  get_option_value ( world ,  ' bw_items ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_sets . add ( ' bw ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  get_option_value ( world ,  ' ext_items ' ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_sets . add ( ' ext ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  allowed_quantity ( name :  str ,  data :  ItemData )  - >  int : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  name  in  excluded_items  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                or  data . type  ==  " Upgrade "  and  ( not  include_upgrades  or  name  not  in  upgrade_included_names [ upgrade_items ] )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                or  not  data . origin . intersection ( item_sets ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  name  in  progressive_if_nco  and  ' nco '  not  in  item_sets : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        elif  name  in  progressive_if_ext  and  ' ext '  not  in  item_sets : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            return  data . quantity 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  name ,  data  in  get_item_table ( ) . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  _  in  range ( allowed_quantity ( name ,  data ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item  =  create_item_with_correct_settings ( world . player ,  name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  name  in  yaml_locked_items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locked_items . append ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                pool . append ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    existing_items  =  starter_items  +  [ item  for  item  in  world . multiworld . precollected_items [ world . player ]  if  item  not  in  starter_items ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    existing_names  =  [ item . name  for  item  in  existing_items ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Check the parent item integrity, exclude items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pool [ : ]  =  [ item  for  item  in  pool  if  pool_contains_parent ( item ,  pool  +  locked_items  +  existing_items ) ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Removing upgrades for excluded items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  item_name  in  excluded_items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  item_name  in  existing_names : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        invalid_upgrades  =  get_item_upgrades ( pool ,  item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  invalid_upgrade  in  invalid_upgrades : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            pool . remove ( invalid_upgrade ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fill_pool_with_kerrigan_levels ( world ,  pool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    filtered_pool  =  filter_items ( world ,  mission_req_table ,  location_cache ,  pool ,  existing_items ,  locked_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  filtered_pool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  fill_item_pool_with_dummy_items ( self :  SC2World ,  locked_locations :  List [ str ] ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    location_cache :  List [ Location ] ,  pool :  List [ Item ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  _  in  range ( len ( location_cache )  -  len ( locked_locations )  -  len ( pool ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item  =  create_item_with_correct_settings ( self . player ,  self . get_filler_item_name ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        pool . append ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  create_item_with_correct_settings ( player :  int ,  name :  str )  - >  Item :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    data  =  get_full_item_list ( ) [ name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item  =  Item ( name ,  data . classification ,  data . code ,  player ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  pool_contains_parent ( item :  Item ,  pool :  Iterable [ Item ] ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item_data  =  get_full_item_list ( ) . get ( item . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  item_data . parent_item  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # The item has not associated parent, the item is valid 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    parent_item  =  item_data . parent_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # Check if the pool contains the parent item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  parent_item  in  [ pool_item . name  for  pool_item  in  pool ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  fill_resource_locations ( world :  World ,  locked_locations :  List [ str ] ,  location_cache :  List [ Location ] ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    Filters  the  locations  in  the  world  using  a  trash  or  Nothing  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    : param  multiworld : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    : param  player : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    : param  locked_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    : param  location_cache : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    : return : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    """ 
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    open_locations  =  [ location  for  location  in  location_cache  if  location . item  is  None ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    plando_locations  =  get_plando_locations ( world ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    resource_location_types  =  get_location_types ( world ,  LocationInclusion . option_resources ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_data  =  { sc2_location . name :  sc2_location  for  sc2_location  in  get_locations ( world ) } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  location  in  open_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # Go through the locations that aren't locked yet (early unit, etc) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  location . name  not  in  plando_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # The location is not plando'd 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sc2_location  =  location_data [ location . name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  sc2_location . type  in  resource_location_types : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_name  =  world . random . choice ( filler_items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item  =  create_item_with_correct_settings ( world . player ,  item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locked_locations . append ( location . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  place_exclusion_item ( item_name ,  location ,  locked_locations ,  player ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    item  =  create_item_with_correct_settings ( player ,  item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location . place_locked_item ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    locked_locations . append ( location . name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  fill_pool_with_kerrigan_levels ( world :  World ,  item_pool :  List [ Item ] ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    total_levels  =  get_option_value ( world ,  " kerrigan_level_item_sum " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  get_option_value ( world ,  " kerrigan_presence " )  not  in  kerrigan_unit_available  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  total_levels  ==  0  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            or  SC2Campaign . HOTS  not  in  get_enabled_campaigns ( world ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  add_kerrigan_level_items ( level_amount :  int ,  item_amount :  int ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        name  =  f " { level_amount }  Kerrigan Level " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  level_amount  >  1 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            name  + =  " s " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  _  in  range ( item_amount ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item_pool . append ( create_item_with_correct_settings ( world . player ,  name ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    sizes  =  [ 70 ,  35 ,  14 ,  10 ,  7 ,  5 ,  2 ,  1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    option  =  get_option_value ( world ,  " kerrigan_level_item_distribution " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  isinstance ( option ,  int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    assert  isinstance ( total_levels ,  int ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  option  in  ( KerriganLevelItemDistribution . option_vanilla ,  KerriganLevelItemDistribution . option_smooth ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        distribution  =  [ 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  option  ==  KerriganLevelItemDistribution . option_vanilla : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            distribution  =  [ 32 ,  0 ,  0 ,  1 ,  3 ,  0 ,  0 ,  0 ,  1 ,  1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else :  # Smooth 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            distribution  =  [ 0 ,  0 ,  0 ,  1 ,  1 ,  2 ,  2 ,  2 ,  1 ,  1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  tier  in  range ( len ( distribution ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            add_kerrigan_level_items ( tier  +  1 ,  distribution [ tier ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        size  =  sizes [ option  -  2 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        round_func :  Callable [ [ float ] ,  int ]  =  round 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  total_levels  >  70 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            round_func  =  floor 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            round_func  =  ceil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        add_kerrigan_level_items ( size ,  round_func ( float ( total_levels )  /  size ) )