Skip to content

Commit

Permalink
Adjusted Systems
Browse files Browse the repository at this point in the history
Adjusted systems and added tests
  • Loading branch information
Coffee-fueled-deadlines committed Sep 3, 2024
1 parent f29d8d9 commit 1b0c8db
Show file tree
Hide file tree
Showing 7 changed files with 300 additions and 10 deletions.
2 changes: 0 additions & 2 deletions PyDnD/LevelingSystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ def removeExp(self, xp):
if self.player.level == 1:
if xp > self.player._experience:
self.player._experience = 0
else:
self.player._experience -= xp
break
else:
self.levelDown()
Expand Down
10 changes: 2 additions & 8 deletions PyDnD/Player.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,16 +436,10 @@ def featpoints(self, value):

# Inventory Methods
def add_item_to_inventory(self, item, quantity=1):
try:
self.inventory.add_item(item, quantity)
except InventoryIsFull as e:
print(e)
self.inventory.add_item(item, quantity)

def remove_item_from_inventory(self, item, quantity=1):
try:
self.inventory.remove_item(item, quantity)
except ItemNotInInventory as e:
print(e)
self.inventory.remove_item(item, quantity)

def get_inventory(self):
return self.inventory.items
Expand Down
26 changes: 26 additions & 0 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,32 @@
newPlayer.add_item_to_inventory("Mjolnir")
print( f"\t\tThor's inventory is: \n\t\t\t{newPlayer.get_inventory()}\n" )

# Oh no he's not worthy again
newPlayer.remove_item_from_inventory("Mjolnir")
print( f"\t\tThor's inventory is: \n\t\t\t{newPlayer.get_inventory()}\n" )
print("\n\n")

print( "LEVEL DOWN")

print("\n\n")
# Lets see what Thor looks like as a level 2
newPlayer.removeExp(500)
print( "\tNew Level: " + str( newPlayer.level ) ) # newPlayer.level is automatically increased when XP threshold increases
print( "\tCurrent Experience: " + str( newPlayer.experience ) ) # Current, experience after leveling up
print( "\tEXP to next Level: " + str( newPlayer.nextLvlExperience ) ) # 3000 Experience total is required to get to level 3
print( "\n\t--Stats--\n")
print( "\t\tStrength is: " + str( newPlayer.strength ))
print( "\t\tDexterity is: " + str( newPlayer.dexterity ))
print( "\t\tConsitution is: " + str( newPlayer.constitution ))
print( "\t\tWisdom is: " + str( newPlayer.wisdom ))
print( "\t\tIntelligence is: " + str( newPlayer.intelligence ))
print( "\t\tCharisma is: " + str( newPlayer.charisma ))
print( "\n\t--Inventory--\n" )

# Lets give Thor back his hammer
newPlayer.add_item_to_inventory("Mjolnir")
print( f"\t\tThor's inventory is: \n\t\t\t{newPlayer.get_inventory()}\n" )

# Oh no he's not worthy again
newPlayer.remove_item_from_inventory("Mjolnir")
print( f"\t\tThor's inventory is: \n\t\t\t{newPlayer.get_inventory()}\n" )
Expand Down
53 changes: 53 additions & 0 deletions tests/test_dice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import unittest
from PyDnD.Dice import Dice

class TestDice(unittest.TestCase):

def test_single_die_roll(self):
"""Test rolling a single die."""
dice = Dice(num_dice=1, sides=6)
dice.roll()
self.assertIn(dice.value, range(1, 7), "Roll value should be between 1 and 6")
self.assertEqual(len(dice.rolls), 1, "Should have only one roll")

def test_multiple_dice_roll(self):
"""Test rolling multiple dice."""
dice = Dice(num_dice=3, sides=6)
dice.roll()
# Ensure the total value is within the expected range for 3d6
self.assertIn(dice.value, range(3, 19), "Roll value should be between 3 and 18")
self.assertEqual(len(dice.rolls), 3, "Should have 3 rolls")

def test_dice_with_modifier(self):
"""Test rolling dice with a modifier."""
dice = Dice(num_dice=2, sides=6, modifier=2)
dice.roll()
# Minimum roll with modifier: 2 * 1 + 2 = 4
# Maximum roll with modifier: 2 * 6 + 2 = 14
self.assertIn(dice.value, range(4, 15), "Roll value with modifier should be between 4 and 14")

def test_dice_with_drop_lowest(self):
"""Test rolling dice and dropping the lowest roll."""
dice = Dice(num_dice=4, sides=6, drop_lowest=1)
dice.roll()
# Check the number of rolls and the value after dropping the lowest
self.assertEqual(len(dice.rolls), 4, "Should have 4 rolls")
self.assertTrue(3 <= dice.value <= 18, "Roll value after dropping lowest should be between 3 and 18")

def test_dice_with_invalid_num_dice(self):
"""Test rolling with an invalid number of dice."""
with self.assertRaises(ValueError):
Dice(num_dice=0, sides=6)

