From b8f721424f40449201eec57eeec564d85ee17500 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 11:56:32 -0600 Subject: [PATCH 01/14] Update character.py --- dnd_character/character.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dnd_character/character.py b/dnd_character/character.py index 608037b..f38bd39 100644 --- a/dnd_character/character.py +++ b/dnd_character/character.py @@ -800,7 +800,20 @@ def give_item(self, item: _Item) -> None: If the item is armor or a shield, the armor_class attribute will be set and any other armor/shields in the inventory will be removed. """ + # Applying armor class if the item is armor or a shield self.apply_armor_class(item) + + # Checking if the item's index property equals "spellbook" + if getattr(item, 'index', None) == 'spellbook': + # Creating a new Spellbook instance with necessary arguments + # Assuming the Spellbook constructor accepts the same arguments as the item + spellbook = Spellbook(contents=item.contents, cost=item.cost, desc=item.desc, index=item.index, + name=item.name, properties=item.properties, special=item.special, + url=item.url, equipment_category=item.equipment_category) + # Replacing the placeholder item with the new Spellbook instance + item = spellbook + + # Adding the item or Spellbook instance to the inventory self.inventory.append(item) def remove_item(self, item: _Item) -> None: From d446212bbd363753625562a6b0a0a333b1239efb Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 15:33:09 -0600 Subject: [PATCH 02/14] Create spellbook.py --- dnd_character/spellbook.py | 167 +++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 dnd_character/spellbook.py diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py new file mode 100644 index 0000000..86dc2f4 --- /dev/null +++ b/dnd_character/spellbook.py @@ -0,0 +1,167 @@ +from dnd_character.equipment import _Item +from .SRD import SRD +import requests +import json +import os + +class Spellbook(_Item): + # Constructor for initializing a new Spellbook instance + def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, + **kwargs): + super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, + special=special, url=url, equipment_category=equipment_category, *args, **kwargs) + self.type = 'Spellbook' + + # Method to add a spell to the spellbook if it passes validation + def add_spell(self, spell): + if self.validate_spell(spell): + self.contents.append(spell) + else: + print("Invalid spell. Only spells can be added to a spellbook.") + + # Method to validate a spell based on D&D wizard spellcasting rules + def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subclass=None): + # Fetch the list of wizard spells by level from the SRD data + wizard_spells_by_level = fetch_wizard_spells_from_json() + + # Check if the spell level exists in the dictionary + if spell.level not in wizard_spells_by_level: + print(f"Spell level {spell.level} not found in wizard spell list.") + return False + + # Check if the spell is of a level the wizard can cast + if spell.level > max_level_for_wizard(wizard_level): + return False + + # Check if the spell is in the wizard spell list + if spell.name not in wizard_spells_by_level[spell.level]: + return False + + # Optional: Check for subclass or component restrictions + if wizard_subclass and not is_spell_allowed_for_subclass(spell, wizard_subclass): + return False + + return True + + +def max_level_for_wizard(wizard_level): + if wizard_level < 1: + return 0 # Invalid wizard level + elif wizard_level < 3: + return 1 # Level 1 spells + elif wizard_level < 5: + return 2 # Level 2 spells + elif wizard_level < 7: + return 3 # Level 3 spells + elif wizard_level < 9: + return 4 # Level 4 spells + elif wizard_level < 11: + return 5 # Level 5 spells + elif wizard_level < 13: + return 6 # Level 6 spells + elif wizard_level < 15: + return 7 # Level 7 spells + elif wizard_level < 17: + return 8 # Level 8 spells + else: + return 9 # Level 9 spells + +#Function to retrieve the wizard spell data from the JSON cache +def fetch_wizard_spells_from_json(): + current_script_path = os.path.dirname(__file__) + json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') + + if not os.path.exists(json_cache_path): + print("JSON file does not exist at the path.") + return None + + wizard_spells_by_level = {} + + try: + with open(json_cache_path, 'r') as f: + spells = json.load(f)["results"] + + for spell in spells: + spell_file_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + + if not os.path.exists(spell_file_path): + continue + + with open(spell_file_path, 'r') as spell_file: + spell_data = json.load(spell_file) + + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) + + return wizard_spells_by_level + + except FileNotFoundError: + print("JSON file not found.") + return None + except json.JSONDecodeError: + print("Error decoding JSON.") + return None + + wizard_spells_by_level = {} + try: + with open(json_cache_path, 'r') as f: # Use json_cache_path instead of json_file_path + spells = json.load(f)["results"] + for spell in spells: + spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + print(f"Attempting to open additional JSON file at {spell_data_path}...") + try: + with open(spell_data_path, 'r') as f: + spell_data = json.load(f) + print("Additional JSON file read successfully. Content:", spell_data) + except FileNotFoundError: + print(f"Additional JSON file {spell_data_path} not found.") + continue + except json.JSONDecodeError: + print("Error decoding additional JSON file.") + continue + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + if level not in wizard_spells_by_level: + wizard_spells_by_level[level] = [] + wizard_spells_by_level[level].append(spell_data['name']) + return wizard_spells_by_level + except FileNotFoundError: + print("JSON file not found.") + return None + except json.JSONDecodeError: + print("Error decoding JSON.") + return None + +# Initialize a Spellbook object +my_spellbook = Spellbook(contents=[], cost={}, desc=[], index="", name="", properties=[], special=[], url="", equipment_category={}) + + +def run_tests(): + # Create mock spell objects + mock_spell1 = type('Spell', (object,), {'level': 2, 'name': 'MockSpell1'}) + mock_spell2 = type('Spell', (object,), {'level': 2, 'name': 'NonWizardSpell'}) + mock_spell3 = type('Spell', (object,), {'level': 3, 'name': 'Fireball'}) + mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'VampiricTouch'}) + + # Test Case 1: Level 1 Wizard tries to add a Level 2 spell (Should fail) + result1 = my_spellbook.validate_spell(spell=mock_spell1, wizard_level=1) + assert result1 == False, "Test Case 1 Failed" + + # Test Case 2: Level 3 Wizard tries to add a Level 2 spell not in wizard spell list (Should fail) + result2 = my_spellbook.validate_spell(spell=mock_spell2, wizard_level=3) + assert result2 == False, "Test Case 2 Failed" + + # Test Case 3: Level 5 Wizard tries to add a Level 3 spell in wizard spell list (Should pass) + result3 = my_spellbook.validate_spell(spell=mock_spell3, wizard_level=5) + assert result3 == True, "Test Case 3 Failed" + + # Test Case 4: Level 5 Wizard of subclass 'Evocation' tries to add a Level 3 spell restricted to 'Necromancy' (Should fail) + result4 = my_spellbook.validate_spell(spell=mock_spell4, wizard_level=5, wizard_subclass="Evocation") + assert result4 == False, "Test Case 4 Failed" + + print("All test cases passed!") + + +# Run the tests +#run_tests() From 73d5f535c62d7cdefaaa82d7cb4b119377dd363c Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 15:43:56 -0600 Subject: [PATCH 03/14] Update spellbook.py --- dnd_character/spellbook.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index 86dc2f4..9c508c5 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -4,6 +4,7 @@ import json import os +#Spellbook is a subclass of the _Item class that only accepts wizard spells as contents class Spellbook(_Item): # Constructor for initializing a new Spellbook instance def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, From 3a8a7cc10b32fad159151bd5c807d0a3e19600f9 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 16:02:37 -0600 Subject: [PATCH 04/14] Update spellbook.py --- dnd_character/spellbook.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index 9c508c5..27ac6e3 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -6,7 +6,8 @@ #Spellbook is a subclass of the _Item class that only accepts wizard spells as contents class Spellbook(_Item): - # Constructor for initializing a new Spellbook instance + MAX_SPELLS = 100 # Class variable to define the maximum number of spells + def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, **kwargs): super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, @@ -15,11 +16,23 @@ def __init__(self, contents, cost, desc, index, name, properties, special, url, # Method to add a spell to the spellbook if it passes validation def add_spell(self, spell): + if len(self.contents) >= Spellbook.MAX_SPELLS: + print("Spellbook is full. Cannot add more spells.") + return + if self.validate_spell(spell): self.contents.append(spell) else: print("Invalid spell. Only spells can be added to a spellbook.") + #Method to remove a spell from a spellbook + def remove_spell(self, spell): + if spell in self.contents: + self.contents.remove(spell) + print(f"Removed {spell} from the spellbook.") + else: + print(f"{spell} not found in the spellbook.") + # Method to validate a spell based on D&D wizard spellcasting rules def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subclass=None): # Fetch the list of wizard spells by level from the SRD data From 30e85646877be7fc660dcea21843c579ec26c5e6 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 17:24:41 -0600 Subject: [PATCH 05/14] Update spellbook.py --- dnd_character/spellbook.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index 27ac6e3..5d0cba2 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -6,6 +6,7 @@ #Spellbook is a subclass of the _Item class that only accepts wizard spells as contents class Spellbook(_Item): + # Constructor for initializing a new Spellbook instance MAX_SPELLS = 100 # Class variable to define the maximum number of spells def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, @@ -153,10 +154,10 @@ def fetch_wizard_spells_from_json(): def run_tests(): # Create mock spell objects - mock_spell1 = type('Spell', (object,), {'level': 2, 'name': 'MockSpell1'}) + mock_spell1 = type('Spell', (object,), {'level': 2, 'name': 'acid-arrow'}) mock_spell2 = type('Spell', (object,), {'level': 2, 'name': 'NonWizardSpell'}) mock_spell3 = type('Spell', (object,), {'level': 3, 'name': 'Fireball'}) - mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'VampiricTouch'}) + mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'Vampiric Touch'}) # Test Case 1: Level 1 Wizard tries to add a Level 2 spell (Should fail) result1 = my_spellbook.validate_spell(spell=mock_spell1, wizard_level=1) From 11483df080a6659393d1cb29f005279f4d1c1b1c Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sat, 30 Sep 2023 17:29:09 -0600 Subject: [PATCH 06/14] Update spellbook.py --- dnd_character/spellbook.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index 5d0cba2..c640ea7 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -33,7 +33,11 @@ def remove_spell(self, spell): print(f"Removed {spell} from the spellbook.") else: print(f"{spell} not found in the spellbook.") - + + def check_components(self, spell, char_current_gp): + cost = spell.level * 50 + return current_gp >= cost + # Method to validate a spell based on D&D wizard spellcasting rules def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subclass=None): # Fetch the list of wizard spells by level from the SRD data @@ -52,8 +56,9 @@ def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subc if spell.name not in wizard_spells_by_level[spell.level]: return False - # Optional: Check for subclass or component restrictions - if wizard_subclass and not is_spell_allowed_for_subclass(spell, wizard_subclass): + # Check for component restrictions + if not self.check_components(spell, current_gp): + print(f"Insufficient gold to scribe {spell.name}.") return False return True From e4b08129b541e5f9f4f4dba20fdef6152459c045 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:35:35 -0600 Subject: [PATCH 07/14] Changed spellbook methods to accept a character instance as argument --- dnd_character/spellbook.py | 110 +++++++++++++++---------------------- 1 file changed, 44 insertions(+), 66 deletions(-) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index c640ea7..3d7ce1f 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -1,10 +1,12 @@ +import dnd_character.character from dnd_character.equipment import _Item -from .SRD import SRD -import requests +from dnd_character import character import json import os +import dnd_character -#Spellbook is a subclass of the _Item class that only accepts wizard spells as contents + +# Spellbook is a subclass of the _Item class that only accepts wizard spells as contents class Spellbook(_Item): # Constructor for initializing a new Spellbook instance MAX_SPELLS = 100 # Class variable to define the maximum number of spells @@ -16,32 +18,37 @@ def __init__(self, contents, cost, desc, index, name, properties, special, url, self.type = 'Spellbook' # Method to add a spell to the spellbook if it passes validation - def add_spell(self, spell): + def add_spell(self, spell, char_instance): if len(self.contents) >= Spellbook.MAX_SPELLS: print("Spellbook is full. Cannot add more spells.") return - if self.validate_spell(spell): + if self.validate_spell(spell, char_instance): self.contents.append(spell) else: print("Invalid spell. Only spells can be added to a spellbook.") - #Method to remove a spell from a spellbook + # Method to remove a spell from a spellbook def remove_spell(self, spell): if spell in self.contents: self.contents.remove(spell) print(f"Removed {spell} from the spellbook.") else: print(f"{spell} not found in the spellbook.") - - def check_components(self, spell, char_current_gp): - cost = spell.level * 50 - return current_gp >= cost - + + def check_components(self, char_instance, cost): + print(char_instance.wealth) + return char_instance.wealth >= cost + # Method to validate a spell based on D&D wizard spellcasting rules - def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subclass=None): + def validate_spell(self, spell, char_instance): # Fetch the list of wizard spells by level from the SRD data wizard_spells_by_level = fetch_wizard_spells_from_json() + print(f"Validating spell: {spell.name}, for character: {char_instance.name}") # Print spell and character info + # Check if character is a wizard + if not char_instance.classs.name == "Wizard": + print(f"{char_instance.name} is not a wizard and cannot scribe spells.") + return False # Check if the spell level exists in the dictionary if spell.level not in wizard_spells_by_level: @@ -49,7 +56,7 @@ def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subc return False # Check if the spell is of a level the wizard can cast - if spell.level > max_level_for_wizard(wizard_level): + if spell.level > max_level_for_wizard(char_instance.level): return False # Check if the spell is in the wizard spell list @@ -57,11 +64,22 @@ def validate_spell(self, spell, spell_level=None, wizard_level=None, wizard_subc return False # Check for component restrictions - if not self.check_components(spell, current_gp): + cost = spell.level * 50 * dnd_character.character.coin_value['gp'] + cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] + + if not self.check_components(char_instance, cost): print(f"Insufficient gold to scribe {spell.name}.") return False - - return True + print(f"Char detailed wealth before transaction: {char_instance.wealth_detailed}") # Debug line + print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line + try: + print(f"Cost of transaction: {cost}") # Debug line + char_instance.change_wealth(cp=-cost_in_cp) # deduct cost + print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line + return True + except ValueError: # Insufficient funds + print("Exception occurred: ValueError - Insufficient funds") + return False def max_level_for_wizard(wizard_level): @@ -86,7 +104,8 @@ def max_level_for_wizard(wizard_level): else: return 9 # Level 9 spells -#Function to retrieve the wizard spell data from the JSON cache + +# Function to retrieve the wizard spell data from the JSON cache def fetch_wizard_spells_from_json(): current_script_path = os.path.dirname(__file__) json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') @@ -114,26 +133,19 @@ def fetch_wizard_spells_from_json(): level = spell_data['level'] wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) - return wizard_spells_by_level - - except FileNotFoundError: - print("JSON file not found.") - return None - except json.JSONDecodeError: - print("Error decoding JSON.") - return None + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") - wizard_spells_by_level = {} try: - with open(json_cache_path, 'r') as f: # Use json_cache_path instead of json_file_path + with open(json_cache_path, 'r') as f: spells = json.load(f)["results"] for spell in spells: spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") - print(f"Attempting to open additional JSON file at {spell_data_path}...") + # print(f"Attempting to open additional JSON file at {spell_data_path}...") try: with open(spell_data_path, 'r') as f: spell_data = json.load(f) - print("Additional JSON file read successfully. Content:", spell_data) + # print("Additional JSON file read successfully. Content:", spell_data) except FileNotFoundError: print(f"Additional JSON file {spell_data_path} not found.") continue @@ -145,43 +157,9 @@ def fetch_wizard_spells_from_json(): if level not in wizard_spells_by_level: wizard_spells_by_level[level] = [] wizard_spells_by_level[level].append(spell_data['name']) - return wizard_spells_by_level - except FileNotFoundError: - print("JSON file not found.") - return None - except json.JSONDecodeError: - print("Error decoding JSON.") - return None - -# Initialize a Spellbook object -my_spellbook = Spellbook(contents=[], cost={}, desc=[], index="", name="", properties=[], special=[], url="", equipment_category={}) - - -def run_tests(): - # Create mock spell objects - mock_spell1 = type('Spell', (object,), {'level': 2, 'name': 'acid-arrow'}) - mock_spell2 = type('Spell', (object,), {'level': 2, 'name': 'NonWizardSpell'}) - mock_spell3 = type('Spell', (object,), {'level': 3, 'name': 'Fireball'}) - mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'Vampiric Touch'}) - - # Test Case 1: Level 1 Wizard tries to add a Level 2 spell (Should fail) - result1 = my_spellbook.validate_spell(spell=mock_spell1, wizard_level=1) - assert result1 == False, "Test Case 1 Failed" - - # Test Case 2: Level 3 Wizard tries to add a Level 2 spell not in wizard spell list (Should fail) - result2 = my_spellbook.validate_spell(spell=mock_spell2, wizard_level=3) - assert result2 == False, "Test Case 2 Failed" - - # Test Case 3: Level 5 Wizard tries to add a Level 3 spell in wizard spell list (Should pass) - result3 = my_spellbook.validate_spell(spell=mock_spell3, wizard_level=5) - assert result3 == True, "Test Case 3 Failed" - - # Test Case 4: Level 5 Wizard of subclass 'Evocation' tries to add a Level 3 spell restricted to 'Necromancy' (Should fail) - result4 = my_spellbook.validate_spell(spell=mock_spell4, wizard_level=5, wizard_subclass="Evocation") - assert result4 == False, "Test Case 4 Failed" + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") - print("All test cases passed!") + return wizard_spells_by_level -# Run the tests -#run_tests() From e67bfea4a6a189938029ba7cda0927f397d25cfd Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:36:17 -0600 Subject: [PATCH 08/14] Create test_spellbook.py --- dnd_character/test_spellbook.py | 165 ++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 dnd_character/test_spellbook.py diff --git a/dnd_character/test_spellbook.py b/dnd_character/test_spellbook.py new file mode 100644 index 0000000..3d7ce1f --- /dev/null +++ b/dnd_character/test_spellbook.py @@ -0,0 +1,165 @@ +import dnd_character.character +from dnd_character.equipment import _Item +from dnd_character import character +import json +import os +import dnd_character + + +# Spellbook is a subclass of the _Item class that only accepts wizard spells as contents +class Spellbook(_Item): + # Constructor for initializing a new Spellbook instance + MAX_SPELLS = 100 # Class variable to define the maximum number of spells + + def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, + **kwargs): + super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, + special=special, url=url, equipment_category=equipment_category, *args, **kwargs) + self.type = 'Spellbook' + + # Method to add a spell to the spellbook if it passes validation + def add_spell(self, spell, char_instance): + if len(self.contents) >= Spellbook.MAX_SPELLS: + print("Spellbook is full. Cannot add more spells.") + return + + if self.validate_spell(spell, char_instance): + self.contents.append(spell) + else: + print("Invalid spell. Only spells can be added to a spellbook.") + + # Method to remove a spell from a spellbook + def remove_spell(self, spell): + if spell in self.contents: + self.contents.remove(spell) + print(f"Removed {spell} from the spellbook.") + else: + print(f"{spell} not found in the spellbook.") + + def check_components(self, char_instance, cost): + print(char_instance.wealth) + return char_instance.wealth >= cost + + # Method to validate a spell based on D&D wizard spellcasting rules + def validate_spell(self, spell, char_instance): + # Fetch the list of wizard spells by level from the SRD data + wizard_spells_by_level = fetch_wizard_spells_from_json() + print(f"Validating spell: {spell.name}, for character: {char_instance.name}") # Print spell and character info + # Check if character is a wizard + if not char_instance.classs.name == "Wizard": + print(f"{char_instance.name} is not a wizard and cannot scribe spells.") + return False + + # Check if the spell level exists in the dictionary + if spell.level not in wizard_spells_by_level: + print(f"Spell level {spell.level} not found in wizard spell list.") + return False + + # Check if the spell is of a level the wizard can cast + if spell.level > max_level_for_wizard(char_instance.level): + return False + + # Check if the spell is in the wizard spell list + if spell.name not in wizard_spells_by_level[spell.level]: + return False + + # Check for component restrictions + cost = spell.level * 50 * dnd_character.character.coin_value['gp'] + cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] + + if not self.check_components(char_instance, cost): + print(f"Insufficient gold to scribe {spell.name}.") + return False + print(f"Char detailed wealth before transaction: {char_instance.wealth_detailed}") # Debug line + print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line + try: + print(f"Cost of transaction: {cost}") # Debug line + char_instance.change_wealth(cp=-cost_in_cp) # deduct cost + print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line + return True + except ValueError: # Insufficient funds + print("Exception occurred: ValueError - Insufficient funds") + return False + + +def max_level_for_wizard(wizard_level): + if wizard_level < 1: + return 0 # Invalid wizard level + elif wizard_level < 3: + return 1 # Level 1 spells + elif wizard_level < 5: + return 2 # Level 2 spells + elif wizard_level < 7: + return 3 # Level 3 spells + elif wizard_level < 9: + return 4 # Level 4 spells + elif wizard_level < 11: + return 5 # Level 5 spells + elif wizard_level < 13: + return 6 # Level 6 spells + elif wizard_level < 15: + return 7 # Level 7 spells + elif wizard_level < 17: + return 8 # Level 8 spells + else: + return 9 # Level 9 spells + + +# Function to retrieve the wizard spell data from the JSON cache +def fetch_wizard_spells_from_json(): + current_script_path = os.path.dirname(__file__) + json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') + + if not os.path.exists(json_cache_path): + print("JSON file does not exist at the path.") + return None + + wizard_spells_by_level = {} + + try: + with open(json_cache_path, 'r') as f: + spells = json.load(f)["results"] + + for spell in spells: + spell_file_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + + if not os.path.exists(spell_file_path): + continue + + with open(spell_file_path, 'r') as spell_file: + spell_data = json.load(spell_file) + + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) + + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") + + try: + with open(json_cache_path, 'r') as f: + spells = json.load(f)["results"] + for spell in spells: + spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + # print(f"Attempting to open additional JSON file at {spell_data_path}...") + try: + with open(spell_data_path, 'r') as f: + spell_data = json.load(f) + # print("Additional JSON file read successfully. Content:", spell_data) + except FileNotFoundError: + print(f"Additional JSON file {spell_data_path} not found.") + continue + except json.JSONDecodeError: + print("Error decoding additional JSON file.") + continue + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + if level not in wizard_spells_by_level: + wizard_spells_by_level[level] = [] + wizard_spells_by_level[level].append(spell_data['name']) + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") + + return wizard_spells_by_level + + From c1fb5c48e0053a0e236cbfb0cd154a2cde662800 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:38:09 -0600 Subject: [PATCH 09/14] Create test_spellbook.py --- test_spellbook.py | 163 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 test_spellbook.py diff --git a/test_spellbook.py b/test_spellbook.py new file mode 100644 index 0000000..00a31f3 --- /dev/null +++ b/test_spellbook.py @@ -0,0 +1,163 @@ +import dnd_character.character +from dnd_character.equipment import _Item +from dnd_character import character +import json +import os +import dnd_character + + +# Spellbook is a subclass of the _Item class that only accepts wizard spells as contents +class Spellbook(_Item): + # Constructor for initializing a new Spellbook instance + MAX_SPELLS = 100 # Class variable to define the maximum number of spells + + def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, + **kwargs): + super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, + special=special, url=url, equipment_category=equipment_category, *args, **kwargs) + self.type = 'Spellbook' + + # Method to add a spell to the spellbook if it passes validation + def add_spell(self, spell, char_instance): + if len(self.contents) >= Spellbook.MAX_SPELLS: + print("Spellbook is full. Cannot add more spells.") + return + + if self.validate_spell(spell, char_instance): + self.contents.append(spell) + else: + print("Invalid spell. Only spells can be added to a spellbook.") + + # Method to remove a spell from a spellbook + def remove_spell(self, spell): + if spell in self.contents: + self.contents.remove(spell) + print(f"Removed {spell} from the spellbook.") + else: + print(f"{spell} not found in the spellbook.") + + def check_components(self, char_instance, cost): + print(char_instance.wealth) + return char_instance.wealth >= cost + + # Method to validate a spell based on D&D wizard spellcasting rules + def validate_spell(self, spell, char_instance): + # Fetch the list of wizard spells by level from the SRD data + wizard_spells_by_level = fetch_wizard_spells_from_json() + print(f"Validating spell: {spell.name}, for character: {char_instance.name}") # Print spell and character info + # Check if character is a wizard + if not char_instance.classs.name == "Wizard": + print(f"{char_instance.name} is not a wizard and cannot scribe spells.") + return False + + # Check if the spell level exists in the dictionary + if spell.level not in wizard_spells_by_level: + print(f"Spell level {spell.level} not found in wizard spell list.") + return False + + # Check if the spell is of a level the wizard can cast + if spell.level > max_level_for_wizard(char_instance.level): + return False + + # Check if the spell is in the wizard spell list + if spell.name not in wizard_spells_by_level[spell.level]: + return False + + # Check for component restrictions + cost = spell.level * 50 * dnd_character.character.coin_value['gp'] + cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] + + if not self.check_components(char_instance, cost): + print(f"Insufficient gold to scribe {spell.name}.") + return False + print(f"Char detailed wealth before transaction: {char_instance.wealth_detailed}") # Debug line + print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line + try: + print(f"Cost of transaction: {cost}") # Debug line + char_instance.change_wealth(cp=-cost_in_cp) # deduct cost + print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line + return True + except ValueError: # Insufficient funds + print("Exception occurred: ValueError - Insufficient funds") + return False + + +def max_level_for_wizard(wizard_level): + if wizard_level < 1: + return 0 # Invalid wizard level + elif wizard_level < 3: + return 1 # Level 1 spells + elif wizard_level < 5: + return 2 # Level 2 spells + elif wizard_level < 7: + return 3 # Level 3 spells + elif wizard_level < 9: + return 4 # Level 4 spells + elif wizard_level < 11: + return 5 # Level 5 spells + elif wizard_level < 13: + return 6 # Level 6 spells + elif wizard_level < 15: + return 7 # Level 7 spells + elif wizard_level < 17: + return 8 # Level 8 spells + else: + return 9 # Level 9 spells + + +# Function to retrieve the wizard spell data from the JSON cache +def fetch_wizard_spells_from_json(): + current_script_path = os.path.dirname(__file__) + json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') + + if not os.path.exists(json_cache_path): + print("JSON file does not exist at the path.") + return None + + wizard_spells_by_level = {} + + try: + with open(json_cache_path, 'r') as f: + spells = json.load(f)["results"] + + for spell in spells: + spell_file_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + + if not os.path.exists(spell_file_path): + continue + + with open(spell_file_path, 'r') as spell_file: + spell_data = json.load(spell_file) + + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) + + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") + + try: + with open(json_cache_path, 'r') as f: + spells = json.load(f)["results"] + for spell in spells: + spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") + # print(f"Attempting to open additional JSON file at {spell_data_path}...") + try: + with open(spell_data_path, 'r') as f: + spell_data = json.load(f) + # print("Additional JSON file read successfully. Content:", spell_data) + except FileNotFoundError: + print(f"Additional JSON file {spell_data_path} not found.") + continue + except json.JSONDecodeError: + print("Error decoding additional JSON file.") + continue + if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: + level = spell_data['level'] + if level not in wizard_spells_by_level: + wizard_spells_by_level[level] = [] + wizard_spells_by_level[level].append(spell_data['name']) + except (FileNotFoundError, json.JSONDecodeError): + print("Error encountered while processing JSON.") + + return wizard_spells_by_level From 92075d9f310440cfadc54e88ad10fb47b885a355 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:38:41 -0600 Subject: [PATCH 10/14] Delete dnd_character/test_spellbook.py --- dnd_character/test_spellbook.py | 165 -------------------------------- 1 file changed, 165 deletions(-) delete mode 100644 dnd_character/test_spellbook.py diff --git a/dnd_character/test_spellbook.py b/dnd_character/test_spellbook.py deleted file mode 100644 index 3d7ce1f..0000000 --- a/dnd_character/test_spellbook.py +++ /dev/null @@ -1,165 +0,0 @@ -import dnd_character.character -from dnd_character.equipment import _Item -from dnd_character import character -import json -import os -import dnd_character - - -# Spellbook is a subclass of the _Item class that only accepts wizard spells as contents -class Spellbook(_Item): - # Constructor for initializing a new Spellbook instance - MAX_SPELLS = 100 # Class variable to define the maximum number of spells - - def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, - **kwargs): - super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, - special=special, url=url, equipment_category=equipment_category, *args, **kwargs) - self.type = 'Spellbook' - - # Method to add a spell to the spellbook if it passes validation - def add_spell(self, spell, char_instance): - if len(self.contents) >= Spellbook.MAX_SPELLS: - print("Spellbook is full. Cannot add more spells.") - return - - if self.validate_spell(spell, char_instance): - self.contents.append(spell) - else: - print("Invalid spell. Only spells can be added to a spellbook.") - - # Method to remove a spell from a spellbook - def remove_spell(self, spell): - if spell in self.contents: - self.contents.remove(spell) - print(f"Removed {spell} from the spellbook.") - else: - print(f"{spell} not found in the spellbook.") - - def check_components(self, char_instance, cost): - print(char_instance.wealth) - return char_instance.wealth >= cost - - # Method to validate a spell based on D&D wizard spellcasting rules - def validate_spell(self, spell, char_instance): - # Fetch the list of wizard spells by level from the SRD data - wizard_spells_by_level = fetch_wizard_spells_from_json() - print(f"Validating spell: {spell.name}, for character: {char_instance.name}") # Print spell and character info - # Check if character is a wizard - if not char_instance.classs.name == "Wizard": - print(f"{char_instance.name} is not a wizard and cannot scribe spells.") - return False - - # Check if the spell level exists in the dictionary - if spell.level not in wizard_spells_by_level: - print(f"Spell level {spell.level} not found in wizard spell list.") - return False - - # Check if the spell is of a level the wizard can cast - if spell.level > max_level_for_wizard(char_instance.level): - return False - - # Check if the spell is in the wizard spell list - if spell.name not in wizard_spells_by_level[spell.level]: - return False - - # Check for component restrictions - cost = spell.level * 50 * dnd_character.character.coin_value['gp'] - cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] - - if not self.check_components(char_instance, cost): - print(f"Insufficient gold to scribe {spell.name}.") - return False - print(f"Char detailed wealth before transaction: {char_instance.wealth_detailed}") # Debug line - print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line - try: - print(f"Cost of transaction: {cost}") # Debug line - char_instance.change_wealth(cp=-cost_in_cp) # deduct cost - print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line - return True - except ValueError: # Insufficient funds - print("Exception occurred: ValueError - Insufficient funds") - return False - - -def max_level_for_wizard(wizard_level): - if wizard_level < 1: - return 0 # Invalid wizard level - elif wizard_level < 3: - return 1 # Level 1 spells - elif wizard_level < 5: - return 2 # Level 2 spells - elif wizard_level < 7: - return 3 # Level 3 spells - elif wizard_level < 9: - return 4 # Level 4 spells - elif wizard_level < 11: - return 5 # Level 5 spells - elif wizard_level < 13: - return 6 # Level 6 spells - elif wizard_level < 15: - return 7 # Level 7 spells - elif wizard_level < 17: - return 8 # Level 8 spells - else: - return 9 # Level 9 spells - - -# Function to retrieve the wizard spell data from the JSON cache -def fetch_wizard_spells_from_json(): - current_script_path = os.path.dirname(__file__) - json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') - - if not os.path.exists(json_cache_path): - print("JSON file does not exist at the path.") - return None - - wizard_spells_by_level = {} - - try: - with open(json_cache_path, 'r') as f: - spells = json.load(f)["results"] - - for spell in spells: - spell_file_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") - - if not os.path.exists(spell_file_path): - continue - - with open(spell_file_path, 'r') as spell_file: - spell_data = json.load(spell_file) - - if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: - level = spell_data['level'] - wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) - - except (FileNotFoundError, json.JSONDecodeError): - print("Error encountered while processing JSON.") - - try: - with open(json_cache_path, 'r') as f: - spells = json.load(f)["results"] - for spell in spells: - spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") - # print(f"Attempting to open additional JSON file at {spell_data_path}...") - try: - with open(spell_data_path, 'r') as f: - spell_data = json.load(f) - # print("Additional JSON file read successfully. Content:", spell_data) - except FileNotFoundError: - print(f"Additional JSON file {spell_data_path} not found.") - continue - except json.JSONDecodeError: - print("Error decoding additional JSON file.") - continue - if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: - level = spell_data['level'] - if level not in wizard_spells_by_level: - wizard_spells_by_level[level] = [] - wizard_spells_by_level[level].append(spell_data['name']) - except (FileNotFoundError, json.JSONDecodeError): - print("Error encountered while processing JSON.") - - return wizard_spells_by_level - - From f0322add37d94bfe6feaa70ad0e57fd650926b0d Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:42:53 -0600 Subject: [PATCH 11/14] Delete test_spellbook.py --- test_spellbook.py | 163 ---------------------------------------------- 1 file changed, 163 deletions(-) delete mode 100644 test_spellbook.py diff --git a/test_spellbook.py b/test_spellbook.py deleted file mode 100644 index 00a31f3..0000000 --- a/test_spellbook.py +++ /dev/null @@ -1,163 +0,0 @@ -import dnd_character.character -from dnd_character.equipment import _Item -from dnd_character import character -import json -import os -import dnd_character - - -# Spellbook is a subclass of the _Item class that only accepts wizard spells as contents -class Spellbook(_Item): - # Constructor for initializing a new Spellbook instance - MAX_SPELLS = 100 # Class variable to define the maximum number of spells - - def __init__(self, contents, cost, desc, index, name, properties, special, url, equipment_category, *args, - **kwargs): - super().__init__(contents=contents, cost=cost, desc=desc, index=index, name=name, properties=properties, - special=special, url=url, equipment_category=equipment_category, *args, **kwargs) - self.type = 'Spellbook' - - # Method to add a spell to the spellbook if it passes validation - def add_spell(self, spell, char_instance): - if len(self.contents) >= Spellbook.MAX_SPELLS: - print("Spellbook is full. Cannot add more spells.") - return - - if self.validate_spell(spell, char_instance): - self.contents.append(spell) - else: - print("Invalid spell. Only spells can be added to a spellbook.") - - # Method to remove a spell from a spellbook - def remove_spell(self, spell): - if spell in self.contents: - self.contents.remove(spell) - print(f"Removed {spell} from the spellbook.") - else: - print(f"{spell} not found in the spellbook.") - - def check_components(self, char_instance, cost): - print(char_instance.wealth) - return char_instance.wealth >= cost - - # Method to validate a spell based on D&D wizard spellcasting rules - def validate_spell(self, spell, char_instance): - # Fetch the list of wizard spells by level from the SRD data - wizard_spells_by_level = fetch_wizard_spells_from_json() - print(f"Validating spell: {spell.name}, for character: {char_instance.name}") # Print spell and character info - # Check if character is a wizard - if not char_instance.classs.name == "Wizard": - print(f"{char_instance.name} is not a wizard and cannot scribe spells.") - return False - - # Check if the spell level exists in the dictionary - if spell.level not in wizard_spells_by_level: - print(f"Spell level {spell.level} not found in wizard spell list.") - return False - - # Check if the spell is of a level the wizard can cast - if spell.level > max_level_for_wizard(char_instance.level): - return False - - # Check if the spell is in the wizard spell list - if spell.name not in wizard_spells_by_level[spell.level]: - return False - - # Check for component restrictions - cost = spell.level * 50 * dnd_character.character.coin_value['gp'] - cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] - - if not self.check_components(char_instance, cost): - print(f"Insufficient gold to scribe {spell.name}.") - return False - print(f"Char detailed wealth before transaction: {char_instance.wealth_detailed}") # Debug line - print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line - try: - print(f"Cost of transaction: {cost}") # Debug line - char_instance.change_wealth(cp=-cost_in_cp) # deduct cost - print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line - return True - except ValueError: # Insufficient funds - print("Exception occurred: ValueError - Insufficient funds") - return False - - -def max_level_for_wizard(wizard_level): - if wizard_level < 1: - return 0 # Invalid wizard level - elif wizard_level < 3: - return 1 # Level 1 spells - elif wizard_level < 5: - return 2 # Level 2 spells - elif wizard_level < 7: - return 3 # Level 3 spells - elif wizard_level < 9: - return 4 # Level 4 spells - elif wizard_level < 11: - return 5 # Level 5 spells - elif wizard_level < 13: - return 6 # Level 6 spells - elif wizard_level < 15: - return 7 # Level 7 spells - elif wizard_level < 17: - return 8 # Level 8 spells - else: - return 9 # Level 9 spells - - -# Function to retrieve the wizard spell data from the JSON cache -def fetch_wizard_spells_from_json(): - current_script_path = os.path.dirname(__file__) - json_cache_path = os.path.join(current_script_path, 'json_cache', 'api_spells.json') - - if not os.path.exists(json_cache_path): - print("JSON file does not exist at the path.") - return None - - wizard_spells_by_level = {} - - try: - with open(json_cache_path, 'r') as f: - spells = json.load(f)["results"] - - for spell in spells: - spell_file_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") - - if not os.path.exists(spell_file_path): - continue - - with open(spell_file_path, 'r') as spell_file: - spell_data = json.load(spell_file) - - if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: - level = spell_data['level'] - wizard_spells_by_level.setdefault(level, []).append(spell_data['name']) - - except (FileNotFoundError, json.JSONDecodeError): - print("Error encountered while processing JSON.") - - try: - with open(json_cache_path, 'r') as f: - spells = json.load(f)["results"] - for spell in spells: - spell_data_path = os.path.join(current_script_path, 'json_cache', f"api_spells_{spell['index']}.json") - # print(f"Attempting to open additional JSON file at {spell_data_path}...") - try: - with open(spell_data_path, 'r') as f: - spell_data = json.load(f) - # print("Additional JSON file read successfully. Content:", spell_data) - except FileNotFoundError: - print(f"Additional JSON file {spell_data_path} not found.") - continue - except json.JSONDecodeError: - print("Error decoding additional JSON file.") - continue - if 'wizard' in [cls['name'].lower() for cls in spell_data.get('classes', [])]: - level = spell_data['level'] - if level not in wizard_spells_by_level: - wizard_spells_by_level[level] = [] - wizard_spells_by_level[level].append(spell_data['name']) - except (FileNotFoundError, json.JSONDecodeError): - print("Error encountered while processing JSON.") - - return wizard_spells_by_level From 99eb4e071454233ad963f3b5e0583d0d71f63e04 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Sun, 1 Oct 2023 16:44:34 -0600 Subject: [PATCH 12/14] Create test_spellbook.py --- tests/test_spellbook.py | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 tests/test_spellbook.py diff --git a/tests/test_spellbook.py b/tests/test_spellbook.py new file mode 100644 index 0000000..d172623 --- /dev/null +++ b/tests/test_spellbook.py @@ -0,0 +1,52 @@ +from dnd_character.spellbook import Spellbook +from dnd_character.classes import Wizard + +# Initialize a Spellbook object +my_spellbook = Spellbook(contents=[], cost={}, desc=[], index="", name="", properties=[], special=[], url="", equipment_category={}) + +lvl_1_wizard = Wizard( + name="Level 1 Wizard ", + level=1, + wealth=75 + ) +print(lvl_1_wizard.classs) +lvl_3_wizard = Wizard( + name="Level 3 Wizard ", + level=3, + wealth=75 + ) +lvl_5_wizard = Wizard( + name="Level 3 Wizard ", + level=5, + wealth=700 + ) + +def run_tests(): + # Create mock spell objects + level_2_spell = type('Spell', (object,), {'level': 2, 'name': 'acid-arrow'}) + nonwizard_spell = type('Spell', (object,), {'level': 2, 'name': 'Animal Friendship'}) + level_3_spell = type('Spell', (object,), {'level': 3, 'name': 'Fireball'}) + mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'Vampiric Touch'}) + + # Test Case 1: Level 1 Wizard tries to add a Level 2 spell (Should fail) + result1 = my_spellbook.validate_spell(spell=level_2_spell , char_instance=lvl_1_wizard) + assert result1 == False, "Test Case 1 Failed" + + + # Test Case 2: Level 3 Wizard tries to add a Level 1 spell not in wizard spell list (Should fail) + result2 = my_spellbook.validate_spell(spell=nonwizard_spell, char_instance=lvl_3_wizard) + assert result2 == False, "Test Case 2 Failed" + + # Test Case 3: Level 5 Wizard tries to add a Level 3 spell in wizard spell list (Should pass) + result3 = my_spellbook.validate_spell(spell=level_3_spell, char_instance=lvl_5_wizard) + assert result3 == True, "Test Case 3 Failed" + + # Test Case 4: Level 5 tries to add a Level 3 spell but does not have enough gold (Should fail) + result4 = my_spellbook.validate_spell(spell=mock_spell4, char_instance=lvl_5_wizard) + assert result4 == False, "Test Case 4 Failed" + + print("All test cases passed!") + + +#Run the tests +run_tests() From f3d00c5da37de62e1242901b564ccc76286c5b49 Mon Sep 17 00:00:00 2001 From: stevebelew Date: Tue, 3 Oct 2023 19:26:41 -0600 Subject: [PATCH 13/14] Update spellbook.py Final working code. --- dnd_character/spellbook.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/dnd_character/spellbook.py b/dnd_character/spellbook.py index 3d7ce1f..558f48f 100644 --- a/dnd_character/spellbook.py +++ b/dnd_character/spellbook.py @@ -1,6 +1,5 @@ import dnd_character.character from dnd_character.equipment import _Item -from dnd_character import character import json import os import dnd_character @@ -37,7 +36,6 @@ def remove_spell(self, spell): print(f"{spell} not found in the spellbook.") def check_components(self, char_instance, cost): - print(char_instance.wealth) return char_instance.wealth >= cost # Method to validate a spell based on D&D wizard spellcasting rules @@ -65,7 +63,6 @@ def validate_spell(self, spell, char_instance): # Check for component restrictions cost = spell.level * 50 * dnd_character.character.coin_value['gp'] - cost_in_cp = cost * (1 / dnd_character.character.coin_value['gp']) * dnd_character.character.coin_value['cp'] if not self.check_components(char_instance, cost): print(f"Insufficient gold to scribe {spell.name}.") @@ -74,7 +71,7 @@ def validate_spell(self, spell, char_instance): print(f"Char wealth before transaction: {char_instance.wealth}") # Debug line try: print(f"Cost of transaction: {cost}") # Debug line - char_instance.change_wealth(cp=-cost_in_cp) # deduct cost + char_instance.change_wealth(gp=-cost, conversion=True) # deduct cost print(f"Char detailed wealth after transaction: {char_instance.wealth_detailed}") # New debug line return True except ValueError: # Insufficient funds @@ -161,5 +158,3 @@ def fetch_wizard_spells_from_json(): print("Error encountered while processing JSON.") return wizard_spells_by_level - - From cd5add20da5501336deff0925ad1ffd35df1745d Mon Sep 17 00:00:00 2001 From: stevebelew Date: Tue, 3 Oct 2023 19:49:04 -0600 Subject: [PATCH 14/14] Update test_spellbook.py --- tests/test_spellbook.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tests/test_spellbook.py b/tests/test_spellbook.py index d172623..cf70c92 100644 --- a/tests/test_spellbook.py +++ b/tests/test_spellbook.py @@ -2,24 +2,30 @@ from dnd_character.classes import Wizard # Initialize a Spellbook object -my_spellbook = Spellbook(contents=[], cost={}, desc=[], index="", name="", properties=[], special=[], url="", equipment_category={}) +my_spellbook = Spellbook(contents=[], cost={}, desc=[], index="", name="", properties=[], special=[], url="", + equipment_category={}) lvl_1_wizard = Wizard( name="Level 1 Wizard ", level=1, wealth=75 - ) -print(lvl_1_wizard.classs) +) lvl_3_wizard = Wizard( name="Level 3 Wizard ", level=3, - wealth=75 - ) + wealth=750 +) lvl_5_wizard = Wizard( name="Level 3 Wizard ", level=5, wealth=700 - ) +) +lvl_7_wizard = Wizard( + name="Level 7 Wizard ", + level=7, + wealth=100 +) + def run_tests(): # Create mock spell objects @@ -29,10 +35,9 @@ def run_tests(): mock_spell4 = type('Spell', (object,), {'level': 3, 'name': 'Vampiric Touch'}) # Test Case 1: Level 1 Wizard tries to add a Level 2 spell (Should fail) - result1 = my_spellbook.validate_spell(spell=level_2_spell , char_instance=lvl_1_wizard) + result1 = my_spellbook.validate_spell(spell=level_2_spell, char_instance=lvl_1_wizard) assert result1 == False, "Test Case 1 Failed" - # Test Case 2: Level 3 Wizard tries to add a Level 1 spell not in wizard spell list (Should fail) result2 = my_spellbook.validate_spell(spell=nonwizard_spell, char_instance=lvl_3_wizard) assert result2 == False, "Test Case 2 Failed" @@ -42,11 +47,11 @@ def run_tests(): assert result3 == True, "Test Case 3 Failed" # Test Case 4: Level 5 tries to add a Level 3 spell but does not have enough gold (Should fail) - result4 = my_spellbook.validate_spell(spell=mock_spell4, char_instance=lvl_5_wizard) + result4 = my_spellbook.validate_spell(spell=mock_spell4, char_instance=lvl_7_wizard) assert result4 == False, "Test Case 4 Failed" print("All test cases passed!") -#Run the tests +# Run the tests run_tests()