From aab29255b97b204276f377f1ee227a7dfb9ce796 Mon Sep 17 00:00:00 2001 From: jamesbrq Date: Sun, 9 Jun 2024 00:38:50 -0400 Subject: [PATCH] Formatting part-2 --- worlds/gl/Arrays.py | 103 +++++++++---------- worlds/gl/GauntletLegendsClient.py | 155 ++++++++++++++--------------- worlds/gl/Items.py | 8 +- worlds/gl/Locations.py | 104 +++++++++---------- worlds/gl/Options.py | 3 +- worlds/gl/Regions.py | 103 +++++++++---------- worlds/gl/Rom.py | 22 ++-- worlds/gl/Rules.py | 29 +++--- worlds/gl/__init__.py | 49 ++++----- 9 files changed, 291 insertions(+), 285 deletions(-) diff --git a/worlds/gl/Arrays.py b/worlds/gl/Arrays.py index dabe073925ea..3bd0848498be 100644 --- a/worlds/gl/Arrays.py +++ b/worlds/gl/Arrays.py @@ -1,31 +1,32 @@ -from typing import List, Dict, Tuple +from typing import Dict, List, Tuple + from .Locations import ( LocationData, - valleyOfFire, - daggerPeak, - cliffsOfDesolation, - lostCave, - volcanicCavern, - dragonsLair, - castleCourtyard, - dungeonOfTorment, - towerArmory, - castleTreasury, - chimerasKeep, - poisonedFields, - hauntedCemetery, - venomousSpire, - toxicAirShip, - arcticDocks, - frozenCamp, - crystalMine, - eruptingFissure, - desecratedTemple, - battleTrenches, - battleTowers, - infernalFortress, - gatesOfTheUnderworld, - plagueFiend, + arctic_docks, + battle_towers, + battle_trenches, + castle_courtyard, + castle_treasury, + chimeras_keep, + cliffs_of_desolation, + crystal_mine, + dagger_peak, + desecrated_temple, + dragons_lair, + dungeon_of_torment, + erupting_fissure, + frozen_camp, + gates_of_the_underworld, + haunted_cemetery, + infernal_fortress, + lost_cave, + plague_fiend, + poisoned_fields, + tower_armory, + toxic_air_ship, + valley_of_fire, + venomous_spire, + volcanic_cavern, yeti, ) @@ -257,32 +258,32 @@ castle_id = [1, 6, 3, 4, 5] level_locations: Dict[int, List[LocationData]] = { - 0x11: castleCourtyard, - 0x12: dungeonOfTorment, - 0x13: towerArmory, - 0x14: castleTreasury, - 0x15: chimerasKeep, - 0x21: valleyOfFire, - 0x22: daggerPeak, - 0x23: cliffsOfDesolation, - 0x24: lostCave, - 0x25: volcanicCavern, - 0x26: dragonsLair, - 0x71: poisonedFields, - 0x72: hauntedCemetery, - 0x73: venomousSpire, - 0x74: toxicAirShip, - 0x75: plagueFiend, - 0x81: gatesOfTheUnderworld, - 0x91: arcticDocks, - 0x92: frozenCamp, - 0x93: crystalMine, - 0x94: eruptingFissure, + 0x11: castle_courtyard, + 0x12: dungeon_of_torment, + 0x13: tower_armory, + 0x14: castle_treasury, + 0x15: chimeras_keep, + 0x21: valley_of_fire, + 0x22: dagger_peak, + 0x23: cliffs_of_desolation, + 0x24: lost_cave, + 0x25: volcanic_cavern, + 0x26: dragons_lair, + 0x71: poisoned_fields, + 0x72: haunted_cemetery, + 0x73: venomous_spire, + 0x74: toxic_air_ship, + 0x75: plague_fiend, + 0x81: gates_of_the_underworld, + 0x91: arctic_docks, + 0x92: frozen_camp, + 0x93: crystal_mine, + 0x94: erupting_fissure, 0x95: yeti, - 0xF1: desecratedTemple, - 0x111: battleTrenches, - 0x112: battleTowers, - 0x113: infernalFortress, + 0xF1: desecrated_temple, + 0x111: battle_trenches, + 0x112: battle_towers, + 0x113: infernal_fortress, } spawners: Dict[int, List[int]] = { diff --git a/worlds/gl/GauntletLegendsClient.py b/worlds/gl/GauntletLegendsClient.py index aad874c3c0e8..c52a61ecfd52 100644 --- a/worlds/gl/GauntletLegendsClient.py +++ b/worlds/gl/GauntletLegendsClient.py @@ -1,29 +1,27 @@ import asyncio -import inspect import socket import traceback -import typing +from typing import List import Patch import Utils from BaseClasses import ItemClassification -from CommonClient import CommonContext, server_loop, gui_enabled, ClientCommandProcessor, logger, get_base_parser -from typing import List - +from CommonClient import ClientCommandProcessor, CommonContext, get_base_parser, gui_enabled, logger, server_loop from NetUtils import ClientStatus, NetworkItem + from worlds.gl.Arrays import ( - inv_dict, - timers, base_count, + boss_level, castle_id, - level_locations, + characters, difficulty_convert, - spawners, + inv_dict, + level_locations, mirror_levels, - characters, - boss_level, + spawners, + timers, ) -from worlds.gl.Items import items_by_id, ItemData +from worlds.gl.Items import ItemData, items_by_id from worlds.gl.Locations import LocationData SYSTEM_MESSAGE_ID = 0 @@ -69,7 +67,7 @@ async def read(self, message) -> bytes | None: except ConnectionResetError: raise Exception("Retroarch is not open. Please open Retroarch and load the correct ROM.") response = data.decode().split(" ") - b = bytes() + b = b"" for s in response[2:]: if "-1" in s: logger.info("-1 response") @@ -95,7 +93,7 @@ def __init__(self, arr: bytes): self.split = [] def iterate(self, length: int): - self.split = [self.raw[i : i + length] for i in range(0, len(self.raw), length)] + self.split = [self.raw[i: i + length] for i in range(0, len(self.raw), length)] def type_to_name(arr) -> str: @@ -143,11 +141,11 @@ def __init__(self, arr=None): self.raw: bytes -def MessageFormat(arg: str, params: str) -> str: +def message_format(arg: str, params: str) -> str: return f"{arg} {params}" -def ParamFormat(adr: int, arr: bytes) -> str: +def param_format(adr: int, arr: bytes) -> str: return " ".join([hex(adr)] + [f"0x{byte:02X}" for byte in arr]) @@ -196,7 +194,7 @@ def __init__(self, server_address, password): self.scaled: bool = False self.offset: int = -1 self.clear_counts = None - self.current_level: bytes = bytes() + self.current_level: bytes = b"" self.movement: int = 0 self.init_refactor: bool = False self.location_scouts: list[NetworkItem] = [] @@ -207,7 +205,7 @@ def inv_count(self): async def inv_read(self): _inv: List[InventoryEntry] = [] - b = RamChunk(await self.socket.read(MessageFormat(READ, f"0x{format(INV_ADDR, 'x')} 3072"))) + b = RamChunk(await self.socket.read(message_format(READ, f"0x{format(INV_ADDR, 'x')} 3072"))) if b is None: return b.iterate(0x10) @@ -243,7 +241,7 @@ async def inv_bitwise(self, name: str, bit: int) -> bool: async def get_obj_addr(self) -> int: return ( - int.from_bytes(await self.socket.read(MessageFormat(READ, f"0x{format(OBJ_ADDR, 'x')} 4")), "little") + int.from_bytes(await self.socket.read(message_format(READ, f"0x{format(OBJ_ADDR, 'x')} 4")), "little") ) & 0xFFFFF # Modes: 0 = items, 1 = chests/barrels @@ -251,7 +249,7 @@ async def obj_read(self, mode=0): obj_address = await self.get_obj_addr() _obj = [] if self.offset == -1: - b = RamChunk(await self.socket.read(MessageFormat(READ, f"0x{format(obj_address, 'x')} 3840"))) + b = RamChunk(await self.socket.read(message_format(READ, f"0x{format(obj_address, 'x')} 3840"))) b.iterate(0x3C) for i, arr in enumerate(b.split): if arr[0] != 0xFF: @@ -261,11 +259,11 @@ async def obj_read(self, mode=0): if mode == 0: b = RamChunk( await self.socket.read( - MessageFormat( + message_format( READ, f"0x{format(obj_address + (self.offset * 0x3C), 'x')} {(len(self.item_locations) + 10) * 0x3C})", - ) - ) + ), + ), ) b.iterate(0x3C) count = 0 @@ -276,11 +274,11 @@ async def obj_read(self, mode=0): else: b = RamChunk( await self.socket.read( - MessageFormat( + message_format( READ, f"0x{format(obj_address + ((self.offset + len(self.item_locations) + self.extra_items + len([spawner for spawner in spawners[(self.current_level[1] << 4) + self.current_level[0]] if self.difficulty >= spawner])) * 0x3C), 'x')} {(len(self.chest_locations) + 10) * 0x3C})", - ) - ) + ), + ), ) b.iterate(0x3C) for arr in b.split: @@ -332,9 +330,9 @@ async def inv_refactor(self, new=None): if item.name is not None: if "Potion" in item.name and item.count != 0: await self.socket.write( - MessageFormat( - WRITE, ParamFormat(ACTIVE_POTION, int.to_bytes(item.type[2] // 0x10, 1, "little")) - ) + message_format( + WRITE, param_format(ACTIVE_POTION, int.to_bytes(item.type[2] // 0x10, 1, "little")), + ), ) if i == 0: item.p_addr = 0 @@ -354,7 +352,7 @@ async def inv_refactor(self, new=None): for item in self.inventory: await self.write_inv(item) - for i, raw in enumerate(self.inventory_raw.split[len(self.inventory) :], len(self.inventory)): + for i, raw in enumerate(self.inventory_raw.split[len(self.inventory):], len(self.inventory)): item = InventoryEntry(raw, i) if item.type != bytes([0, 0, 0]): await self.write_inv( @@ -363,14 +361,15 @@ async def inv_refactor(self, new=None): + int.to_bytes(item.addr + 0x10, 3, "little") + bytes([0xE0, 0, 0, 0, 0]), i, - ) + ), ) await self.socket.write( - MessageFormat(WRITE, ParamFormat(INV_UPDATE_ADDR, int.to_bytes(self.inventory[-1].addr, 3, "little"))) + message_format(WRITE, param_format(INV_UPDATE_ADDR, int.to_bytes(self.inventory[-1].addr, 3, "little"))), ) await self.socket.write( - MessageFormat(WRITE, ParamFormat(INV_LAST_ADDR, int.to_bytes(self.inventory[-1].addr + 0x10, 3, "little"))) + message_format(WRITE, + param_format(INV_LAST_ADDR, int.to_bytes(self.inventory[-1].addr + 0x10, 3, "little"))), ) await self.socket.write(f"{WRITE} 0xC6BF0 0x{format(self.inv_count(), 'x')}") @@ -393,10 +392,10 @@ async def inv_add(self, name: str, count: int): async def write_inv(self, item: InventoryEntry): b = ( - int.to_bytes(item.on, 1) - + item.type - + int.to_bytes(item.count, 4, "little") - + int.to_bytes(item.p_addr, 3, "little") + int.to_bytes(item.on, 1) + + item.type + + int.to_bytes(item.count, 4, "little") + + int.to_bytes(item.p_addr, 3, "little") ) if item.p_addr != 0: b += int.to_bytes(0xE0) @@ -405,7 +404,7 @@ async def write_inv(self, item: InventoryEntry): b += int.to_bytes(item.n_addr, 3, "little") if item.n_addr != 0: b += int.to_bytes(0xE0) - await self.socket.write(MessageFormat(WRITE, ParamFormat(item.addr, b))) + await self.socket.write(message_format(WRITE, param_format(item.addr, b))) async def server_auth(self, password_requested: bool = False): if password_requested and not self.password: @@ -428,7 +427,7 @@ def on_package(self, cmd: str, args: dict): cc = None try: cc = self.stored_data.get(f"gl_cc_T{self.team}_P{self.slot}", None) - except Exception as e: + except Exception: logger.info(traceback.format_exc()) if cc is not None: logger.info("Received clear counts from server") @@ -457,17 +456,17 @@ async def handle_items(self): if i - 1 != len(self.items_received): for index in range(i - 1, len(self.items_received)): item = self.items_received[index].item - await self.inv_update(items_by_id[item].itemName, base_count[items_by_id[item].itemName]) + await self.inv_update(items_by_id[item].item_name, base_count[items_by_id[item].item_name]) await self.inv_update("Compass", len(self.items_received) + 1) async def read_time(self) -> int: - return int.from_bytes(await self.socket.read(MessageFormat(READ, f"0x{format(TIME, 'x')} 2")), "little") + return int.from_bytes(await self.socket.read(message_format(READ, f"0x{format(TIME, 'x')} 2")), "little") async def read_input(self) -> int: - return int.from_bytes(await self.socket.read(MessageFormat(READ, f"0x{format(INPUT, 'x')} 1"))) + return int.from_bytes(await self.socket.read(message_format(READ, f"0x{format(INPUT, 'x')} 1"))) async def read_level(self) -> bytes: - return await self.socket.read(MessageFormat(READ, f"0x{format(ACTIVE_LEVEL, 'x')} 2")) + return await self.socket.read(message_format(READ, f"0x{format(ACTIVE_LEVEL, 'x')} 2")) async def check_loading(self) -> bool: if self.in_portal or self.level_loading: @@ -475,11 +474,11 @@ async def check_loading(self) -> bool: return False async def active_players(self) -> int: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_COUNT, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_COUNT, 'x')} 1")) return temp[0] async def player_level(self) -> int: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_LEVEL, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_LEVEL, 'x')} 1")) return temp[0] async def scale(self): @@ -496,7 +495,7 @@ async def scale(self): if level[1] == 2 and self.clear_counts.get(str(level), 0) != 0: scale_value -= min(player_level // 10, 3) await self.socket.write( - MessageFormat(WRITE, f"0x{format(PLAYER_COUNT, 'x')} 0x{format(min(players + scale_value, 4), 'x')}") + message_format(WRITE, f"0x{format(PLAYER_COUNT, 'x')} 0x{format(min(players + scale_value, 4), 'x')}"), ) self.scaled = True @@ -505,12 +504,12 @@ async def scout_locations(self, ctx: "GauntletLegendsContext") -> None: if level in boss_level: for i in range(4): await self.socket.write( - MessageFormat( + message_format( WRITE, - ParamFormat( - BOSS_ADDR, bytes([self.glslotdata["shards"][i][1], 0x0, self.glslotdata["shards"][i][0]]) + param_format( + BOSS_ADDR, bytes([self.glslotdata["shards"][i][1], 0x0, self.glslotdata["shards"][i][0]]), ), - ) + ), ) if self.movement != 0x12: level = [0x1, 0xF] @@ -534,19 +533,19 @@ async def scout_locations(self, ctx: "GauntletLegendsContext") -> None: location.id for location in raw_locations if "Chest" not in location.name - and ("Barrel" not in location.name or "Barrel of Gold" in location.name) + and ("Barrel" not in location.name or "Barrel of Gold" in location.name) ], "create_as_hint": 0, - } - ] + }, + ], ) while len(self.location_scouts) == 0: await asyncio.sleep(0.1) self.obelisks = [ item for item in self.location_scouts - if "Obelisk" in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).itemName - and item.player == self.slot + if "Obelisk" in items_by_id.get(item.item, ItemData(0, "", ItemClassification.filler)).item_name + and item.player == self.slot ] self.obelisk_locations = [ location for location in raw_locations if location.id in [item.location for item in self.obelisks] @@ -555,18 +554,18 @@ async def scout_locations(self, ctx: "GauntletLegendsContext") -> None: location for location in raw_locations if "Chest" not in location.name - and ("Barrel" not in location.name or "Barrel of Gold" in location.name) - and location not in self.obelisk_locations + and ("Barrel" not in location.name or "Barrel of Gold" in location.name) + and location not in self.obelisk_locations ] self.chest_locations = [ location for location in raw_locations if "Chest" in location.name - or ("Barrel" in location.name and "Barrel of Gold" not in location.name) - and location not in self.obelisk_locations + or ("Barrel" in location.name and "Barrel of Gold" not in location.name) + and location not in self.obelisk_locations ] logger.info( - f"Locations: {len(self.obelisk_locations + self.item_locations + self.chest_locations)} Difficulty: {self.difficulty}" + f"Locations: {len(self.obelisk_locations + self.item_locations + self.chest_locations)} Difficulty: {self.difficulty}", ) async def location_loop(self) -> List[int]: @@ -579,7 +578,7 @@ async def location_loop(self) -> List[int]: self.locations_checked += [self.item_locations[i].id] acquired += [self.item_locations[i].id] for j in range(len(self.obelisk_locations)): - if await self.inv_bitwise("Obelisk", base_count[items_by_id[self.obelisks[j].item].itemName]): + if await self.inv_bitwise("Obelisk", base_count[items_by_id[self.obelisks[j].item].item_name]): self.locations_checked += [self.obelisk_locations[j].id] acquired += [self.obelisk_locations[j].id] for k, obj in enumerate(self.chest_objects): @@ -598,19 +597,19 @@ async def location_loop(self) -> List[int]: return acquired async def portaling(self) -> int: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_PORTAL, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_PORTAL, 'x')} 1")) return temp[0] async def limbo_check(self, offset=0) -> int: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_MOVEMENT + offset, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_MOVEMENT + offset, 'x')} 1")) return temp[0] async def dead(self) -> bool: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_ALIVE, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_ALIVE, 'x')} 1")) return temp[0] == 0x0 async def boss(self) -> int: - temp = await self.socket.read(MessageFormat(READ, f"0x{format(PLAYER_BOSSING, 'x')} 1")) + temp = await self.socket.read(message_format(READ, f"0x{format(PLAYER_BOSSING, 'x')} 1")) return temp[0] async def level_status(self, ctx: "GauntletLegendsContext") -> bool: @@ -630,11 +629,11 @@ async def level_status(self, ctx: "GauntletLegendsContext") -> bool: location.id for location in level_locations[ (self.current_level[1] << 4) + self.current_level[0] - ] + ] if "Mirror" in location.name ], - } - ] + }, + ], ) if dead: if self.current_level == bytes([0x2, 0xF]): @@ -688,7 +687,7 @@ async def gl_sync_task(ctx: GauntletLegendsContext): if not ctx.auth: ctx.retro_connected = False continue - except Exception as e: + except Exception: logger.info(traceback.format_exc()) if ctx.limbo: try: @@ -699,11 +698,11 @@ async def gl_sync_task(ctx: GauntletLegendsContext): else: await asyncio.sleep(0.05) continue - except Exception as e: + except Exception: logger.info(traceback.format_exc()) try: await ctx.handle_items() - except Exception as e: + except Exception: logger.info(traceback.format_exc()) if not ctx.level_loading and not ctx.in_game: try: @@ -715,7 +714,7 @@ async def gl_sync_task(ctx: GauntletLegendsContext): await ctx.inv_refactor() ctx.init_refactor = True ctx.level_loading = await ctx.check_loading() - except Exception as e: + except Exception: logger.info(traceback.format_exc()) if ctx.level_loading: try: @@ -726,7 +725,7 @@ async def gl_sync_task(ctx: GauntletLegendsContext): await asyncio.sleep(0.2) await ctx.scale() ctx.in_game = not await ctx.check_loading() - except Exception as e: + except Exception: logger.info(traceback.format_exc()) if ctx.in_game: ctx.level_loading = False @@ -748,12 +747,12 @@ async def gl_sync_task(ctx: GauntletLegendsContext): { "operation": "replace", "value": ctx.clear_counts, - } + }, ], - } - ] + }, + ], ) - except Exception as e: + except Exception: logger.info(traceback.format_exc()) ctx.limbo = True await asyncio.sleep(0.05) @@ -763,7 +762,7 @@ async def gl_sync_task(ctx: GauntletLegendsContext): await ctx.send_msgs([{"cmd": "LocationChecks", "locations": checking}]) if not ctx.finished_game and await ctx.inv_bitwise("Hell", 0x100): await ctx.send_msgs([{"cmd": "StatusUpdate", "status": ClientStatus.CLIENT_GOAL}]) - except Exception as e: + except Exception: logger.info(traceback.format_exc()) await asyncio.sleep(0.1) else: diff --git a/worlds/gl/Items.py b/worlds/gl/Items.py index f9553a6e4399..e9f3216b17cd 100644 --- a/worlds/gl/Items.py +++ b/worlds/gl/Items.py @@ -5,7 +5,7 @@ class ItemData(typing.NamedTuple): code: int - itemName: str + item_name: str progression: ItemClassification @@ -13,7 +13,7 @@ class GLItem(Item): game: str = "Gauntlet Legends" -itemList: typing.List[ItemData] = [ +item_list: typing.List[ItemData] = [ ItemData(77780000, "Key", ItemClassification.filler), ItemData(77780001, "Lightning Potion", ItemClassification.filler), ItemData(77780002, "Light Potion", ItemClassification.filler), @@ -113,5 +113,5 @@ class GLItem(Item): "Gold": 150, } -item_table: typing.Dict[str, ItemData] = {item.itemName: item for item in itemList} -items_by_id: typing.Dict[int, ItemData] = {item.code: item for item in itemList} +item_table: typing.Dict[str, ItemData] = {item.item_name: item for item in item_list} +items_by_id: typing.Dict[int, ItemData] = {item.code: item for item in item_list} diff --git a/worlds/gl/Locations.py b/worlds/gl/Locations.py index 2963eb71a94e..ee9d4ebf27f3 100644 --- a/worlds/gl/Locations.py +++ b/worlds/gl/Locations.py @@ -18,7 +18,7 @@ class GLLocation(Location): game: str = "Gauntlet Legends" -valleyOfFire: typing.List[LocationData] = [ +valley_of_fire: typing.List[LocationData] = [ LocationData("Valley of Fire - Scroll", 88870001, 1), LocationData("Valley of Fire - Key 1", 88870002, 1), LocationData("Valley of Fire - Key 2", 88870003, 1), @@ -65,7 +65,7 @@ class GLLocation(Location): LocationData("Valley of Fire Barrel - Potion 1", 88873520, 1), ] -daggerPeak: typing.List[LocationData] = [ +dagger_peak: typing.List[LocationData] = [ LocationData("Dagger Peak - Growth", 88870023, 1), LocationData("Dagger Peak - Runestone", 88870024, 1), LocationData("Dagger Peak - Key 1", 88870025, 1), @@ -131,7 +131,7 @@ class GLLocation(Location): LocationData("Dagger Peak Chest - Timestop 1 (Dif. 3)", 88873626, 3), ] -cliffsOfDesolation: typing.List[LocationData] = [ +cliffs_of_desolation: typing.List[LocationData] = [ LocationData("Cliffs of Desolation - Scroll 1", 88870058, 1), LocationData("Cliffs of Desolation - Reflective Shot (Dif. 4)", 88870059, 4), LocationData("Cliffs of Desolation - Key 1 (Dif. 2)", 88870060, 2), @@ -225,7 +225,7 @@ class GLLocation(Location): LocationData("Cliffs of Desolation Chest - Fruit 3", 88873748, 1), ] -lostCave: typing.List[LocationData] = [ +lost_cave: typing.List[LocationData] = [ LocationData("Lost Cave - Scroll 1", 88870099, 1), LocationData("Lost Cave - Runestone", 88870100, 1), LocationData("Lost Cave - Very Small Pile of Gold 1 (Dif. 2)", 88870101, 2), @@ -309,7 +309,7 @@ class GLLocation(Location): LocationData("Lost Cave Chest - Gold 6", 88873836, 1), ] -volcanicCavern: typing.List[LocationData] = [ +volcanic_cavern: typing.List[LocationData] = [ LocationData("Volcanic Cavern - Key 1", 88870143, 1), LocationData("Volcanic Cavern - Scimitar of Decapitation", 88870144, 1), LocationData("Volcanic Cavern - Runestone", 88870145, 1), @@ -402,7 +402,7 @@ class GLLocation(Location): LocationData("Volcanic Cavern Barrel - Nothing 13 (Dif. 2)", 88873956, 2), ] -dragonsLair: typing.List[LocationData] = [ +dragons_lair: typing.List[LocationData] = [ LocationData("Dragon's Lair - Slab of Meat (Dif. 2)", 88870176, 2), LocationData("Dragon's Lair - Rapid Fire (Dif. 2)", 88870177, 2), LocationData("Dragon's Lair - Growth (Dif. 4)", 88870178, 4), @@ -412,7 +412,7 @@ class GLLocation(Location): LocationData("Dragon's Lair - Dragon Mirror Shard", 88870607, 1), ] -castleCourtyard: typing.List[LocationData] = [ +castle_courtyard: typing.List[LocationData] = [ LocationData("Castle Courtyard - Runestone", 88870182, 1), LocationData("Castle Courtyard - Key 1", 88870183, 1), LocationData("Castle Courtyard - Key 2", 88870184, 1), @@ -511,7 +511,7 @@ class GLLocation(Location): LocationData("Castle Courtyard Barrel - Key 12 (Dif. 4)", 88873057, 4), ] -dungeonOfTorment: typing.List[LocationData] = [ +dungeon_of_torment: typing.List[LocationData] = [ LocationData("Dungeon of Torment - Lightning Potion 1 (Dif. 4)", 88870219, 4), LocationData("Dungeon of Torment - Key 1", 88870220, 1), LocationData("Dungeon of Torment - Runestone", 88870221, 1), @@ -567,7 +567,7 @@ class GLLocation(Location): LocationData("Dungeon of Torment Barrel - Scroll 2", 88873131, 1), ] -towerArmory: typing.List[LocationData] = [ +tower_armory: typing.List[LocationData] = [ LocationData("Tower Armory - Key 1 (Dif. 4)", 88870239, 4), LocationData("Tower Armory - Key 2", 88870240, 1), LocationData("Tower Armory - Key 3", 88870241, 1), @@ -652,7 +652,7 @@ class GLLocation(Location): LocationData("Tower Armory Chest - Reflective Shield 1 (Dif. 2)", 88873236, 2), ] -castleTreasury: typing.List[LocationData] = [ +castle_treasury: typing.List[LocationData] = [ LocationData("Castle Treasury - Lightning Potion 1", 88870284, 1), LocationData("Castle Treasury - Key 1", 88870285, 1), LocationData("Castle Treasury - Key 2", 88870286, 1), @@ -733,7 +733,7 @@ class GLLocation(Location): LocationData("Castle Treasury Chest - Random 1", 88873332, 1), ] -chimerasKeep: typing.List[LocationData] = [ +chimeras_keep: typing.List[LocationData] = [ LocationData("Chimera's Keep - Speed Boots", 88870329, 1), LocationData("Chimera's Keep - Growth (Dif. 4)", 88870330, 4), LocationData("Chimera's Keep - 3-Way Shot (Dif. 2)", 88870331, 2), @@ -753,7 +753,7 @@ class GLLocation(Location): "Dungeon of Torment - Obelisk", ] -poisonedFields: typing.List[LocationData] = [ +poisoned_fields: typing.List[LocationData] = [ LocationData("Poisoned Fields - Fruit Pile 1", 88870335, 1), LocationData("Poisoned Fields - Fruit Pile 2 (Dif. 4)", 88870336, 4), LocationData("Poisoned Fields - Fruit Pile 3 (Dif. 3)", 88870337, 3), @@ -888,7 +888,7 @@ class GLLocation(Location): LocationData("Poisoned Fields Chest - Gold 14", 88871183, 1), ] -hauntedCemetery: typing.List[LocationData] = [ +haunted_cemetery: typing.List[LocationData] = [ LocationData("Haunted Cemetery - Acid Potion 1", 88870382, 1), LocationData("Haunted Cemetery - Runestone", 88870383, 1), LocationData("Haunted Cemetery - Small Pile of Gold", 88870384, 1), @@ -954,7 +954,7 @@ class GLLocation(Location): LocationData("Haunted Cemetery Chest - Meat 2 (Dif. 4)", 88871242, 4), ] -venomousSpire: typing.List[LocationData] = [ +venomous_spire: typing.List[LocationData] = [ LocationData("Venemous Spire - Acid Potion 1", 88870401, 1), LocationData("Venemous Spire - Invisibility", 88870402, 1), LocationData("Venemous Spire - Flame of Tarkana", 88870403, 1), @@ -1037,7 +1037,7 @@ class GLLocation(Location): LocationData("Venemous Spire Barrel - Key 19", 88871363, 1), ] -toxicAirShip: typing.List[LocationData] = [ +toxic_air_ship: typing.List[LocationData] = [ LocationData("Toxic Air Ship - Acid Breath", 88870417, 1), LocationData("Toxic Air Ship - Scroll", 88870418, 1), LocationData("Toxic Air Ship - Key 1", 88870419, 1), @@ -1103,11 +1103,11 @@ class GLLocation(Location): LocationData("Toxic Air Ship Barrel - Potion 3 (Dif. 4)", 88871443, 4), ] -plagueFiend: typing.List[LocationData] = [ - LocationData("Vat of the Plague Fiend - Plague Fiend Mirror Shard", 88870609, 1) +plague_fiend: typing.List[LocationData] = [ + LocationData("Vat of the Plague Fiend - Plague Fiend Mirror Shard", 88870609, 1), ] -arcticDocks: typing.List[LocationData] = [ +arctic_docks: typing.List[LocationData] = [ LocationData("Arctic Docks - Light Potion 1", 88870436, 1), LocationData("Arctic Docks - Scroll", 88870437, 1), LocationData("Arctic Docks - Light Potion 2 (Dif. 2)", 88870438, 2), @@ -1203,7 +1203,7 @@ class GLLocation(Location): LocationData("Arctic Docks Chest - Meat 3 (Dif. 4)", 88871666, 4), ] -frozenCamp: typing.List[LocationData] = [ +frozen_camp: typing.List[LocationData] = [ LocationData("Frozen Camp - Light Potion 1", 88870462, 1), LocationData("Frozen Camp - Full Barrel of Gold 1 (Dif. 4)", 88870463, 4), LocationData("Frozen Camp - Half Barrel of Gold 1 1", 88870464, 1), @@ -1320,7 +1320,7 @@ class GLLocation(Location): LocationData("Frozen Camp Barrel - Death 1 (Dif. 2)", 88871777, 2), ] -crystalMine: typing.List[LocationData] = [ +crystal_mine: typing.List[LocationData] = [ LocationData("Crystal Mine - Rapid Fire", 88870498, 1), LocationData("Crystal Mine - Speed Boots", 88870499, 1), LocationData("Crystal Mine - Key 1 (Dif. 2)", 88870500, 2), @@ -1406,7 +1406,7 @@ class GLLocation(Location): LocationData("Crystal Mine Chest - Gold 10 (Dif. 2)", 88871868, 2), ] -eruptingFissure: typing.List[LocationData] = [ +erupting_fissure: typing.List[LocationData] = [ LocationData("Erupting Fissure - Light Potion", 88870512, 1), LocationData("Erupting Fissure - Growth", 88870513, 1), LocationData("Erupting Fissure - Reflective Shield", 88870514, 1), @@ -1507,7 +1507,7 @@ class GLLocation(Location): yeti: typing.List[LocationData] = [LocationData("Yeti's Cavern - Yeti Mirror Shard", 88870610, 1)] -desecratedTemple: typing.List[LocationData] = [ +desecrated_temple: typing.List[LocationData] = [ LocationData("Desecrated Temple - Death 1", 88870530, 1), LocationData("Desecrated Temple - Death 2 (Dif. 2)", 88870531, 2), LocationData("Desecrated Temple - Speed Boots", 88870532, 1), @@ -1549,7 +1549,7 @@ class GLLocation(Location): LocationData("Desecrated Temple Chest - Phoenix Familiar 1 (Dif. 3)", 88872032, 3), ] -battleTrenches: typing.List[LocationData] = [ +battle_trenches: typing.List[LocationData] = [ LocationData("Battle Trenches - Fire Potion 1", 88870536, 1), LocationData("Battle Trenches - Light Potion", 88870537, 1), LocationData("Battle Trenches - Scroll 1", 88870538, 1), @@ -1632,7 +1632,7 @@ class GLLocation(Location): LocationData("Battle Trenches Chest - Meat 4 (Dif. 3)", 88872155, 3), ] -battleTowers: typing.List[LocationData] = [ +battle_towers: typing.List[LocationData] = [ LocationData("Battle Towers - Ham (Dif. 3)", 88870560, 3), LocationData("Battle Towers - Key 1", 88870561, 1), LocationData("Battle Towers - Large Pile of Gold (Dif. 3)", 88870562, 3), @@ -1685,7 +1685,7 @@ class GLLocation(Location): LocationData("Battle Towers Chest - Fire Breath 1", 88872242, 1), ] -infernalFortress: typing.List[LocationData] = [ +infernal_fortress: typing.List[LocationData] = [ LocationData("Infernal Fortress - Thunder Hammer", 88870567, 1), LocationData("Infernal Fortress - Key 1 (Dif. 2)", 88870568, 2), LocationData("Infernal Fortress - Runestone", 88870569, 1), @@ -1760,7 +1760,7 @@ class GLLocation(Location): LocationData("Infernal Fortress Chest - Meat 1 (Dif. 3)", 88872354, 3), ] -gatesOfTheUnderworld: typing.List[LocationData] = [ +gates_of_the_underworld: typing.List[LocationData] = [ LocationData("Gates of the Underworld - Potion Pile", 88870584, 1), LocationData("Gates of the Underworld - Rapid Fire (Dif. 3)", 88870585, 3), LocationData("Gates of the Underworld - Reflective Shield (Dif. 2)", 88870586, 2), @@ -1787,32 +1787,32 @@ class GLLocation(Location): ] all_locations: typing.List[LocationData] = ( - valleyOfFire - + daggerPeak - + cliffsOfDesolation - + lostCave - + volcanicCavern - + dragonsLair - + castleCourtyard - + dungeonOfTorment - + towerArmory - + castleTreasury - + chimerasKeep - + poisonedFields - + hauntedCemetery - + venomousSpire - + toxicAirShip - + arcticDocks - + frozenCamp - + crystalMine - + eruptingFissure - + desecratedTemple - + battleTrenches - + battleTowers - + infernalFortress - + gatesOfTheUnderworld - + plagueFiend - + yeti + valley_of_fire + + dagger_peak + + cliffs_of_desolation + + lost_cave + + volcanic_cavern + + dragons_lair + + castle_courtyard + + dungeon_of_torment + + tower_armory + + castle_treasury + + chimeras_keep + + poisoned_fields + + haunted_cemetery + + venomous_spire + + toxic_air_ship + + arctic_docks + + frozen_camp + + crystal_mine + + erupting_fissure + + desecrated_temple + + battle_trenches + + battle_towers + + infernal_fortress + + gates_of_the_underworld + + plague_fiend + + yeti ) diff --git a/worlds/gl/Options.py b/worlds/gl/Options.py index 08bd2bcc50ce..d88343db106e 100644 --- a/worlds/gl/Options.py +++ b/worlds/gl/Options.py @@ -1,6 +1,7 @@ -from Options import StartInventoryPool, PerGameCommonOptions, Choice, Toggle from dataclasses import dataclass +from Options import Choice, PerGameCommonOptions, StartInventoryPool, Toggle + class PermaSpeed(Toggle): """ diff --git a/worlds/gl/Regions.py b/worlds/gl/Regions.py index a470bd482a9a..df1e372c55f4 100644 --- a/worlds/gl/Regions.py +++ b/worlds/gl/Regions.py @@ -1,33 +1,34 @@ import typing -from BaseClasses import Region, Entrance +from BaseClasses import Entrance, Region + from .Locations import ( GLLocation, - valleyOfFire, - daggerPeak, - cliffsOfDesolation, - lostCave, - volcanicCavern, - dragonsLair, - castleCourtyard, - dungeonOfTorment, - towerArmory, - castleTreasury, - chimerasKeep, - poisonedFields, - hauntedCemetery, - venomousSpire, - toxicAirShip, - arcticDocks, - frozenCamp, - crystalMine, - eruptingFissure, - desecratedTemple, - battleTrenches, - battleTowers, - infernalFortress, - gatesOfTheUnderworld, - plagueFiend, + arctic_docks, + battle_towers, + battle_trenches, + castle_courtyard, + castle_treasury, + chimeras_keep, + cliffs_of_desolation, + crystal_mine, + dagger_peak, + desecrated_temple, + dragons_lair, + dungeon_of_torment, + erupting_fissure, + frozen_camp, + gates_of_the_underworld, + haunted_cemetery, + infernal_fortress, + lost_cave, + plague_fiend, + poisoned_fields, + tower_armory, + toxic_air_ship, + valley_of_fire, + venomous_spire, + volcanic_cavern, yeti, ) @@ -38,57 +39,57 @@ def create_regions(world: "GauntletLegendsWorld"): world.multiworld.regions.append(Region("Menu", world.player, world.multiworld)) - create_region(world, "Valley of Fire", valleyOfFire) + create_region(world, "Valley of Fire", valley_of_fire) - create_region(world, "Dagger Peak", daggerPeak) + create_region(world, "Dagger Peak", dagger_peak) - create_region(world, "Cliffs of Desolation", cliffsOfDesolation) + create_region(world, "Cliffs of Desolation", cliffs_of_desolation) - create_region(world, "Lost Cave", lostCave) + create_region(world, "Lost Cave", lost_cave) - create_region(world, "Volcanic Caverns", volcanicCavern) + create_region(world, "Volcanic Caverns", volcanic_cavern) - create_region(world, "Dragon's Lair", dragonsLair) + create_region(world, "Dragon's Lair", dragons_lair) - create_region(world, "Castle Courtyard", castleCourtyard) + create_region(world, "Castle Courtyard", castle_courtyard) - create_region(world, "Dungeon of Torment", dungeonOfTorment) + create_region(world, "Dungeon of Torment", dungeon_of_torment) - create_region(world, "Tower Armory", towerArmory) + create_region(world, "Tower Armory", tower_armory) - create_region(world, "Castle Treasury", castleTreasury) + create_region(world, "Castle Treasury", castle_treasury) - create_region(world, "Chimera's Keep", chimerasKeep) + create_region(world, "Chimera's Keep", chimeras_keep) - create_region(world, "Poisonous Fields", poisonedFields) + create_region(world, "Poisonous Fields", poisoned_fields) - create_region(world, "Haunted Cemetery", hauntedCemetery) + create_region(world, "Haunted Cemetery", haunted_cemetery) - create_region(world, "Venomous Spire", venomousSpire) + create_region(world, "Venomous Spire", venomous_spire) - create_region(world, "Toxic Air Ship", toxicAirShip) + create_region(world, "Toxic Air Ship", toxic_air_ship) - create_region(world, "Vat of the Plague Fiend", plagueFiend) + create_region(world, "Vat of the Plague Fiend", plague_fiend) - create_region(world, "Arctic Docks", arcticDocks) + create_region(world, "Arctic Docks", arctic_docks) - create_region(world, "Frozen Camp", frozenCamp) + create_region(world, "Frozen Camp", frozen_camp) - create_region(world, "Crystal Mine", crystalMine) + create_region(world, "Crystal Mine", crystal_mine) - create_region(world, "Erupting Fissure", eruptingFissure) + create_region(world, "Erupting Fissure", erupting_fissure) create_region(world, "Yeti", yeti) - create_region(world, "Desecrated Temple", desecratedTemple) + create_region(world, "Desecrated Temple", desecrated_temple) - create_region(world, "Battle Trenches", battleTrenches) + create_region(world, "Battle Trenches", battle_trenches) - create_region(world, "Battle Towers", battleTowers) + create_region(world, "Battle Towers", battle_towers) - create_region(world, "Infernal Fortress", infernalFortress) + create_region(world, "Infernal Fortress", infernal_fortress) - create_region(world, "Gates of the Underworld", gatesOfTheUnderworld) + create_region(world, "Gates of the Underworld", gates_of_the_underworld) def connect_regions(world: "GauntletLegendsWorld"): diff --git a/worlds/gl/Rom.py b/worlds/gl/Rom.py index ee6472b600c3..1d846dc6b584 100644 --- a/worlds/gl/Rom.py +++ b/worlds/gl/Rom.py @@ -1,16 +1,18 @@ +import io import json +import os import traceback import typing import zlib -import io -import os +from typing import Dict, List, Tuple import Utils -from typing import List, Dict, Tuple from BaseClasses import Location from settings import get_settings + from worlds.Files import APPatchExtension, APProcedurePatch, APTokenMixin -from .Arrays import level_locations, level_size, level_address, item_dict, level_header + +from .Arrays import item_dict, level_address, level_header, level_locations, level_size from .Items import items_by_id from .Locations import location_data @@ -22,7 +24,7 @@ def get_base_rom_as_bytes() -> bytes: try: with open(get_settings().gl_options.rom_file, "rb") as infile: base_rom_bytes = bytes(infile.read()) - except Exception as e: + except Exception: traceback.print_exc() return base_rom_bytes @@ -57,7 +59,7 @@ def __init__(self): self.spawners = [] self.objects = [] self.chests = [] - self.end = bytes() + self.end = b"" class GLPatchExtension(APPatchExtension): @@ -115,7 +117,7 @@ def patch_items(caller: APProcedurePatch, rom: bytes): data.items += [ bytearray(data.objects[index][0:6]) + bytes(item_dict[item[0]] if item[1] == options["player"] else [0x27, 0x4]) - + bytes([0x0, 0x0, 0x0, 0x0]) + + bytes([0x0, 0x0, 0x0, 0x0]), ] del data.objects[index] data.item += 1 @@ -133,7 +135,7 @@ def patch_items(caller: APProcedurePatch, rom: bytes): data.items[j - data.obelisk][6] = 0x27 data.items[j - data.obelisk][7] = 0x4 else: - if "Obelisk" in items_by_id[item[0]].itemName: + if "Obelisk" in items_by_id[item[0]].item_name: data.objects += [ bytearray(data.items[j - data.obelisk][0:6]) + bytearray( @@ -156,8 +158,8 @@ def patch_items(caller: APProcedurePatch, rom: bytes): 0x0, 0x0, 0x0, - ] - ) + ], + ), ] del data.items[j - data.obelisk] data.obelisk += 1 diff --git a/worlds/gl/Rules.py b/worlds/gl/Rules.py index 0ccc46465d3f..0724a8d8d025 100644 --- a/worlds/gl/Rules.py +++ b/worlds/gl/Rules.py @@ -1,9 +1,10 @@ import typing from worlds.generic.Rules import add_rule, forbid_item -from .Locations import all_locations, chimerasKeep, dragonsLair, LocationData, gatesOfTheUnderworld -from .Items import itemList -from .Arrays import level_locations, difficulty_lambda + +from .Arrays import difficulty_lambda, level_locations +from .Items import item_list +from .Locations import all_locations, chimeras_keep, dragons_lair, gates_of_the_underworld if typing.TYPE_CHECKING: from . import GauntletLegendsWorld @@ -23,23 +24,23 @@ def set_rules(world: "GauntletLegendsWorld"): location for location in all_locations if "Obelisk" in location.name - or "Chest" in location.name - or "Mirror" in location.name - or ("Barrel" in location.name and "Barrel of Gold" not in location.name) - or location in dragonsLair - or location in chimerasKeep - or location in gatesOfTheUnderworld + or "Chest" in location.name + or "Mirror" in location.name + or ("Barrel" in location.name and "Barrel of Gold" not in location.name) + or location in dragons_lair + or location in chimeras_keep + or location in gates_of_the_underworld ]: - for item in [item for item in itemList if "Obelisk" in item.itemName]: + for item in [item for item in item_list if "Obelisk" in item.item_name]: if location.name not in world.disabled_locations: - forbid_item(world.get_location(location.name), item.itemName, world.player) + forbid_item(world.get_location(location.name), item.item_name, world.player) for location in [ location for location in all_locations if "Barrel" in location.name and "Barrel of Gold" not in location.name ]: - for item in [item for item in itemList if "Runestone" in item.itemName]: + for item in [item for item in item_list if "Runestone" in item.item_name]: if location.name not in world.disabled_locations: - forbid_item(world.get_location(location.name), item.itemName, world.player) + forbid_item(world.get_location(location.name), item.item_name, world.player) for level_id, locations in level_locations.items(): for location in locations: @@ -48,6 +49,6 @@ def set_rules(world: "GauntletLegendsWorld"): add_rule( world.get_location(location.name), lambda state, level_id_=level_id >> 4, difficulty=location.difficulty - 1: prog_count( - state, world.player, difficulty_lambda[level_id_][difficulty] + state, world.player, difficulty_lambda[level_id_][difficulty], ), ) diff --git a/worlds/gl/__init__.py b/worlds/gl/__init__.py index 93775d1adb7d..8cc406218d05 100644 --- a/worlds/gl/__init__.py +++ b/worlds/gl/__init__.py @@ -1,18 +1,19 @@ import os -import threading import typing import settings -from BaseClasses import Tutorial, ItemClassification +from BaseClasses import ItemClassification, Tutorial + +from worlds.AutoWorld import WebWorld, World + +from ..LauncherComponents import Component, SuffixIdentifier, Type, components, launch_subprocess from .Arrays import item_dict +from .Items import GLItem, item_frequencies, item_list, item_table +from .Locations import LocationData, all_locations, location_table from .Options import GLOptions -from worlds.AutoWorld import WebWorld, World -from .Locations import all_locations, location_table, LocationData -from .Items import GLItem, itemList, item_table, item_frequencies -from .Regions import create_regions, connect_regions +from .Regions import connect_regions, create_regions from .Rom import GLProcedurePatch, write_files from .Rules import set_rules -from ..LauncherComponents import components, Component, launch_subprocess, Type, SuffixIdentifier def launch_client(*args): @@ -28,7 +29,7 @@ def launch_client(*args): func=launch_client, component_type=Type.CLIENT, file_identifier=SuffixIdentifier(".apgl"), - ) + ), ) @@ -43,7 +44,7 @@ class GauntletLegendsWebWorld(WebWorld): file_name="setup_en.md", link="setup/en", authors=["jamesbrq"], - ) + ), ] @@ -147,33 +148,33 @@ def fill_slot_data(self) -> dict: def create_items(self) -> None: # First add in all progression and useful items required_items = [] - precollected = [item for item in itemList if item in self.multiworld.precollected_items[self.player]] - for item in itemList: + precollected = [item for item in item_list if item in self.multiworld.precollected_items[self.player]] + for item in item_list: if item.progression != ItemClassification.filler and item not in precollected: - if "Obelisk" in item.itemName and self.options.obelisks == 0: + if "Obelisk" in item.item_name and self.options.obelisks == 0: continue - if "Mirror" in item.itemName and self.options.mirror_shards == 0: + if "Mirror" in item.item_name and self.options.mirror_shards == 0: continue - if "Key" in item.itemName and self.options.infinite_keys: + if "Key" in item.item_name and self.options.infinite_keys: continue - freq = item_frequencies.get(item.itemName, 1) + ( + freq = item_frequencies.get(item.item_name, 1) + ( 30 if self.options.infinite_keys and item.progression is ItemClassification.filler else 0 ) if freq is None: freq = 1 - required_items += [item.itemName for _ in range(freq)] + required_items += [item.item_name for _ in range(freq)] - for itemName in required_items: - self.multiworld.itempool.append(self.create_item(itemName)) + for item_name in required_items: + self.multiworld.itempool.append(self.create_item(item_name)) # Then, get a random amount of fillers until we have as many items as we have locations filler_items = [] - for item in itemList: + for item in item_list: if item.progression == ItemClassification.filler: - freq = item_frequencies.get(item.itemName) + freq = item_frequencies.get(item.item_name) if freq is None: freq = 1 - filler_items += [item.itemName for _ in range(freq)] + filler_items += [item.item_name for _ in range(freq)] remaining = len(all_locations) - len(required_items) - len(self.disabled_locations) - 2 if self.options.obelisks == 0: @@ -189,17 +190,17 @@ def create_items(self) -> None: def set_rules(self) -> None: set_rules(self) self.multiworld.completion_condition[self.player] = lambda state: state.can_reach( - "Gates of the Underworld", "Region", self.player + "Gates of the Underworld", "Region", self.player, ) def create_item(self, name: str) -> GLItem: item = item_table[name] - return GLItem(item.itemName, item.progression, item.code, self.player) + return GLItem(item.item_name, item.progression, item.code, self.player) def generate_output(self, output_directory: str) -> None: patch = GLProcedurePatch(player=self.player, player_name=self.multiworld.player_name[self.player]) write_files(self, patch) rom_path = os.path.join( - output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}" f"{patch.patch_file_ending}" + output_directory, f"{self.multiworld.get_out_file_name_base(self.player)}{patch.patch_file_ending}", ) patch.write(rom_path)