Core: Actually take item from pool when plandoing from_pool (#2420)
* Actually take item from pool when plandoing from_pool * Remove the awkward index thing * oops left a comment in * there wasn't a line break here before * Only remove if actually found, check against player number * oops * Go back to index based system so we can just remove at the end * Comment * Fix error on None * Update Fill.py Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com> --------- Co-authored-by: Exempt-Medic <60412657+Exempt-Medic@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									30b414429f
								
							
						
					
					
						commit
						1371c63a8d
					
				
							
								
								
									
										37
									
								
								Fill.py
								
								
								
								
							
							
						
						
									
										37
									
								
								Fill.py
								
								
								
								
							| 
						 | 
				
			
			@ -978,15 +978,32 @@ def distribute_planned(multiworld: MultiWorld) -> None:
 | 
			
		|||
            multiworld.random.shuffle(items)
 | 
			
		||||
            count = 0
 | 
			
		||||
            err: typing.List[str] = []
 | 
			
		||||
            successful_pairs: typing.List[typing.Tuple[Item, Location]] = []
 | 
			
		||||
            successful_pairs: typing.List[typing.Tuple[int, Item, Location]] = []
 | 
			
		||||
            claimed_indices: typing.Set[typing.Optional[int]] = set()
 | 
			
		||||
            for item_name in items:
 | 
			
		||||
                index_to_delete: typing.Optional[int] = None
 | 
			
		||||
                if from_pool:
 | 
			
		||||
                    try:
 | 
			
		||||
                        # If from_pool, try to find an existing item with this name & player in the itempool and use it
 | 
			
		||||
                        index_to_delete, item = next(
 | 
			
		||||
                            (i, item) for i, item in enumerate(multiworld.itempool)
 | 
			
		||||
                            if item.player == player and item.name == item_name and i not in claimed_indices
 | 
			
		||||
                        )
 | 
			
		||||
                    except StopIteration:
 | 
			
		||||
                        warn(
 | 
			
		||||
                        f"Could not remove {item_name} from pool for {multiworld.player_name[player]} as it's already missing from it.",
 | 
			
		||||
                        placement['force'])
 | 
			
		||||
                        item = multiworld.worlds[player].create_item(item_name)
 | 
			
		||||
                else:
 | 
			
		||||
                    item = multiworld.worlds[player].create_item(item_name)
 | 
			
		||||
 | 
			
		||||
                for location in reversed(candidates):
 | 
			
		||||
                    if (location.address is None) == (item.code is None):  # either both None or both not None
 | 
			
		||||
                        if not location.item:
 | 
			
		||||
                            if location.item_rule(item):
 | 
			
		||||
                                if location.can_fill(multiworld.state, item, False):
 | 
			
		||||
                                    successful_pairs.append((item, location))
 | 
			
		||||
                                    successful_pairs.append((index_to_delete, item, location))
 | 
			
		||||
                                    claimed_indices.add(index_to_delete)
 | 
			
		||||
                                    candidates.remove(location)
 | 
			
		||||
                                    count = count + 1
 | 
			
		||||
                                    break
 | 
			
		||||
| 
						 | 
				
			
			@ -998,6 +1015,7 @@ def distribute_planned(multiworld: MultiWorld) -> None:
 | 
			
		|||
                            err.append(f"Cannot place {item_name} into already filled location {location}.")
 | 
			
		||||
                    else:
 | 
			
		||||
                        err.append(f"Mismatch between {item_name} and {location}, only one is an event.")
 | 
			
		||||
 | 
			
		||||
                if count == maxcount:
 | 
			
		||||
                    break
 | 
			
		||||
            if count < placement['count']['min']:
 | 
			
		||||
| 
						 | 
				
			
			@ -1005,17 +1023,16 @@ def distribute_planned(multiworld: MultiWorld) -> None:
 | 
			
		|||
                failed(
 | 
			
		||||
                    f"Plando block failed to place {m - count} of {m} item(s) for {multiworld.player_name[player]}, error(s): {' '.join(err)}",
 | 
			
		||||
                    placement['force'])
 | 
			
		||||
            for (item, location) in successful_pairs:
 | 
			
		||||
 | 
			
		||||
            # Sort indices in reverse so we can remove them one by one
 | 
			
		||||
            successful_pairs = sorted(successful_pairs, key=lambda successful_pair: successful_pair[0] or 0, reverse=True)
 | 
			
		||||
 | 
			
		||||
            for (index, item, location) in successful_pairs:
 | 
			
		||||
                multiworld.push_item(location, item, collect=False)
 | 
			
		||||
                location.locked = True
 | 
			
		||||
                logging.debug(f"Plando placed {item} at {location}")
 | 
			
		||||
                if from_pool:
 | 
			
		||||
                    try:
 | 
			
		||||
                        multiworld.itempool.remove(item)
 | 
			
		||||
                    except ValueError:
 | 
			
		||||
                        warn(
 | 
			
		||||
                            f"Could not remove {item} from pool for {multiworld.player_name[player]} as it's already missing from it.",
 | 
			
		||||
                            placement['force'])
 | 
			
		||||
                if index is not None:  # If this item is from_pool and was found in the pool, remove it.
 | 
			
		||||
                    multiworld.itempool.pop(index)
 | 
			
		||||
 | 
			
		||||
        except Exception as e:
 | 
			
		||||
            raise Exception(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue