def test_GameSession_create_session_entry(clean_database, has_description, test_files_dir, mocker): # Setup description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", "seed_a.rdvgame")) someone = database.User.create(name="Someone") s = database.GameSession.create(name="Debug", num_teams=1, creator=someone) game_details = None if has_description: s.layout_description = description s.save() game_details = { 'seed_hash': '5IENQWDS', 'spoiler': True, 'word_hash': 'Biostorage Cavern Watch', } # Run session = database.GameSession.get_by_id(1) result = session.create_session_entry() readable_result = construct_lib.convert_to_raw_python(BinaryGameSessionEntry.parse(result)) # Assert assert readable_result == { 'allowed_games': ['prime1', 'prime2'], 'game_details': game_details, 'generation_in_progress': None, 'id': 1, 'name': 'Debug', 'players': [], 'presets': [], 'state': 'setup', }
def _create_patch_data(test_files_dir, mocker, in_file, out_file, cosmetic): # Setup f = test_files_dir.joinpath("log_files", "cave_story", f"{in_file}.rdvgame") description = LayoutDescription.from_file(f) players_config = PlayersConfiguration(0, {0: "Cave Story"}) mocker.patch( "randovania.layout.layout_description.LayoutDescription.shareable_hash_bytes", new_callable=PropertyMock, return_value=b'\x00\x00\x00\x00\x00') # Run data = CSPatchDataFactory(description, players_config, cosmetic).create_data() # Expected Result # strip mychar to just the filename rather than full path if data["mychar"] is not None: mychar = Path(data["mychar"]) data["mychar"] = mychar.name # Uncomment the following lines to update: # with test_files_dir.joinpath("caver_expected_data", f"{out_file}.json").open("w") as f: # json.dump(data, f) with test_files_dir.joinpath("caver_expected_data", f"{out_file}.json").open("r") as f: expected_data = json.load(f) assert data == expected_data
def validate_command_logic(args): debug.set_level(args.debug) description = LayoutDescription.from_file(args.layout_file) if description.player_count != 1: raise ValueError( f"Validator does not support layouts with more than 1 player.") configuration = description.get_preset(0).configuration patches = description.all_patches[0] total_times = [] final_state_by_resolve = None for _ in range(args.repeat): before = time.perf_counter() final_state_by_resolve = asyncio.run( resolver.resolve(configuration=configuration, patches=patches)) after = time.perf_counter() total_times.append(after - before) print("Took {:.3f} seconds. Game is {}.".format( total_times[-1], "possible" if final_state_by_resolve is not None else "impossible")) if args.repeat > 1: cli_lib.print_report_multiple_times(total_times) if args.repeat < 1: raise ValueError("Expected at least 1 repeat") return 0 if final_state_by_resolve is not None else 1
def test_update_content(skip_qtbot, test_files_dir): # Setup description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", "seed_a.rdvgame")) tab = TranslatorGateDetailsTab(None, RandovaniaGame.METROID_PRIME_ECHOES) # Run tab.update_content( description.get_preset(0).configuration, description.all_patches, PlayersConfiguration(0, {0: "You"}), ) # Assert counts = {} for i in range(tab.tree_widget.topLevelItemCount()): item = tab.tree_widget.topLevelItem(i) counts[item.text(0)] = item.childCount() assert counts == { 'Agon Wastes': 2, 'Great Temple': 3, 'Sanctuary Fortress': 2, 'Temple Grounds': 7, 'Torvus Bog': 3, }
def _test_preset(rdvgame_file, expected_results_file, mocker): # Setup description = LayoutDescription.from_file(rdvgame_file) players_config = PlayersConfiguration(0, {0: "Prime", 1: "Echoes"}) cosmetic_patches = PrimeCosmeticPatches(use_hud_color=True, hud_color=(255, 0, 0), suit_color_rotations=(0, 40, 350, 12)) mocker.patch( "randovania.layout.layout_description.LayoutDescription.shareable_hash_bytes", new_callable=PropertyMock, return_value=b"\x00\x00\x00\x00\x00") # Run data = PrimePatchDataFactory(description, players_config, cosmetic_patches).create_data() # Expected Result with expected_results_file.open("r") as file: expected_data = json.load(file) # Uncomment to easily view diff of failed test # with expected_results_file.open("w") as file: # file.write(json.dumps(data, indent=4, separators=(',', ': '))) # Ignore the part of the main menu message which has the randovania version in it data["gameConfig"]["mainMenuMessage"] = data["gameConfig"][ "mainMenuMessage"].split("\n")[1] expected_data["gameConfig"]["mainMenuMessage"] = expected_data[ "gameConfig"]["mainMenuMessage"].split("\n")[1] assert data == expected_data
def show_game_details(app: QApplication, options, game: Path): from randovania.layout.layout_description import LayoutDescription from randovania.gui.seed_details_window import SeedDetailsWindow layout = LayoutDescription.from_file(game) details_window = SeedDetailsWindow(None, options) details_window.update_layout_description(layout) details_window.show() app.details_window = details_window
def show_game_details(app: QtWidgets.QApplication, options, game: Path): from randovania.layout.layout_description import LayoutDescription from randovania.gui.game_details.game_details_window import GameDetailsWindow layout = LayoutDescription.from_file(game) details_window = GameDetailsWindow(None, options) details_window.update_layout_description(layout) logger.info("Displaying game details") details_window.show() app.details_window = details_window
def __init__(self, json_path: Path): super().__init__() self.setupUi(self) set_default_window_icon(self) self.layout_description = LayoutDescription.from_file(json_path) # Keep the Layout Description visualizer ready, but invisible. self._create_pickup_spoilers() # And update self.update_layout_description(self.layout_description)
def dropEvent(self, event: QtGui.QDropEvent): from randovania.layout.versioned_preset import VersionedPreset for url in event.mimeData().urls(): path = Path(url.toLocalFile()) if path.suffix == f".{LayoutDescription.file_extension()}": self.open_game_details(LayoutDescription.from_file(path)) return elif path.suffix == f".{VersionedPreset.file_extension()}": self.main_tab_widget.setCurrentWidget(self.tab_create_seed) self.generate_seed_tab.import_preset_file(path) return
def validate_command_logic(args): debug.set_level(args.debug) data = prime_database.decode_data_file(args) game = data_reader.decode_data(data) description = LayoutDescription.from_file(args.layout_file) configuration = description.permalink.layout_configuration patches = description.patches final_state_by_resolve = resolver.resolve(configuration=configuration, game=game, patches=patches) print(final_state_by_resolve)
def test_dangerous_settings(test_files_dir, rdvgame_filename="prime1_crazy_seed.rdvgame"): rdvgame = test_files_dir.joinpath("log_files", rdvgame_filename) layout_description = LayoutDescription.from_file(rdvgame) preset = layout_description.get_preset(0) assert preset.dangerous_settings() == [ 'One-way anywhere elevators', 'Shuffled Item Position', 'Room Randomizer', 'Extra Superheated Rooms', 'Submerged Rooms', 'Dangerous Gravity Suit Logic', ]
async def test_resolver_with_log_file(test_files_dir, seed_name: str): # Setup debug.set_level(2) description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", seed_name)) configuration = description.permalink.presets[0].configuration patches = description.all_patches[0] # Run final_state_by_resolve = await resolver.resolve(configuration=configuration, patches=patches) # Assert assert final_state_by_resolve is not None
def _randomize_from_file(self): if not self._pre_export_checks([self._check_has_output_directory]): return json_path = prompt_user_for_seed_log(self) if json_path is None: return layout = LayoutDescription.from_file(json_path) self._background_exporter( simplified_patcher.patch_game_with_existing_layout, message="Randomizing...", layout=layout)
def test_resolver_with_log_file(test_files_dir): # Setup debug.set_level(0) description = LayoutDescription.from_file(test_files_dir.joinpath("log_files", "seed_a.json")) configuration = description.permalink.presets[0].layout_configuration patches = description.all_patches[0] # Run final_state_by_resolve = resolver.resolve(configuration=configuration, patches=patches) # Assert assert final_state_by_resolve is not None
def test_generate_patcher_data(test_files_dir): # Setup description = LayoutDescription.from_file( test_files_dir.joinpath("log_files", "seed_a.rdvgame")) player_index = 0 preset = description.get_preset(player_index) cosmetic_patches = EchoesCosmeticPatches() assert isinstance(preset.configuration, EchoesConfiguration) # Run result = patch_data_factory.generate_patcher_data( description, PlayersConfiguration(player_index, {0: "you"}), cosmetic_patches) # Assert assert isinstance(result["spawn_point"], dict) assert isinstance(result["pickups"], list) assert len(result["pickups"]) == 119 assert isinstance(result["elevators"], list) assert len(result["elevators"]) == 22 assert isinstance(result["translator_gates"], list) assert len(result["translator_gates"]) == 17 assert isinstance(result["string_patches"], list) assert len(result["string_patches"]) == 61 assert result["specific_patches"] == { "hive_chamber_b_post_state": True, "intro_in_post_state": True, "warp_to_start": preset.configuration.warp_to_start, "credits_length": 75 if cosmetic_patches.speed_up_credits else 259, "disable_hud_popup": cosmetic_patches.disable_hud_popup, "pickup_map_icons": cosmetic_patches.pickup_markers, "full_map_at_start": cosmetic_patches.open_map, "dark_world_varia_suit_damage": preset.configuration.varia_suit_damage, "dark_world_dark_suit_damage": preset.configuration.dark_suit_damage, "always_up_gfmc_compound": True, "always_up_torvus_temple": True, "always_up_great_temple": False, 'hud_color': None, } # TODO: check all fields? assert result["dol_patches"]["default_items"] == { "visor": "Combat Visor", "beam": "Power Beam", }
def test_update_layout_description_actual_seed(skip_qtbot, test_files_dir): description = LayoutDescription.from_file( test_files_dir.joinpath("log_files", "seed_a.rdvgame")) # Run window = SeedDetailsWindow(None, MagicMock()) skip_qtbot.addWidget(window) window.update_layout_description(description) # Assert assert len(window.pickup_spoiler_buttons) == 119 assert window.pickup_spoiler_show_all_button.text() == "Show All" skip_qtbot.mouseClick(window.pickup_spoiler_show_all_button, QtCore.Qt.LeftButton) assert window.pickup_spoiler_show_all_button.text() == "Hide All"
def test_create_patch_data(test_files_dir, mocker): # Setup file = test_files_dir.joinpath("log_files", "dread_1.rdvgame") description = LayoutDescription.from_file(file) players_config = PlayersConfiguration(0, {0: "Dread"}) cosmetic_patches = DreadCosmeticPatches() # Run data = DreadPatchDataFactory(description, players_config, cosmetic_patches).create_data() # Expected Result with test_files_dir.joinpath("dread_expected_data.json").open("r") as file: expected_data = json.load(file) assert data == expected_data
def validate_command_logic(args): debug.set_level(args.debug) description = LayoutDescription.from_file(args.layout_file) if description.permalink.player_count != 1: raise ValueError(f"Validator does not support layouts with more than 1 player.") configuration = description.permalink.presets[0].layout_configuration patches = description.all_patches[0] final_state_by_resolve = resolver.resolve( configuration=configuration, patches=patches ) print(final_state_by_resolve)
def test_resolver_with_log_file(test_files_dir): # Setup debug.set_level(0) description = LayoutDescription.from_file( test_files_dir.joinpath("log_files", "seed_a.json")) configuration = description.permalink.layout_configuration game = data_reader.decode_data(configuration.game_data) patches = description.patches # Run final_state_by_resolve = resolver.resolve(configuration=configuration, game=game, patches=patches) # Assert assert final_state_by_resolve is not None
def validate_command_logic(args): debug._DEBUG_LEVEL = args.debug data = prime_database.decode_data_file(args) game = data_reader.decode_data(data) if args.layout_file is not None: description = LayoutDescription.from_file(Path(args.layout_file)) configuration = description.permalink.layout_configuration patches = description.patches else: configuration = LayoutConfiguration.default() patches = GamePatches.with_game(game).assign_pickup_assignment( game.pickup_database.original_pickup_mapping) final_state_by_resolve = resolver.resolve(configuration=configuration, game=game, patches=patches) print(final_state_by_resolve)
def test_create_patcher_file(test_files_dir): # Setup description = LayoutDescription.from_file( test_files_dir.joinpath("log_files", "seed_a.rdvgame")) player_index = 0 preset = description.permalink.get_preset(player_index) cosmetic_patches = CosmeticPatches() # Run result = patcher_file.create_patcher_file( description, PlayersConfiguration(player_index, {0: "you"}), cosmetic_patches) # Assert assert isinstance(result["spawn_point"], dict) assert isinstance(result["pickups"], list) assert len(result["pickups"]) == 119 assert isinstance(result["elevators"], list) assert len(result["elevators"]) == 22 assert isinstance(result["translator_gates"], list) assert len(result["translator_gates"]) == 17 assert isinstance(result["string_patches"], list) assert len(result["string_patches"]) == 60 assert result["specific_patches"] == { "hive_chamber_b_post_state": True, "intro_in_post_state": True, "warp_to_start": preset.patcher_configuration.warp_to_start, "speed_up_credits": cosmetic_patches.speed_up_credits, "disable_hud_popup": cosmetic_patches.disable_hud_popup, "pickup_map_icons": cosmetic_patches.pickup_markers, "full_map_at_start": cosmetic_patches.open_map, "dark_world_varia_suit_damage": preset.patcher_configuration.varia_suit_damage, "dark_world_dark_suit_damage": preset.patcher_configuration.dark_suit_damage, "always_up_gfmc_compound": True, "always_up_torvus_temple": True, "always_up_great_temple": False, }
def validate_command_logic(args): debug.set_level(args.debug) description = LayoutDescription.from_file(args.layout_file) if description.player_count != 1: raise ValueError( f"Validator does not support layouts with more than 1 player.") configuration = description.get_preset(0).configuration patches = description.all_patches[0] before = time.perf_counter() final_state_by_resolve = asyncio.run( resolver.resolve(configuration=configuration, patches=patches)) after = time.perf_counter() print("Took {} seconds. Game is {}.".format( after - before, "possible" if final_state_by_resolve is not None else "impossible")) return 0 if final_state_by_resolve is not None else 1
async def patcher_data_command_logic_async(args): from randovania.interface_common.players_configuration import PlayersConfiguration from randovania.layout.layout_description import LayoutDescription layout_description = LayoutDescription.from_file(args.log_file) players_config = PlayersConfiguration( args.player_index, {i: f"Player {i + 1}" for i in range(layout_description.player_count)}) preset = layout_description.get_preset(players_config.player_index) cosmetic_patches = preset.game.data.layout.cosmetic_patches.default() data_factory = preset.game.patch_data_factory(layout_description, players_config, cosmetic_patches) patch_data = data_factory.create_data() print(json.dumps( patch_data, indent=4, ))
def randomize_command_logic(args): def status_update(s): if args.verbose: print(s) if args.permalink is not None: layout_description = generator.generate_description(permalink=Permalink.from_str(args.permalink), status_update=status_update, validate_after_generation=True) else: layout_description = LayoutDescription.from_file(args.log_file) cosmetic_patches = CosmeticPatches( disable_hud_popup=args.disable_hud_popup, speed_up_credits=args.speed_up_credits) claris_randomizer.apply_layout(description=layout_description, cosmetic_patches=cosmetic_patches, backup_files_path=args.backup_files, progress_update=lambda x, _: status_update(x), game_root=args.game_files, )
async def randomize_command_logic_async(args): from randovania.games.patcher_provider import PatcherProvider from randovania.generator import generator from randovania.interface_common.cosmetic_patches import CosmeticPatches from randovania.interface_common.players_configuration import PlayersConfiguration from randovania.layout.layout_description import LayoutDescription from randovania.layout.permalink import Permalink from randovania.interface_common.options import Options def status_update(s): if args.verbose: print(s) if args.permalink is not None: permalink = Permalink.from_str(args.permalink) layout_description = await generator.generate_and_validate_description( permalink=permalink, status_update=status_update, validate_after_generation=True, ) else: layout_description = LayoutDescription.from_file(args.log_file) cosmetic_patches = CosmeticPatches( disable_hud_popup=args.disable_hud_popup, speed_up_credits=args.speed_up_credits) players_config = PlayersConfiguration(args.player_index, {i: f"Player {i + 1}" for i in range(layout_description.permalink.player_count)}) preset = layout_description.permalink.get_preset(players_config.player_index) game_files_path = Options.with_default_data_dir().game_files_path patcher_provider = PatcherProvider() patcher = patcher_provider.patcher_for_game(preset.game) patch_data = patcher.create_patch_data(layout_description, players_config, cosmetic_patches) patcher.patch_game(args.input_file, args.output_file, patch_data, game_files_path, lambda x, _: status_update(x))
def test_create_patch_data(test_files_dir, mocker): # Setup file = test_files_dir.joinpath("log_files", "dread_1.rdvgame") description = LayoutDescription.from_file(file) players_config = PlayersConfiguration(0, {0: "Dread"}) cosmetic_patches = DreadCosmeticPatches() mocker.patch( "randovania.layout.layout_description.LayoutDescription.shareable_word_hash", new_callable=PropertyMock, return_value="Words Hash") mocker.patch( "randovania.layout.layout_description.LayoutDescription.shareable_hash", new_callable=PropertyMock, return_value="$$$$$") # Run data = DreadPatchDataFactory(description, players_config, cosmetic_patches).create_data() # Expected Result with test_files_dir.joinpath("dread_expected_data.json").open("r") as file: expected_data = json.load(file) assert data == expected_data
def _import_spoiler_log(self): json_path = common_qt_lib.prompt_user_for_input_game_log(self) if json_path is not None: layout = LayoutDescription.from_file(json_path) self.open_game_details(layout)