From 6a3d1fcaf4f054a07217a7f9d9a610be1bd595b2 Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Sat, 21 Aug 2021 06:55:08 +0200 Subject: [PATCH] LttP & Factorio: fix item state removal for progressive items. --- WebHostLib/upload.py | 2 +- worlds/AutoWorld.py | 8 ++- worlds/alttp/__init__.py | 115 ++++++++++++++++++++++++------------ worlds/factorio/__init__.py | 15 +++-- 4 files changed, 92 insertions(+), 48 deletions(-) diff --git a/WebHostLib/upload.py b/WebHostLib/upload.py index be0a7deb..97087629 100644 --- a/WebHostLib/upload.py +++ b/WebHostLib/upload.py @@ -58,7 +58,7 @@ def uploads(): game="Minecraft")) elif file.filename.endswith(".zip"): - # Factorio mods needs a specific name or they do no function + # Factorio mods needs a specific name or they do not function _, seed_name, slot_id, slot_name = file.filename.rsplit("_", 1)[0].split("-") slots.add(Slot(data=zfile.open(file, "r").read(), player_name=slot_name, player_id=int(slot_id[1:]), game="Factorio")) diff --git a/worlds/AutoWorld.py b/worlds/AutoWorld.py index 71a2dcc9..11fca3a5 100644 --- a/worlds/AutoWorld.py +++ b/worlds/AutoWorld.py @@ -150,9 +150,10 @@ class World(metaclass=AutoWorldRegister): # end of Main.py calls - def collect_item(self, state: CollectionState, item: Item) -> Optional[str]: + def collect_item(self, state: CollectionState, item: Item, remove=False) -> Optional[str]: """Collect an item name into state. For speed reasons items that aren't logically useful get skipped. - Collect None to skip item.""" + Collect None to skip item. + :param remove: indicate if this is meant to remove from state instead of adding.""" if item.advancement: return item.name @@ -170,7 +171,7 @@ class World(metaclass=AutoWorldRegister): return False def remove(self, state: CollectionState, item: Item) -> bool: - name = self.collect_item(state, item) + name = self.collect_item(state, item, True) if name: state.prog_items[name, item.player] -= 1 if state.prog_items[name, item.player] < 1: @@ -178,6 +179,7 @@ class World(metaclass=AutoWorldRegister): return True return False + # any methods attached to this can be used as part of CollectionState, # please use a prefix as all of them get clobbered together class LogicMixin(metaclass=AutoLogicRegister): diff --git a/worlds/alttp/__init__.py b/worlds/alttp/__init__.py index 5bbe2472..d2046e52 100644 --- a/worlds/alttp/__init__.py +++ b/worlds/alttp/__init__.py @@ -86,46 +86,83 @@ class ALTTPWorld(World): world.random = old_random plando_connect(world, player) - def collect_item(self, state: CollectionState, item: Item): - if item.name.startswith('Progressive '): - if 'Sword' in item.name: - if state.has('Golden Sword', item.player): - pass - elif state.has('Tempered Sword', item.player) and self.world.difficulty_requirements[ - item.player].progressive_sword_limit >= 4: - return 'Golden Sword' - elif state.has('Master Sword', item.player) and self.world.difficulty_requirements[ - item.player].progressive_sword_limit >= 3: - return 'Tempered Sword' - elif state.has('Fighter Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 2: - return 'Master Sword' - elif self.world.difficulty_requirements[item.player].progressive_sword_limit >= 1: - return 'Fighter Sword' - elif 'Glove' in item.name: - if state.has('Titans Mitts', item.player): - return - elif state.has('Power Glove', item.player): - return 'Titans Mitts' - else: - return 'Power Glove' - elif 'Shield' in item.name: - if state.has('Mirror Shield', item.player): - return - elif state.has('Red Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 3: - return 'Mirror Shield' - elif state.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2: - return 'Red Shield' - elif self.world.difficulty_requirements[item.player].progressive_shield_limit >= 1: - return 'Blue Shield' - elif 'Bow' in item.name: - if state.has('Silver', item.player): - return - elif state.has('Bow', item.player) and self.world.difficulty_requirements[item.player].progressive_bow_limit >= 2: - return 'Silver Bow' - elif self.world.difficulty_requirements[item.player].progressive_bow_limit >= 1: - return 'Bow' + def collect_item(self, state: CollectionState, item: Item, remove=False): + item_name = item.name + if item_name.startswith('Progressive '): + if remove: + if 'Sword' in item_name: + if state.has('Golden Sword', item.player): + return 'Golden Sword' + elif state.has('Tempered Sword', item.player): + return 'Tempered Sword' + elif state.has('Master Sword', item.player): + return 'Master Sword' + elif state.has('Fighter Sword', item.player): + return 'Fighter Sword' + else: + return None + elif 'Glove' in item.name: + if state.has('Titans Mitts', item.player): + return 'Titans Mitts' + elif state.has('Power Glove', item.player): + return 'Power Glove' + else: + return None + elif 'Shield' in item_name: + if state.has('Mirror Shield', item.player): + return 'Mirror Shield' + elif state.has('Red Shield', item.player): + return 'Red Shield' + elif state.has('Blue Shield', item.player): + return 'Blue Shield' + else: + return None + elif 'Bow' in item_name: + if state.has('Silver Bow', item.player): + return 'Silver Bow' + elif state.has('Bow', item.player): + return 'Bow' + else: + return None + else: + if 'Sword' in item_name: + if state.has('Golden Sword', item.player): + pass + elif state.has('Tempered Sword', item.player) and self.world.difficulty_requirements[ + item.player].progressive_sword_limit >= 4: + return 'Golden Sword' + elif state.has('Master Sword', item.player) and self.world.difficulty_requirements[ + item.player].progressive_sword_limit >= 3: + return 'Tempered Sword' + elif state.has('Fighter Sword', item.player) and self.world.difficulty_requirements[item.player].progressive_sword_limit >= 2: + return 'Master Sword' + elif self.world.difficulty_requirements[item.player].progressive_sword_limit >= 1: + return 'Fighter Sword' + elif 'Glove' in item_name: + if state.has('Titans Mitts', item.player): + return + elif state.has('Power Glove', item.player): + return 'Titans Mitts' + else: + return 'Power Glove' + elif 'Shield' in item_name: + if state.has('Mirror Shield', item.player): + return + elif state.has('Red Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 3: + return 'Mirror Shield' + elif state.has('Blue Shield', item.player) and self.world.difficulty_requirements[item.player].progressive_shield_limit >= 2: + return 'Red Shield' + elif self.world.difficulty_requirements[item.player].progressive_shield_limit >= 1: + return 'Blue Shield' + elif 'Bow' in item_name: + if state.has('Silver', item.player): + return + elif state.has('Bow', item.player) and self.world.difficulty_requirements[item.player].progressive_bow_limit >= 2: + return 'Silver Bow' + elif self.world.difficulty_requirements[item.player].progressive_bow_limit >= 1: + return 'Bow' elif item.advancement: - return item.name + return item_name def pre_fill(self): from Fill import fill_restrictive, FillError diff --git a/worlds/factorio/__init__.py b/worlds/factorio/__init__.py index 24b62965..c5ca837f 100644 --- a/worlds/factorio/__init__.py +++ b/worlds/factorio/__init__.py @@ -140,14 +140,19 @@ class Factorio(World): world.completion_condition[player] = lambda state: state.has('Victory', player) - def collect_item(self, state, item): + def collect_item(self, state, item, remove=False): if item.advancement and item.name in progressive_technology_table: prog_table = progressive_technology_table[item.name].progressive - for item_name in prog_table: - if not state.has(item_name, item.player): - return item_name + if remove: + for item_name in reversed(prog_table): + if state.has(item_name, item.player): + return item_name + else: + for item_name in prog_table: + if not state.has(item_name, item.player): + return item_name - return super(Factorio, self).collect_item(state, item) + return super(Factorio, self).collect_item(state, item, remove) def get_required_client_version(self) -> tuple: return max((0, 1, 6), super(Factorio, self).get_required_client_version())