def test_dice_with_invalid_sides(self):
"""Test rolling with an invalid number of sides."""
with self.assertRaises(ValueError):
Dice(num_dice=1, sides=0)

def test_dice_with_invalid_drop_lowest(self):
"""Test rolling with drop_lowest greater than num_dice."""
with self.assertRaises(ValueError):
Dice(num_dice=2, sides=6, drop_lowest=3)

if __name__ == '__main__':
unittest.main()
61 changes: 61 additions & 0 deletions tests/test_levelingsystem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import unittest
from unittest.mock import MagicMock

from PyDnD.LevelingSystem import LevelingSystem
from PyDnD.Player import Player

class TestLevelingSystem(unittest.TestCase):

def setUp(self):
"""Set up a basic player and leveling system for testing."""
self.player = Player(name="Test Player", level=1)
self.leveling_system = LevelingSystem(self.player)

def test_initial_experience(self):
"""Test that the player starts with the correct initial experience."""
self.assertEqual(self.player.experience, 0, "Initial experience should be 0 at level 1")

def test_give_experience_level_up(self):
"""Test that giving experience correctly levels up the player."""
self.leveling_system.giveExp(1000)
self.assertEqual(self.player.level, 2, "Player should level up to 2 after gaining 1000 XP")
self.assertEqual(self.player.experience, 1000, "Player's experience should be 1000 after leveling up")
self.assertEqual(self.leveling_system.nextLvlExperience, 3000 - 1000, "Next level experience should be correctly calculated")

def test_remove_experience_level_down(self):
"""Test that removing experience correctly levels down the player."""
self.leveling_system.giveExp(3000)
self.assertEqual(self.player.level, 3, "Player should level up to 3 after gaining 3000 XP")

self.leveling_system.removeExp(2000)
self.assertEqual(self.player.level, 2, "Player should level down to 2 after losing 2000 XP")
self.assertEqual(self.player.experience, 1000, "Player's experience should be 1000 after leveling down")
self.assertEqual(self.leveling_system.nextLvlExperience, 3000 - 1000, "Next level experience should be correctly calculated for level 2")

def test_no_level_down_below_1(self):
"""Test that the player does not level down below level 1."""
self.leveling_system.giveExp(500)
self.leveling_system.removeExp(1000)
self.assertEqual(self.player.level, 1, "Player should not level down below 1")
self.assertEqual(self.player.experience, 0, "Player's experience should be 0 after losing all XP")

def test_get_threshold_for_next_level(self):
"""Test calculation of the experience threshold for the next level."""
threshold = self.leveling_system.getThresholdForNextLevel()
expected_threshold = int(1000 * (2 + LevelingSystem.nCr(2, 2)) - 2 * 1000)
self.assertEqual(threshold, expected_threshold, "Threshold for next level should be correctly calculated")

def test_get_threshold_for_current_level(self):
"""Test calculation of the experience threshold for the current level."""
threshold = self.leveling_system.getThresholdForCurrentLevel()
expected_threshold = int(1000 * (1 + LevelingSystem.nCr(1, 2)) - 1 * 1000)
self.assertEqual(threshold, expected_threshold, "Threshold for current level should be correctly calculated")

def test_invalid_nCr(self):
"""Test that nCr calculation handles invalid inputs."""
self.assertEqual(LevelingSystem.nCr(5, 0), 1.0, "nCr with r=0 should be 1.0")
self.assertEqual(LevelingSystem.nCr(5, 5), 1.0, "nCr with r=n should be 1.0")
self.assertEqual(LevelingSystem.nCr(5, 3), 10.0, "nCr should correctly calculate the combinations")

if __name__ == '__main__':
unittest.main()
103 changes: 103 additions & 0 deletions tests/test_player.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import unittest
from PyDnD.Player import Player
from PyDnD.Inventory import ItemNotInInventory, InventoryIsFull

class TestPlayer(unittest.TestCase):

def setUp(self):
"""Set up a basic player for testing."""
self.player = Player(
name="Test Player",
age="25",
gender="Male",
alignment="NG",
description="A brave warrior",
biography="Born to be a hero",
level=1,
wealth=100,
strength=15,
dexterity=12,
constitution=14,
wisdom=10,
intelligence=13,
charisma=8,
hp=10,
mp=5,
inventory_size=10
)

def test_initialization(self):
"""Test that the player is initialized correctly."""
self.assertEqual(self.player.name, "Test Player")
self.assertEqual(self.player.age, "25")
self.assertEqual(self.player.gender, "Male")
self.assertEqual(self.player.alignment, "NG")
self.assertEqual(self.player.description, "A brave warrior")
self.assertEqual(self.player.biography, "Born to be a hero")
self.assertEqual(self.player.level, 1)
self.assertEqual(self.player.wealth, 100)
self.assertEqual(self.player.strength, 15)
self.assertEqual(self.player.dexterity, 12)
self.assertEqual(self.player.constitution, 14)
self.assertEqual(self.player.wisdom, 10)
self.assertEqual(self.player.intelligence, 13)
self.assertEqual(self.player.charisma, 8)
self.assertEqual(self.player.hp, 10)
self.assertEqual(self.player.mp, 5)
self.assertEqual(len(self.player.inventory.items), 0)

