def _energy_tank_difference( new_resources: CurrentResources, old_resources: CurrentResources, database: ResourceDatabase, ) -> int: return new_resources.get(database.energy_tank, 0) - old_resources.get( database.energy_tank, 0)
def prime1_absolute_damage_reduction(self, db: ResourceDatabase, current_resources: CurrentResources): if current_resources.get(db.get_item_by_name("Phazon Suit"), 0) > 0: return 0.5 elif current_resources.get(db.get_item_by_name("Gravity Suit"), 0) > 0: return 0.8 elif current_resources.get(db.get_item_by_name("Varia Suit"), 0) > 0: return 0.9 else: return 1
def _update_tracker_from_hook(self, inventory: CurrentResources): for item, label in self._item_to_label.items(): current = inventory.get(item, 0) label.set_checked(current > 0) self._energy_tank_label.setText("x {}/14".format( inventory.get(self._energy_tank_item, 0))) for label, keys in self._labels_for_keys: num_keys = sum(inventory.get(key, 0) for key in keys) label.setText("x {}/{}".format(num_keys, len(keys)))
def can_collect(self, patches: GamePatches, current_resources: CurrentResources) -> bool: """ Checks if this TranslatorGate can be opened with the given resources and translator gate mapping :param patches: :param current_resources: :return: """ if current_resources.get(self.gate, 0) != 0: return False translator = patches.translator_gates[self.gate] return current_resources.get(self.scan_visor, 0) > 0 and current_resources.get(translator, 0) > 0
def requirement_to_leave( self, patches: GamePatches, current_resources: CurrentResources) -> Requirement: if current_resources.get("add_self_as_requirement_to_resources") == 1: return ResourceRequirement(self.event, 1, False) else: return Requirement.trivial()
def _starting_items_value_for(resource_database: ResourceDatabase, starting_items: CurrentResources, index: str) -> Union[bool, int]: item = resource_database.get_item(index) value = starting_items.get(item, 0) if item.max_capacity > 1: return value else: return value > 0
def requirement_to_leave( self, patches: GamePatches, current_resources: CurrentResources) -> Requirement: # FIXME: using non-resource as key in CurrentResources if current_resources.get("add_self_as_requirement_to_resources") == 1: return ResourceRequirement(self.pickup_index, 1, False) else: return Requirement.trivial()
def can_collect(self, patches: GamePatches, current_resources: CurrentResources) -> bool: """ Checks if this TranslatorGate can be opened with the given resources and translator gate mapping :param patches: :param current_resources: :return: """ if current_resources.get(self.resource(), 0) != 0: return False if current_resources.get(self.scan_visor, 0) == 0: return False if self.required_translator is not None: return current_resources.get(self.required_translator, 0) > 0 else: return True
def _calculate_starting_inventory(self, resources: CurrentResources): result = {} for resource, quantity in resources.items(): try: result[_get_item_id_for_item(resource)] = quantity except KeyError: print(f"Skipping {resource} for starting inventory: no item id") continue return result
def requirements_to_leave(self, patches: GamePatches, current_resources: CurrentResources) -> RequirementSet: if current_resources.get("add_self_as_requirement_to_resources") == 1: return RequirementSet([ RequirementList(0, [ IndividualRequirement(self.event, 1, False), ]) ]) else: return RequirementSet.trivial()
def can_collect(self, patches: GamePatches, current_resources: CurrentResources, all_nodes: Tuple[Node, ...]) -> bool: """ Checks if this TranslatorGate can be opened with the given resources and translator gate mapping :param patches: :param current_resources: :param all_nodes: :return: """ if current_resources.get(self.item_to_summon, 0) == 0 and current_resources.get( self.resource(), 0) == 0: return False return any( current_resources.get(node.resource(), 0) == 0 for node in all_nodes if isinstance(node, PlayerShipNode) and node.is_unlocked.satisfied(current_resources, 0))
def additional_starting_items(layout_configuration: LayoutConfiguration, resource_database: ResourceDatabase, starting_items: CurrentResources) -> List[str]: initial_items = pool_creator.calculate_pool_results(layout_configuration, resource_database)[2] return [ "{}{}".format("{} ".format(quantity) if quantity > 1 else "", _resource_user_friendly_name(item)) for item, quantity in starting_items.items() if 0 < quantity != initial_items.get(item, 0) ]
def get_damage_reduction(self, resource: SimpleResourceInfo, current_resources: CurrentResources): multiplier = self.base_damage_reduction(self, current_resources) for reduction in self.damage_reductions.get(resource, []): if reduction.inventory_item is None or current_resources.get( reduction.inventory_item, 0) > 0: multiplier *= reduction.damage_multiplier return multiplier
def patch_requirements(self, static_resources: CurrentResources, damage_multiplier: float, ) -> Requirement: if static_resources.get(self.resource) is not None: if self.satisfied(static_resources, 0): return Requirement.trivial() else: return Requirement.impossible() else: if self.is_damage: return self.multiply_amount(damage_multiplier) else: return self
def assign_extra_initial_items( self, new_resources: CurrentResources) -> "GamePatches": current = copy.copy(self.starting_items) for resource, quantity in new_resources.items(): if resource.resource_type != ResourceType.ITEM: raise ValueError( "Only ITEM is supported as extra initial items, got {}". format(resource.resource_type)) current[resource] = current.get(resource, 0) + quantity return dataclasses.replace(self, starting_items=current)
def additional_starting_items(layout_configuration: BaseConfiguration, resource_database: ResourceDatabase, starting_items: CurrentResources) -> List[str]: initial_items = calculate_pool_results(layout_configuration, resource_database)[2] return [ add_quantity_to_resource(resource_user_friendly_name(item), quantity) for item, quantity in sorted( starting_items.items(), key=lambda a: resource_user_friendly_name(a[0])) if 0 < quantity != initial_items.get(item, 0) ]
def conditional_for_resources( self, current_resources: CurrentResources) -> ConditionalResources: last_conditional: Optional[ConditionalResources] = None for conditional in self.conditional_resources: if conditional.item is None or current_resources.get( conditional.item, 0) > 0: last_conditional = conditional else: break assert last_conditional is not None return last_conditional
def prime1_progressive_damage_reduction( self, db: ResourceDatabase, current_resources: CurrentResources): num_suits = sum( current_resources.get(db.get_item_by_name(suit), 0) for suit in ["Varia Suit", "Gravity Suit", "Phazon Suit"]) if num_suits >= 3: return 0.5 elif num_suits == 2: return 0.8 elif num_suits == 1: return 0.9 else: return 1
def satisfied(self, current_resources: CurrentResources, current_energy: int) -> bool: """Checks if a given resources dict satisfies this requirement""" if self.is_damage: assert not self.negate, "Damage requirements shouldn't have the negate flag" return current_energy > self.damage(current_resources) has_amount = current_resources.get(self.resource, 0) >= self.amount if self.negate: return not has_amount else: return has_amount
def resource_gain(self, current_resources: CurrentResources, force_lock: bool = False) -> ResourceGain: resources = self.conditional_for_resources(current_resources).resources if (force_lock or self.respects_lock) and not self.unlocks_resource and ( self.resource_lock is not None and current_resources.get( self.resource_lock.locked_by, 0) == 0): yield from self.resource_lock.convert_gain(resources) else: yield from resources yield from self.conversion_resource_gain(current_resources)
def starting_items_for(resources: CurrentResources) -> str: capacity_by_short_name = { item.short_name: capacity for item, capacity in resources.items() if isinstance(item, ItemResourceInfo) } result_values = [ capacity_by_short_name.get(STARTING_ITEMS_NAME_ALIAS.get(item, item), 0) for item in STARTING_ITEMS_ORDER ] return "custom " + "".join([ "{:02x}".format(value) if index in _TWO_BYTE_VALUES else "{:x}".format(value) for index, value in enumerate(result_values) ])
def _create_starting_popup(layout_configuration: LayoutConfiguration, resource_database: ResourceDatabase, starting_items: CurrentResources) -> list: initial_items = pool_creator.calculate_pool_results( layout_configuration, resource_database)[2] extra_items = [ "{}{}".format("{} ".format(quantity) if quantity > 1 else "", _resource_user_friendly_name(item)) for item, quantity in starting_items.items() if 0 < quantity != initial_items.get(item, 0) ] if extra_items: return ["Extra starting items:", ", ".join(extra_items)] else: return []
def simplify( self, static_resources: CurrentResources) -> Optional["RequirementList"]: """ Creates a new RequirementList that does not contain reference to resources in static_resources :param static_resources: :return: None if this RequirementList is impossible to satisfy, otherwise the simplified RequirementList. """ items = [] for item in self.values(): if static_resources.get(item.resource) is not None: # If the resource is a static resource, we either remove it from the list or # consider this list impossible if not item.satisfied(static_resources, 0): return None else: # An empty RequirementList is considered satisfied, so we don't have to add the trivial resource items.append(item) return RequirementList(self.difficulty_level, items)
def _energy_for(self, resources: CurrentResources) -> int: num_tanks = resources.get(self.game_data.resource_database.energy_tank, 0) energy_per_tank = self.game_data.energy_per_tank return (energy_per_tank - 1) + (energy_per_tank * num_tanks)
def can_collect(self, patches: GamePatches, current_resources: CurrentResources) -> bool: return current_resources.get(self.pickup_index, 0) == 0
def can_collect(self, patches: GamePatches, current_resources: CurrentResources, all_nodes: Tuple[Node, ...]) -> bool: return current_resources.get(self.pickup_index, 0) == 0
def _energy_for( resources: CurrentResources, database: ResourceDatabase, ) -> int: return 99 + (ENERGY_PER_TANK * resources.get(database.energy_tank, 0))
def conversion_resource_gain( self, current_resources: CurrentResources) -> ResourceGain: for conversion in self.convert_resources: quantity = current_resources.get(conversion.source, 0) yield conversion.source, -quantity yield conversion.target, quantity
def _energy_for(self, resources: CurrentResources) -> int: energy_per_tank = self.patches.game_specific.energy_per_tank return (energy_per_tank - 1) + (energy_per_tank * resources.get( self.resource_database.energy_tank, 0))