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.
This commit is contained in:
Fabian Dill 2020-06-19 03:01:23 +02:00
parent cb1d4cc39e
commit f311d3a8b9
3 changed files with 29 additions and 2 deletions

View File

@ -116,6 +116,10 @@ class World(object):
set_player_attr('triforce_pieces_available', 30) set_player_attr('triforce_pieces_available', 30)
set_player_attr('triforce_pieces_required', 20) 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: 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)})' return obj.name if self.players == 1 else f'{obj.name} ({self.get_player_names(obj.player)})'

View File

@ -208,3 +208,5 @@ for basename, substring in _simple_groups:
tempset.add(itemname) tempset.add(itemname)
del (_simple_groups) del (_simple_groups)
progression_items = {name for name, data in item_table.items() if type(data[3]) == int and data[0]}

View File

@ -2,20 +2,24 @@ import collections
import logging import logging
import OverworldGlitchRules import OverworldGlitchRules
from BaseClasses import RegionType, World, Entrance 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 from OverworldGlitchRules import overworld_glitches_rules
def set_rules(world, player): def set_rules(world, player):
locality_rules(world, player) locality_rules(world, player)
if world.logic[player] == 'nologic': 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 world.get_region('Menu', player).can_reach_private = lambda state: True
for exit in world.get_region('Menu', player).exits: for exit in world.get_region('Menu', player).exits:
exit.hide_path = True exit.hide_path = True
return return
crossover_logic(world, player)
global_rules(world, player) global_rules(world, player)
if world.mode[player] != 'inverted': if world.mode[player] != 'inverted':
default_rules(world, player) default_rules(world, player)
@ -148,6 +152,23 @@ def locality_rules(world, player):
forbid_item(location, item, 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): def global_rules(world, player):
# ganon can only carry triforce # ganon can only carry triforce
add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player) add_item_rule(world.get_location('Ganon', player), lambda item: item.name == 'Triforce' and item.player == player)