def test_experience_and_leveling(self):
"""Test the experience and leveling system."""
self.player.giveExp(1000)
self.assertEqual(self.player.level, 2)
self.assertEqual(self.player.experience, 1000)
self.assertEqual(self.player.nextLvlExperience, 2000)

self.player.removeExp(500)
self.assertEqual(self.player.level, 1)
self.assertEqual(self.player.experience, 500)
self.assertEqual(self.player.nextLvlExperience, 500)

def test_inventory_addition(self):
"""Test adding items to the player's inventory."""
self.player.add_item_to_inventory("Sword", quantity=9) # Fill inventory to 9/10 slots
self.assertEqual(len(self.player.get_inventory()), 9)

self.player.add_item_to_inventory("Shield") # 10/10 slots now
self.assertEqual(len(self.player.get_inventory()), 10)

with self.assertRaises(InventoryIsFull):
self.player.add_item_to_inventory("Helmet") # Should raise InventoryIsFull since it's full


def test_inventory_removal(self):
"""Test removing items from the player's inventory."""
self.player.add_item_to_inventory("Potion", quantity=2)
self.player.remove_item_from_inventory("Potion") # Removes one potion
self.assertEqual(self.player.get_inventory().count("Potion"), 1)

with self.assertRaises(ItemNotInInventory):
self.player.remove_item_from_inventory("Potion", quantity=2) # Only 1 potion left, removing 2 should raise error


def test_alignment_validation(self):
"""Test alignment validation."""
with self.assertRaises(ValueError):
self.player.alignment = "ABC"

def test_negative_hp(self):
"""Test that negative HP raises an error."""
with self.assertRaises(ValueError):
self.player.hp = -5

def test_invalid_stat(self):
"""Test that invalid stats raise an error."""
with self.assertRaises(ValueError):
self.player.strength = -1
with self.assertRaises(ValueError):
self.player.dexterity = "high"

def test_inventory_full(self):
"""Test that adding too many items raises an InventoryIsFull exception."""
self.player.add_item_to_inventory("Gold Coin", quantity=10)

55 changes: 55 additions & 0 deletions tests/test_roll.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import unittest
from PyDnD.Roll import Roll

class TestRoll(unittest.TestCase):

def test_single_die_roll(self):
"""Test rolling a single die without modifiers or drop_lowest."""
result = Roll.roll(num_dice=1, sides=6)
self.assertIn(result, range(1, 7), "Roll value should be between 1 and 6")

def test_multiple_dice_roll(self):
"""Test rolling multiple dice without modifiers or drop_lowest."""
result = Roll.roll(num_dice=3, sides=6)
self.assertIn(result, range(3, 19), "Roll value should be between 3 and 18")

def test_dice_with_modifier(self):
"""Test rolling dice with a positive modifier."""
result = Roll.roll(num_dice=2, sides=6, modifier=2)
self.assertIn(result, range(4, 15), "Roll value with modifier should be between 4 and 14")

def test_dice_with_negative_modifier(self):
"""Test rolling dice with a negative modifier."""
result = Roll.roll(num_dice=2, sides=6, modifier=-2)
self.assertIn(result, range(0, 13), "Roll value with negative modifier should be between 0 and 13")

def test_dice_with_drop_lowest(self):
"""Test rolling dice and dropping the lowest roll."""
result = Roll.roll(num_dice=4, sides=6, drop_lowest=1)
self.assertIn(result, range(3, 19), "Roll value after dropping lowest should be between 3 and 18")

def test_roll_with_return_rolls(self):
"""Test rolling dice and returning the individual rolls."""
total, rolls = Roll.roll(num_dice=5, sides=6, return_rolls=True)
self.assertEqual(len(rolls), 5, "Should return a list of 5 rolls")
for roll in rolls:
self.assertIn(roll, range(1, 7), "Each roll should be between 1 and 6")
self.assertEqual(total, sum(rolls), "Total should be the sum of the rolls")

def test_invalid_num_dice(self):
"""Test that an invalid number of dice raises a ValueError."""
with self.assertRaises(ValueError):
Roll.roll(num_dice=0, sides=6)

def test_invalid_sides(self):
"""Test that an invalid number of sides raises a ValueError."""
with self.assertRaises(ValueError):
Roll.roll(num_dice=1, sides=0)

def test_invalid_drop_lowest(self):
"""Test that dropping more dice than rolled raises a ValueError."""
with self.assertRaises(ValueError):
Roll.roll(num_dice=2, sides=6, drop_lowest=3)

if __name__ == '__main__':
unittest.main()

0 comments on commit 1b0c8db

Please sign in to comment.