Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Development -> Main #8

Merged
merged 4 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
Loading