2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								import  random  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  logging  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								class  FillError ( RuntimeError ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    pass 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  distribute_items_cutoff ( world ,  cutoffrate = 0.33 ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get list of locations to fill in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fill_locations  =  world . get_unfilled_locations ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( world . itempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    itempool  =  world . itempool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    total_advancement_items  =  len ( [ item  for  item  in  itempool  if  item . advancement ] ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    placed_advancement_items  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    progress_done  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    advancement_placed  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # sweep once to pick up preplaced items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . state . sweep_for_events ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  itempool  and  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        candidate_item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  advancement_placed  or  ( progress_done  and  ( item . advancement  or  item . priority ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . advancement : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                candidate_item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  world . unlocks_new_location ( item ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    placed_advancement_items  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  item_to_place  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # check if we can reach all locations and that is why we find no new locations to place 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  progress_done  and  len ( world . get_reachable_locations ( ) )  ==  len ( world . get_locations ( ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                progress_done  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # check if we have now placed all advancement items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  progress_done : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                advancement_placed  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # 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  candidate_item_to_place  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_to_place  =  candidate_item_to_place 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                placed_advancement_items  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # we placed all available progress items. Maybe the game can be beaten anyway? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    logging . getLogger ( ' ' ) . warning ( ' Not all locations reachable. Game beatable anyway. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    progress_done  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    continue 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        spot_to_fill  =  None 
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        for  location  in  fill_locations  if  placed_advancement_items  /  total_advancement_items  <  cutoffrate  else  reversed ( fill_locations ) : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . can_fill ( world . state ,  item_to_place ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                spot_to_fill  =  location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  spot_to_fill  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # we filled all reachable spots. Maybe the game can be beaten anyway? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                logging . getLogger ( ' ' ) . warning ( ' Not all items placed. Game beatable anyway. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FillError ( ' No more spots to place  %s '  %  item_to_place ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . push_item ( spot_to_fill ,  item_to_place ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itempool . remove ( item_to_place ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_locations . remove ( spot_to_fill ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . getLogger ( ' ' ) . debug ( ' Unplaced items:  %s  - Unfilled Locations:  %s ' ,  [ item . name  for  item  in  itempool ] ,  [ location . name  for  location  in  fill_locations ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  distribute_items_staleness ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get list of locations to fill in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fill_locations  =  world . get_unfilled_locations ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( world . itempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    itempool  =  world . itempool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    progress_done  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    advancement_placed  =  False 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # sweep once to pick up preplaced items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    world . state . sweep_for_events ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  itempool  and  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        candidate_item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_to_place  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  advancement_placed  or  ( progress_done  and  ( item . advancement  or  item . priority ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  item . advancement : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                candidate_item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  world . unlocks_new_location ( item ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    item_to_place  =  item 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  item_to_place  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # check if we can reach all locations and that is why we find no new locations to place 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  progress_done  and  len ( world . get_reachable_locations ( ) )  ==  len ( world . get_locations ( ) ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                progress_done  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # check if we have now placed all advancement items 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  progress_done : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                advancement_placed  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # 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  candidate_item_to_place  is  not  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                item_to_place  =  candidate_item_to_place 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # we placed all available progress items. Maybe the game can be beaten anyway? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    logging . getLogger ( ' ' ) . warning ( ' Not all locations reachable. Game beatable anyway. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    progress_done  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    continue 
							 
						 
					
						
							
								
									
										
										
										
											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 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        spot_to_fill  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # increase likelyhood of skipping a location if it has been found stale 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  not  progress_done  and  random . randint ( 0 ,  location . staleness_count )  >  2 : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                continue 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . can_fill ( world . state ,  item_to_place ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                spot_to_fill  =  location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            else : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                location . staleness_count  + =  1 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        # might have skipped too many locations due to potential staleness. Do not check for staleness now to find a candidate 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  spot_to_fill  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            for  location  in  fill_locations : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								                if  location . can_fill ( world . state ,  item_to_place ) : 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								                    spot_to_fill  =  location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    break 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  spot_to_fill  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # we filled all reachable spots. Maybe the game can be beaten anyway? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                logging . getLogger ( ' ' ) . warning ( ' Not all items placed. Game beatable anyway. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FillError ( ' No more spots to place  %s '  %  item_to_place ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . push_item ( spot_to_fill ,  item_to_place ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        itempool . remove ( item_to_place ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_locations . remove ( spot_to_fill ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . getLogger ( ' ' ) . debug ( ' Unplaced items:  %s  - Unfilled Locations:  %s ' ,  [ item . name  for  item  in  itempool ] ,  [ location . name  for  location  in  fill_locations ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								def  fill_restrictive ( world ,  base_state ,  locations ,  itempool ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    def  sweep_from_pool ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        new_state  =  base_state . copy ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  item  in  itempool : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            new_state . collect ( item ,  True ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        new_state . sweep_for_events ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        return  new_state 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  itempool  and  locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_to_place  =  itempool . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        maximum_exploration_state  =  sweep_from_pool ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-18 20:43:37 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        perform_access_check  =  True 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-05 22:08:36 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        if  world . check_beatable_only : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            perform_access_check  =  not  world . has_beaten_game ( maximum_exploration_state ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        spot_to_fill  =  None 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  locations : 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-02 00:39:53 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            if  location . can_fill ( maximum_exploration_state ,  item_to_place ,  perform_access_check ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                spot_to_fill  =  location 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        if  spot_to_fill  is  None : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            # we filled all reachable spots. Maybe the game can be beaten anyway? 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  world . can_beat_game ( ) : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                if  not  world . check_beatable_only : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                    logging . getLogger ( ' ' ) . warning ( ' Not all items placed. Game beatable anyway. ' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                break 
							 
						 
					
						
							
								
									
										
										
										
											2018-01-27 16:21:32 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								            raise  FillError ( ' No more spots to place  %s '  %  item_to_place ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . push_item ( spot_to_fill ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        locations . remove ( spot_to_fill ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        spot_to_fill . event  =  True 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  distribute_items_restrictive ( world ,  gftower_trash_count = 0 ,  fill_locations = None ) :  
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    # If not passed in, then get a shuffled list of locations to fill in 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    if  not  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        fill_locations  =  world . get_unfilled_locations ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( world . itempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    progitempool  =  [ item  for  item  in  world . itempool  if  item . advancement ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    prioitempool  =  [ item  for  item  in  world . itempool  if  not  item . advancement  and  item . priority ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    restitempool  =  [ item  for  item  in  world . itempool  if  not  item . advancement  and  not  item . priority ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # fill in gtower locations with trash first 
							 
						 
					
						
							
								
									
										
										
										
											2018-02-24 22:42:18 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    if  world . ganonstower_vanilla : 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-09 04:46:59 -06:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								        gtower_locations  =  [ location  for  location  in  fill_locations  if  ' Ganons Tower '  in  location . name ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . shuffle ( gtower_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        trashcnt  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        while  gtower_locations  and  restitempool  and  trashcnt  <  gftower_trash_count : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            spot_to_fill  =  gtower_locations . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            item_to_place  =  restitempool . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            world . push_item ( spot_to_fill ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            fill_locations . remove ( spot_to_fill ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            trashcnt  + =  1 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fill_locations . reverse ( ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    fill_restrictive ( world ,  world . state ,  fill_locations ,  progitempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( fill_locations ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fast_fill ( world ,  prioitempool ,  fill_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    fast_fill ( world ,  restitempool ,  fill_locations ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-12-17 00:25:46 -05:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								    logging . getLogger ( ' ' ) . debug ( ' Unplaced items:  %s  - Unfilled Locations:  %s ' ,  [ item . name  for  item  in  progitempool  +  prioitempool  +  restitempool ] ,  [ location . name  for  location  in  fill_locations ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 16:34:46 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								def  fast_fill ( world ,  item_pool ,  fill_locations ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    while  item_pool  and  fill_locations : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        spot_to_fill  =  fill_locations . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        item_to_place  =  item_pool . pop ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        world . push_item ( spot_to_fill ,  item_to_place ,  False ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-04 14:23:57 -04:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-10-15 15:35:45 -04:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								def  flood_items ( world ) :  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    # get items to distribute 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    random . shuffle ( world . itempool ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								    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 ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . shuffle ( location_list ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        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 ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        random . shuffle ( location_list ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								        for  location  in  location_list : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								            if  location . item  is  not  None  and  not  location . item . advancement  and  not  location . item . priority  and  not  location . item . key : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								                # 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