mirror of
https://github.com/MarioSpore/Grinch-AP.git
synced 2025-10-21 20:21:32 -06:00
Lingo: New game (#1806)
Co-authored-by: Aaron Wagener <mmmcheese158@gmail.com> Co-authored-by: Fabian Dill <Berserker66@users.noreply.github.com> Co-authored-by: Phar <zach@alliware.com>
This commit is contained in:

committed by
GitHub

parent
154e17f4ff
commit
ea9c31392d
178
worlds/lingo/utils/assign_ids.rb
Normal file
178
worlds/lingo/utils/assign_ids.rb
Normal file
@@ -0,0 +1,178 @@
|
||||
# This utility goes through the provided Lingo config and assigns item and
|
||||
# location IDs to entities that require them (such as doors and panels). These
|
||||
# IDs are output in a separate yaml file. If the output file already exists,
|
||||
# then it will be updated with any newly assigned IDs rather than overwritten.
|
||||
# In this event, all new IDs will be greater than any already existing IDs,
|
||||
# even if there are gaps in the ID space; this is to prevent collision when IDs
|
||||
# are retired.
|
||||
#
|
||||
# This utility should be run whenever logically new items or locations are
|
||||
# required. If an item or location is created that is logically equivalent to
|
||||
# one that used to exist, this utility should not be used, and instead the ID
|
||||
# file should be manually edited so that the old ID can be reused.
|
||||
|
||||
require 'set'
|
||||
require 'yaml'
|
||||
|
||||
configpath = ARGV[0]
|
||||
outputpath = ARGV[1]
|
||||
|
||||
next_item_id = 444400
|
||||
next_location_id = 444400
|
||||
|
||||
location_id_by_name = {}
|
||||
|
||||
old_generated = YAML.load_file(outputpath)
|
||||
File.write(outputpath + ".old", old_generated.to_yaml)
|
||||
|
||||
if old_generated.include? "special_items" then
|
||||
old_generated["special_items"].each do |name, id|
|
||||
if id >= next_item_id then
|
||||
next_item_id = id + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "special_locations" then
|
||||
old_generated["special_locations"].each do |name, id|
|
||||
if id >= next_location_id then
|
||||
next_location_id = id + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "panels" then
|
||||
old_generated["panels"].each do |room, panels|
|
||||
panels.each do |name, id|
|
||||
if id >= next_location_id then
|
||||
next_location_id = id + 1
|
||||
end
|
||||
location_name = "#{room} - #{name}"
|
||||
location_id_by_name[location_name] = id
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "doors" then
|
||||
old_generated["doors"].each do |room, doors|
|
||||
doors.each do |name, ids|
|
||||
if ids.include? "location" then
|
||||
if ids["location"] >= next_location_id then
|
||||
next_location_id = ids["location"] + 1
|
||||
end
|
||||
end
|
||||
if ids.include? "item" then
|
||||
if ids["item"] >= next_item_id then
|
||||
next_item_id = ids["item"] + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if old_generated.include? "door_groups" then
|
||||
old_generated["door_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
|
||||
next_item_id = id + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
door_groups = Set[]
|
||||
|
||||
config = YAML.load_file(configpath)
|
||||
config.each do |room_name, room_data|
|
||||
if room_data.include? "panels"
|
||||
room_data["panels"].each do |panel_name, panel|
|
||||
unless old_generated.include? "panels" and old_generated["panels"].include? room_name and old_generated["panels"][room_name].include? panel_name then
|
||||
old_generated["panels"] ||= {}
|
||||
old_generated["panels"][room_name] ||= {}
|
||||
old_generated["panels"][room_name][panel_name] = next_location_id
|
||||
|
||||
location_name = "#{room_name} - #{panel_name}"
|
||||
location_id_by_name[location_name] = next_location_id
|
||||
|
||||
next_location_id += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
config.each do |room_name, room_data|
|
||||
if room_data.include? "doors"
|
||||
room_data["doors"].each do |door_name, door|
|
||||
if door.include? "event" and door["event"] then
|
||||
next
|
||||
end
|
||||
|
||||
unless door.include? "skip_item" and door["skip_item"] then
|
||||
unless old_generated.include? "doors" and old_generated["doors"].include? room_name and old_generated["doors"][room_name].include? door_name and old_generated["doors"][room_name][door_name].include? "item" then
|
||||
old_generated["doors"] ||= {}
|
||||
old_generated["doors"][room_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name]["item"] = next_item_id
|
||||
|
||||
next_item_id += 1
|
||||
end
|
||||
|
||||
if door.include? "group" and not door_groups.include? door["group"] then
|
||||
door_groups.add(door["group"])
|
||||
|
||||
unless old_generated.include? "door_groups" and old_generated["door_groups"].include? door["group"] then
|
||||
old_generated["door_groups"] ||= {}
|
||||
old_generated["door_groups"][door["group"]] = next_item_id
|
||||
|
||||
next_item_id += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless door.include? "skip_location" and door["skip_location"] then
|
||||
location_name = ""
|
||||
if door.include? "location_name" then
|
||||
location_name = door["location_name"]
|
||||
elsif door.include? "panels" then
|
||||
location_name = door["panels"].map do |panel|
|
||||
if panel.kind_of? Hash then
|
||||
panel
|
||||
else
|
||||
{"room" => room_name, "panel" => panel}
|
||||
end
|
||||
end.sort_by {|panel| panel["room"]}.chunk {|panel| panel["room"]}.map do |room_panels|
|
||||
room_panels[0] + " - " + room_panels[1].map{|panel| panel["panel"]}.join(", ")
|
||||
end.join(" and ")
|
||||
end
|
||||
|
||||
if location_id_by_name.has_key? location_name then
|
||||
old_generated["doors"] ||= {}
|
||||
old_generated["doors"][room_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name]["location"] = location_id_by_name[location_name]
|
||||
elsif not (old_generated.include? "doors" and old_generated["doors"].include? room_name and old_generated["doors"][room_name].include? door_name and old_generated["doors"][room_name][door_name].include? "location") then
|
||||
old_generated["doors"] ||= {}
|
||||
old_generated["doors"][room_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name] ||= {}
|
||||
old_generated["doors"][room_name][door_name]["location"] = next_location_id
|
||||
|
||||
next_location_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
|
||||
old_generated["progression"] ||= {}
|
||||
old_generated["progression"][progression_name] = next_item_id
|
||||
|
||||
next_item_id += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
File.write(outputpath, old_generated.to_yaml)
|
329
worlds/lingo/utils/validate_config.rb
Normal file
329
worlds/lingo/utils/validate_config.rb
Normal file
@@ -0,0 +1,329 @@
|
||||
# Script to validate a level config file. This checks that the names used within
|
||||
# the file are consistent. It also checks that the panel and door IDs mentioned
|
||||
# all exist in the map file.
|
||||
#
|
||||
# Usage: validate_config.rb [config file] [map file]
|
||||
|
||||
require 'set'
|
||||
require 'yaml'
|
||||
|
||||
configpath = ARGV[0]
|
||||
mappath = ARGV[1]
|
||||
|
||||
panels = Set["Countdown Panels/Panel_1234567890_wanderlust"]
|
||||
doors = Set["Naps Room Doors/Door_hider_new1", "Tower Room Area Doors/Door_wanderer_entrance"]
|
||||
paintings = Set[]
|
||||
|
||||
File.readlines(mappath).each do |line|
|
||||
line.match(/node name=\"(.*)\" parent=\"Panels\/(.*)\" instance/) do |m|
|
||||
panels.add(m[2] + "/" + m[1])
|
||||
end
|
||||
line.match(/node name=\"(.*)\" parent=\"Doors\/(.*)\" instance/) do |m|
|
||||
doors.add(m[2] + "/" + m[1])
|
||||
end
|
||||
line.match(/node name=\"(.*)\" parent=\"Decorations\/Paintings\" instance/) do |m|
|
||||
paintings.add(m[1])
|
||||
end
|
||||
line.match(/node name=\"(.*)\" parent=\"Decorations\/EndPanel\" instance/) do |m|
|
||||
panels.add("EndPanel/" + m[1])
|
||||
end
|
||||
end
|
||||
|
||||
configured_rooms = Set["Menu"]
|
||||
configured_doors = Set[]
|
||||
configured_panels = Set[]
|
||||
|
||||
mentioned_rooms = Set[]
|
||||
mentioned_doors = Set[]
|
||||
mentioned_panels = Set[]
|
||||
|
||||
door_groups = {}
|
||||
|
||||
directives = Set["entrances", "panels", "doors", "paintings", "progression"]
|
||||
panel_directives = Set["id", "required_room", "required_door", "required_panel", "colors", "check", "exclude_reduce", "tag", "link", "subtag", "achievement", "copy_to_sign", "non_counting"]
|
||||
door_directives = Set["id", "painting_id", "panels", "item_name", "location_name", "skip_location", "skip_item", "group", "include_reduce", "junk_item", "event"]
|
||||
painting_directives = Set["id", "enter_only", "exit_only", "orientation", "required_door", "required", "required_when_no_doors", "move"]
|
||||
|
||||
non_counting = 0
|
||||
|
||||
config = YAML.load_file(configpath)
|
||||
config.each do |room_name, room|
|
||||
configured_rooms.add(room_name)
|
||||
|
||||
used_directives = Set[]
|
||||
room.each_key do |key|
|
||||
used_directives.add(key)
|
||||
end
|
||||
diff_directives = used_directives - directives
|
||||
unless diff_directives.empty? then
|
||||
puts("#{room_name} has the following invalid top-level directives: #{diff_directives.to_s}")
|
||||
end
|
||||
|
||||
(room["entrances"] || {}).each do |source_room, entrance|
|
||||
mentioned_rooms.add(source_room)
|
||||
|
||||
entrances = []
|
||||
if entrance.kind_of? Hash
|
||||
if entrance.keys() != ["painting"] then
|
||||
entrances = [entrance]
|
||||
end
|
||||
elsif entrance.kind_of? Array
|
||||
entrances = entrance
|
||||
end
|
||||
|
||||
entrances.each do |e|
|
||||
entrance_room = e.include?("room") ? e["room"] : room_name
|
||||
mentioned_rooms.add(entrance_room)
|
||||
mentioned_doors.add(entrance_room + " - " + e["door"])
|
||||
end
|
||||
end
|
||||
|
||||
(room["panels"] || {}).each do |panel_name, panel|
|
||||
unless panel_name.kind_of? String then
|
||||
puts "#{room_name} has an invalid panel name"
|
||||
end
|
||||
|
||||
configured_panels.add(room_name + " - " + panel_name)
|
||||
|
||||
if panel.include?("id")
|
||||
panel_ids = []
|
||||
if panel["id"].kind_of? Array
|
||||
panel_ids = panel["id"]
|
||||
else
|
||||
panel_ids = [panel["id"]]
|
||||
end
|
||||
|
||||
panel_ids.each do |panel_id|
|
||||
unless panels.include? panel_id then
|
||||
puts "#{room_name} - #{panel_name} :::: Invalid Panel ID #{panel_id}"
|
||||
end
|
||||
end
|
||||
else
|
||||
puts "#{room_name} - #{panel_name} :::: Panel is missing an ID"
|
||||
end
|
||||
|
||||
if panel.include?("required_room")
|
||||
required_rooms = []
|
||||
if panel["required_room"].kind_of? Array
|
||||
required_rooms = panel["required_room"]
|
||||
else
|
||||
required_rooms = [panel["required_room"]]
|
||||
end
|
||||
|
||||
required_rooms.each do |required_room|
|
||||
mentioned_rooms.add(required_room)
|
||||
end
|
||||
end
|
||||
|
||||
if panel.include?("required_door")
|
||||
required_doors = []
|
||||
if panel["required_door"].kind_of? Array
|
||||
required_doors = panel["required_door"]
|
||||
else
|
||||
required_doors = [panel["required_door"]]
|
||||
end
|
||||
|
||||
required_doors.each do |required_door|
|
||||
other_room = required_door.include?("room") ? required_door["room"] : room_name
|
||||
mentioned_rooms.add(other_room)
|
||||
mentioned_doors.add("#{other_room} - #{required_door["door"]}")
|
||||
end
|
||||
end
|
||||
|
||||
if panel.include?("required_panel")
|
||||
required_panels = []
|
||||
if panel["required_panel"].kind_of? Array
|
||||
required_panels = panel["required_panel"]
|
||||
else
|
||||
required_panels = [panel["required_panel"]]
|
||||
end
|
||||
|
||||
required_panels.each do |required_panel|
|
||||
other_room = required_panel.include?("room") ? required_panel["room"] : room_name
|
||||
mentioned_rooms.add(other_room)
|
||||
mentioned_panels.add("#{other_room} - #{required_panel["panel"]}")
|
||||
end
|
||||
end
|
||||
|
||||
unless panel.include?("tag") then
|
||||
puts "#{room_name} - #{panel_name} :::: Panel is missing a tag"
|
||||
end
|
||||
|
||||
if panel.include?("non_counting") then
|
||||
non_counting += 1
|
||||
end
|
||||
|
||||
bad_subdirectives = []
|
||||
panel.keys.each do |key|
|
||||
unless panel_directives.include?(key) then
|
||||
bad_subdirectives << key
|
||||
end
|
||||
end
|
||||
unless bad_subdirectives.empty? then
|
||||
puts "#{room_name} - #{panel_name} :::: Panel has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
|
||||
end
|
||||
end
|
||||
|
||||
(room["doors"] || {}).each do |door_name, door|
|
||||
configured_doors.add("#{room_name} - #{door_name}")
|
||||
|
||||
if door.include?("id")
|
||||
door_ids = []
|
||||
if door["id"].kind_of? Array
|
||||
door_ids = door["id"]
|
||||
else
|
||||
door_ids = [door["id"]]
|
||||
end
|
||||
|
||||
door_ids.each do |door_id|
|
||||
unless doors.include? door_id then
|
||||
puts "#{room_name} - #{door_name} :::: Invalid Door ID #{door_id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if door.include?("painting_id")
|
||||
painting_ids = []
|
||||
if door["painting_id"].kind_of? Array
|
||||
painting_ids = door["painting_id"]
|
||||
else
|
||||
painting_ids = [door["painting_id"]]
|
||||
end
|
||||
|
||||
painting_ids.each do |painting_id|
|
||||
unless paintings.include? painting_id then
|
||||
puts "#{room_name} - #{door_name} :::: Invalid Painting ID #{painting_id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not door.include?("id") and not door.include?("painting_id") and not door["skip_item"] and not door["event"] then
|
||||
puts "#{room_name} - #{door_name} :::: Should be marked skip_item or event if there are no doors or paintings"
|
||||
end
|
||||
|
||||
if door.include?("panels")
|
||||
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
|
||||
elsif not door["skip_location"]
|
||||
puts "#{room_name} - #{door_name} :::: Should be marked skip_location if there are no panels"
|
||||
end
|
||||
|
||||
if door.include?("group")
|
||||
door_groups[door["group"]] ||= 0
|
||||
door_groups[door["group"]] += 1
|
||||
end
|
||||
|
||||
bad_subdirectives = []
|
||||
door.keys.each do |key|
|
||||
unless door_directives.include?(key) then
|
||||
bad_subdirectives << key
|
||||
end
|
||||
end
|
||||
unless bad_subdirectives.empty? then
|
||||
puts "#{room_name} - #{door_name} :::: Door has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
|
||||
end
|
||||
end
|
||||
|
||||
(room["paintings"] || []).each do |painting|
|
||||
if painting.include?("id") and painting["id"].kind_of? String then
|
||||
unless paintings.include? painting["id"] then
|
||||
puts "#{room_name} :::: Invalid Painting ID #{painting["id"]}"
|
||||
end
|
||||
else
|
||||
puts "#{room_name} :::: Painting is missing an ID"
|
||||
end
|
||||
|
||||
if painting["disable"] then
|
||||
# We're good.
|
||||
next
|
||||
end
|
||||
|
||||
if painting.include?("orientation") then
|
||||
unless ["north", "south", "east", "west"].include? painting["orientation"] then
|
||||
puts "#{room_name} - #{painting["id"] || "painting"} :::: Invalid orientation #{painting["orientation"]}"
|
||||
end
|
||||
else
|
||||
puts "#{room_name} :::: Painting is missing an orientation"
|
||||
end
|
||||
|
||||
if painting.include?("required_door")
|
||||
other_room = painting["required_door"].include?("room") ? painting["required_door"]["room"] : room_name
|
||||
mentioned_doors.add("#{other_room} - #{painting["required_door"]["door"]}")
|
||||
|
||||
unless painting["enter_only"] then
|
||||
puts "#{room_name} - #{painting["id"] || "painting"} :::: Should be marked enter_only if there is a required_door"
|
||||
end
|
||||
end
|
||||
|
||||
bad_subdirectives = []
|
||||
painting.keys.each do |key|
|
||||
unless painting_directives.include?(key) then
|
||||
bad_subdirectives << key
|
||||
end
|
||||
end
|
||||
unless bad_subdirectives.empty? then
|
||||
puts "#{room_name} - #{painting["id"] || "painting"} :::: Painting has the following invalid subdirectives: #{bad_subdirectives.join(", ")}"
|
||||
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}")
|
||||
end
|
||||
end
|
||||
end
|
||||
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
|
||||
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
|
||||
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
|
||||
end
|
||||
|
||||
door_groups.each do |group,num|
|
||||
if num == 1 then
|
||||
puts "Door group \"#{group}\" only has one door in it"
|
||||
end
|
||||
end
|
||||
|
||||
slashed_rooms = configured_rooms.select do |room|
|
||||
room.include? "/"
|
||||
end
|
||||
unless slashed_rooms.empty? then
|
||||
puts "The following rooms have slashes in their names: " + slashed_rooms.to_s
|
||||
end
|
||||
|
||||
slashed_panels = configured_panels.select do |panel|
|
||||
panel.include? "/"
|
||||
end
|
||||
unless slashed_panels.empty? then
|
||||
puts "The following panels have slashes in their names: " + slashed_panels.to_s
|
||||
end
|
||||
|
||||
slashed_doors = configured_doors.select do |door|
|
||||
door.include? "/"
|
||||
end
|
||||
unless slashed_doors.empty? then
|
||||
puts "The following doors have slashes in their names: " + slashed_doors.to_s
|
||||
end
|
||||
|
||||
puts "#{configured_panels.size} panels (#{non_counting} non counting)"
|
Reference in New Issue
Block a user