summary refs log tree commit diff stats
path: root/tools/validator
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2025-08-30 12:00:03 -0400
committerStar Rauchenberger <fefferburbia@gmail.com>2025-08-30 12:00:03 -0400
commitd2bc5b2811171685e8bdc895122987b53defcf0a (patch)
treedabf111e8d4ba8caceee46189075968e223e3ee8 /tools/validator
parent3b77044a6a53d38a6960eb2a5855283a00b24d75 (diff)
downloadlingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.tar.gz
lingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.tar.bz2
lingo2-archipelago-d2bc5b2811171685e8bdc895122987b53defcf0a.zip
Changed how door location names are formatted
STANDARD type doors with at most four panels in the same map area and no
other trigger objects will have their location names generated from the
names of the panels used to open the door, similar to Lingo 1. Other
door types will use the door's name. In either case, the name can be
overridden using the new location_name field.

Rooms can also set a panel_display_name field, which will be used in
location names for doors, and is used to group panels into areas.

Panels themselves can set display names, which differentiates their
locations from other panels in the same area.

Many maps were updated for this, but note that the_symbolic and
the_unyielding have validator failures because of duplicate panel names.
This won't matter until panelsanity is implemented.
Diffstat (limited to 'tools/validator')
-rw-r--r--tools/validator/CMakeLists.txt3
-rw-r--r--tools/validator/human_processor.cpp25
-rw-r--r--tools/validator/structs.h7
-rw-r--r--tools/validator/validator.cpp494
4 files changed, 315 insertions, 214 deletions
diff --git a/tools/validator/CMakeLists.txt b/tools/validator/CMakeLists.txt index 967b890..1a8fd9c 100644 --- a/tools/validator/CMakeLists.txt +++ b/tools/validator/CMakeLists.txt
@@ -1,3 +1,4 @@
1find_package(fmt REQUIRED)
1find_package(Protobuf REQUIRED) 2find_package(Protobuf REQUIRED)
2 3
3add_executable(validator 4add_executable(validator
@@ -9,4 +10,4 @@ add_executable(validator
9set_property(TARGET validator PROPERTY CXX_STANDARD 20) 10set_property(TARGET validator PROPERTY CXX_STANDARD 20)
10set_property(TARGET validator PROPERTY CXX_STANDARD_REQUIRED ON) 11set_property(TARGET validator PROPERTY CXX_STANDARD_REQUIRED ON)
11target_include_directories(validator PUBLIC ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tools) 12target_include_directories(validator PUBLIC ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/tools)
12target_link_libraries(validator PUBLIC protos util protobuf::libprotobuf) 13target_link_libraries(validator PUBLIC protos util fmt::fmt protobuf::libprotobuf)
diff --git a/tools/validator/human_processor.cpp b/tools/validator/human_processor.cpp index fb06d31..0f63936 100644 --- a/tools/validator/human_processor.cpp +++ b/tools/validator/human_processor.cpp
@@ -1,5 +1,6 @@
1#include "human_processor.h" 1#include "human_processor.h"
2 2
3#include <fmt/core.h>
3#include <google/protobuf/message.h> 4#include <google/protobuf/message.h>
4#include <google/protobuf/text_format.h> 5#include <google/protobuf/text_format.h>
5 6
@@ -93,7 +94,7 @@ class HumanProcessor {
93 room_info.definitions.push_back(h_room); 94 room_info.definitions.push_back(h_room);
94 95
95 for (const HumanPanel& h_panel : h_room.panels()) { 96 for (const HumanPanel& h_panel : h_room.panels()) {
96 ProcessPanel(h_panel, current_map_name, h_room.name()); 97 ProcessPanel(h_panel, current_map_name, h_room);
97 } 98 }
98 99
99 for (const HumanPainting& h_painting : h_room.paintings()) { 100 for (const HumanPainting& h_painting : h_room.paintings()) {
@@ -123,10 +124,10 @@ class HumanProcessor {
123 124
124 void ProcessPanel(const HumanPanel& h_panel, 125 void ProcessPanel(const HumanPanel& h_panel,
125 const std::string& current_map_name, 126 const std::string& current_map_name,
126 const std::string& current_room_name) { 127 const HumanRoom& h_room) {
127 PanelIdentifier panel_identifier; 128 PanelIdentifier panel_identifier;
128 panel_identifier.set_map(current_map_name); 129 panel_identifier.set_map(current_map_name);
129 panel_identifier.set_room(current_room_name); 130 panel_identifier.set_room(h_room.name());
130 panel_identifier.set_name(h_panel.name()); 131 panel_identifier.set_name(h_panel.name());
131 132
132 PanelInfo& panel_info = info_.panels[panel_identifier]; 133 PanelInfo& panel_info = info_.panels[panel_identifier];
@@ -155,6 +156,24 @@ class HumanProcessor {
155 RoomInfo& required_room_info = info_.rooms[required_room_identifier]; 156 RoomInfo& required_room_info = info_.rooms[required_room_identifier];
156 required_room_info.panels_referenced_by.push_back(panel_identifier); 157 required_room_info.panels_referenced_by.push_back(panel_identifier);
157 } 158 }
159
160 std::string map_area_name = current_map_name;
161 if (h_room.has_panel_display_name()) {
162 map_area_name =
163 fmt::format("{} ({})", current_map_name, h_room.panel_display_name());
164 }
165
166 panel_info.map_area_name = map_area_name;
167
168 std::string panelsanity_name;
169 if (h_panel.has_display_name()) {
170 panelsanity_name =
171 fmt::format("{} - {}", map_area_name, h_panel.display_name());
172 } else {
173 panelsanity_name = fmt::format("{} - {}", map_area_name, h_panel.name());
174 }
175 info_.panel_names[panelsanity_name].panels_used_by.push_back(
176 panel_identifier);
158 } 177 }
159 178
160 void ProcessPainting(const HumanPainting& h_painting, 179 void ProcessPainting(const HumanPainting& h_painting,
diff --git a/tools/validator/structs.h b/tools/validator/structs.h index 958038d..0ca96fe 100644 --- a/tools/validator/structs.h +++ b/tools/validator/structs.h
@@ -72,6 +72,8 @@ struct ProxyInfo {
72struct PanelInfo { 72struct PanelInfo {
73 std::vector<HumanPanel> definitions; 73 std::vector<HumanPanel> definitions;
74 74
75 std::string map_area_name;
76
75 std::vector<HumanConnection> connections_referenced_by; 77 std::vector<HumanConnection> connections_referenced_by;
76 std::vector<DoorIdentifier> doors_referenced_by; 78 std::vector<DoorIdentifier> doors_referenced_by;
77 79
@@ -96,6 +98,10 @@ struct EndingInfo {
96 std::vector<DoorIdentifier> doors_referenced_by; 98 std::vector<DoorIdentifier> doors_referenced_by;
97}; 99};
98 100
101struct PanelNameInfo {
102 std::vector<PanelIdentifier> panels_used_by;
103};
104
99struct CollectedInfo { 105struct CollectedInfo {
100 std::map<std::string, MapInfo> maps; 106 std::map<std::string, MapInfo> maps;
101 std::map<RoomIdentifier, RoomInfo, RoomIdentifierLess> rooms; 107 std::map<RoomIdentifier, RoomInfo, RoomIdentifierLess> rooms;
@@ -107,6 +113,7 @@ struct CollectedInfo {
107 keyholders; 113 keyholders;
108 std::map<LetterIdentifier, LetterInfo> letters; 114 std::map<LetterIdentifier, LetterInfo> letters;
109 std::map<std::string, EndingInfo> endings; 115 std::map<std::string, EndingInfo> endings;
116 std::map<std::string, PanelNameInfo> panel_names;
110}; 117};
111 118
112} // namespace com::fourisland::lingo2_archipelago 119} // namespace com::fourisland::lingo2_archipelago
diff --git a/tools/validator/validator.cpp b/tools/validator/validator.cpp index f802460..f5524c3 100644 --- a/tools/validator/validator.cpp +++ b/tools/validator/validator.cpp
@@ -9,291 +9,365 @@
9namespace com::fourisland::lingo2_archipelago { 9namespace com::fourisland::lingo2_archipelago {
10namespace { 10namespace {
11 11
12void ValidateMap(const std::string& map_name, const MapInfo& map_info) { 12class Validator {
13 for (const auto& [node_path, node_info] : map_info.game_nodes) { 13 public:
14 if (node_info.uses > 1) { 14 explicit Validator(const CollectedInfo& info) : info_(info) {}
15 std::cout << "Map " << map_name << " node " << node_path
16 << " is used in multiple places." << std::endl;
17 } else if (node_info.uses == 0) {
18 std::cout << "Map " << map_name << " node " << node_path
19 << " is not used." << std::endl;
20 }
21 15
22 if (!node_info.defined) { 16 void Validate() const {
23 std::cout << "Map " << map_name << " node " << node_path 17 for (const auto& [map_name, map_info] : info_.maps) {
24 << " is not defined in the game file." << std::endl; 18 ValidateMap(map_name, map_info);
19 }
20 for (const auto& [room_identifier, room_info] : info_.rooms) {
21 ValidateRoom(room_identifier, room_info);
22 }
23 for (const auto& [door_identifier, door_info] : info_.doors) {
24 ValidateDoor(door_identifier, door_info);
25 }
26 for (const auto& [port_identifier, port_info] : info_.ports) {
27 ValidatePort(port_identifier, port_info);
28 }
29 for (const auto& [painting_identifier, painting_info] : info_.paintings) {
30 ValidatePainting(painting_identifier, painting_info);
31 }
32 for (const auto& [panel_identifier, panel_info] : info_.panels) {
33 ValidatePanel(panel_identifier, panel_info);
34 }
35 for (const auto& [keyholder_identifier, keyholder_info] :
36 info_.keyholders) {
37 ValidateKeyholder(keyholder_identifier, keyholder_info);
38 }
39 for (const auto& [letter_identifier, letter_info] : info_.letters) {
40 ValidateLetter(letter_identifier, letter_info);
41 }
42 for (const auto& [ending_name, ending_info] : info_.endings) {
43 ValidateEnding(ending_name, ending_info);
44 }
45 for (const auto& [panel_name, panel_info] : info_.panel_names) {
46 ValidatePanelName(panel_name, panel_info);
25 } 47 }
26 } 48 }
27}
28 49
29void ValidateRoom(const RoomIdentifier& room_identifier, 50 private:
30 const RoomInfo& room_info) { 51 void ValidateMap(const std::string& map_name, const MapInfo& map_info) const {
31 if (room_info.definitions.empty()) { 52 for (const auto& [node_path, node_info] : map_info.game_nodes) {
32 std::cout << "Room " << room_identifier.ShortDebugString() 53 if (node_info.uses > 1) {
33 << " has no definition, but was referenced:" << std::endl; 54 std::cout << "Map " << map_name << " node " << node_path
55 << " is used in multiple places." << std::endl;
56 } else if (node_info.uses == 0) {
57 std::cout << "Map " << map_name << " node " << node_path
58 << " is not used." << std::endl;
59 }
34 60
35 for (const DoorIdentifier& door_identifier : 61 if (!node_info.defined) {
36 room_info.doors_referenced_by) { 62 std::cout << "Map " << map_name << " node " << node_path
37 std::cout << " DOOR " << door_identifier.ShortDebugString() 63 << " is not defined in the game file." << std::endl;
38 << std::endl; 64 }
39 } 65 }
66 }
40 67
41 for (const PanelIdentifier& panel_identifier : 68 void ValidateRoom(const RoomIdentifier& room_identifier,
42 room_info.panels_referenced_by) { 69 const RoomInfo& room_info) const {
43 std::cout << " PANEL " << panel_identifier.ShortDebugString() 70 if (room_info.definitions.empty()) {
44 << std::endl; 71 std::cout << "Room " << room_identifier.ShortDebugString()
45 } 72 << " has no definition, but was referenced:" << std::endl;
73
74 for (const DoorIdentifier& door_identifier :
75 room_info.doors_referenced_by) {
76 std::cout << " DOOR " << door_identifier.ShortDebugString()
77 << std::endl;
78 }
79
80 for (const PanelIdentifier& panel_identifier :
81 room_info.panels_referenced_by) {
82 std::cout << " PANEL " << panel_identifier.ShortDebugString()
83 << std::endl;
84 }
46 85
47 for (const HumanConnection& connection : 86 for (const HumanConnection& connection :
48 room_info.connections_referenced_by) { 87 room_info.connections_referenced_by) {
49 std::cout << " CONNECTION " << connection.ShortDebugString() 88 std::cout << " CONNECTION " << connection.ShortDebugString()
50 << std::endl; 89 << std::endl;
90 }
91 } else if (room_info.definitions.size() > 1) {
92 std::cout << "Room " << room_identifier.ShortDebugString()
93 << " was defined multiple times." << std::endl;
51 } 94 }
52 } else if (room_info.definitions.size() > 1) {
53 std::cout << "Room " << room_identifier.ShortDebugString()
54 << " was defined multiple times." << std::endl;
55 } 95 }
56}
57 96
58void ValidateDoor(const DoorIdentifier& door_identifier, 97 bool DoesDoorNeedLocationName(const HumanDoor& h_door,
59 const DoorInfo& door_info) { 98 const std::string& map_name) const {
60 if (door_info.definitions.empty()) { 99 if (h_door.type() != DoorType::STANDARD) {
61 std::cout << "Door " << door_identifier.ShortDebugString() 100 return false;
62 << " has no definition, but was referenced:" << std::endl;
63
64 for (const DoorIdentifier& other_door_identifier :
65 door_info.doors_referenced_by) {
66 std::cout << " DOOR " << other_door_identifier.ShortDebugString()
67 << std::endl;
68 } 101 }
69 102
70 for (const PanelIdentifier& panel_identifier : 103 if (h_door.keyholders_size() > 0 || h_door.endings_size() > 0) {
71 door_info.panels_referenced_by) { 104 return true;
72 std::cout << " PANEL " << panel_identifier.ShortDebugString()
73 << std::endl;
74 } 105 }
75 106
76 for (const PaintingIdentifier& painting_identifier : 107 if (h_door.panels_size() > 4) {
77 door_info.paintings_referenced_by) { 108 return true;
78 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
79 << std::endl;
80 } 109 }
81 110
82 for (const PortIdentifier& port_identifier : 111 std::set<std::string> map_areas;
83 door_info.ports_referenced_by) { 112 for (const PanelIdentifier& pi : h_door.panels()) {
84 std::cout << " PORT " << port_identifier.ShortDebugString() 113 auto full_pi =
85 << std::endl; 114 GetCompletePanelIdentifierWithoutAnswer(pi, map_name, std::nullopt);
115 if (full_pi) {
116 auto panel_info_it = info_.panels.find(*full_pi);
117 if (panel_info_it != info_.panels.end()) {
118 const PanelInfo& panel_info = panel_info_it->second;
119
120 map_areas.insert(panel_info.map_area_name);
121 }
122 }
86 } 123 }
87 124
88 for (const HumanConnection& connection : 125 if (map_areas.size() > 1) {
89 door_info.connections_referenced_by) { 126 return true;
90 std::cout << " CONNECTION " << connection.ShortDebugString()
91 << std::endl;
92 } 127 }
93 } else if (door_info.definitions.size() > 1) { 128
94 std::cout << "Door " << door_identifier.ShortDebugString() 129 return false;
95 << " was defined multiple times." << std::endl;
96 } 130 }
97 131
98 if (door_info.malformed_identifiers.HasAny()) { 132 void ValidateDoor(const DoorIdentifier& door_identifier,
99 std::cout << "Door " << door_identifier.ShortDebugString() 133 const DoorInfo& door_info) const {
100 << " has malformed identifiers:" << std::endl; 134 if (door_info.definitions.empty()) {
135 std::cout << "Door " << door_identifier.ShortDebugString()
136 << " has no definition, but was referenced:" << std::endl;
101 137
102 for (const PaintingIdentifier& painting_identifier : 138 for (const DoorIdentifier& other_door_identifier :
103 door_info.malformed_identifiers.paintings) { 139 door_info.doors_referenced_by) {
104 std::cout << " PAINTING " << painting_identifier.ShortDebugString() 140 std::cout << " DOOR " << other_door_identifier.ShortDebugString()
105 << std::endl; 141 << std::endl;
106 } 142 }
107 143
108 for (const PanelIdentifier& panel_identifier : 144 for (const PanelIdentifier& panel_identifier :
109 door_info.malformed_identifiers.panels) { 145 door_info.panels_referenced_by) {
110 std::cout << " PANEL " << panel_identifier.ShortDebugString() 146 std::cout << " PANEL " << panel_identifier.ShortDebugString()
111 << std::endl; 147 << std::endl;
112 } 148 }
113 149
114 for (const KeyholderIdentifier& keyholder_identifier : 150 for (const PaintingIdentifier& painting_identifier :
115 door_info.malformed_identifiers.keyholders) { 151 door_info.paintings_referenced_by) {
116 std::cout << " KEYHOLDER " << keyholder_identifier.ShortDebugString() 152 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
117 << std::endl; 153 << std::endl;
118 } 154 }
119 }
120}
121 155
122void ValidatePort(const PortIdentifier& port_identifier, 156 for (const PortIdentifier& port_identifier :
123 const PortInfo& port_info) { 157 door_info.ports_referenced_by) {
124 if (port_info.definitions.empty()) { 158 std::cout << " PORT " << port_identifier.ShortDebugString()
125 std::cout << "Port " << port_identifier.ShortDebugString() 159 << std::endl;
126 << " has no definition, but was referenced:" << std::endl; 160 }
127 161
128 for (const HumanConnection& connection : 162 for (const HumanConnection& connection :
129 port_info.connections_referenced_by) { 163 door_info.connections_referenced_by) {
130 std::cout << " CONNECTION " << connection.ShortDebugString() 164 std::cout << " CONNECTION " << connection.ShortDebugString()
131 << std::endl; 165 << std::endl;
166 }
167 } else if (door_info.definitions.size() > 1) {
168 std::cout << "Door " << door_identifier.ShortDebugString()
169 << " was defined multiple times." << std::endl;
132 } 170 }
133 } else if (port_info.definitions.size() > 1) {
134 std::cout << "Port " << port_identifier.ShortDebugString()
135 << " was defined multiple times." << std::endl;
136 }
137}
138 171
139void ValidatePainting(const PaintingIdentifier& painting_identifier, 172 if (door_info.malformed_identifiers.HasAny()) {
140 const PaintingInfo& painting_info) { 173 std::cout << "Door " << door_identifier.ShortDebugString()
141 if (painting_info.definitions.empty()) { 174 << " has malformed identifiers:" << std::endl;
142 std::cout << "Painting " << painting_identifier.ShortDebugString() 175
143 << " has no definition, but was referenced:" << std::endl; 176 for (const PaintingIdentifier& painting_identifier :
177 door_info.malformed_identifiers.paintings) {
178 std::cout << " PAINTING " << painting_identifier.ShortDebugString()
179 << std::endl;
180 }
181
182 for (const PanelIdentifier& panel_identifier :
183 door_info.malformed_identifiers.panels) {
184 std::cout << " PANEL " << panel_identifier.ShortDebugString()
185 << std::endl;
186 }
144 187
145 for (const DoorIdentifier& door_identifier : 188 for (const KeyholderIdentifier& keyholder_identifier :
146 painting_info.doors_referenced_by) { 189 door_info.malformed_identifiers.keyholders) {
147 std::cout << " DOOR " << door_identifier.ShortDebugString() 190 std::cout << " KEYHOLDER " << keyholder_identifier.ShortDebugString()
148 << std::endl; 191 << std::endl;
192 }
149 } 193 }
150 194
151 for (const HumanConnection& connection : 195 for (const HumanDoor& h_door : door_info.definitions) {
152 painting_info.connections_referenced_by) { 196 if (DoesDoorNeedLocationName(h_door, door_identifier.map()) &&
153 std::cout << " CONNECTION " << connection.ShortDebugString() 197 !h_door.has_location_name()) {
154 << std::endl; 198 std::cout << "Door " << door_identifier.ShortDebugString()
199 << " needs an explicit location name." << std::endl;
200 }
155 } 201 }
156 } else if (painting_info.definitions.size() > 1) {
157 std::cout << "Painting " << painting_identifier.ShortDebugString()
158 << " was defined multiple times." << std::endl;
159 } 202 }
160}
161 203
162void ValidatePanel(const PanelIdentifier& panel_identifier, 204 void ValidatePort(const PortIdentifier& port_identifier,
163 const PanelInfo& panel_info) { 205 const PortInfo& port_info) const {
164 if (panel_identifier.name().empty()) { 206 if (port_info.definitions.empty()) {
165 std::cout << "Panel " << panel_identifier.ShortDebugString() 207 std::cout << "Port " << port_identifier.ShortDebugString()
166 << " has no name." << std::endl; 208 << " has no definition, but was referenced:" << std::endl;
209
210 for (const HumanConnection& connection :
211 port_info.connections_referenced_by) {
212 std::cout << " CONNECTION " << connection.ShortDebugString()
213 << std::endl;
214 }
215 } else if (port_info.definitions.size() > 1) {
216 std::cout << "Port " << port_identifier.ShortDebugString()
217 << " was defined multiple times." << std::endl;
218 }
167 } 219 }
168 220
169 if (panel_info.definitions.empty()) { 221 void ValidatePainting(const PaintingIdentifier& painting_identifier,
170 std::cout << "Panel " << panel_identifier.ShortDebugString() 222 const PaintingInfo& painting_info) const {
171 << " has no definition, but was referenced:" << std::endl; 223 if (painting_info.definitions.empty()) {
224 std::cout << "Painting " << painting_identifier.ShortDebugString()
225 << " has no definition, but was referenced:" << std::endl;
172 226
173 for (const DoorIdentifier& door_identifier : 227 for (const DoorIdentifier& door_identifier :
174 panel_info.doors_referenced_by) { 228 painting_info.doors_referenced_by) {
175 std::cout << " DOOR " << door_identifier.ShortDebugString() 229 std::cout << " DOOR " << door_identifier.ShortDebugString()
176 << std::endl; 230 << std::endl;
177 } 231 }
178 232
179 for (const HumanConnection& connection : 233 for (const HumanConnection& connection :
180 panel_info.connections_referenced_by) { 234 painting_info.connections_referenced_by) {
181 std::cout << " CONNECTION " << connection.ShortDebugString() 235 std::cout << " CONNECTION " << connection.ShortDebugString()
182 << std::endl; 236 << std::endl;
237 }
238 } else if (painting_info.definitions.size() > 1) {
239 std::cout << "Painting " << painting_identifier.ShortDebugString()
240 << " was defined multiple times." << std::endl;
183 } 241 }
184 } else if (panel_info.definitions.size() > 1) {
185 std::cout << "Panel " << panel_identifier.ShortDebugString()
186 << " was defined multiple times." << std::endl;
187 } 242 }
188 243
189 for (const auto& [answer, proxy_info] : panel_info.proxies) { 244 void ValidatePanel(const PanelIdentifier& panel_identifier,
190 if (proxy_info.definitions.empty()) { 245 const PanelInfo& panel_info) const {
246 if (panel_identifier.name().empty()) {
247 std::cout << "Panel " << panel_identifier.ShortDebugString()
248 << " has no name." << std::endl;
249 }
250
251 if (panel_info.definitions.empty()) {
191 std::cout << "Panel " << panel_identifier.ShortDebugString() 252 std::cout << "Panel " << panel_identifier.ShortDebugString()
192 << " with answer \"" << answer 253 << " has no definition, but was referenced:" << std::endl;
193 << "\" has no definition, but was referenced:" << std::endl;
194 254
195 for (const DoorIdentifier& door_identifier : 255 for (const DoorIdentifier& door_identifier :
196 proxy_info.doors_referenced_by) { 256 panel_info.doors_referenced_by) {
197 std::cout << " DOOR " << door_identifier.ShortDebugString() 257 std::cout << " DOOR " << door_identifier.ShortDebugString()
198 << std::endl; 258 << std::endl;
199 } 259 }
200 260
201 for (const HumanConnection& connection : 261 for (const HumanConnection& connection :
202 proxy_info.connections_referenced_by) { 262 panel_info.connections_referenced_by) {
203 std::cout << " CONNECTION " << connection.ShortDebugString() 263 std::cout << " CONNECTION " << connection.ShortDebugString()
204 << std::endl; 264 << std::endl;
205 } 265 }
206 } else if (proxy_info.definitions.size() > 1) { 266 } else if (panel_info.definitions.size() > 1) {
207 std::cout << "Panel " << panel_identifier.ShortDebugString() 267 std::cout << "Panel " << panel_identifier.ShortDebugString()
208 << " with answer \"" << answer 268 << " was defined multiple times." << std::endl;
209 << "\" was defined multiple times." << std::endl; 269 }
270
271 for (const auto& [answer, proxy_info] : panel_info.proxies) {
272 if (proxy_info.definitions.empty()) {
273 std::cout << "Panel " << panel_identifier.ShortDebugString()
274 << " with answer \"" << answer
275 << "\" has no definition, but was referenced:" << std::endl;
276
277 for (const DoorIdentifier& door_identifier :
278 proxy_info.doors_referenced_by) {
279 std::cout << " DOOR " << door_identifier.ShortDebugString()
280 << std::endl;
281 }
282
283 for (const HumanConnection& connection :
284 proxy_info.connections_referenced_by) {
285 std::cout << " CONNECTION " << connection.ShortDebugString()
286 << std::endl;
287 }
288 } else if (proxy_info.definitions.size() > 1) {
289 std::cout << "Panel " << panel_identifier.ShortDebugString()
290 << " with answer \"" << answer
291 << "\" was defined multiple times." << std::endl;
292 }
210 } 293 }
211 } 294 }
212}
213 295
214void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier, 296 void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier,
215 const KeyholderInfo& keyholder_info) { 297 const KeyholderInfo& keyholder_info) const {
216 if (keyholder_info.definitions.empty()) { 298 if (keyholder_info.definitions.empty()) {
217 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() 299 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
218 << " has no definition, but was referenced:" << std::endl; 300 << " has no definition, but was referenced:" << std::endl;
219 301
220 for (const DoorIdentifier& door_identifier : 302 for (const DoorIdentifier& door_identifier :
221 keyholder_info.doors_referenced_by) { 303 keyholder_info.doors_referenced_by) {
222 std::cout << " DOOR " << door_identifier.ShortDebugString() 304 std::cout << " DOOR " << door_identifier.ShortDebugString()
223 << std::endl; 305 << std::endl;
306 }
307 } else if (keyholder_info.definitions.size() > 1) {
308 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
309 << " was defined multiple times." << std::endl;
224 } 310 }
225 } else if (keyholder_info.definitions.size() > 1) {
226 std::cout << "Keyholder " << keyholder_identifier.ShortDebugString()
227 << " was defined multiple times." << std::endl;
228 } 311 }
229}
230 312
231void ValidateLetter(const LetterIdentifier& letter_identifier, 313 void ValidateLetter(const LetterIdentifier& letter_identifier,
232 const LetterInfo& letter_info) { 314 const LetterInfo& letter_info) const {
233 std::string letter_name = std::string(1, std::get<0>(letter_identifier)) + 315 std::string letter_name = std::string(1, std::get<0>(letter_identifier)) +
234 (std::get<1>(letter_identifier) ? "2" : "1"); 316 (std::get<1>(letter_identifier) ? "2" : "1");
235 317
236 if (letter_info.defined_in.size() > 1) { 318 if (letter_info.defined_in.size() > 1) {
237 std::cout << "Letter " << letter_name 319 std::cout << "Letter " << letter_name
238 << " was defined in multiple places:" << std::endl; 320 << " was defined in multiple places:" << std::endl;
239 321
240 for (const RoomIdentifier& room_identifier : letter_info.defined_in) { 322 for (const RoomIdentifier& room_identifier : letter_info.defined_in) {
241 std::cout << " " << room_identifier.ShortDebugString() << std::endl; 323 std::cout << " " << room_identifier.ShortDebugString() << std::endl;
324 }
242 } 325 }
243 } 326 }
244}
245 327
246void ValidateEnding(const std::string& ending_name, 328 void ValidateEnding(const std::string& ending_name,
247 const EndingInfo& ending_info) { 329 const EndingInfo& ending_info) const {
248 if (ending_info.defined_in.empty()) { 330 if (ending_info.defined_in.empty()) {
249 std::cout << "Ending " << ending_name 331 std::cout << "Ending " << ending_name
250 << " has no definition, but was referenced:" << std::endl; 332 << " has no definition, but was referenced:" << std::endl;
333
334 for (const DoorIdentifier& door_identifier :
335 ending_info.doors_referenced_by) {
336 std::cout << " DOOR " << door_identifier.ShortDebugString()
337 << std::endl;
338 }
339 } else if (ending_info.defined_in.size() > 1) {
340 std::cout << "Ending " << ending_name
341 << " was defined in multiple places:" << std::endl;
251 342
252 for (const DoorIdentifier& door_identifier : 343 for (const RoomIdentifier& room_identifier : ending_info.defined_in) {
253 ending_info.doors_referenced_by) { 344 std::cout << " " << room_identifier.ShortDebugString() << std::endl;
254 std::cout << " DOOR " << door_identifier.ShortDebugString() 345 }
255 << std::endl;
256 } 346 }
257 } else if (ending_info.defined_in.size() > 1) { 347 }
258 std::cout << "Ending " << ending_name 348
259 << " was defined in multiple places:" << std::endl; 349 void ValidatePanelName(const std::string& panel_name,
350 const PanelNameInfo& panel_info) const {
351 if (panel_info.panels_used_by.size() > 1) {
352 std::cout << "The location name \"" << panel_name
353 << "\" is used by multiple panels:" << std::endl;
260 354
261 for (const RoomIdentifier& room_identifier : ending_info.defined_in) { 355 for (const PanelIdentifier& panel_identifier :
262 std::cout << " " << room_identifier.ShortDebugString() << std::endl; 356 panel_info.panels_used_by) {
357 std::cout << " PANEL " << panel_identifier.ShortDebugString()
358 << std::endl;
359 }
263 } 360 }
264 } 361 }
265} 362
363 const CollectedInfo& info_;
364};
266 365
267} // namespace 366} // namespace
268 367
269void ValidateCollectedInfo(const CollectedInfo& info) { 368void ValidateCollectedInfo(const CollectedInfo& info) {
270 for (const auto& [map_name, map_info] : info.maps) { 369 Validator validator(info);
271 ValidateMap(map_name, map_info); 370 validator.Validate();
272 }
273 for (const auto& [room_identifier, room_info] : info.rooms) {
274 ValidateRoom(room_identifier, room_info);
275 }
276 for (const auto& [door_identifier, door_info] : info.doors) {
277 ValidateDoor(door_identifier, door_info);
278 }
279 for (const auto& [port_identifier, port_info] : info.ports) {
280 ValidatePort(port_identifier, port_info);
281 }
282 for (const auto& [painting_identifier, painting_info] : info.paintings) {
283 ValidatePainting(painting_identifier, painting_info);
284 }
285 for (const auto& [panel_identifier, panel_info] : info.panels) {
286 ValidatePanel(panel_identifier, panel_info);
287 }
288 for (const auto& [keyholder_identifier, keyholder_info] : info.keyholders) {
289 ValidateKeyholder(keyholder_identifier, keyholder_info);
290 }
291 for (const auto& [letter_identifier, letter_info] : info.letters) {
292 ValidateLetter(letter_identifier, letter_info);
293 }
294 for (const auto& [ending_name, ending_info] : info.endings) {
295 ValidateEnding(ending_name, ending_info);
296 }
297} 371}
298 372
299} // namespace com::fourisland::lingo2_archipelago 373} // namespace com::fourisland::lingo2_archipelago