|
12 | 12 | import unittest |
13 | 13 | from collections import Counter, defaultdict |
14 | 14 | from typing import Literal, Optional, Any, overload |
| 15 | +from unittest.mock import patch |
15 | 16 |
|
16 | 17 | from EntranceShuffle import EntranceShuffleError |
17 | 18 | from Fill import ShuffleError |
@@ -567,6 +568,68 @@ def test_fix_broken_drops(self): |
567 | 568 |
|
568 | 569 |
|
569 | 570 | class TestHints(unittest.TestCase): |
| 571 | + def test_multiworld_goal_weights_initialized_per_world(self): |
| 572 | + settings = make_settings_for_test({ |
| 573 | + "world_count": 2, |
| 574 | + "bridge": "medallions", |
| 575 | + "bridge_medallions": 4, |
| 576 | + "shuffle_ganon_bosskey": "medallions", |
| 577 | + "ganon_bosskey_medallions": 6, |
| 578 | + "item_pool_value": "minimal", |
| 579 | + "trials_random": False, |
| 580 | + "trials": 0, |
| 581 | + "open_forest": "closed_deku", |
| 582 | + "open_door_of_time": "open", |
| 583 | + "shuffle_song_items": "song", |
| 584 | + "tokensanity": "off", |
| 585 | + "mq_dungeons_mode": "vanilla", |
| 586 | + "hint_dist_user": { |
| 587 | + "name": "goal_weight_regression", |
| 588 | + "gui_name": "Goal Weight Regression", |
| 589 | + "description": "Custom hint distribution for multiworld goal weight regression testing.", |
| 590 | + "add_locations": [], |
| 591 | + "remove_locations": [], |
| 592 | + "add_items": [], |
| 593 | + "remove_items": [], |
| 594 | + "dungeons_woth_limit": 2, |
| 595 | + "dungeons_barren_limit": 1, |
| 596 | + "named_items_required": True, |
| 597 | + "vague_named_items": False, |
| 598 | + "use_default_goals": True, |
| 599 | + "distribution": { |
| 600 | + "trial": {"order": 1, "weight": 0.0, "fixed": 0, "copies": 1}, |
| 601 | + "always": {"order": 2, "weight": 0.0, "fixed": 0, "copies": 1}, |
| 602 | + "woth": {"order": 3, "weight": 0.0, "fixed": 0, "copies": 1}, |
| 603 | + "goal": {"order": 4, "weight": 0.0, "fixed": 6, "copies": 1}, |
| 604 | + "barren": {"order": 5, "weight": 0.0, "fixed": 0, "copies": 1}, |
| 605 | + "entrance": {"order": 6, "weight": 0.0, "fixed": 0, "copies": 1}, |
| 606 | + "sometimes": {"order": 7, "weight": 0.0, "fixed": 99, "copies": 1}, |
| 607 | + }, |
| 608 | + }, |
| 609 | + }, seed="TESTTESTTEST", outfilename="multiworld-goal-weight-regression") |
| 610 | + |
| 611 | + # Build weights via update_goal_items and skip hint generation, which mutates weights. |
| 612 | + with patch("Main.build_gossip_hints", return_value=None): |
| 613 | + spoiler = main(settings) |
| 614 | + |
| 615 | + self.assertGreater(len(spoiler.worlds), 1) |
| 616 | + for world in spoiler.worlds[1:]: |
| 617 | + with self.subTest(world=world.id + 1): |
| 618 | + self.assertIn(world.id, spoiler.goal_locations) |
| 619 | + self.assertGreater(len(spoiler.goal_locations[world.id]), 0) |
| 620 | + |
| 621 | + weighted_goals = 0 |
| 622 | + for category_name, goals in spoiler.goal_locations[world.id].items(): |
| 623 | + category = world.goal_categories[category_name] |
| 624 | + for goal_name, goal_worlds in goals.items(): |
| 625 | + if not any(len(locations) > 0 for locations in goal_worlds.values()): |
| 626 | + continue |
| 627 | + weighted_goals += 1 |
| 628 | + self.assertEqual(category.weight, 1) |
| 629 | + self.assertEqual(category.get_goal(goal_name).weight, 1) |
| 630 | + |
| 631 | + self.assertGreater(weighted_goals, 0) |
| 632 | + |
570 | 633 | def test_skip_zelda(self): |
571 | 634 | # Song from Impa would be WotH, but instead of relying on random chance to get HC WotH, |
572 | 635 | # just exclude all other locations to see if HC is barren. |
|
0 commit comments