From 41022d7a5f0f61ce8b2b2ce41dbea42b5b4a6f01 Mon Sep 17 00:00:00 2001 From: RPINerd <RPINerd@gmail.com> Date: Mon, 9 Dec 2024 19:47:28 -0500 Subject: [PATCH] Documentation and formatting update, upgrading to Ruff and stricter rules --- spacetrader.py | 3 +- src/commander.py | 13 ++- src/constants.py | 208 +++++++++++++++++++++++++------------ src/screens/char_create.py | 28 ++--- src/screens/gamescreens.py | 3 +- src/ui_actions.py | 6 +- src/universe.py | 22 ++-- src/utils.py | 4 +- 8 files changed, 175 insertions(+), 112 deletions(-) diff --git a/spacetrader.py b/spacetrader.py index b9cc933..b7543d3 100644 --- a/spacetrader.py +++ b/spacetrader.py @@ -40,13 +40,12 @@ def _center_window(self, screen_x: int, screen_y: int) -> str: x_adj = int((screen_x / 2) - (res / 2)) y_adj = int((screen_y / 2) - (res / 2)) - return f"{str(res)}x{str(res)}+{x_adj}+{y_adj}" + return f"{res!s}x{res!s}+{x_adj}+{y_adj}" def _load_assets(self): """ Loads all game assets, currently just pointers to directories """ - # Load the configuration file # self.config = configparser.ConfigParser() # self.config.read(os.path.join("src/config", "config.ini")) diff --git a/src/commander.py b/src/commander.py index 14a2380..972978a 100644 --- a/src/commander.py +++ b/src/commander.py @@ -1,5 +1,6 @@ """ Space Trader | RPINerd, 2024 + An elite-inspired space trading RPG originally on PalmOS Commander Module @@ -67,7 +68,7 @@ def pay_interest(self): self.debt = self.debt * 1.1 def pay_insurance(self): - #! AI generated placeholder + # ! AI generated placeholder insurance = self.ship.get_value() * INSURANCE_RATE if self.credits > insurance: self.credits -= insurance @@ -145,16 +146,14 @@ def mod_random_skill(self, amount: int): param amount: The amount to modify the skill by. """ - # Create a sublist of skills that will be within the bounds skills = [skill for skill in self.get_skills() if 1 <= skill + amount <= MAXSKILL] # If there are no skills that can be modified, return if not skills: return - else: - # Choose a random skill from the sublist - skill = random.choice(skills) + # Choose a random skill from the sublist + skill = random.choice(skills) - # Modify the skill by the given amount - skill += amount + # Modify the skill by the given amount + skill += amount diff --git a/src/constants.py b/src/constants.py index ca9e5df..38f04ad 100644 --- a/src/constants.py +++ b/src/constants.py @@ -1,5 +1,6 @@ """ Space Trader | RPINerd, 2024 + An elite-inspired space trading RPG originally on PalmOS Constants Module @@ -86,9 +87,8 @@ class Activity: - """ - General class to associate an int with a level of activity - """ + + """Enum-esque class to associate an int with an activity level""" ABSENT = 0 MINIMAL = 1 @@ -100,7 +100,7 @@ class Activity: SWARMS = 7 UNAVAILABLE = 100 - NAMES = [ + NAMES = ( "Absent", "Minimal", "Few", @@ -110,16 +110,25 @@ class Activity: "Abundant", "Swarms", "Unavailable", - ] + ) @classmethod def name(cls, activity: int) -> str: + """ + Provides the name of the activity level + + Raises: + ValueError on invalid index given + """ if activity < 0 or activity >= len(cls.NAMES): raise ValueError(f"Invalid activity: {activity}") return cls.NAMES[activity] class TechLevel: + + """Enum-esque class to associate an int with a tech level""" + PRE_AGRICULTURAL = 0 AGRICULTURAL = 1 MEDIEVAL = 2 @@ -130,7 +139,7 @@ class TechLevel: HI_TECH = 7 UNAVAILABLE = 8 - NAMES = [ + NAMES = ( "Pre-Agricultural", "Agricultural", "Medieval", @@ -140,19 +149,24 @@ class TechLevel: "Post-Industrial", "Hi-Tech", "Unavailable", - ] + ) @classmethod def name(cls, tech: int) -> str: + """ + Provides the name of the tech level + + Raises: + ValueError on invalid index given + """ if tech < 0 or tech >= len(cls.NAMES): raise ValueError(f"Invalid tech level: {tech}") return cls.NAMES[tech] class Size: - """ - General class to associate an int with the size of a planet - """ + + """Enum-esque class to associate an int with a size""" TINY = 0 SMALL = 1 @@ -161,16 +175,25 @@ class Size: HUGE = 4 GARGANTUAN = 5 - NAMES = ["Tiny", "Small", "Medium", "Large", "Huge", "Gargantuan"] + NAMES = ("Tiny", "Small", "Medium", "Large", "Huge", "Gargantuan") @classmethod def name(cls, size: int) -> str: + """ + Provides the name of the size + + Raises: + ValueError on invalid index given + """ if size < 0 or size >= len(cls.NAMES): raise ValueError(f"Invalid size: {size}") return cls.NAMES[size] class SpecialResource: + + """Enum-esque class to associate an int with a special resource""" + NOTHING = 0 MINERAL_RICH = 1 MINERAL_POOR = 2 @@ -185,7 +208,7 @@ class SpecialResource: ARTISTIC = 11 WARLIKE = 12 - NAMES = [ + NAMES = ( "Nothing special", # Uneventful "Mineral rich", # produce Ore "Mineral poor", # Ore in demand @@ -199,20 +222,30 @@ class SpecialResource: "Special herbs", # produce Narcotics "Artistic populace", # Narcotics in demand "Warlike populace", # Weapons in demand - ] + ) @classmethod def name(cls, resource: int) -> str: + """ + Provides the name of the special resource + + Raises: + ValueError on invalid index given + """ if resource < 0 or resource >= len(cls.NAMES): raise ValueError(f"Invalid resource: {resource}") return cls.NAMES[resource] @staticmethod def random() -> int: + """Gives the index value of a random special resource""" return randint(1, 12) class SocietalPressure: + + """Enum-esque class to associate an int with a societal pressure""" + NONE = 0 WAR = 1 PLAGUE = 2 @@ -222,7 +255,7 @@ class SocietalPressure: CROPFAILURE = 6 EMPLOYMENT = 7 - NAMES = [ + NAMES = ( "under no particular pressure", # Uneventful "at war", # Ore and Weapons in demand "ravaged by a plague", # Medicine in demand @@ -231,21 +264,37 @@ class SocietalPressure: "suffering from a cold spell", # Furs in demand "suffering from a crop failure", # Food in demand "lacking enough workers", # Machinery and Robots in demand - ] + ) @classmethod def name(cls, pressure: int) -> str: + """ + Provides the flavor text of the societal pressure + + Args: + pressure: int + + Raises: + ValueError on invalid index given + + Returns: + str: Flavor text for the corresponding societal pressure + """ if pressure < 0 or pressure >= len(cls.NAMES): raise ValueError(f"Invalid pressure: {pressure}") return cls.NAMES[pressure] @staticmethod def random() -> int: + """Gives the index value of a random societal pressure""" return randint(1, 7) # Character class Skills: + + """Enum-esque class to associate an int with a skill""" + NONE = 0 PILOT = 1 FIGHTER = 2 @@ -254,22 +303,40 @@ class Skills: class Difficulty: + + """Enum-esque class to associate an int with a difficulty level""" + BEGINNER = 0 EASY = 1 NORMAL = 2 HARD = 3 IMPOSSIBLE = 4 - NAMES = ["Beginner", "Easy", "Normal", "Hard", "Impossible"] + NAMES = ("Beginner", "Easy", "Normal", "Hard", "Impossible") @classmethod def name(cls, difficulty: int) -> str: + """ + Provides the name of the difficulty level + + Args: + difficulty: int + + Raises: + ValueError on invalid index given + + Returns: + str: Name of the difficulty level + """ if difficulty < 0 or difficulty >= len(cls.NAMES): raise ValueError(f"Invalid difficulty: {difficulty}") return cls.NAMES[difficulty] class CriminalRecord: + + """Enum-esque class to associate an int with a criminal record""" + PSYCHOPATH = 0 VILLAIN = 1 CRIMINAL = 2 @@ -282,40 +349,44 @@ class CriminalRecord: HERO = 9 ERRNO = 10 - NAMES = { - PSYCHOPATH: "Psychopath", - VILLAIN: "Villain", - CRIMINAL: "Criminal", - CROOK: "Crook", - DUBIOUS: "Dubious", - CLEAN: "Clean", - LAWFUL: "Lawful", - TRUSTED: "Trusted", - LIKED: "Liked", - HERO: "Hero", - ERRNO: "ERRNO", - } - - SCORES = { - PSYCHOPATH: -100, - VILLAIN: -70, - CRIMINAL: -30, - CROOK: -10, - DUBIOUS: -5, - CLEAN: 0, - LAWFUL: 5, - TRUSTED: 10, - LIKED: 25, - HERO: 75, - ERRNO: 100, - } + NAMES = ( + "Psychopath", + "Villain", + "Criminal", + "Crook", + "Dubious", + "Clean", + "Lawful", + "Trusted", + "Liked", + "Hero", + "ERRNO", + ) + + SCORES = ( + -100, + -70, + -30, + -10, + -5, + 0, + 5, + 10, + 25, + 75, + 100, + ) @staticmethod def get_record_string(record: int) -> str: + """Provides the name of the criminal record""" return CriminalRecord.NAMES[record] class CombatReputation: + + """Enum-esque class to associate an int with a combat reputation""" + HARMLESS = 0 MOSTLY_HARMLESS = 1 POOR = 2 @@ -327,34 +398,35 @@ class CombatReputation: ELITE = 8 BORG = 9 - NAMES = { - HARMLESS: "Harmless", - MOSTLY_HARMLESS: "Mostly Harmless", - POOR: "Poor", - AVERAGE: "Average", - ABOVE_AVERAGE: "Above Average", - COMPETENT: "Competent", - DANGEROUS: "Dangerous", - DEADLY: "Deadly", - ELITE: "Elite", - BORG: "Borg", - } - - SCORES = { - HARMLESS: 0, - MOSTLY_HARMLESS: 10, - POOR: 20, - AVERAGE: 40, - ABOVE_AVERAGE: 80, - COMPETENT: 150, - DANGEROUS: 300, - DEADLY: 600, - ELITE: 1500, - BORG: 3000, - } + NAMES = ( + "Harmless", + "Mostly Harmless", + "Poor", + "Average", + "Above Average", + "Competent", + "Dangerous", + "Deadly", + "Elite", + "Borg", + ) + + SCORES = ( + 0, + 10, + 20, + 40, + 80, + 150, + 300, + 600, + 1500, + 3000, + ) @staticmethod def get_reputation_string(reputation: int) -> str: + """Provides the name of the combat reputation""" return CombatReputation.NAMES[reputation] diff --git a/src/screens/char_create.py b/src/screens/char_create.py index e85f67c..1bd5228 100644 --- a/src/screens/char_create.py +++ b/src/screens/char_create.py @@ -12,6 +12,7 @@ class StatAdjuster(ttk.Frame): + """ A frame that contains a label, a decrement button, a value label, and an increment button. """ @@ -148,19 +149,18 @@ def cmdr_create(self) -> None: if points_pool.get() != 0: print("You have unspent skill points!") return - elif self.cmdr_name.get() == "": + if self.cmdr_name.get() == "": print("You must enter a name!") return - else: - cmdr = Commander( - self.cmdr_name.get(), - self.pilot_skill.get_value(), - self.fighter_skill.get_value(), - self.trader_skill.get_value(), - self.engineer_skill.get_value(), - ) - GAME["commander"] = cmdr - GAME["difficulty"] = self.diff_current_value - print(cmdr.pprint()) - self.destroy() - self.parent.manager.build_screens() + cmdr = Commander( + self.cmdr_name.get(), + self.pilot_skill.get_value(), + self.fighter_skill.get_value(), + self.trader_skill.get_value(), + self.engineer_skill.get_value(), + ) + GAME["commander"] = cmdr + GAME["difficulty"] = self.diff_current_value + print(cmdr.pprint()) + self.destroy() + self.parent.manager.build_screens() diff --git a/src/screens/gamescreens.py b/src/screens/gamescreens.py index 77b3c45..a8de9be 100644 --- a/src/screens/gamescreens.py +++ b/src/screens/gamescreens.py @@ -1,4 +1,3 @@ -import tkinter as tk from random import randint from tkinter import ttk @@ -34,7 +33,7 @@ def create_widgets(self): ttk.Label(self.info_frame, text=heading, style="Heading.TLabel", justify="left").grid( row=i, column=0, sticky="ew" ) - #! Placeholder content + # ! Placeholder content for i, stat in enumerate(system_info): ttk.Label(self.info_frame, text=stat, justify="left").grid(row=i, column=1, sticky="ew") self.info_frame.pack(fill="x", expand=True) diff --git a/src/ui_actions.py b/src/ui_actions.py index 8f86277..1537cd2 100644 --- a/src/ui_actions.py +++ b/src/ui_actions.py @@ -98,7 +98,7 @@ def get_ware_list() -> list[str]: def get_bays() -> str: # TODO placeholder value, not currently tracked - #return f"{c.GAME["commander"].ship.bays} bays" + # return f"{c.GAME["commander"].ship.bays} bays" return "Bays: 3/25" @@ -122,7 +122,7 @@ def get_equip_sold() -> list[str]: for _, equip in equips.items(): if equip.tech_level == e.TechLevel.UNAVAILABLE: continue - elif equip.tech_level <= current_system_tech: + if equip.tech_level <= current_system_tech: sold_equipment.append(("", equip.name, f"{equip.price} cr.")) else: sold_equipment.append(("x", equip.name, "not sold")) @@ -157,7 +157,7 @@ def get_ship_value() -> str: def get_no_claim() -> str: # TODO placeholder until I figure out how this is calculated in source - return f"0%" + return "0%" def get_insurance_rate() -> str: diff --git a/src/universe.py b/src/universe.py index 3f73537..20323cf 100644 --- a/src/universe.py +++ b/src/universe.py @@ -1,5 +1,6 @@ """ Space Trader | RPINerd, 2024 + An elite-inspired space trading RPG originally on PalmOS Universe Module @@ -526,6 +527,7 @@ class Planet: + """ Object representing a single planet in the game world. @@ -704,15 +706,13 @@ def get_special_resource(self) -> int: if self.visited: return self.special_resource # TODO maybe not random here? - else: - self.special_resource = SpecialResource.random() - return self.special_resource + self.special_resource = SpecialResource.random() + return self.special_resource def initialize_trade_items(self): """ Set the starting quantity of each trade good for the planet """ - for item_id in Ware.enum(): # Make sure the item is allowed to be traded @@ -743,8 +743,7 @@ def initialize_trade_items(self): self.trade_items[item_id] = self.trade_items[item_id] - randint(1, 10) + randint(1, 10) # Finally just make sure it's not negative - if self.trade_items[item_id] < 0: - self.trade_items[item_id] = 0 + self.trade_items[item_id] = max(self.trade_items[item_id], 0) def is_item_traded(self, item) -> bool: """ @@ -754,18 +753,16 @@ def is_item_traded(self, item) -> bool: return: bool - whether the item can be traded """ - if item not in [Ware.FIREARMS, Ware.NARCOTICS]: return True if item == Ware.FIREARMS: return self.government.firearms_ok() - elif item == Ware.NARCOTICS: + if item == Ware.NARCOTICS: return self.government.drugs_ok() - else: - raise ValueError(f"Item ID {item} not valid!") + raise ValueError(f"Item ID {item} not valid!") def item_used(self, item): raise NotImplementedError("Planet.item_used not implemented") @@ -951,6 +948,7 @@ def show_quest_button(self): class Universe: + """ Responsible for managing the game world, including planets locations and attributes. @@ -966,7 +964,6 @@ def generate_planets(self): """ Generate the planets for the game world. """ - for id, planet_name in PLANET_NAMES.items(): planet_size = randint(0, 5) @@ -1005,7 +1002,6 @@ def pick_valid_xy(self, id: int) -> tuple[int, int]: there is likely a good way to refactor this, if nothing else as a good exercise in algorithm design! """ - x: int = 0 y: int = 0 @@ -1047,7 +1043,6 @@ def extra_planet_shuffle(self): Apparently without this extra step, the planets with names at the beginning of the alphabet are all clustered in the center of the galaxy. """ - for planet in self.planets.values(): i = randint(0, len(self.planets) - 1) if not wormhole_exists(self.wormholes, i, -1): @@ -1100,7 +1095,6 @@ def wormhole_exists(wormholes: list[int], a: int, b: int) -> bool: returns: True if wormhole exists, False otherwise """ - # TODO bit of a mess, probably should have small separate functions for each check if a in wormholes: diff --git a/src/utils.py b/src/utils.py index e4fd911..3c23487 100644 --- a/src/utils.py +++ b/src/utils.py @@ -1,5 +1,6 @@ """ Space Trader | RPINerd, 2024 + An elite-inspired space trading RPG originally on PalmOS Utils Module @@ -39,7 +40,6 @@ def windows_load_font(cls, font_path: Union[str, bytes], private: bool = True, e Function taken from: https://stackoverflow.com/questions/11993290/truly-custom-font-in-tkinter/30631309#30631309 """ - from ctypes import byref, create_string_buffer, create_unicode_buffer, windll FR_PRIVATE = 0x10 @@ -65,7 +65,7 @@ def load_font(cls, font_path: str) -> bool: return cls.windows_load_font(font_path, private=True, enumerable=False) # Linux - elif sys.platform.startswith("linux"): + if sys.platform.startswith("linux"): try: shutil.copy(font_path, os.path.expanduser(cls.linux_font_path)) return True