From 2c490ef6375c21876541a9cb83d561c1541055d6 Mon Sep 17 00:00:00 2001 From: Carter Hesterman Date: Tue, 20 Aug 2024 20:54:12 -0600 Subject: [PATCH] Implement feedback --- worlds/civ_6/Civ6Client.py | 14 +++++++------- worlds/civ_6/CivVIInterface.py | 6 +++--- worlds/civ_6/Data.py | 10 +++++----- worlds/civ_6/Locations.py | 14 +++++++------- worlds/civ_6/Options.py | 15 +++++++++++++-- worlds/civ_6/Rules.py | 10 +--------- worlds/civ_6/TunerClient.py | 10 +++++----- worlds/civ_6/__init__.py | 10 +++++----- 8 files changed, 46 insertions(+), 43 deletions(-) diff --git a/worlds/civ_6/Civ6Client.py b/worlds/civ_6/Civ6Client.py index f1053a989b..cb222c2869 100644 --- a/worlds/civ_6/Civ6Client.py +++ b/worlds/civ_6/Civ6Client.py @@ -29,7 +29,7 @@ class CivVICommandProcessor(ClientCommandProcessor): Utils.async_start(self.ctx.update_death_link( self.ctx.death_link_enabled), name="Update Deathlink") self.ctx.logger.info( - f"Deathlink is now {'enabled' if self.ctx.death_link_enabled else 'disabled'}") + f"Deathlink is now {"enabled" if self.ctx.death_link_enabled else "disabled"}") def _cmd_resync(self): """Resends all items to client, and has client resend all locations to server. This can take up to a minute if the player has received a lot of items""" @@ -101,7 +101,7 @@ class CivVIContext(CommonContext): if text: message = text else: - message = f"Received from {data['source']}" + message = f"Received from {data["source"]}" self.death_link_message = message self.received_death_link = True @@ -284,7 +284,7 @@ def main(connect=None, password=None, name=None): async def _main(connect, password, name): parser = get_base_parser() - parser.add_argument('apcivvi_file', default="", type=str, nargs='?', help="Path to apcivvi file") + parser.add_argument("apcivvi_file", default="", type=str, nargs="?", help="Path to apcivvi file") args = parser.parse_args() ctx = CivVIContext(connect, password, args.apcivvi_file) @@ -295,7 +295,7 @@ def main(connect=None, password=None, name=None): if not os.path.exists(target_path): os.makedirs(target_path, exist_ok=True) logger.info("Extracting mod files to %s", target_path) - with zipfile.ZipFile(args.apcivvi_file, 'r') as zip_ref: + with zipfile.ZipFile(args.apcivvi_file, "r") as zip_ref: for member in zip_ref.namelist(): zip_ref.extract(member, target_path) @@ -327,10 +327,10 @@ def main(connect=None, password=None, name=None): def debug_main(): parser = get_base_parser() - parser.add_argument('apcivvi_file', default="", type=str, nargs='?', help="Path to apcivvi file") - parser.add_argument('--name', default=None, + parser.add_argument("apcivvi_file", default="", type=str, nargs="?", help="Path to apcivvi file") + parser.add_argument("--name", default=None, help="Slot Name to connect as.") - parser.add_argument('--debug', default=None, + parser.add_argument("--debug", default=None, help="debug mode, additional logging") args = parser.parse_args() if args.debug: diff --git a/worlds/civ_6/CivVIInterface.py b/worlds/civ_6/CivVIInterface.py index 45cf15d09b..aba4032bf0 100644 --- a/worlds/civ_6/CivVIInterface.py +++ b/worlds/civ_6/CivVIInterface.py @@ -5,13 +5,13 @@ from typing import List from .Items import CivVIItemData from .TunerClient import TunerClient, TunerConnectionException, TunerTimeoutException + class ConnectionState(Enum): DISCONNECTED = 0 IN_GAME = 1 IN_MENU = 2 - class CivVIInterface: logger: Logger tuner: TunerClient @@ -28,7 +28,7 @@ class CivVIInterface: if result == "false": return ConnectionState.IN_MENU self.last_error = None - return ConnectionState.IN_GAME + return ConnectionState.IN_GAME except TunerTimeoutException: self.print_connection_error( "Not connected to game, waiting for connection to be available") @@ -55,7 +55,7 @@ class CivVIInterface: if isinstance(item.civ_vi_id, str): item_id = f'"{item.civ_vi_id}"' else: - item_id = item.civ_vi_id + item_id = item.civ_vi_id command = f"HandleReceiveItem({item_id}, \"{item.name}\", \"{item.item_type.value}\", \"{sender}\", {amount})" await self.tuner.send_game_command(command) diff --git a/worlds/civ_6/Data.py b/worlds/civ_6/Data.py index a278931933..8e3eb40f5e 100644 --- a/worlds/civ_6/Data.py +++ b/worlds/civ_6/Data.py @@ -33,11 +33,11 @@ def get_boosts_data() -> List[CivVIBoostData]: boosts = [] for boost in boosts_json: boosts.append(CivVIBoostData( - Type=boost['Type'], - EraType=boost['EraType'], - Prereq=boost['Prereq'], - PrereqRequiredCount=boost['PrereqRequiredCount'], - Classification=boost['Classification'] + Type=boost["Type"], + EraType=boost["EraType"], + Prereq=boost["Prereq"], + PrereqRequiredCount=boost["PrereqRequiredCount"], + Classification=boost["Classification"] )) return boosts diff --git a/worlds/civ_6/Locations.py b/worlds/civ_6/Locations.py index 1c53a2da87..2063bb3423 100644 --- a/worlds/civ_6/Locations.py +++ b/worlds/civ_6/Locations.py @@ -78,7 +78,7 @@ class CivVILocation(Location): game: str = "Civilization VI" location_type: CivVICheckType - def __init__(self, player: int, name: str = '', address: Optional[int] = None, parent: Optional[Region] = None): + def __init__(self, player: int, name: str = "", address: Optional[int] = None, parent: Optional[Region] = None): super().__init__(player, name, address, parent) if name.split("_")[0] == "TECH": self.location_type = CivVICheckType.TECH @@ -142,28 +142,28 @@ def generate_era_location_table() -> Dict[EraType, Dict[str, CivVILocationData]] id_base = 0 # Techs for data in new_techs: - era_type = data['EraType'] + era_type = data["EraType"] if era_type not in era_locations: era_locations[era_type] = {} prereq_data = [ - item for item in new_tech_prereqs if item['Technology'] == data['Type']] + item for item in new_tech_prereqs if item["Technology"] == data["Type"]] era_locations[era_type][data["Type"]] = CivVILocationData( - data["Type"], data['Cost'], data['UITreeRow'], id_base, era_type, CivVICheckType.TECH, prereq_data) + data["Type"], data["Cost"], data["UITreeRow"], id_base, era_type, CivVICheckType.TECH, prereq_data) id_base += 1 # Civics new_civic_prereqs = get_new_civic_prereqs_data() new_civics = get_new_civics_data() for data in new_civics: - era_type = data['EraType'] + era_type = data["EraType"] if era_type not in era_locations: era_locations[era_type] = {} prereq_data = [ - item for item in new_civic_prereqs if item['Civic'] == data['Type']] + item for item in new_civic_prereqs if item["Civic"] == data["Type"]] era_locations[era_type][data["Type"]] = CivVILocationData( - data["Type"], data['Cost'], data['UITreeRow'], id_base, era_type, CivVICheckType.CIVIC, prereq_data) + data["Type"], data["Cost"], data["UITreeRow"], id_base, era_type, CivVICheckType.CIVIC, prereq_data) id_base += 1 # Eras diff --git a/worlds/civ_6/Options.py b/worlds/civ_6/Options.py index 3e6d730a7f..2789bd6641 100644 --- a/worlds/civ_6/Options.py +++ b/worlds/civ_6/Options.py @@ -1,5 +1,5 @@ from dataclasses import dataclass -from Options import Choice, DeathLink, DefaultOnToggle, PerGameCommonOptions, Range, Toggle +from Options import Choice, DeathLink, DefaultOnToggle, PerGameCommonOptions, Range, StartInventory, Toggle class ProgressionStyle(Choice): @@ -27,7 +27,6 @@ class BoostSanity(Toggle): display_name = "Boostsanity" - class ExcludeMissableBoosts(Toggle): """If boostsanity is enabled, this will prevent any boosts that are 'missable' from having progression items. Disabling this will potentially require multiple playthroughs to complete the seed.""" display_name = "Exclude Missable Boosts" @@ -66,6 +65,7 @@ class InGameFlagProgressionItems(DefaultOnToggle): """If enabled, an advisor icon will be added to any location that contains a progression item""" display_name = "Advisor Indicates Progression Items" + class DeathLinkEffect(Choice): """What happens when a unit dies. Default is Unit Killed.\n Faith, and Gold will be decreased by the amount specified in 'Death Link Effect Percent'. \n @@ -89,8 +89,19 @@ class DeathLinkEffectPercent(Range): range_end = 100 +class StartInventoryPool(StartInventory): + """Start with these items and don't place them in the world. + + The game decides what the replacement items will be. + """ + verify_item_name = True + display_name = "Start Inventory from Pool" + rich_text_doc = True + + @dataclass class CivVIOptions(PerGameCommonOptions): + start_inventory_from_pool: StartInventoryPool progression_style: ProgressionStyle shuffle_goody_hut_rewards: ShuffleGoodyHuts boostsanity: BoostSanity diff --git a/worlds/civ_6/Rules.py b/worlds/civ_6/Rules.py index bdcd688d84..b51e187769 100644 --- a/worlds/civ_6/Rules.py +++ b/worlds/civ_6/Rules.py @@ -12,12 +12,6 @@ if TYPE_CHECKING: from . import CivVIWorld -def generate_has_required_items_lambda(prereqs: List[str], required_count: int, player: int) -> Callable[[CollectionState, int], bool]: - def has_required_items_lambda(state: CollectionState): - return has_required_items(state, prereqs, required_count, player) - return has_required_items_lambda - - def create_boost_rules(world: 'CivVIWorld'): boost_data_list = get_boosts_data() boost_locations = [location for location in world.location_table.values() if location.location_type == CivVICheckType.BOOST] @@ -28,9 +22,7 @@ def create_boost_rules(world: 'CivVIWorld'): if not boost_data or boost_data.PrereqRequiredCount == 0: continue - set_rule(world_location, - generate_has_required_items_lambda(boost_data.Prereq, boost_data.PrereqRequiredCount, world.player) - ) + set_rule(world_location, lambda state, prereqs=boost_data.Prereq, required_count=boost_data.PrereqRequiredCount: has_required_items(state, prereqs, required_count, world.player)) def has_required_items(state: CollectionState, prereqs: List[str], required_count: int, player: int) -> bool: diff --git a/worlds/civ_6/TunerClient.py b/worlds/civ_6/TunerClient.py index c75d95c0f5..bf08d1c9ae 100644 --- a/worlds/civ_6/TunerClient.py +++ b/worlds/civ_6/TunerClient.py @@ -10,7 +10,7 @@ CLIENT_POSTFIX = ":APEND" def decode_mixed_string(data): - return ''.join(chr(b) if 32 <= b < 127 else '?' for b in data) + return "".join(chr(b) if 32 <= b < 127 else "?" for b in data) class TunerException(Exception): @@ -57,14 +57,14 @@ class TunerClient: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) - b_command_string = command_string.encode('utf-8') + b_command_string = command_string.encode("utf-8") # Send data to the server command_prefix = b"CMD:0:" delimiter = b"\x00" full_command = b_command_string message = command_prefix + full_command + delimiter - message_length = len(message).to_bytes(1, byteorder='little') + message_length = len(message).to_bytes(1, byteorder="little") # game expects this to be added before any command that is sent, indicates payload size message_header = message_length + b"\x00\x00\x00\x03\x00\x00\x00" @@ -84,10 +84,10 @@ class TunerClient: return self.__parse_response(response) except socket.timeout: - self.logger.debug('Timeout occurred while receiving data') + self.logger.debug("Timeout occurred while receiving data") raise TunerTimeoutException() except Exception as e: - self.logger.debug(f'Error occurred while receiving data: {str(e)}') + self.logger.debug(f"Error occurred while receiving data: {str(e)}") # check if No connection could be made is present in the error message connection_errors = [ "The remote computer refused the network connection", diff --git a/worlds/civ_6/__init__.py b/worlds/civ_6/__init__.py index 4a6b366d7b..a9cb2dd5cd 100644 --- a/worlds/civ_6/__init__.py +++ b/worlds/civ_6/__init__.py @@ -1,6 +1,6 @@ import math import os -from typing import Dict, Optional, Set +from typing import Any, Dict, Optional, Set from .Data import get_boosts_data @@ -76,7 +76,7 @@ class CivVIWorld(World): def get_filler_item_name(self) -> str: return get_random_filler_by_rarity(self, FillerItemRarity.COMMON, self.item_table).name - def create_regions(self): + def create_regions(self) -> None: create_regions(self, self.options, self.player) def set_rules(self) -> None: @@ -92,7 +92,7 @@ class CivVIWorld(World): return CivVIItem(item, self.player, classification) - def create_items(self): + def create_items(self) -> None: progressive_era_item = None for item_name, data in self.item_table.items(): # Don't add progressive items to the itempool here @@ -145,7 +145,7 @@ class CivVIWorld(World): get_random_filler_by_rarity(self, rarity, self.item_table).name)] total_created += 1 - def post_fill(self): + def post_fill(self) -> None: if self.options.pre_hint_items == "none": return @@ -167,7 +167,7 @@ class CivVIWorld(World): start_location_hints.add(location_name) - def fill_slot_data(self): + def fill_slot_data(self) -> Dict[str, Any]: return { "progression_style": self.options.progression_style, "death_link": self.options.death_link,