From f311d3a8b92dc5aeb8bf2ff7eaad698e3d80f0ad Mon Sep 17 00:00:00 2001 From: Fabian Dill Date: Fri, 19 Jun 2020 03:01:23 +0200 Subject: [PATCH] implement "crossover logic". Makes it impossible that logical progression for a logic-having player is placed inside a no-logic world. All other placements remain available. --- BaseClasses.py | 4 ++++ Items.py | 2 ++ Rules.py | 25 +++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/BaseClasses.py b/BaseClasses.py index a4da1657..28ef84df 100644 --- a/BaseClasses.py +++ b/BaseClasses.py @@ -116,6 +116,10 @@ class World(object): set_player_attr('triforce_pieces_available', 30) set_player_attr('triforce_pieces_required', 20) + @property + def player_ids(self): + yield from range(1, self.players + 1) + def get_name_string_for_object(self, obj) -> str: return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})' diff --git a/Items.py b/Items.py index d4cd15ca..315627b3 100644 --- a/Items.py +++ b/Items.py @@ -208,3 +208,5 @@ for basename, substring in _simple_groups: tempset.add(itemname) del (_simple_groups) + +progression_items = {name for name, data in item_table.items() if type(data[3]) == int and data[0]} diff --git a/Rules.py b/Rules.py index 48ac31c7..110caaf4 100644 --- a/Rules.py +++ b/Rules.py @@ -2,20 +2,24 @@ import collections import logging import OverworldGlitchRules from BaseClasses import RegionType, World, Entrance -from Items import ItemFactory +from Items import ItemFactory, progression_items, item_name_groups from OverworldGlitchRules import overworld_glitches_rules def set_rules(world, player): locality_rules(world, player) if world.logic[player] == 'nologic': - logging.getLogger('').info('WARNING! Seeds generated under this logic often require major glitches and may be impossible!') + logging.getLogger('').info( + 'WARNING! Seeds generated under this logic often require major glitches and may be impossible!') world.get_region('Menu', player).can_reach_private = lambda state: True for exit in world.get_region('Menu', player).exits: exit.hide_path = True return + crossover_logic(world, player) + global_rules(world, player) + if world.mode[player] != 'inverted': default_rules(world, player) @@ -148,6 +152,23 @@ def locality_rules(world, player): forbid_item(location, item, player) +def crossover_logic(world, player): + """ Simple and not graceful solution to logic loops if you mix no logic and logic. + Making it so that logical progression cannot be placed in no logic worlds.""" + no_logic_players = set() + for other_player in world.player_ids: + if world.logic[other_player] == 'nologic': + no_logic_players.add(other_player) + if no_logic_players: + for location in world.get_locations(): + if location.player in no_logic_players: + for item in progression_items: + forbid_item(location, item, player) + for item in item_name_groups["Small Keys"]: + forbid_item(location, item, player) + for item in item_name_groups["Big Keys"]: + forbid_item(location, item, player) + def global_rules(world, player): # ganon can only carry triforce add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)