Lingo: Add panels mode door shuffle (#3163)
* Created panels mode door shuffle * Added some panel door item names * Remove RUNT TURN panel door Not really useful. * Fix logic with First SIX related stuff * Add group_doors to slot data * Fix LEVEL 2 behavior with panels mode * Fixed unit tests * Fixed duplicate IDs from merge * Just regenerated new IDs * Fixed duplication of color and door group items * Removed unnecessary unit test option * Fix The Seeker being achievable without entrance door * Fix The Observant being achievable without locked panels * Added some more panel doors * Added Progressive Suits Area * Lingo: Fix Basement access with THE MASTER * Added indirect conditions for MASTER-blocked entrances * Fixed Incomparable achievement access * Fix STAIRS panel logic * Fix merge error with good items * Is this clearer? * DREAD and TURN LEARN * Allow a weird edge case for reduced locations Panels mode door shuffle + grouped doors + color shuffle + pilgrimage enabled is exactly the right number of items for reduced locations. Removing color shuffle also allows for disabling pilgrimage, adding sunwarp locking, or both, with a couple of locations left over. * Prevent small sphere one on panels mode * Added shuffle_doors aliases for old options * Fixed a unit test * Updated datafile * Tweaked requirements for reduced locations * Added player name to OptionError messages * Update generated.dat
This commit is contained in:
committed by
GitHub
parent
d030a698a6
commit
cc22161644
@@ -73,6 +73,22 @@ if old_generated.include? "door_groups" then
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "panel_doors" then
|
||||
old_generated["panel_doors"].each do |room, panel_doors|
|
||||
panel_doors.each do |name, id|
|
||||
if id >= next_item_id then
|
||||
next_item_id = id + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "panel_groups" then
|
||||
old_generated["panel_groups"].each do |name, id|
|
||||
if id >= next_item_id then
|
||||
next_item_id = id + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "progression" then
|
||||
old_generated["progression"].each do |name, id|
|
||||
if id >= next_item_id then
|
||||
@@ -82,6 +98,7 @@ if old_generated.include? "progression" then
|
||||
end
|
||||
|
||||
door_groups = Set[]
|
||||
panel_groups = Set[]
|
||||
|
||||
config = YAML.load_file(configpath)
|
||||
config.each do |room_name, room_data|
|
||||
@@ -163,6 +180,29 @@ config.each do |room_name, room_data|
|
||||
end
|
||||
end
|
||||
|
||||
if room_data.include? "panel_doors"
|
||||
room_data["panel_doors"].each do |panel_door_name, panel_door|
|
||||
unless old_generated.include? "panel_doors" and old_generated["panel_doors"].include? room_name and old_generated["panel_doors"][room_name].include? panel_door_name then
|
||||
old_generated["panel_doors"] ||= {}
|
||||
old_generated["panel_doors"][room_name] ||= {}
|
||||
old_generated["panel_doors"][room_name][panel_door_name] = next_item_id
|
||||
|
||||
next_item_id += 1
|
||||
end
|
||||
|
||||
if panel_door.include? "panel_group" and not panel_groups.include? panel_door["panel_group"] then
|
||||
panel_groups.add(panel_door["panel_group"])
|
||||
|
||||
unless old_generated.include? "panel_groups" and old_generated["panel_groups"].include? panel_door["panel_group"] then
|
||||
old_generated["panel_groups"] ||= {}
|
||||
old_generated["panel_groups"][panel_door["panel_group"]] = next_item_id
|
||||
|
||||
next_item_id += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if room_data.include? "progression"
|
||||
room_data["progression"].each do |progression_name, pdata|
|
||||
unless old_generated.include? "progression" and old_generated["progression"].include? progression_name then
|
||||
|
||||
@@ -6,8 +6,8 @@ import sys
|
||||
sys.path.append(os.path.join("worlds", "lingo"))
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
from datatypes import Door, DoorType, EntranceType, Painting, Panel, Progression, Room, RoomAndDoor, RoomAndPanel,\
|
||||
RoomEntrance
|
||||
from datatypes import Door, DoorType, EntranceType, Painting, Panel, PanelDoor, Progression, Room, RoomAndDoor,\
|
||||
RoomAndPanel, RoomAndPanelDoor, RoomEntrance
|
||||
|
||||
import hashlib
|
||||
import pickle
|
||||
@@ -18,10 +18,12 @@ import Utils
|
||||
ALL_ROOMS: List[Room] = []
|
||||
DOORS_BY_ROOM: Dict[str, Dict[str, Door]] = {}
|
||||
PANELS_BY_ROOM: Dict[str, Dict[str, Panel]] = {}
|
||||
PANEL_DOORS_BY_ROOM: Dict[str, Dict[str, PanelDoor]] = {}
|
||||
PAINTINGS: Dict[str, Painting] = {}
|
||||
|
||||
PROGRESSIVE_ITEMS: List[str] = []
|
||||
PROGRESSION_BY_ROOM: Dict[str, Dict[str, Progression]] = {}
|
||||
PROGRESSIVE_ITEMS: Set[str] = set()
|
||||
PROGRESSIVE_DOORS_BY_ROOM: Dict[str, Dict[str, Progression]] = {}
|
||||
PROGRESSIVE_PANELS_BY_ROOM: Dict[str, Dict[str, Progression]] = {}
|
||||
|
||||
PAINTING_ENTRANCES: int = 0
|
||||
PAINTING_EXIT_ROOMS: Set[str] = set()
|
||||
@@ -37,8 +39,13 @@ PANEL_LOCATION_IDS: Dict[str, Dict[str, int]] = {}
|
||||
DOOR_LOCATION_IDS: Dict[str, Dict[str, int]] = {}
|
||||
DOOR_ITEM_IDS: Dict[str, Dict[str, int]] = {}
|
||||
DOOR_GROUP_ITEM_IDS: Dict[str, int] = {}
|
||||
PANEL_DOOR_ITEM_IDS: Dict[str, Dict[str, int]] = {}
|
||||
PANEL_GROUP_ITEM_IDS: Dict[str, int] = {}
|
||||
PROGRESSIVE_ITEM_IDS: Dict[str, int] = {}
|
||||
|
||||
# This doesn't need to be stored in the datafile.
|
||||
PANEL_DOOR_BY_PANEL_BY_ROOM: Dict[str, Dict[str, str]] = {}
|
||||
|
||||
|
||||
def hash_file(path):
|
||||
md5 = hashlib.md5()
|
||||
@@ -53,7 +60,7 @@ def hash_file(path):
|
||||
|
||||
def load_static_data(ll1_path, ids_path):
|
||||
global PAINTING_EXITS, SPECIAL_ITEM_IDS, PANEL_LOCATION_IDS, DOOR_LOCATION_IDS, DOOR_ITEM_IDS, \
|
||||
DOOR_GROUP_ITEM_IDS, PROGRESSIVE_ITEM_IDS
|
||||
DOOR_GROUP_ITEM_IDS, PROGRESSIVE_ITEM_IDS, PANEL_DOOR_ITEM_IDS, PANEL_GROUP_ITEM_IDS
|
||||
|
||||
# Load in all item and location IDs. These are broken up into groups based on the type of item/location.
|
||||
with open(ids_path, "r") as file:
|
||||
@@ -86,6 +93,17 @@ def load_static_data(ll1_path, ids_path):
|
||||
for item_name, item_id in config["door_groups"].items():
|
||||
DOOR_GROUP_ITEM_IDS[item_name] = item_id
|
||||
|
||||
if "panel_doors" in config:
|
||||
for room_name, panel_doors in config["panel_doors"].items():
|
||||
PANEL_DOOR_ITEM_IDS[room_name] = {}
|
||||
|
||||
for panel_door, item_id in panel_doors.items():
|
||||
PANEL_DOOR_ITEM_IDS[room_name][panel_door] = item_id
|
||||
|
||||
if "panel_groups" in config:
|
||||
for item_name, item_id in config["panel_groups"].items():
|
||||
PANEL_GROUP_ITEM_IDS[item_name] = item_id
|
||||
|
||||
if "progression" in config:
|
||||
for item_name, item_id in config["progression"].items():
|
||||
PROGRESSIVE_ITEM_IDS[item_name] = item_id
|
||||
@@ -147,6 +165,46 @@ def process_entrance(source_room, doors, room_obj):
|
||||
room_obj.entrances.append(RoomEntrance(source_room, door, entrance_type))
|
||||
|
||||
|
||||
def process_panel_door(room_name, panel_door_name, panel_door_data):
|
||||
global PANEL_DOORS_BY_ROOM, PANEL_DOOR_BY_PANEL_BY_ROOM
|
||||
|
||||
panels: List[RoomAndPanel] = list()
|
||||
for panel in panel_door_data["panels"]:
|
||||
if isinstance(panel, dict):
|
||||
panels.append(RoomAndPanel(panel["room"], panel["panel"]))
|
||||
else:
|
||||
panels.append(RoomAndPanel(room_name, panel))
|
||||
|
||||
for panel in panels:
|
||||
PANEL_DOOR_BY_PANEL_BY_ROOM.setdefault(panel.room, {})[panel.panel] = RoomAndPanelDoor(room_name,
|
||||
panel_door_name)
|
||||
|
||||
if "item_name" in panel_door_data:
|
||||
item_name = panel_door_data["item_name"]
|
||||
else:
|
||||
panel_per_room = dict()
|
||||
for panel in panels:
|
||||
panel_room_name = room_name if panel.room is None else panel.room
|
||||
panel_per_room.setdefault(panel_room_name, []).append(panel.panel)
|
||||
|
||||
room_strs = list()
|
||||
for door_room_str, door_panels_str in panel_per_room.items():
|
||||
room_strs.append(door_room_str + " - " + ", ".join(door_panels_str))
|
||||
|
||||
if len(panels) == 1:
|
||||
item_name = f"{room_strs[0]} (Panel)"
|
||||
else:
|
||||
item_name = " and ".join(room_strs) + " (Panels)"
|
||||
|
||||
if "panel_group" in panel_door_data:
|
||||
panel_group = panel_door_data["panel_group"]
|
||||
else:
|
||||
panel_group = None
|
||||
|
||||
panel_door_obj = PanelDoor(item_name, panel_group)
|
||||
PANEL_DOORS_BY_ROOM[room_name][panel_door_name] = panel_door_obj
|
||||
|
||||
|
||||
def process_panel(room_name, panel_name, panel_data):
|
||||
global PANELS_BY_ROOM
|
||||
|
||||
@@ -227,13 +285,18 @@ def process_panel(room_name, panel_name, panel_data):
|
||||
else:
|
||||
non_counting = False
|
||||
|
||||
if room_name in PANEL_DOOR_BY_PANEL_BY_ROOM and panel_name in PANEL_DOOR_BY_PANEL_BY_ROOM[room_name]:
|
||||
panel_door = PANEL_DOOR_BY_PANEL_BY_ROOM[room_name][panel_name]
|
||||
else:
|
||||
panel_door = None
|
||||
|
||||
if "location_name" in panel_data:
|
||||
location_name = panel_data["location_name"]
|
||||
else:
|
||||
location_name = None
|
||||
|
||||
panel_obj = Panel(required_rooms, required_doors, required_panels, colors, check, event, exclude_reduce,
|
||||
achievement, non_counting, location_name)
|
||||
achievement, non_counting, panel_door, location_name)
|
||||
PANELS_BY_ROOM[room_name][panel_name] = panel_obj
|
||||
|
||||
|
||||
@@ -325,7 +388,7 @@ def process_door(room_name, door_name, door_data):
|
||||
painting_ids = []
|
||||
|
||||
door_type = DoorType.NORMAL
|
||||
if door_name.endswith(" Sunwarp"):
|
||||
if room_name == "Sunwarps":
|
||||
door_type = DoorType.SUNWARP
|
||||
elif room_name == "Pilgrim Antechamber" and door_name == "Sun Painting":
|
||||
door_type = DoorType.SUN_PAINTING
|
||||
@@ -404,11 +467,11 @@ def process_sunwarp(room_name, sunwarp_data):
|
||||
SUNWARP_EXITS[sunwarp_data["dots"] - 1] = room_name
|
||||
|
||||
|
||||
def process_progression(room_name, progression_name, progression_doors):
|
||||
global PROGRESSIVE_ITEMS, PROGRESSION_BY_ROOM
|
||||
def process_progressive_door(room_name, progression_name, progression_doors):
|
||||
global PROGRESSIVE_ITEMS, PROGRESSIVE_DOORS_BY_ROOM
|
||||
|
||||
# Progressive items are configured as a list of doors.
|
||||
PROGRESSIVE_ITEMS.append(progression_name)
|
||||
PROGRESSIVE_ITEMS.add(progression_name)
|
||||
|
||||
progression_index = 1
|
||||
for door in progression_doors:
|
||||
@@ -419,11 +482,31 @@ def process_progression(room_name, progression_name, progression_doors):
|
||||
door_room = room_name
|
||||
door_door = door
|
||||
|
||||
room_progressions = PROGRESSION_BY_ROOM.setdefault(door_room, {})
|
||||
room_progressions = PROGRESSIVE_DOORS_BY_ROOM.setdefault(door_room, {})
|
||||
room_progressions[door_door] = Progression(progression_name, progression_index)
|
||||
progression_index += 1
|
||||
|
||||
|
||||
def process_progressive_panel(room_name, progression_name, progression_panel_doors):
|
||||
global PROGRESSIVE_ITEMS, PROGRESSIVE_PANELS_BY_ROOM
|
||||
|
||||
# Progressive items are configured as a list of panel doors.
|
||||
PROGRESSIVE_ITEMS.add(progression_name)
|
||||
|
||||
progression_index = 1
|
||||
for panel_door in progression_panel_doors:
|
||||
if isinstance(panel_door, Dict):
|
||||
panel_door_room = panel_door["room"]
|
||||
panel_door_door = panel_door["panel_door"]
|
||||
else:
|
||||
panel_door_room = room_name
|
||||
panel_door_door = panel_door
|
||||
|
||||
room_progressions = PROGRESSIVE_PANELS_BY_ROOM.setdefault(panel_door_room, {})
|
||||
room_progressions[panel_door_door] = Progression(progression_name, progression_index)
|
||||
progression_index += 1
|
||||
|
||||
|
||||
def process_room(room_name, room_data):
|
||||
global ALL_ROOMS
|
||||
|
||||
@@ -433,6 +516,12 @@ def process_room(room_name, room_data):
|
||||
for source_room, doors in room_data["entrances"].items():
|
||||
process_entrance(source_room, doors, room_obj)
|
||||
|
||||
if "panel_doors" in room_data:
|
||||
PANEL_DOORS_BY_ROOM[room_name] = dict()
|
||||
|
||||
for panel_door_name, panel_door_data in room_data["panel_doors"].items():
|
||||
process_panel_door(room_name, panel_door_name, panel_door_data)
|
||||
|
||||
if "panels" in room_data:
|
||||
PANELS_BY_ROOM[room_name] = dict()
|
||||
|
||||
@@ -454,8 +543,11 @@ def process_room(room_name, room_data):
|
||||
process_sunwarp(room_name, sunwarp_data)
|
||||
|
||||
if "progression" in room_data:
|
||||
for progression_name, progression_doors in room_data["progression"].items():
|
||||
process_progression(room_name, progression_name, progression_doors)
|
||||
for progression_name, pdata in room_data["progression"].items():
|
||||
if "doors" in pdata:
|
||||
process_progressive_door(room_name, progression_name, pdata["doors"])
|
||||
if "panel_doors" in pdata:
|
||||
process_progressive_panel(room_name, progression_name, pdata["panel_doors"])
|
||||
|
||||
ALL_ROOMS.append(room_obj)
|
||||
|
||||
@@ -492,8 +584,10 @@ if __name__ == '__main__':
|
||||
"ALL_ROOMS": ALL_ROOMS,
|
||||
"DOORS_BY_ROOM": DOORS_BY_ROOM,
|
||||
"PANELS_BY_ROOM": PANELS_BY_ROOM,
|
||||
"PANEL_DOORS_BY_ROOM": PANEL_DOORS_BY_ROOM,
|
||||
"PROGRESSIVE_ITEMS": PROGRESSIVE_ITEMS,
|
||||
"PROGRESSION_BY_ROOM": PROGRESSION_BY_ROOM,
|
||||
"PROGRESSIVE_DOORS_BY_ROOM": PROGRESSIVE_DOORS_BY_ROOM,
|
||||
"PROGRESSIVE_PANELS_BY_ROOM": PROGRESSIVE_PANELS_BY_ROOM,
|
||||
"PAINTING_ENTRANCES": PAINTING_ENTRANCES,
|
||||
"PAINTING_EXIT_ROOMS": PAINTING_EXIT_ROOMS,
|
||||
"PAINTING_EXITS": PAINTING_EXITS,
|
||||
@@ -506,6 +600,8 @@ if __name__ == '__main__':
|
||||
"DOOR_LOCATION_IDS": DOOR_LOCATION_IDS,
|
||||
"DOOR_ITEM_IDS": DOOR_ITEM_IDS,
|
||||
"DOOR_GROUP_ITEM_IDS": DOOR_GROUP_ITEM_IDS,
|
||||
"PANEL_DOOR_ITEM_IDS": PANEL_DOOR_ITEM_IDS,
|
||||
"PANEL_GROUP_ITEM_IDS": PANEL_GROUP_ITEM_IDS,
|
||||
"PROGRESSIVE_ITEM_IDS": PROGRESSIVE_ITEM_IDS,
|
||||
}
|
||||
|
||||
|
||||
@@ -33,19 +33,23 @@ end
|
||||
configured_rooms = Set["Menu"]
|
||||
configured_doors = Set[]
|
||||
configured_panels = Set[]
|
||||
configured_panel_doors = Set[]
|
||||
|
||||
mentioned_rooms = Set[]
|
||||
mentioned_doors = Set[]
|
||||
mentioned_panels = Set[]
|
||||
mentioned_panel_doors = Set[]
|
||||
mentioned_sunwarp_entrances = Set[]
|
||||
mentioned_sunwarp_exits = Set[]
|
||||
mentioned_paintings = Set[]
|
||||
|
||||
door_groups = {}
|
||||
panel_groups = {}
|
||||
|
||||
directives = Set["entrances", "panels", "doors", "paintings", "sunwarps", "progression"]
|
||||
directives = Set["entrances", "panels", "doors", "panel_doors", "paintings", "sunwarps", "progression"]
|
||||
panel_directives = Set["id", "required_room", "required_door", "required_panel", "colors", "check", "exclude_reduce", "tag", "link", "subtag", "achievement", "copy_to_sign", "non_counting", "hunt", "location_name"]
|
||||
door_directives = Set["id", "painting_id", "panels", "item_name", "item_group", "location_name", "skip_location", "skip_item", "door_group", "include_reduce", "event", "warp_id"]
|
||||
panel_door_directives = Set["panels", "item_name", "panel_group"]
|
||||
painting_directives = Set["id", "enter_only", "exit_only", "orientation", "required_door", "required", "required_when_no_doors", "move", "req_blocked", "req_blocked_when_no_doors"]
|
||||
|
||||
non_counting = 0
|
||||
@@ -253,6 +257,43 @@ config.each do |room_name, room|
|
||||
end
|
||||
end
|
||||
|
||||
(room["panel_doors"] || {}).each do |panel_door_name, panel_door|
|
||||
configured_panel_doors.add("#{room_name} - #{panel_door_name}")
|
||||
|
||||
if panel_door.include?("panels")
|
||||
panel_door["panels"].each do |panel|
|
||||
if panel.kind_of? Hash then
|
||||
other_room = panel.include?("room") ? panel["room"] : room_name
|
||||
mentioned_panels.add("#{other_room} - #{panel["panel"]}")
|
||||
else
|
||||
other_room = panel.include?("room") ? panel["room"] : room_name
|
||||
mentioned_panels.add("#{room_name} - #{panel}")
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "#{room_name} - #{panel_door_name} :::: Missing panels field"
|
||||
end
|
||||
|
||||
if panel_door.include?("panel_group")
|
||||
panel_groups[panel_door["panel_group"]] ||= 0
|
||||
panel_groups[panel_door["panel_group"]] += 1
|
||||
end
|
||||
|
||||
bad_subdirectives = []
|
||||
panel_door.keys.each do |key|
|
||||
unless panel_door_directives.include?(key) then
|
||||
bad_subdirectives << key
|
||||
end
|
||||
end
|
||||
unless bad_subdirectives.empty? then
|
||||
puts "#{room_name} - #{panel_door_name} :::: Panel door has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
|
||||
end
|
||||
|
||||
unless ids.include?("panel_doors") and ids["panel_doors"].include?(room_name) and ids["panel_doors"][room_name].include?(panel_door_name)
|
||||
puts "#{room_name} - #{panel_door_name} :::: Panel door is missing an item ID"
|
||||
end
|
||||
end
|
||||
|
||||
(room["paintings"] || []).each do |painting|
|
||||
if painting.include?("id") and painting["id"].kind_of? String then
|
||||
unless paintings.include? painting["id"] then
|
||||
@@ -327,12 +368,24 @@ config.each do |room_name, room|
|
||||
end
|
||||
end
|
||||
|
||||
(room["progression"] || {}).each do |progression_name, door_list|
|
||||
door_list.each do |door|
|
||||
if door.kind_of? Hash then
|
||||
mentioned_doors.add("#{door["room"]} - #{door["door"]}")
|
||||
else
|
||||
mentioned_doors.add("#{room_name} - #{door}")
|
||||
(room["progression"] || {}).each do |progression_name, pdata|
|
||||
if pdata.include? "doors" then
|
||||
pdata["doors"].each do |door|
|
||||
if door.kind_of? Hash then
|
||||
mentioned_doors.add("#{door["room"]} - #{door["door"]}")
|
||||
else
|
||||
mentioned_doors.add("#{room_name} - #{door}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if pdata.include? "panel_doors" then
|
||||
pdata["panel_doors"].each do |panel_door|
|
||||
if panel_door.kind_of? Hash then
|
||||
mentioned_panel_doors.add("#{panel_door["room"]} - #{panel_door["panel_door"]}")
|
||||
else
|
||||
mentioned_panel_doors.add("#{room_name} - #{panel_door}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -344,17 +397,22 @@ end
|
||||
|
||||
errored_rooms = mentioned_rooms - configured_rooms
|
||||
unless errored_rooms.empty? then
|
||||
puts "The folloring rooms are mentioned but do not exist: " + errored_rooms.to_s
|
||||
puts "The following rooms are mentioned but do not exist: " + errored_rooms.to_s
|
||||
end
|
||||
|
||||
errored_panels = mentioned_panels - configured_panels
|
||||
unless errored_panels.empty? then
|
||||
puts "The folloring panels are mentioned but do not exist: " + errored_panels.to_s
|
||||
puts "The following panels are mentioned but do not exist: " + errored_panels.to_s
|
||||
end
|
||||
|
||||
errored_doors = mentioned_doors - configured_doors
|
||||
unless errored_doors.empty? then
|
||||
puts "The folloring doors are mentioned but do not exist: " + errored_doors.to_s
|
||||
puts "The following doors are mentioned but do not exist: " + errored_doors.to_s
|
||||
end
|
||||
|
||||
errored_panel_doors = mentioned_panel_doors - configured_panel_doors
|
||||
unless errored_panel_doors.empty? then
|
||||
puts "The following panel doors are mentioned but do not exist: " + errored_panel_doors.to_s
|
||||
end
|
||||
|
||||
door_groups.each do |group,num|
|
||||
@@ -367,6 +425,16 @@ door_groups.each do |group,num|
|
||||
end
|
||||
end
|
||||
|
||||
panel_groups.each do |group,num|
|
||||
if num == 1 then
|
||||
puts "Panel group \"#{group}\" only has one panel in it"
|
||||
end
|
||||
|
||||
unless ids.include?("panel_groups") and ids["panel_groups"].include?(group)
|
||||
puts "#{group} :::: Panel group is missing an item ID"
|
||||
end
|
||||
end
|
||||
|
||||
slashed_rooms = configured_rooms.select do |room|
|
||||
room.include? "/"
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user