diff options
Diffstat (limited to 'tools/validator/validator.cpp')
| -rw-r--r-- | tools/validator/validator.cpp | 247 |
1 files changed, 241 insertions, 6 deletions
| diff --git a/tools/validator/validator.cpp b/tools/validator/validator.cpp index f5524c3..e9fbb74 100644 --- a/tools/validator/validator.cpp +++ b/tools/validator/validator.cpp | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | #include "validator.h" | 1 | #include "validator.h" |
| 2 | 2 | ||
| 3 | #include <algorithm> | ||
| 3 | #include <iostream> | 4 | #include <iostream> |
| 4 | 5 | ||
| 5 | #include "proto/human.pb.h" | 6 | #include "proto/human.pb.h" |
| @@ -45,6 +46,12 @@ class Validator { | |||
| 45 | for (const auto& [panel_name, panel_info] : info_.panel_names) { | 46 | for (const auto& [panel_name, panel_info] : info_.panel_names) { |
| 46 | ValidatePanelName(panel_name, panel_info); | 47 | ValidatePanelName(panel_name, panel_info); |
| 47 | } | 48 | } |
| 49 | for (const auto& [prog_name, prog_info] : info_.progressives) { | ||
| 50 | ValidateProgressive(prog_name, prog_info); | ||
| 51 | } | ||
| 52 | for (const auto& [group_name, group_info] : info_.door_groups) { | ||
| 53 | ValidateDoorGroup(group_name, group_info); | ||
| 54 | } | ||
| 48 | } | 55 | } |
| 49 | 56 | ||
| 50 | private: | 57 | private: |
| @@ -63,6 +70,27 @@ class Validator { | |||
| 63 | << " is not defined in the game file." << std::endl; | 70 | << " is not defined in the game file." << std::endl; |
| 64 | } | 71 | } |
| 65 | } | 72 | } |
| 73 | |||
| 74 | if (map_info.malformed_worldport_entrance) { | ||
| 75 | std::cout << "The worldport entrance for map " << map_name | ||
| 76 | << " is malformed." << std::endl; | ||
| 77 | } | ||
| 78 | |||
| 79 | if (map_info.has_rte_id) { | ||
| 80 | if (!std::any_of( | ||
| 81 | map_info.definitions.begin(), map_info.definitions.end(), | ||
| 82 | [](const HumanMap& h_map) { return h_map.has_rte_room(); })) { | ||
| 83 | std::cout << "Map " << map_name << " has an RTE ID but no RTE room." | ||
| 84 | << std::endl; | ||
| 85 | } | ||
| 86 | } else { | ||
| 87 | if (std::any_of( | ||
| 88 | map_info.definitions.begin(), map_info.definitions.end(), | ||
| 89 | [](const HumanMap& h_map) { return h_map.has_rte_room(); })) { | ||
| 90 | std::cout << "Map " << map_name << " has an RTE room but no RTE ID." | ||
| 91 | << std::endl; | ||
| 92 | } | ||
| 93 | } | ||
| 66 | } | 94 | } |
| 67 | 95 | ||
| 68 | void ValidateRoom(const RoomIdentifier& room_identifier, | 96 | void ValidateRoom(const RoomIdentifier& room_identifier, |
| @@ -88,6 +116,10 @@ class Validator { | |||
| 88 | std::cout << " CONNECTION " << connection.ShortDebugString() | 116 | std::cout << " CONNECTION " << connection.ShortDebugString() |
| 89 | << std::endl; | 117 | << std::endl; |
| 90 | } | 118 | } |
| 119 | |||
| 120 | for (const std::string& map_name : room_info.map_rtes_referenced_by) { | ||
| 121 | std::cout << " MAP RTE " << map_name << std::endl; | ||
| 122 | } | ||
| 91 | } else if (room_info.definitions.size() > 1) { | 123 | } else if (room_info.definitions.size() > 1) { |
| 92 | std::cout << "Room " << room_identifier.ShortDebugString() | 124 | std::cout << "Room " << room_identifier.ShortDebugString() |
| 93 | << " was defined multiple times." << std::endl; | 125 | << " was defined multiple times." << std::endl; |
| @@ -100,7 +132,8 @@ class Validator { | |||
| 100 | return false; | 132 | return false; |
| 101 | } | 133 | } |
| 102 | 134 | ||
| 103 | if (h_door.keyholders_size() > 0 || h_door.endings_size() > 0) { | 135 | if (h_door.keyholders_size() > 0 || h_door.white_ending() || |
| 136 | h_door.complete_at() > 0) { | ||
| 104 | return true; | 137 | return true; |
| 105 | } | 138 | } |
| 106 | 139 | ||
| @@ -164,6 +197,20 @@ class Validator { | |||
| 164 | std::cout << " CONNECTION " << connection.ShortDebugString() | 197 | std::cout << " CONNECTION " << connection.ShortDebugString() |
| 165 | << std::endl; | 198 | << std::endl; |
| 166 | } | 199 | } |
| 200 | |||
| 201 | for (const std::string& prog_name : | ||
| 202 | door_info.progressives_referenced_by) { | ||
| 203 | std::cout << " PROGRESSIVE " << prog_name << std::endl; | ||
| 204 | } | ||
| 205 | |||
| 206 | for (const std::string& group_name : | ||
| 207 | door_info.door_groups_referenced_by) { | ||
| 208 | std::cout << " DOOR GROUP " << group_name << std::endl; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (door_info.has_id) { | ||
| 212 | std::cout << " An AP ID is present." << std::endl; | ||
| 213 | } | ||
| 167 | } else if (door_info.definitions.size() > 1) { | 214 | } else if (door_info.definitions.size() > 1) { |
| 168 | std::cout << "Door " << door_identifier.ShortDebugString() | 215 | std::cout << "Door " << door_identifier.ShortDebugString() |
| 169 | << " was defined multiple times." << std::endl; | 216 | << " was defined multiple times." << std::endl; |
| @@ -198,6 +245,33 @@ class Validator { | |||
| 198 | std::cout << "Door " << door_identifier.ShortDebugString() | 245 | std::cout << "Door " << door_identifier.ShortDebugString() |
| 199 | << " needs an explicit location name." << std::endl; | 246 | << " needs an explicit location name." << std::endl; |
| 200 | } | 247 | } |
| 248 | |||
| 249 | if (h_door.type() == DoorType::STANDARD || | ||
| 250 | h_door.type() == DoorType::LOCATION_ONLY || | ||
| 251 | h_door.type() == DoorType::GRAVESTONE || h_door.legacy_location()) { | ||
| 252 | if (h_door.double_letters()) { | ||
| 253 | std::cout << "Door " << door_identifier.ShortDebugString() | ||
| 254 | << " is a location that depends on double_letters." | ||
| 255 | << std::endl; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (!h_door.has_location_room()) { | ||
| 259 | std::cout << "Door " << door_identifier.ShortDebugString() | ||
| 260 | << " is missing a location_room." << std::endl; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | bool needs_id = (h_door.type() != DoorType::EVENT || h_door.latch() || | ||
| 265 | h_door.legacy_location()); | ||
| 266 | if (door_info.has_id != needs_id) { | ||
| 267 | if (needs_id) { | ||
| 268 | std::cout << "Door " << door_identifier.ShortDebugString() | ||
| 269 | << " is missing an AP ID." << std::endl; | ||
| 270 | } else { | ||
| 271 | std::cout << "Door " << door_identifier.ShortDebugString() | ||
| 272 | << " should not have an AP ID." << std::endl; | ||
| 273 | } | ||
| 274 | } | ||
| 201 | } | 275 | } |
| 202 | } | 276 | } |
| 203 | 277 | ||
| @@ -212,10 +286,57 @@ class Validator { | |||
| 212 | std::cout << " CONNECTION " << connection.ShortDebugString() | 286 | std::cout << " CONNECTION " << connection.ShortDebugString() |
| 213 | << std::endl; | 287 | << std::endl; |
| 214 | } | 288 | } |
| 289 | |||
| 290 | for (const std::string& map_name : port_info.map_worldport_entrances) { | ||
| 291 | std::cout << " MAP (worldport_entrance) " << map_name << std::endl; | ||
| 292 | } | ||
| 293 | |||
| 294 | if (port_info.has_id) { | ||
| 295 | std::cout << " An AP ID is present." << std::endl; | ||
| 296 | } | ||
| 215 | } else if (port_info.definitions.size() > 1) { | 297 | } else if (port_info.definitions.size() > 1) { |
| 216 | std::cout << "Port " << port_identifier.ShortDebugString() | 298 | std::cout << "Port " << port_identifier.ShortDebugString() |
| 217 | << " was defined multiple times." << std::endl; | 299 | << " was defined multiple times." << std::endl; |
| 218 | } | 300 | } |
| 301 | |||
| 302 | if (!port_info.target_connections_referenced_by.empty()) { | ||
| 303 | for (const HumanPort& port : port_info.definitions) { | ||
| 304 | if (port.has_required_door()) { | ||
| 305 | std::cout << "Port " << port_identifier.ShortDebugString() | ||
| 306 | << " has a required door but is the target of a connection:" | ||
| 307 | << std::endl; | ||
| 308 | |||
| 309 | for (const HumanConnection& connection : | ||
| 310 | port_info.target_connections_referenced_by) { | ||
| 311 | std::cout << " CONNECTION " << connection.ShortDebugString() | ||
| 312 | << std::endl; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | for (const HumanPort& port : port_info.definitions) { | ||
| 319 | if (!port.no_shuffle()) { | ||
| 320 | if (!port.has_destination()) { | ||
| 321 | std::cout << "Port " << port_identifier.ShortDebugString() | ||
| 322 | << " is shuffleable and missing a destination." | ||
| 323 | << std::endl; | ||
| 324 | } | ||
| 325 | if (!port.has_rotation()) { | ||
| 326 | std::cout << "Port " << port_identifier.ShortDebugString() | ||
| 327 | << " is shuffleable and missing a rotation." << std::endl; | ||
| 328 | } | ||
| 329 | if (!port_info.has_id) { | ||
| 330 | std::cout << "Port " << port_identifier.ShortDebugString() | ||
| 331 | << " is missing an AP ID." << std::endl; | ||
| 332 | } | ||
| 333 | } else { | ||
| 334 | if (port_info.has_id) { | ||
| 335 | std::cout << "Port " << port_identifier.ShortDebugString() | ||
| 336 | << " should not have an AP ID." << std::endl; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | } | ||
| 219 | } | 340 | } |
| 220 | 341 | ||
| 221 | void ValidatePainting(const PaintingIdentifier& painting_identifier, | 342 | void ValidatePainting(const PaintingIdentifier& painting_identifier, |
| @@ -239,6 +360,22 @@ class Validator { | |||
| 239 | std::cout << "Painting " << painting_identifier.ShortDebugString() | 360 | std::cout << "Painting " << painting_identifier.ShortDebugString() |
| 240 | << " was defined multiple times." << std::endl; | 361 | << " was defined multiple times." << std::endl; |
| 241 | } | 362 | } |
| 363 | |||
| 364 | if (!painting_info.target_connections_referenced_by.empty()) { | ||
| 365 | for (const HumanPainting& painting : painting_info.definitions) { | ||
| 366 | if (painting.has_required_door()) { | ||
| 367 | std::cout << "Painting " << painting_identifier.ShortDebugString() | ||
| 368 | << " has a required door but is the target of a connection:" | ||
| 369 | << std::endl; | ||
| 370 | |||
| 371 | for (const HumanConnection& connection : | ||
| 372 | painting_info.target_connections_referenced_by) { | ||
| 373 | std::cout << " CONNECTION " << connection.ShortDebugString() | ||
| 374 | << std::endl; | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | } | ||
| 242 | } | 379 | } |
| 243 | 380 | ||
| 244 | void ValidatePanel(const PanelIdentifier& panel_identifier, | 381 | void ValidatePanel(const PanelIdentifier& panel_identifier, |
| @@ -263,6 +400,10 @@ class Validator { | |||
| 263 | std::cout << " CONNECTION " << connection.ShortDebugString() | 400 | std::cout << " CONNECTION " << connection.ShortDebugString() |
| 264 | << std::endl; | 401 | << std::endl; |
| 265 | } | 402 | } |
| 403 | |||
| 404 | if (panel_info.has_id) { | ||
| 405 | std::cout << " An AP ID is present." << std::endl; | ||
| 406 | } | ||
| 266 | } else if (panel_info.definitions.size() > 1) { | 407 | } else if (panel_info.definitions.size() > 1) { |
| 267 | std::cout << "Panel " << panel_identifier.ShortDebugString() | 408 | std::cout << "Panel " << panel_identifier.ShortDebugString() |
| 268 | << " was defined multiple times." << std::endl; | 409 | << " was defined multiple times." << std::endl; |
| @@ -291,6 +432,27 @@ class Validator { | |||
| 291 | << "\" was defined multiple times." << std::endl; | 432 | << "\" was defined multiple times." << std::endl; |
| 292 | } | 433 | } |
| 293 | } | 434 | } |
| 435 | |||
| 436 | if (!panel_info.has_id) { | ||
| 437 | std::cout << "Panel " << panel_identifier.ShortDebugString() | ||
| 438 | << " is missing an AP ID." << std::endl; | ||
| 439 | } | ||
| 440 | |||
| 441 | if (!panel_info.target_connections_referenced_by.empty()) { | ||
| 442 | for (const HumanPanel& panel : panel_info.definitions) { | ||
| 443 | if (panel.has_required_door()) { | ||
| 444 | std::cout << "Panel " << panel_identifier.ShortDebugString() | ||
| 445 | << " has a required door but is the target of a connection:" | ||
| 446 | << std::endl; | ||
| 447 | |||
| 448 | for (const HumanConnection& connection : | ||
| 449 | panel_info.target_connections_referenced_by) { | ||
| 450 | std::cout << " CONNECTION " << connection.ShortDebugString() | ||
| 451 | << std::endl; | ||
| 452 | } | ||
| 453 | } | ||
| 454 | } | ||
| 455 | } | ||
| 294 | } | 456 | } |
| 295 | 457 | ||
| 296 | void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier, | 458 | void ValidateKeyholder(const KeyholderIdentifier& keyholder_identifier, |
| @@ -304,10 +466,28 @@ class Validator { | |||
| 304 | std::cout << " DOOR " << door_identifier.ShortDebugString() | 466 | std::cout << " DOOR " << door_identifier.ShortDebugString() |
| 305 | << std::endl; | 467 | << std::endl; |
| 306 | } | 468 | } |
| 469 | |||
| 470 | if (keyholder_info.has_id) { | ||
| 471 | std::cout << " An AP ID is present." << std::endl; | ||
| 472 | } | ||
| 307 | } else if (keyholder_info.definitions.size() > 1) { | 473 | } else if (keyholder_info.definitions.size() > 1) { |
| 308 | std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() | 474 | std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() |
| 309 | << " was defined multiple times." << std::endl; | 475 | << " was defined multiple times." << std::endl; |
| 310 | } | 476 | } |
| 477 | |||
| 478 | for (const HumanKeyholder& h_keyholder : keyholder_info.definitions) { | ||
| 479 | bool needs_id = (h_keyholder.has_key()); | ||
| 480 | |||
| 481 | if (needs_id != keyholder_info.has_id) { | ||
| 482 | if (needs_id) { | ||
| 483 | std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() | ||
| 484 | << " is missing an AP ID." << std::endl; | ||
| 485 | } else { | ||
| 486 | std::cout << "Keyholder " << keyholder_identifier.ShortDebugString() | ||
| 487 | << " should not have an AP ID." << std::endl; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | } | ||
| 311 | } | 491 | } |
| 312 | 492 | ||
| 313 | void ValidateLetter(const LetterIdentifier& letter_identifier, | 493 | void ValidateLetter(const LetterIdentifier& letter_identifier, |
| @@ -315,7 +495,14 @@ class Validator { | |||
| 315 | std::string letter_name = std::string(1, std::get<0>(letter_identifier)) + | 495 | std::string letter_name = std::string(1, std::get<0>(letter_identifier)) + |
| 316 | (std::get<1>(letter_identifier) ? "2" : "1"); | 496 | (std::get<1>(letter_identifier) ? "2" : "1"); |
| 317 | 497 | ||
| 318 | if (letter_info.defined_in.size() > 1) { | 498 | if (letter_info.defined_in.empty()) { |
| 499 | std::cout << "Letter " << letter_name | ||
| 500 | << " has no definition, but was referenced:" << std::endl; | ||
| 501 | |||
| 502 | if (letter_info.has_id) { | ||
| 503 | std::cout << " An AP ID is present." << std::endl; | ||
| 504 | } | ||
| 505 | } else if (letter_info.defined_in.size() > 1) { | ||
| 319 | std::cout << "Letter " << letter_name | 506 | std::cout << "Letter " << letter_name |
| 320 | << " was defined in multiple places:" << std::endl; | 507 | << " was defined in multiple places:" << std::endl; |
| 321 | 508 | ||
| @@ -323,6 +510,11 @@ class Validator { | |||
| 323 | std::cout << " " << room_identifier.ShortDebugString() << std::endl; | 510 | std::cout << " " << room_identifier.ShortDebugString() << std::endl; |
| 324 | } | 511 | } |
| 325 | } | 512 | } |
| 513 | |||
| 514 | if (!letter_info.has_id) { | ||
| 515 | std::cout << "Letter " << letter_name << " is missing an AP ID." | ||
| 516 | << std::endl; | ||
| 517 | } | ||
| 326 | } | 518 | } |
| 327 | 519 | ||
| 328 | void ValidateEnding(const std::string& ending_name, | 520 | void ValidateEnding(const std::string& ending_name, |
| @@ -331,10 +523,8 @@ class Validator { | |||
| 331 | std::cout << "Ending " << ending_name | 523 | std::cout << "Ending " << ending_name |
| 332 | << " has no definition, but was referenced:" << std::endl; | 524 | << " has no definition, but was referenced:" << std::endl; |
| 333 | 525 | ||
| 334 | for (const DoorIdentifier& door_identifier : | 526 | if (ending_info.has_id) { |
| 335 | ending_info.doors_referenced_by) { | 527 | std::cout << " An AP ID is present." << std::endl; |
| 336 | std::cout << " DOOR " << door_identifier.ShortDebugString() | ||
| 337 | << std::endl; | ||
| 338 | } | 528 | } |
| 339 | } else if (ending_info.defined_in.size() > 1) { | 529 | } else if (ending_info.defined_in.size() > 1) { |
| 340 | std::cout << "Ending " << ending_name | 530 | std::cout << "Ending " << ending_name |
| @@ -344,6 +534,11 @@ class Validator { | |||
| 344 | std::cout << " " << room_identifier.ShortDebugString() << std::endl; | 534 | std::cout << " " << room_identifier.ShortDebugString() << std::endl; |
| 345 | } | 535 | } |
| 346 | } | 536 | } |
| 537 | |||
| 538 | if (!ending_info.has_id) { | ||
| 539 | std::cout << "Ending " << ending_name << " is missing an AP ID." | ||
| 540 | << std::endl; | ||
| 541 | } | ||
| 347 | } | 542 | } |
| 348 | 543 | ||
| 349 | void ValidatePanelName(const std::string& panel_name, | 544 | void ValidatePanelName(const std::string& panel_name, |
| @@ -360,6 +555,46 @@ class Validator { | |||
| 360 | } | 555 | } |
| 361 | } | 556 | } |
| 362 | 557 | ||
| 558 | void ValidateProgressive(const std::string& prog_name, | ||
| 559 | const ProgressiveInfo& prog_info) const { | ||
| 560 | if (prog_info.definitions.empty()) { | ||
| 561 | std::cout << "Progressive \"" << prog_name | ||
| 562 | << "\" has no definition, but was referenced:" << std::endl; | ||
| 563 | |||
| 564 | if (prog_info.has_id) { | ||
| 565 | std::cout << " An AP ID is present." << std::endl; | ||
| 566 | } | ||
| 567 | } else if (prog_info.definitions.size() > 1) { | ||
| 568 | std::cout << "Progressive \"" << prog_name | ||
| 569 | << "\" has multiple definitions." << std::endl; | ||
| 570 | } | ||
| 571 | |||
| 572 | if (!prog_info.has_id) { | ||
| 573 | std::cout << "Progressive \"" << prog_name << "\" is missing an AP ID." | ||
| 574 | << std::endl; | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | void ValidateDoorGroup(const std::string& group_name, | ||
| 579 | const DoorGroupInfo& group_info) const { | ||
| 580 | if (group_info.definitions.empty()) { | ||
| 581 | std::cout << "Door group \"" << group_name | ||
| 582 | << "\" has no definition, but was referenced:" << std::endl; | ||
| 583 | |||
| 584 | if (group_info.has_id) { | ||
| 585 | std::cout << " An AP ID is present." << std::endl; | ||
| 586 | } | ||
| 587 | } else if (group_info.definitions.size() > 1) { | ||
| 588 | std::cout << "Door group \"" << group_name | ||
| 589 | << "\" has multiple definitions." << std::endl; | ||
| 590 | } | ||
| 591 | |||
| 592 | if (!group_info.has_id) { | ||
| 593 | std::cout << "Door group \"" << group_name << "\" is missing an AP ID." | ||
| 594 | << std::endl; | ||
| 595 | } | ||
| 596 | } | ||
| 597 | |||
| 363 | const CollectedInfo& info_; | 598 | const CollectedInfo& info_; |
| 364 | }; | 599 | }; |
| 365 | 600 | ||
