2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
									
										
										
										
											2020-08-14 00:34:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  typing  
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								import  collections  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  itertools  
						 
					
						
							
								
									
										
										
										
											2021-12-21 22:55:10 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  collections  import  Counter ,  deque  
						 
					
						
							
								
									
										
										
										
											2021-12-20 18:14:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  BaseClasses  import  CollectionState ,  Location ,  LocationProgressType ,  MultiWorld ,  Item  
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								from  worlds . AutoWorld  import  call_all  
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  FillError ( RuntimeError ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pass 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-04 15:14:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  sweep_from_pool ( base_state :  CollectionState ,  itempool :  typing . Sequence [ Item ]  =  tuple ( ) ) :  
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    new_state  =  base_state . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  item  in  itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        new_state . collect ( item ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    new_state . sweep_for_events ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  new_state 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  fill_restrictive ( world :  MultiWorld ,  base_state :  CollectionState ,  locations :  typing . List [ Location ] ,  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                     itempool :  typing . List [ Item ] ,  single_player_placement = False ,  lock = False ) : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 17:47:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    unplaced_items  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    placements :  typing . List [ Location ]  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 17:47:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 18:20:01 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    swapped_items  =  Counter ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    reachable_items :  typing . Dict [ int ,  deque ]  =  { } 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 17:47:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  item  in  itempool : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-21 22:55:10 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        reachable_items . setdefault ( item . player ,  deque ( ) ) . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-18 20:47:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    while  any ( reachable_items . values ( ) )  and  locations : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        # grab one item per player 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        items_to_place  =  [ items . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                          for  items  in  reachable_items . values ( )  if  items ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  item  in  items_to_place : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            itempool . remove ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-31 14:23:01 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        maximum_exploration_state  =  sweep_from_pool ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            base_state ,  itempool  +  unplaced_items ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        has_beaten_game  =  world . has_beaten_game ( maximum_exploration_state ) 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-18 20:47:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  item_to_place  in  items_to_place : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spot_to_fill :  typing . Optional [ Location ]  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-17 00:17:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  world . accessibility [ item_to_place . player ]  ==  ' minimal ' : 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                perform_access_check  =  not  world . has_beaten_game ( maximum_exploration_state , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                 item_to_place . player )  if  single_player_placement  else  not  has_beaten_game 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2019-12-18 20:47:35 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                perform_access_check  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  i ,  location  in  enumerate ( locations ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ( not  single_player_placement  or  location . player  ==  item_to_place . player )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        and  location . can_fill ( maximum_exploration_state ,  item_to_place ,  perform_access_check ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # poping by index is faster than removing by content, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    spot_to_fill  =  locations . pop ( i ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # skipping a scan for the element 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # we filled all reachable spots. 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                # try swapping this item with previously placed items 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                for  ( i ,  location )  in  enumerate ( placements ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    placed_item  =  location . item 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-28 11:57:48 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # Unplaceable items can sometimes be swapped infinitely. Limit the 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 18:23:19 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # number of times we will swap an individual item to prevent this 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    swap_count  =  swapped_items [ placed_item . player , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                               placed_item . name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  swap_count  >  1 : 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 18:14:50 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    location . item  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    placed_item . location  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    swap_state  =  sweep_from_pool ( base_state ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  ( not  single_player_placement  or  location . player  ==  item_to_place . player )  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            and  location . can_fill ( swap_state ,  item_to_place ,  perform_access_check ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 21:40:08 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        # Verify that placing this item won't reduce available locations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        prev_state  =  swap_state . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        prev_state . collect ( placed_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        prev_loc_count  =  len ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            world . get_reachable_locations ( prev_state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        swap_state . collect ( item_to_place ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        new_loc_count  =  len ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            world . get_reachable_locations ( swap_state ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  new_loc_count  > =  prev_loc_count : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            # Add this item to the existing placement, and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            # add the old item to the back of the queue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            spot_to_fill  =  placements . pop ( i ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            swap_count  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            swapped_items [ placed_item . player , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          placed_item . name ]  =  swap_count 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            reachable_items [ placed_item . player ] . appendleft ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                placed_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            itempool . append ( placed_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # Item can't be placed here, restore original item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    location . item  =  placed_item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    placed_item . location  =  location 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  spot_to_fill  is  None : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-29 09:20:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # Can't place this item, move on to the next 
							 
						 
					
						
							
								
									
										
										
										
											2021-12-20 17:47:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    unplaced_items . append ( item_to_place ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-29 09:20:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    continue 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-18 17:27:31 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . push_item ( spot_to_fill ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spot_to_fill . locked  =  lock 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            placements . append ( spot_to_fill ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-31 14:23:01 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            spot_to_fill . event  =  item_to_place . advancement 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-29 09:20:04 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  len ( unplaced_items )  >  0  and  len ( locations )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # There are leftover unplaceable items and locations that won't accept them 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logging . warning ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f ' Not all items placed. Game beatable anyway. (Could not place  { unplaced_items } ) ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            raise  FillError ( f ' No more spots to place  { unplaced_items } , locations  { locations }  are invalid.  ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            f ' Already placed  { len ( placements ) } :  { " ,  " . join ( str ( place )  for  place  in  placements ) } ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2019-12-14 17:47:36 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    itempool . extend ( unplaced_items ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  distribute_items_restrictive ( world :  MultiWorld ) :  
						 
					
						
							
								
									
										
										
										
											2022-01-27 09:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_locations  =  sorted ( world . get_unfilled_locations ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 09:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    itempool  =  sorted ( world . itempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . random . shuffle ( itempool ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    progitempool  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-15 16:52:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    nonexcludeditempool  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    localrestitempool  =  { player :  [ ]  for  player  in  range ( 1 ,  world . players  +  1 ) } 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    nonlocalrestitempool  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    restitempool  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-27 09:25:42 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  item  in  itempool : 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-15 16:52:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  item . advancement : 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            progitempool . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-23 08:55:44 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        elif  item . never_exclude :   # this only gets nonprogression items which should not appear in excluded locations 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-15 16:52:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            nonexcludeditempool . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-17 00:17:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        elif  item . name  in  world . local_items [ item . player ] . value : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-30 09:57:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            localrestitempool [ item . player ] . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-17 00:17:54 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        elif  item . name  in  world . non_local_items [ item . player ] . value : 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            nonlocalrestitempool . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            restitempool . append ( item ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    call_all ( world ,  " fill_hook " ,  progitempool ,  nonexcludeditempool , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								             localrestitempool ,  nonlocalrestitempool ,  restitempool ,  fill_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 05:19:33 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    locations :  typing . Dict [ LocationProgressType ,  typing . List [ Location ] ]  =  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-02 16:29:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        loc_type :  [ ]  for  loc_type  in  LocationProgressType } 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-21 20:34:59 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  loc  in  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        locations [ loc . progress_type ] . append ( loc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    prioritylocations  =  locations [ LocationProgressType . PRIORITY ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    defaultlocations  =  locations [ LocationProgressType . DEFAULT ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    excludedlocations  =  locations [ LocationProgressType . EXCLUDED ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_restrictive ( world ,  world . state ,  prioritylocations ,  progitempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  prioritylocations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        defaultlocations  =  prioritylocations  +  defaultlocations 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 09:03:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  progitempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_restrictive ( world ,  world . state ,  defaultlocations ,  progitempool ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-28 09:29:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  progitempool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-21 20:34:59 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FillError ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f ' Not enough locations for progress items. There are  { len ( progitempool ) }  more items than locations ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-07-15 16:52:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  nonexcludeditempool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . random . shuffle ( defaultlocations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # needs logical fill to not conflict with local items 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-31 14:23:01 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        fill_restrictive ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world ,  world . state ,  defaultlocations ,  nonexcludeditempool ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-28 09:29:29 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  nonexcludeditempool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FillError ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f ' Not enough locations for non-excluded items. There are  { len ( nonexcludeditempool ) }  more items than locations ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    defaultlocations  =  defaultlocations  +  excludedlocations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . random . shuffle ( defaultlocations ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-15 16:52:30 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-30 09:57:25 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  any ( localrestitempool . values ( ) ) :   # we need to make sure some fills are limited to certain worlds 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-07 12:43:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        local_locations  =  { player :  [ ]  for  player  in  world . player_ids } 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  location  in  defaultlocations : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-07 12:43:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            local_locations [ location . player ] . append ( location ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  player_locations  in  local_locations . values ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . random . shuffle ( player_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-07 12:43:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-07-09 16:16:31 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  player ,  items  in  localrestitempool . items ( ) :   # items already shuffled 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-07 12:43:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            player_local_locations  =  local_locations [ player ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            for  item_to_place  in  items : 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-07 12:43:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  not  player_local_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    logging . warning ( f " Ran out of local locations for player  { player } ,  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    f " cannot place  { item_to_place } . " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                spot_to_fill  =  player_local_locations . pop ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                world . push_item ( spot_to_fill ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                defaultlocations . remove ( spot_to_fill ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-06-04 03:30:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    for  item_to_place  in  nonlocalrestitempool : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  i ,  location  in  enumerate ( defaultlocations ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . player  !=  item_to_place . player : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                world . push_item ( defaultlocations . pop ( i ) ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . warning ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f " Could not place non_local_item  { item_to_place }  among  { defaultlocations } , tossing. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-30 22:20:44 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . random . shuffle ( defaultlocations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    restitempool ,  defaultlocations  =  fast_fill ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world ,  restitempool ,  defaultlocations ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-24 09:52:12 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    unplaced  =  progitempool  +  restitempool 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    unfilled  =  [ location . name  for  location  in  defaultlocations ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-08-01 06:22:59 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  unplaced  or  unfilled : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        logging . warning ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            f ' Unplaced items( { len ( unplaced ) } ):  { unplaced }  - Unfilled Locations( { len ( unfilled ) } ):  { unfilled } ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-24 00:18:00 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        items_counter  =  Counter ( [ location . item . player  for  location  in  world . get_locations ( ) ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        locations_counter  =  Counter ( [ location . player  for  location  in  world . get_locations ( ) ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        items_counter . update ( [ item . player  for  item  in  unplaced ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        locations_counter . update ( [ location . player  for  location  in  unfilled ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        print_data  =  { " items " :  items_counter ,  " locations " :  locations_counter } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        logging . info ( f ' Per-Player counts:  { print_data } ) ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  fast_fill ( world :  MultiWorld ,  item_pool :  typing . List ,  fill_locations :  typing . List )  - >  typing . Tuple [  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    typing . List ,  typing . List ] : 
							 
						 
					
						
							
								
									
										
										
										
											2020-08-14 00:34:41 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    placing  =  min ( len ( item_pool ) ,  len ( fill_locations ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  item ,  location  in  zip ( item_pool ,  fill_locations ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . push_item ( location ,  item ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    return  item_pool [ placing : ] ,  fill_locations [ placing : ] 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-13 07:57:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  flood_items ( world :  MultiWorld ) :  
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-14 07:01:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . random . shuffle ( world . itempool ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								    itempool  =  world . itempool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    progress_done  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # sweep once to pick up preplaced items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . state . sweep_for_events ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # fill world from top of itempool while we can 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  not  progress_done : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        location_list  =  world . get_unfilled_locations ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-14 07:01:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . random . shuffle ( location_list ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        spot_to_fill  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  location_list : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . can_fill ( world . state ,  itempool [ 0 ] ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                spot_to_fill  =  location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  spot_to_fill : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item  =  itempool . pop ( 0 ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . push_item ( spot_to_fill ,  item ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # ran out of spots, check if we need to step in and correct things 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  len ( world . get_reachable_locations ( ) )  ==  len ( world . get_locations ( ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            progress_done  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # need to place a progress item instead of an already placed item, find candidate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        candidate_item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . advancement : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                candidate_item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  world . unlocks_new_location ( item ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # we might be in a situation where all new locations require multiple items to reach. If that is the case, just place any advancement item we've found and continue trying 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  item_to_place  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  candidate_item_to_place  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_to_place  =  candidate_item_to_place 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                raise  FillError ( ' No more progress items left to place. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # find item to replace with progress item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        location_list  =  world . get_reachable_locations ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-14 07:01:51 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        world . random . shuffle ( location_list ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								        for  location  in  location_list : 
							 
						 
					
						
							
								
									
										
										
										
											2021-08-10 09:47:28 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . item  is  not  None  and  not  location . item . advancement : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                # safe to replace 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                replace_item  =  location . item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                replace_item . location  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                itempool . append ( replace_item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                world . push_item ( location ,  item_to_place ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                itempool . remove ( item_to_place ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2019-04-18 11:23:24 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-12-23 11:28:42 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-13 07:57:34 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  balance_multiworld_progression ( world :  MultiWorld ) :  
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    balanceable_players  =  { player  for  player  in  range ( 1 ,  world . players  +  1 )  if  world . progression_balancing [ player ] } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  balanceable_players : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        logging . info ( ' Skipping multiworld progression balancing. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    else : 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-30 20:17:04 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        logging . info ( f ' Balancing multiworld progression for  { len ( balanceable_players ) }  Players. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        state  =  CollectionState ( world ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        checked_locations  =  set ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        unchecked_locations  =  set ( world . get_locations ( ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-02-17 06:07:11 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        reachable_locations_count  =  { player :  0  for  player  in  world . get_all_ids ( ) } 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-17 22:08:28 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        def  get_sphere_locations ( sphere_state ,  locations ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sphere_state . sweep_for_events ( key_only = True ,  locations = locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            return  { loc  for  loc  in  locations  if  sphere_state . can_reach ( loc ) } 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        while  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            sphere_locations  =  get_sphere_locations ( state ,  unchecked_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  location  in  sphere_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                unchecked_locations . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                reachable_locations_count [ location . player ]  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  checked_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                threshold  =  max ( reachable_locations_count . values ( ) )  -  20 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                balancing_players  =  { player  for  player ,  reachables  in  reachable_locations_count . items ( )  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                     reachables  <  threshold  and  player  in  balanceable_players } 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  balancing_players : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    balancing_state  =  state . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    balancing_unchecked_locations  =  unchecked_locations . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    balancing_reachables  =  reachable_locations_count . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    balancing_sphere  =  sphere_locations . copy ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    candidate_items  =  collections . defaultdict ( set ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    while  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        for  location  in  balancing_sphere : 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            if  location . event : 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                balancing_state . collect ( location . item ,  True ,  location ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                player  =  location . item . player 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                # only replace items that end up in another player's world 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                if  ( not  location . locked  and 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-19 20:19:07 -07:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                        player  in  balancing_players  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        location . player  !=  player  and 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                        location . progress_type  !=  LocationProgressType . PRIORITY ) : 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                    candidate_items [ player ] . add ( location ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        balancing_sphere  =  get_sphere_locations ( balancing_state ,  balancing_unchecked_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        for  location  in  balancing_sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            balancing_unchecked_locations . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            balancing_reachables [ location . player ]  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  world . has_beaten_game ( balancing_state )  or  all ( 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                reachables  > =  threshold  for  reachables  in  balancing_reachables . values ( ) ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        elif  not  balancing_sphere : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            raise  RuntimeError ( ' Not all required items reachable. Something went terribly wrong here. ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    unlocked_locations  =  collections . defaultdict ( set ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    for  l  in  unchecked_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  l  not  in  balancing_unchecked_locations : 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            unlocked_locations [ l . player ] . add ( l ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    items_to_replace  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    for  player  in  balancing_players : 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        locations_to_test  =  unlocked_locations [ player ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        items_to_test  =  candidate_items [ player ] 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        while  items_to_test : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            testing  =  items_to_test . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            reducing_state  =  state . copy ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            for  location  in  itertools . chain ( ( l  for  l  in  items_to_replace  if  l . item . player  ==  player ) , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                            items_to_test ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                reducing_state . collect ( location . item ,  True ,  location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            reducing_state . sweep_for_events ( locations = locations_to_test ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            if  world . has_beaten_game ( balancing_state ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                if  not  world . has_beaten_game ( reducing_state ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    items_to_replace . append ( testing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                reduced_sphere  =  get_sphere_locations ( reducing_state ,  locations_to_test ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                if  reachable_locations_count [ player ]  +  len ( reduced_sphere )  <  threshold : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    items_to_replace . append ( testing ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    replaced_items  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    # sort then shuffle to maintain deterministic behaviour, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    # while allowing use of set for better algorithm growth behaviour elsewhere 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    replacement_locations  =  sorted ( l  for  l  in  checked_locations  if  not  l . event  and  not  l . locked ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    world . random . shuffle ( replacement_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    items_to_replace . sort ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    world . random . shuffle ( items_to_replace ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    while  replacement_locations  and  items_to_replace : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        old_location  =  items_to_replace . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        for  new_location  in  replacement_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            if  new_location . can_fill ( state ,  old_location . item ,  False )  and  \
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                    old_location . can_fill ( state ,  new_location . item ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                replacement_locations . remove ( new_location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                swap_location_item ( old_location ,  new_location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                logging . debug ( f " Progression balancing moved  { new_location . item }  to  { new_location } ,  " 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                              f " displacing  { old_location . item }  into  { old_location } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                state . collect ( new_location . item ,  True ,  new_location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                replaced_items  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            logging . warning ( f " Could not Progression Balance  { old_location . item } " ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  replaced_items : 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        unlocked  =  { fresh  for  player  in  balancing_players  for  fresh  in  unlocked_locations [ player ] } 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        for  location  in  get_sphere_locations ( state ,  unlocked ) : 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            unchecked_locations . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            reachable_locations_count [ location . player ]  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            sphere_locations . add ( location ) 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  location  in  sphere_locations : 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  location . event : 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    state . collect ( location . item ,  True ,  location ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-03-04 08:10:30 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            checked_locations  | =  sphere_locations 
							 
						 
					
						
							
								
									
										
										
										
											2020-05-18 03:54:29 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  world . has_beaten_game ( state ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  not  sphere_locations : 
							 
						 
					
						
							
								
									
										
										
										
											2021-07-24 01:42:00 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                logging . warning ( " Progression Balancing ran out of paths. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-04 15:14:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 13:35:48 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  swap_location_item ( location_1 :  Location ,  location_2 :  Location ,  check_locked = True ) :  
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    """ Swaps Items of locations. Does NOT swap flags like shop_slot or locked, but does swap event """ 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 13:35:48 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  check_locked : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  location_1 . locked : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logging . warning ( f " Swapping  { location_1 } , which is marked as locked. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  location_2 . locked : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logging . warning ( f " Swapping  { location_2 } , which is marked as locked. " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_2 . item ,  location_1 . item  =  location_1 . item ,  location_2 . item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_1 . item . location  =  location_1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    location_2 . item . location  =  location_2 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-05 08:07:12 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    location_1 . event ,  location_2 . event  =  location_2 . event ,  location_1 . event 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-15 06:29:57 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  distribute_planned ( world :  MultiWorld ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  warn ( warning :  str ,  force ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  force  in  [ True ,  ' fail ' ,  ' failure ' ,  ' none ' ,  False ,  ' warn ' ,  ' warning ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            logging . warning ( f ' { warning } ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            logging . debug ( f ' { warning } ' ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 13:35:48 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    def  failed ( warning :  str ,  force ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  force  in  [ True ,  ' fail ' ,  ' failure ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  Exception ( warning ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            warn ( warning ,  force ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-11 13:35:48 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-02 03:45:37 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # TODO: remove. Preferably by implementing key drop 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    from  worlds . alttp . Regions  import  key_drop_data 
							 
						 
					
						
							
								
									
										
										
										
											2021-02-20 02:30:55 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world_name_lookup  =  world . world_name_lookup 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-04 15:14:20 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    plando_blocks  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    player_ids  =  set ( world . player_ids ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  player  in  player_ids : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  block  in  world . plando_items [ player ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            block [ ' player ' ]  =  player 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ' force '  not  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' force ' ]  =  ' silent ' 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ' from_pool '  not  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' from_pool ' ]  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ' world '  not  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' world ' ]  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            items  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  " items "  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                items  =  block [ " items " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ' count '  not  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    block [ ' count ' ]  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  " item "  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                items  =  block [ " item " ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  ' count '  not  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    block [ ' count ' ]  =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                failed ( " You must specify at least one item to place items with plando. " ,  block [ ' force ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  isinstance ( items ,  dict ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_list  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  key ,  value  in  items . items ( ) : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  value  is  True : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        value  =  world . itempool . count ( world . worlds [ player ] . create_item ( key ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    item_list  + =  [ key ]  *  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                items  =  item_list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  isinstance ( items ,  str ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                items  =  [ items ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            block [ ' items ' ]  =  items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locations  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  ' location '  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  =  block [ ' location ' ]   # just allow 'location' to keep old yamls compatible 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            elif  ' locations '  in  block : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  =  block [ ' locations ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  isinstance ( locations ,  str ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  =  [ locations ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  isinstance ( locations ,  dict ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location_list  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  key ,  value  in  locations . items ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    location_list  + =  [ key ]  *  value 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  =  location_list 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  isinstance ( locations ,  str ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                locations  =  [ locations ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            block [ ' locations ' ]  =  locations 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  block [ ' count ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                block [ ' count ' ]  =  ( min ( len ( block [ ' items ' ] ) ,  len ( block [ ' locations ' ] ) )  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                  len ( block [ ' locations ' ] )  >  0  else  len ( block [ ' items ' ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  isinstance ( block [ ' count ' ] ,  int ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' count ' ]  =  { ' min ' :  block [ ' count ' ] ,  ' max ' :  block [ ' count ' ] } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ' min '  not  in  block [ ' count ' ] : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' count ' ] [ ' min ' ]  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  ' max '  not  in  block [ ' count ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2022-02-22 09:49:01 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                block [ ' count ' ] [ ' max ' ]  =  ( min ( len ( block [ ' items ' ] ) ,  len ( block [ ' locations ' ] ) )  if 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                         len ( block [ ' locations ' ] )  >  0  else  len ( block [ ' items ' ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  block [ ' count ' ] [ ' max ' ]  >  len ( block [ ' items ' ] ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                count  =  block [ ' count ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                failed ( f " Plando count  { count }  greater than items specified " ,  block [ ' force ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                block [ ' count ' ]  =  len ( block [ ' items ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  block [ ' count ' ] [ ' max ' ]  >  len ( block [ ' locations ' ] )  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                count  =  block [ ' count ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                failed ( f " Plando count  { count }  greater than locations specified " ,  block [ ' force ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                block [ ' count ' ]  =  len ( block [ ' locations ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            block [ ' count ' ] [ ' target ' ]  =  world . random . randint ( block [ ' count ' ] [ ' min ' ] ,  block [ ' count ' ] [ ' max ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  block [ ' count ' ] [ ' target ' ]  >  0 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                plando_blocks . append ( block ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # shuffle, but then sort blocks by number of locations minus number of items, 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # so less-flexible blocks get priority 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    world . random . shuffle ( plando_blocks ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    plando_blocks . sort ( key = lambda  block :  ( len ( block [ ' locations ' ] )  -  block [ ' count ' ] [ ' target ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          if  len ( block [ ' locations ' ] )  >  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                          else  len ( world . get_unfilled_locations ( player ) )  -  block [ ' count ' ] [ ' target ' ] ) ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    for  placement  in  plando_blocks : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        player  =  placement [ ' player ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-14 23:42:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        try : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            target_world  =  placement [ ' world ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            locations  =  placement [ ' locations ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            items  =  placement [ ' items ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            maxcount  =  placement [ ' count ' ] [ ' target ' ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            from_pool  =  placement [ ' from_pool ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  target_world  is  False  or  world . players  ==  1 :   # target own world 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  { player } 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  target_world  is  True :   # target any worlds besides own 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  set ( world . player_ids )  -  { player } 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  target_world  is  None :   # target all worlds 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  set ( world . player_ids ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  type ( target_world )  ==  list :   # list of target worlds 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  listed_world  in  target_world : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  listed_world  not  in  world_name_lookup : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        failed ( f " Cannot place item to  { target_world } ' s world as that world does not exist. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                               placement [ ' force ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-14 23:42:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    worlds . append ( world_name_lookup [ listed_world ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                worlds  =  set ( worlds ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            elif  type ( target_world )  ==  int :   # target world by slot number 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  target_world  not  in  range ( 1 ,  world . players  +  1 ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    failed ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        f " Cannot place item in world  { target_world }  as it is not in range of (1,  { world . players } ) " , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        placement [ ' force ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-05 09:53:52 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  { target_world } 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            else :   # target world by slot name 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  target_world  not  in  world_name_lookup : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    failed ( f " Cannot place item to  { target_world } ' s world as that world does not exist. " , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                           placement [ ' force ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-05 09:53:52 -08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                worlds  =  { world_name_lookup [ target_world ] } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            candidates  =  list ( location  for  location  in  world . get_unfilled_locations_for_players ( locations , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                                                                                worlds ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . random . shuffle ( candidates ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . random . shuffle ( items ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            count  =  0 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            err  =  [ ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            successful_pairs  =  [ ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  item_name  in  items : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item  =  world . worlds [ player ] . create_item ( item_name ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                for  location  in  reversed ( candidates ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    if  location  in  key_drop_data : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        warn ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            f " Can ' t place  ' { item_name } '  at  ' { placement . location } ' , as key drop shuffle locations are not supported yet. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        continue 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    if  not  location . item : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        if  location . item_rule ( item ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            if  location . can_fill ( world . state ,  item ,  False ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                successful_pairs . append ( [ item ,  location ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                candidates . remove ( location ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                count  =  count  +  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                                err . append ( f " Can ' t place item at  { location }  due to fill condition not met. " ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            err . append ( f " { item_name }  not allowed at  { location } . " ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    else : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        err . append ( f " Cannot place  { item_name }  into already filled location  { location } . " ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  count  ==  maxcount : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  count  <  placement [ ' count ' ] [ ' min ' ] : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                err  =  "   " . join ( err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                m  =  placement [ ' count ' ] [ ' min ' ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                failed ( 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    f " Plando block failed to place  { m  -  count }  of  { m }  item(s) for  { world . player_name [ player ] } , error(s):  { err } " , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    placement [ ' force ' ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  ( item ,  location )  in  successful_pairs : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                world . push_item ( location ,  item ,  collect = False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . event  =  True   # flag location to be checked during fill 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . locked  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                logging . debug ( f " Plando placed  { item }  at  { location } " ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  from_pool : 
							 
						 
					
						
							
								
									
										
										
										
											2021-06-14 23:42:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                    try : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                        world . itempool . remove ( item ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    except  ValueError : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                        warn ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                            f " Could not remove  { item }  from pool for  { world . player_name [ player ] }  as it ' s already missing from it. " , 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-22 15:03:13 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                            placement [ ' force ' ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-06-14 23:42:13 +02:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        except  Exception  as  e : 
							 
						 
					
						
							
								
									
										
										
										
											2022-01-20 13:34:17 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  Exception ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                f " Error running plando for player  { player }  ( { world . player_name [ player ] } ) " )  from  e