2024-09-02 12:39:59 -07:00
|
|
|
from ttfrog.db.schema.container import Container
|
2024-07-30 23:17:20 -07:00
|
|
|
from ttfrog.db.schema.item import Item, ItemType, Spell
|
2024-07-28 13:55:19 -07:00
|
|
|
|
|
|
|
|
|
|
|
def test_equipment_inventory(db, carl):
|
|
|
|
with db.transaction():
|
|
|
|
# trigger the creation of inventory mappings
|
|
|
|
db.add_or_update(carl)
|
|
|
|
|
2024-07-28 20:47:42 -07:00
|
|
|
# create some items
|
2024-07-28 13:55:19 -07:00
|
|
|
ten_foot_pole = Item(name="10ft. Pole", item_type=ItemType.ITEM, consumable=False)
|
2024-07-28 20:47:42 -07:00
|
|
|
fireball = Spell(name="Fireball", level=3, concentration=False)
|
|
|
|
db.add_or_update([ten_foot_pole, fireball])
|
2024-07-28 13:55:19 -07:00
|
|
|
|
2024-07-28 20:47:42 -07:00
|
|
|
# add the pole to carl's equipment, and the spell to his spell list.
|
|
|
|
assert carl.equipment.add(ten_foot_pole)
|
|
|
|
assert carl.spells.add(fireball)
|
|
|
|
|
|
|
|
# can't mix and match inventory item types
|
|
|
|
assert not carl.equipment.add(fireball)
|
|
|
|
assert not carl.spells.add(ten_foot_pole)
|
|
|
|
|
|
|
|
# add two more 10 foot poles. You can never have too many.
|
|
|
|
carl.equipment.add(ten_foot_pole)
|
2024-07-28 13:55:19 -07:00
|
|
|
carl.equipment.add(ten_foot_pole)
|
|
|
|
db.add_or_update(carl)
|
2024-07-28 20:47:42 -07:00
|
|
|
|
2024-08-29 15:14:47 -07:00
|
|
|
all_carls_poles = carl.equipment.get_all(ten_foot_pole)
|
2024-07-28 20:47:42 -07:00
|
|
|
assert len(all_carls_poles) == 3
|
|
|
|
|
|
|
|
# check the "contains" logic
|
|
|
|
assert ten_foot_pole in carl.equipment
|
|
|
|
assert ten_foot_pole not in carl.spells
|
|
|
|
assert fireball in carl.spells
|
|
|
|
assert fireball not in carl.equipment
|
|
|
|
|
2024-08-29 16:41:15 -07:00
|
|
|
pole_one = all_carls_poles[0]
|
|
|
|
|
2024-07-28 20:47:42 -07:00
|
|
|
# equip one pole
|
2024-08-29 16:41:15 -07:00
|
|
|
assert pole_one.equip()
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# can't equip it twice
|
2024-08-29 16:41:15 -07:00
|
|
|
assert not pole_one.equip()
|
2024-07-28 20:47:42 -07:00
|
|
|
|
2024-09-02 12:39:59 -07:00
|
|
|
# can't prepare or cast an item
|
|
|
|
assert not pole_one.prepare()
|
|
|
|
assert not pole_one.unprepare()
|
|
|
|
assert not pole_one.cast()
|
|
|
|
|
|
|
|
# not consumable or attunable
|
|
|
|
assert not pole_one.consume()
|
|
|
|
assert not pole_one.attune()
|
|
|
|
|
2024-08-29 16:41:15 -07:00
|
|
|
assert pole_one.unequip()
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# can't unequip the unequipped ones
|
2024-08-29 16:41:15 -07:00
|
|
|
assert not all_carls_poles[1].unequip()
|
|
|
|
assert not all_carls_poles[2].unequip()
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# drop one pole
|
2024-08-29 16:41:15 -07:00
|
|
|
assert carl.equipment.remove(pole_one)
|
2024-07-28 13:55:19 -07:00
|
|
|
assert ten_foot_pole in carl.equipment
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# drop the remaining poles
|
|
|
|
assert carl.equipment.remove(all_carls_poles[1])
|
|
|
|
assert carl.equipment.remove(all_carls_poles[2])
|
|
|
|
assert ten_foot_pole not in carl.equipment
|
|
|
|
|
|
|
|
# can't drop what you don't have
|
2024-08-29 16:41:15 -07:00
|
|
|
assert not carl.equipment.remove(pole_one)
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
|
|
|
|
def test_inventory_bundles(db, carl):
|
|
|
|
with db.transaction():
|
|
|
|
arrows = Item(name="Arrows", item_type=ItemType.ITEM, consumable=True, count=20)
|
|
|
|
db.add_or_update([carl, arrows])
|
|
|
|
quiver = carl.equipment.add(arrows)
|
|
|
|
db.add_or_update(carl)
|
|
|
|
|
|
|
|
# full quiver
|
|
|
|
assert arrows in carl.equipment
|
|
|
|
assert quiver.count == 20
|
|
|
|
|
|
|
|
# use one
|
2024-08-29 15:14:47 -07:00
|
|
|
assert quiver.consume(1) == 19
|
2024-07-28 20:47:42 -07:00
|
|
|
assert quiver.count == 19
|
|
|
|
|
|
|
|
# cannot use more than you have
|
2024-08-29 15:14:47 -07:00
|
|
|
assert not quiver.consume(20)
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# cannot use a negative amount
|
2024-08-29 15:14:47 -07:00
|
|
|
assert not quiver.consume(-1)
|
2024-07-28 20:47:42 -07:00
|
|
|
|
|
|
|
# consume all remaining arrows
|
2024-08-29 15:14:47 -07:00
|
|
|
assert quiver.consume(19) == 0
|
2024-07-28 20:47:42 -07:00
|
|
|
assert arrows not in carl.equipment
|
2024-07-30 23:17:20 -07:00
|
|
|
|
|
|
|
|
|
|
|
def test_spell_slots(db, carl, wizard):
|
|
|
|
with db.transaction():
|
|
|
|
prestidigitation = Spell(name="Prestidigitation", level=0, concentration=False)
|
|
|
|
fireball = Spell(name="Fireball", level=3, concentration=False)
|
|
|
|
db.add_or_update([carl, prestidigitation, fireball])
|
|
|
|
|
|
|
|
carl.spells.add(prestidigitation)
|
|
|
|
carl.spells.add(fireball)
|
|
|
|
db.add_or_update(carl)
|
|
|
|
|
|
|
|
# verify carl has the spell slots granted by wizard at 1st level
|
|
|
|
assert len(carl.spell_slots) == 2
|
|
|
|
assert carl.spell_slots[0].spell_level == 1
|
|
|
|
assert carl.spell_slots[1].spell_level == 1
|
|
|
|
|
|
|
|
# carl knows the spells but hasn't prepared them
|
|
|
|
assert prestidigitation in carl.spells
|
|
|
|
assert fireball in carl.spells
|
|
|
|
assert prestidigitation not in carl.prepared_spells
|
|
|
|
assert fireball not in carl.prepared_spells
|
|
|
|
|
|
|
|
# prepare the cantrip
|
2024-08-29 15:14:47 -07:00
|
|
|
carls_prestidigitation = carl.spells.get(prestidigitation)
|
2024-08-29 16:41:15 -07:00
|
|
|
assert carls_prestidigitation.prepare()
|
|
|
|
assert carls_prestidigitation.cast()
|
2024-07-30 23:17:20 -07:00
|
|
|
|
|
|
|
# can't prepare a 3rd level spell if you don't have 3rd level slots
|
|
|
|
assert carl.spellcaster_level == 1
|
2024-08-29 16:41:15 -07:00
|
|
|
assert not carl.spells.get(fireball).prepare()
|
2024-07-30 23:17:20 -07:00
|
|
|
|
|
|
|
# make carl a 5th level wizard so he gets a 3rd level spell slot
|
|
|
|
carl.level_up(wizard, num_levels=4)
|
|
|
|
assert carl.level == 5
|
|
|
|
assert carl.spellcaster_level == 3
|
|
|
|
|
|
|
|
# cast fireball until he's out of 3rd level slots
|
2024-09-02 12:39:59 -07:00
|
|
|
assert not carl.spells.get(fireball).cast()
|
2024-08-29 16:41:15 -07:00
|
|
|
assert carl.spells.get(fireball).prepare()
|
|
|
|
assert carl.spells.get(fireball).cast()
|
|
|
|
assert carl.spells.get(fireball).cast()
|
|
|
|
assert not carl.spells.get(fireball).cast()
|
2024-07-30 23:17:20 -07:00
|
|
|
|
|
|
|
# level up to 7th level, gaining 1 4th level slot and 1 more 3rd level slot
|
|
|
|
carl.add_class(wizard)
|
|
|
|
carl.level_up(wizard, num_levels=2)
|
|
|
|
assert carl.spellcaster_level == 4
|
|
|
|
assert len(carl.spell_slots_available[4]) == 1
|
|
|
|
assert len(carl.spell_slots_available[3]) == 1
|
|
|
|
|
|
|
|
# cast at 4th level
|
2024-08-29 16:41:15 -07:00
|
|
|
assert carl.spells.get(fireball).cast(level=4)
|
|
|
|
assert not carl.spells.get(fireball).cast(level=4)
|
2024-07-30 23:17:20 -07:00
|
|
|
|
|
|
|
# use the last 3rd level slot
|
2024-08-29 16:41:15 -07:00
|
|
|
assert carl.spells.get(fireball).cast()
|
|
|
|
assert not carl.spells.get(fireball).cast()
|
2024-09-02 12:39:59 -07:00
|
|
|
|
|
|
|
# unprepare it
|
|
|
|
assert carl.spells.get(fireball).unprepare()
|
|
|
|
assert not carl.spells.get(fireball).unprepare()
|
|
|
|
|
|
|
|
|
|
|
|
def test_containers(db, carl):
|
|
|
|
with db.transaction():
|
2024-09-02 19:45:52 -07:00
|
|
|
ten_foot_pole = Item(name="10ft. Pole")
|
|
|
|
rope = Item(name="50 ft. of Rope", consumable=True, count=50)
|
2024-09-02 12:39:59 -07:00
|
|
|
bag_of_holding = Container(name="Bag of Holding")
|
2024-09-02 14:53:49 -07:00
|
|
|
db.add_or_update([carl, ten_foot_pole, rope, bag_of_holding])
|
2024-09-02 12:39:59 -07:00
|
|
|
|
2024-09-02 14:53:49 -07:00
|
|
|
# add some items to the bag of holding
|
2024-09-02 14:02:16 -07:00
|
|
|
assert bag_of_holding.add(ten_foot_pole)
|
2024-09-02 14:53:49 -07:00
|
|
|
assert bag_of_holding.add(rope)
|
2024-09-02 12:39:59 -07:00
|
|
|
db.add_or_update(bag_of_holding)
|
2024-09-02 14:53:49 -07:00
|
|
|
|
2024-09-02 14:02:16 -07:00
|
|
|
pole_from_bag = bag_of_holding.get(ten_foot_pole)
|
2024-09-02 14:53:49 -07:00
|
|
|
rope_from_bag = bag_of_holding.get(rope)
|
|
|
|
|
2024-09-02 14:02:16 -07:00
|
|
|
assert pole_from_bag.item == ten_foot_pole
|
|
|
|
assert pole_from_bag in bag_of_holding
|
2024-09-02 12:39:59 -07:00
|
|
|
assert pole_from_bag not in carl.equipment
|
|
|
|
|
|
|
|
# add the bag of holding to carl's equipment
|
|
|
|
assert carl.equipment.add(bag_of_holding)
|
|
|
|
db.add_or_update(bag_of_holding)
|
|
|
|
assert pole_from_bag in carl.equipment
|
2024-09-02 14:53:49 -07:00
|
|
|
assert rope_from_bag in carl.equipment
|
2024-09-02 12:39:59 -07:00
|
|
|
|
|
|
|
# test equality of mappings
|
|
|
|
carls_bag = carl.equipment.get(bag_of_holding)
|
|
|
|
carls_pole = carl.equipment.get(ten_foot_pole)
|
2024-09-02 14:53:49 -07:00
|
|
|
carls_rope = carl.equipment.get(rope)
|
2024-09-02 12:39:59 -07:00
|
|
|
assert carls_pole == pole_from_bag
|
2024-09-02 14:53:49 -07:00
|
|
|
assert carls_rope == rope_from_bag
|
|
|
|
|
|
|
|
# use some rope
|
|
|
|
carls_rope.consume(10)
|
|
|
|
assert carls_rope.count == 40
|
|
|
|
|
|
|
|
# move the rope out of the bag of holding, but not the pole
|
|
|
|
assert carls_rope.move_to(carl.equipment)
|
|
|
|
assert carls_rope not in carls_bag
|
|
|
|
assert carls_pole in carls_bag
|
|
|
|
db.add_or_update(carl)
|
2024-09-02 12:39:59 -07:00
|
|
|
|
2024-09-02 14:53:49 -07:00
|
|
|
# get the db record anew, in case the in-memory representation isn't
|
|
|
|
# what's recorded in the database. Then make sure we didn't break
|
|
|
|
# anything by asserting we still only have 40ft of rope.
|
|
|
|
carl = db.Character.filter_by(name="carl").one()
|
|
|
|
assert carls_rope in carl.equipment
|
|
|
|
assert carls_rope not in carl.equipment.get(bag_of_holding)
|
|
|
|
assert carls_rope.count == 40
|
|
|
|
|
|
|
|
# old references are still valid
|
|
|
|
assert rope_from_bag == carls_rope
|
|
|
|
|
|
|
|
# use the rest of the rope
|
|
|
|
assert carls_rope.consume(40) == 0
|
|
|
|
print(rope_from_bag.inventory)
|
|
|
|
assert rope_from_bag not in carl.equipment
|
|
|
|
assert rope_from_bag not in carl.equipment.get(bag_of_holding)
|