fix(logic): exception for vanilla mire key door layout, crystal switches can be reached with two keys, just can't tell which one was chosen
This commit is contained in:
@@ -695,7 +695,7 @@ class CollectionState(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def valid_crystal(door, new_crystal_state):
|
def valid_crystal(door, new_crystal_state):
|
||||||
return (not door.crystal or door.crystal == CrystalBarrier.Either or new_crystal_state == CrystalBarrier.Either
|
return (not door.crystal or door.crystal == CrystalBarrier.Either or new_crystal_state == CrystalBarrier.Either
|
||||||
or new_crystal_state == door.crystal)
|
or new_crystal_state == door.crystal or door.alternative_crystal_rule)
|
||||||
|
|
||||||
def check_key_doors_in_dungeons(self, rrp, player):
|
def check_key_doors_in_dungeons(self, rrp, player):
|
||||||
for dungeon_name, checklist in self.dungeons_to_check[player].items():
|
for dungeon_name, checklist in self.dungeons_to_check[player].items():
|
||||||
@@ -1828,6 +1828,7 @@ class Door(object):
|
|||||||
self.bigKey = False # There's a big key door on this side
|
self.bigKey = False # There's a big key door on this side
|
||||||
self.ugly = False # Indicates that it can't be seen from the front (e.g. back of a big key door)
|
self.ugly = False # Indicates that it can't be seen from the front (e.g. back of a big key door)
|
||||||
self.crystal = CrystalBarrier.Null # How your crystal state changes if you use this door
|
self.crystal = CrystalBarrier.Null # How your crystal state changes if you use this door
|
||||||
|
self.alternative_crystal_rule = False
|
||||||
self.req_event = None # if a dungeon event is required for this door - swamp palace mostly
|
self.req_event = None # if a dungeon event is required for this door - swamp palace mostly
|
||||||
self.controller = None
|
self.controller = None
|
||||||
self.dependents = []
|
self.dependents = []
|
||||||
@@ -3209,3 +3210,4 @@ class KeyRuleType(FastEnum):
|
|||||||
WorstCase = 0
|
WorstCase = 0
|
||||||
AllowSmall = 1
|
AllowSmall = 1
|
||||||
Lock = 2
|
Lock = 2
|
||||||
|
CrystalAlternative = 3
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from DungeonGenerator import create_dungeon_builders, split_dungeon_builder, sim
|
|||||||
from DungeonGenerator import dungeon_portals, dungeon_drops, connect_doors, count_reserved_locations
|
from DungeonGenerator import dungeon_portals, dungeon_drops, connect_doors, count_reserved_locations
|
||||||
from DungeonGenerator import valid_region_to_explore
|
from DungeonGenerator import valid_region_to_explore
|
||||||
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
|
from KeyDoorShuffle import analyze_dungeon, build_key_layout, validate_key_layout, determine_prize_lock
|
||||||
from KeyDoorShuffle import validate_bk_layout
|
from KeyDoorShuffle import validate_bk_layout, DoorRules
|
||||||
from Utils import ncr, kth_combination
|
from Utils import ncr, kth_combination
|
||||||
|
|
||||||
|
|
||||||
@@ -263,7 +263,7 @@ def vanilla_key_logic(world, player):
|
|||||||
log_key_logic(builder.name, key_layout.key_logic)
|
log_key_logic(builder.name, key_layout.key_logic)
|
||||||
# special adjustments for vanilla
|
# special adjustments for vanilla
|
||||||
if world.keyshuffle[player] != 'universal':
|
if world.keyshuffle[player] != 'universal':
|
||||||
if world.mode[player] != 'standard' and world.dropshuffle[player] == 'none' :
|
if world.mode[player] != 'standard' and world.dropshuffle[player] == 'none':
|
||||||
# adjust hc doors
|
# adjust hc doors
|
||||||
def adjust_hc_door(door_rule):
|
def adjust_hc_door(door_rule):
|
||||||
if door_rule.new_rules[KeyRuleType.WorstCase] == 3:
|
if door_rule.new_rules[KeyRuleType.WorstCase] == 3:
|
||||||
@@ -279,9 +279,28 @@ def vanilla_key_logic(world, player):
|
|||||||
if pod_front.new_rules[KeyRuleType.WorstCase] == 6:
|
if pod_front.new_rules[KeyRuleType.WorstCase] == 6:
|
||||||
pod_front.new_rules[KeyRuleType.WorstCase] = 1
|
pod_front.new_rules[KeyRuleType.WorstCase] = 1
|
||||||
pod_front.small_key_num = 1
|
pod_front.small_key_num = 1
|
||||||
|
# adjust mire key logic - this currently cannot be done dynamically
|
||||||
|
create_alternative_door_rules('Mire Hub Upper Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Hub Lower Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Hub Right Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Hub Top Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Hub Switch Blue Barrier N', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Hub Switch Blue Barrier S', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Map Spot Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Map Spike Side Blue Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Crystal Dead End Left Barrier', 2, 'Misery Mire', world, player)
|
||||||
|
create_alternative_door_rules('Mire Crystal Dead End Right Barrier', 2, 'Misery Mire', world, player)
|
||||||
# gt logic? I'm unsure it needs adjusting
|
# gt logic? I'm unsure it needs adjusting
|
||||||
|
|
||||||
|
|
||||||
|
def create_alternative_door_rules(door, amount, dungeon, world, player):
|
||||||
|
rules = DoorRules(0, True)
|
||||||
|
world.key_logic[player][dungeon].door_rules[door] = rules
|
||||||
|
rules.new_rules[KeyRuleType.CrystalAlternative] = amount
|
||||||
|
world.get_door(door, player).alternative_crystal_rule = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def validate_vanilla_reservation(dungeon, world, player):
|
def validate_vanilla_reservation(dungeon, world, player):
|
||||||
return validate_key_layout(world.key_layout[player][dungeon.name], world, player)
|
return validate_key_layout(world.key_layout[player][dungeon.name], world, player)
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ These are now independent of retro mode and have three options: None, Random, an
|
|||||||
# Patch Notes
|
# Patch Notes
|
||||||
|
|
||||||
* 1.4.1.10u
|
* 1.4.1.10u
|
||||||
* ?
|
* Vanilla key logic: Fix for vanilla layout Misery Mire which allows more complex key logic. Locations blocked by crystal switch access is only locked by 2 keys thanks to that being the minimun in Mire to reach one of two crystal switches.
|
||||||
* Autotracking: Fix for chest turn counter with chest containing multiworld items (Thanks Hiimcody)
|
* Autotracking: Fix for chest turn counter with chest containing multiworld items (Thanks Hiimcody)
|
||||||
* Rom: Code prettification and fixing byte designations by Codemann
|
* Rom: Code prettification and fixing byte designations by Codemann
|
||||||
* 1.4.1.9u
|
* 1.4.1.9u
|
||||||
|
|||||||
24
Rules.py
24
Rules.py
@@ -2332,10 +2332,13 @@ def add_key_logic_rules(world, player):
|
|||||||
for d_name, d_logic in key_logic.items():
|
for d_name, d_logic in key_logic.items():
|
||||||
for door_name, rule in d_logic.door_rules.items():
|
for door_name, rule in d_logic.door_rules.items():
|
||||||
door_entrance = world.get_entrance(door_name, player)
|
door_entrance = world.get_entrance(door_name, player)
|
||||||
add_rule(door_entrance, eval_func(door_name, d_name, player))
|
if not door_entrance.door.smallKey and door_entrance.door.crystal == CrystalBarrier.Blue:
|
||||||
if door_entrance.door.dependents:
|
add_rule(door_entrance, eval_alternative_crystal(door_name, d_name, player), 'or')
|
||||||
for dep in door_entrance.door.dependents:
|
else:
|
||||||
add_rule(dep.entrance, eval_func(door_name, d_name, player))
|
add_rule(door_entrance, eval_func(door_name, d_name, player))
|
||||||
|
if door_entrance.door.dependents:
|
||||||
|
for dep in door_entrance.door.dependents:
|
||||||
|
add_rule(dep.entrance, eval_func(door_name, d_name, player))
|
||||||
for location in d_logic.bk_restricted:
|
for location in d_logic.bk_restricted:
|
||||||
if not location.forced_item:
|
if not location.forced_item:
|
||||||
forbid_item(location, d_logic.bk_name, player)
|
forbid_item(location, d_logic.bk_name, player)
|
||||||
@@ -2427,6 +2430,15 @@ def eval_small_key_door_strict_main(state, door_name, dungeon, player):
|
|||||||
return state.has_sm_key_strict(key_layout.key_logic.small_key_name, player, number)
|
return state.has_sm_key_strict(key_layout.key_logic.small_key_name, player, number)
|
||||||
|
|
||||||
|
|
||||||
|
def eval_alternative_crystal_main(state, door_name, dungeon, player):
|
||||||
|
key_logic = state.world.key_logic[player][dungeon]
|
||||||
|
door_rule = key_logic.door_rules[door_name]
|
||||||
|
for ruleType, number in door_rule.new_rules.items():
|
||||||
|
if ruleType == KeyRuleType.CrystalAlternative:
|
||||||
|
return state.has_sm_key(key_logic.small_key_name, player, number)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def eval_small_key_door(door_name, dungeon, player):
|
def eval_small_key_door(door_name, dungeon, player):
|
||||||
return lambda state: eval_small_key_door_main(state, door_name, dungeon, player)
|
return lambda state: eval_small_key_door_main(state, door_name, dungeon, player)
|
||||||
|
|
||||||
@@ -2439,6 +2451,10 @@ def eval_small_key_door_strict(door_name, dungeon, player):
|
|||||||
return lambda state: eval_small_key_door_strict_main(state, door_name, dungeon, player)
|
return lambda state: eval_small_key_door_strict_main(state, door_name, dungeon, player)
|
||||||
|
|
||||||
|
|
||||||
|
def eval_alternative_crystal(door_name, dungeon, player):
|
||||||
|
return lambda state: eval_alternative_crystal_main(state, door_name, dungeon, player)
|
||||||
|
|
||||||
|
|
||||||
def allow_big_key_in_big_chest(bk_name, player):
|
def allow_big_key_in_big_chest(bk_name, player):
|
||||||
return lambda state, item: item.name == bk_name and item.player == player
|
return lambda state, item: item.name == bk_name and item.player == player
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user