 c944ecf628
			
		
	
	c944ecf628
	
	
	
		
			
			Co-authored-by: Chris Wilson <chris@legendserver.info> Co-authored-by: Zach Parks <zach@alliware.com>
		
			
				
	
	
		
			99 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from typing import Dict
 | |
| import random
 | |
| 
 | |
| from BaseClasses import MultiWorld
 | |
| from Options import NamedRange, Range
 | |
| from .option_names import options_to_include
 | |
| from .. import setup_solo_multiworld, SVTestCase
 | |
| from ..checks.goal_checks import assert_perfection_world_is_valid, assert_goal_world_is_valid
 | |
| from ..checks.option_checks import assert_can_reach_island_if_should, assert_cropsanity_same_number_items_and_locations, \
 | |
|     assert_festivals_give_access_to_deluxe_scarecrow
 | |
| from ..checks.world_checks import assert_same_number_items_locations, assert_victory_exists
 | |
| 
 | |
| 
 | |
| def get_option_choices(option) -> Dict[str, int]:
 | |
|     if issubclass(option, NamedRange):
 | |
|         return option.special_range_names
 | |
|     if issubclass(option, Range):
 | |
|         return {f"{val}": val for val in range(option.range_start, option.range_end + 1)}
 | |
|     elif option.options:
 | |
|         return option.options
 | |
|     return {}
 | |
| 
 | |
| 
 | |
| def generate_random_multiworld(world_id: int):
 | |
|     world_options = generate_random_world_options(world_id)
 | |
|     multiworld = setup_solo_multiworld(world_options, seed=world_id)
 | |
|     return multiworld
 | |
| 
 | |
| 
 | |
| def generate_random_world_options(world_id: int) -> Dict[str, int]:
 | |
|     num_options = len(options_to_include)
 | |
|     world_options = dict()
 | |
|     rng = random.Random(world_id)
 | |
|     for option_index in range(0, num_options):
 | |
|         option = options_to_include[option_index]
 | |
|         option_choices = get_option_choices(option)
 | |
|         if not option_choices:
 | |
|             continue
 | |
|         chosen_option_value = rng.choice(list(option_choices.values()))
 | |
|         world_options[option.internal_name] = chosen_option_value
 | |
|     return world_options
 | |
| 
 | |
| 
 | |
| def get_number_log_steps(number_worlds: int) -> int:
 | |
|     if number_worlds <= 10:
 | |
|         return 2
 | |
|     if number_worlds <= 100:
 | |
|         return 5
 | |
|     if number_worlds <= 500:
 | |
|         return 10
 | |
|     if number_worlds <= 1000:
 | |
|         return 20
 | |
|     if number_worlds <= 5000:
 | |
|         return 25
 | |
|     if number_worlds <= 10000:
 | |
|         return 50
 | |
|     return 100
 | |
| 
 | |
| 
 | |
| def generate_many_worlds(number_worlds: int, start_index: int) -> Dict[int, MultiWorld]:
 | |
|     num_steps = get_number_log_steps(number_worlds)
 | |
|     log_step = number_worlds / num_steps
 | |
|     multiworlds = dict()
 | |
|     print(f"Generating {number_worlds} Solo Multiworlds [Start Seed: {start_index}] for Stardew Valley...")
 | |
|     for world_number in range(0, number_worlds + 1):
 | |
|         world_id = world_number + start_index
 | |
|         multiworld = generate_random_multiworld(world_id)
 | |
|         multiworlds[world_id] = multiworld
 | |
|         if world_number > 0 and world_number % log_step == 0:
 | |
|             print(f"Generated {world_number}/{number_worlds} worlds [{(world_number * 100) // number_worlds}%]")
 | |
|     print(f"Finished generating {number_worlds} Solo Multiworlds for Stardew Valley")
 | |
|     return multiworlds
 | |
| 
 | |
| 
 | |
| def check_every_multiworld_is_valid(tester: SVTestCase, multiworlds: Dict[int, MultiWorld]):
 | |
|     for multiworld_id in multiworlds:
 | |
|         multiworld = multiworlds[multiworld_id]
 | |
|         with tester.subTest(f"Checking validity of world {multiworld_id}"):
 | |
|             check_multiworld_is_valid(tester, multiworld_id, multiworld)
 | |
| 
 | |
| 
 | |
| def check_multiworld_is_valid(tester: SVTestCase, multiworld_id: int, multiworld: MultiWorld):
 | |
|     assert_victory_exists(tester, multiworld)
 | |
|     assert_same_number_items_locations(tester, multiworld)
 | |
|     assert_goal_world_is_valid(tester, multiworld)
 | |
|     assert_can_reach_island_if_should(tester, multiworld)
 | |
|     assert_cropsanity_same_number_items_and_locations(tester, multiworld)
 | |
|     assert_festivals_give_access_to_deluxe_scarecrow(tester, multiworld)
 | |
| 
 | |
| 
 | |
| class TestGenerateManyWorlds(SVTestCase):
 | |
|     def test_generate_many_worlds_then_check_results(self):
 | |
|         if self.skip_long_tests:
 | |
|             return
 | |
|         number_worlds = 1000
 | |
|         start_index = random.Random().randint(0, 9999999999)
 | |
|         multiworlds = generate_many_worlds(number_worlds, start_index)
 | |
|         check_every_multiworld_is_valid(self, multiworlds)
 |