add ability to generate items of specific rarity

This commit is contained in:
evilchili 2023-12-31 11:17:11 -08:00
parent d13878a7ce
commit b1aad7b0f4
3 changed files with 47 additions and 14 deletions

View File

@ -39,8 +39,7 @@ metadata:
uncommon: 0.05
rare: 0.5
very rare: 0.5
#legendary: 0.3
legendary: 0.0
legendary: 0.3
common:
- 0
uncommon:

View File

@ -280,15 +280,17 @@ class ItemGenerator:
def __init__(self):
super().__init__(
bases=WeightedSet(
(dict(name='{type} stick', type='wooden', ...), 0.3),
(dict(name='{type} stick', type='lead', ...), 1.0),
(dict(name='{type} stick', type='silver', ...), 0.5),
(dict(name='{type} stick', type='glass', ...), 0.1),
(dict(name='{type} stick', type='wooden'), 0.3),
(dict(name='{type} stick', type='lead'), 1.0),
(dict(name='{type} stick', type='silver'), 0.5),
(dict(name='{type} stick', type='glass'), 0.1),
),
raritytypes.RARITY,
rarity.types.RARITY,
properties_by_rarity=types.PROPERTIES_BY_RARITY,
)
# ...Add callbacks for string templates in PROPERTIES_BY_RARITY...
Generating Random Items
Given an ItemGenerator class, use the ItemGenerator.random() method to
@ -300,7 +302,7 @@ class ItemGenerator:
Example:
>>> stick = SharpStickGenerator().random(count=1, challenge_rating=17)
>>> stick = SharpStickGenerator().random(count=1, rarity='legendary')
>>> stick[0].name
Silver Stick
>>> stick[0].rarity
@ -369,7 +371,7 @@ class ItemGenerator:
return set(getreqs(item))
def random_properties(self) -> dict:
def random_properties(self, rarity: str = '') -> dict:
"""
Create a dictionary of item attributes appropriate for a given rarity.
Dictionaries generated by this method are used as arguments to the
@ -395,14 +397,17 @@ class ItemGenerator:
This will result in:
>>> item['extras']['owner']
Jules Ultandottir
Jules Ultardottir
"""
# select a random base
item = self.bases.random()
# select a random rarity
item["rarity"] = self.rarity.random()
if rarity:
item["rarity"] = self.rarity.source.as_dict()[rarity]
else:
item["rarity"] = self.rarity.random()
# select a number of properties appropriate to the rarity
num_properties = self._property_count_by_rarity(item["rarity"]["rarity"])
@ -431,12 +436,12 @@ class ItemGenerator:
try:
item[requirement] = getattr(self, f"get_{requirement}")(**item)
except AttributeError:
logging.error("{item['name']} requires {self.__class__.__name__} to have a get_{requirement}() method.")
logging.error(f"{item['name']} requires {self.__class__.__name__} to define get_{requirement}().")
raise
return item
def random(self, count: int = 1, challenge_rating: int = 0) -> list:
def random(self, count: int = 1, challenge_rating: int = 0, rarity: str = '') -> list:
"""
Generate one or more random Item instances by selecting random values
from the available data sources, appropriate to the specified challenge
@ -446,6 +451,9 @@ class ItemGenerator:
an encounter for an adventuring party of four. This will prevent
lower-level encounters from generating legendary weapons and so on. If
challenge_rating is 0, a rarity is chosen at random.
If a rarity is supplied, ensure we return items of that rarity; in this
case challenge_rating is ignored.
"""
if challenge_rating in range(1, 5):
frequency = "1-4"
@ -461,7 +469,7 @@ class ItemGenerator:
items = []
for _ in range(count):
items.append(self.item_class.from_dict(self.random_properties()))
items.append(self.item_class.from_dict(self.random_properties(rarity=rarity)))
return items

View File

@ -61,3 +61,29 @@ def test_Item_overrides():
ten_foot_pole = types.Item.from_dict(attrs)
assert ten_foot_pole.name == '7ft. Pole'
assert ten_foot_pole.description == 'Broken. The end of this 10ft. pole has been snapped off.'
def test_ItemGenerator_subclass():
class SharpStickGenerator(types.ItemGenerator):
def __init__(self):
super().__init__(
bases=types.WeightedSet(
(dict(name='{type} stick', type='wooden'), 0.3),
(dict(name='{type} stick', type='lead'), 1.0),
(dict(name='{type} stick', type='silver'), 0.5),
(dict(name='{type} stick', type='glass'), 0.1),
),
rarity=types.RARITY,
properties_by_rarity=types.PROPERTIES_BY_RARITY,
)
stick = SharpStickGenerator().random(count=1, rarity='common')
assert stick[0].name in [
'wooden stick',
'lead stick',
'silver stick',
'glass stick',
]
assert stick[0].rarity.rarity == 'common'
assert stick[0].description == ''