tuning naming algorithm

This commit is contained in:
evilchili 2023-12-29 19:22:51 -08:00
parent 86c2fce87d
commit 51ecf83357
8 changed files with 58 additions and 31 deletions

View File

@ -61,7 +61,7 @@ def table(
True, True,
help='If True, collapse multiple die values with the same option.'), help='If True, collapse multiple die values with the same option.'),
width: int = typer.Option( width: int = typer.Option(
120, 180,
help='Width of the table.'), help='Width of the table.'),
output: OUTPUT_FORMATS = typer.Option( output: OUTPUT_FORMATS = typer.Option(
'text', 'text',

View File

@ -3,22 +3,24 @@ metadata:
- name - name
- description - description
light: light:
- 'A light weapon is small and easy to handle, making it ideal for use when fighting with two weapons.' - "A light weapon is small and easy to handle, making it ideal for use when fighting with two weapons."
thrown: thrown:
- '' - "If a weapon has the thrown property, you can throw the weapon to make a ranged attack. If the weapon is a melee weapon, you use the same ability modifier for that attack roll and damage roll that you would use for a melee attack with the weapon."
heavy: heavy:
- '' - "Small creatures have disadvantage on attack rolls with heavy weapons. A heavy weapons size and bulk make it too large for a Small creature to use effectively."
special:
- ''
two-handed: two-handed:
- '' - "This weapon requires two hands when you attack with it."
versatile: versatile:
- '' - "This weapon can be used with one or two hands. A damage value in parentheses appears with the property—the damage when the weapon is used with two hands to make a melee attack."
finesse: finesse:
- '' - "When making an attack with a finesse weapon, you use your choice of your Strength or Dexterity modifier for the attack and damage rolls. You must use the same modifier for both rolls."
ammunition: ammunition:
- '' - "You can use a weapon that has the ammunition property to make a ranged attack only if you have ammunition to fire from the weapon. Each time you attack with the weapon, you expend one piece of ammunition. Drawing the ammunition from a quiver, case, or other container is part of the attack (you need a free hand to load a one-handed weapon)."
reach: reach:
- '' - "This weapon adds 5 feet to your reach when you attack with it, as well as when determining your reach for opportunity attacks with it."
loading: loading:
- '' - "Because of the time required to load this weapon, you can fire only one piece of ammunition from it when you use an action, bonus action, or reaction to fire it, regardless of the number of attacks you can normally make."
ranged:
- "A weapon that can be used to make a ranged attack has a range in parentheses after the ammunition or thrown property. The range lists two numbers. The first is the weapons normal range in feet, and the second indicates the weapons long range. When attacking a target beyond normal range, you have disadvantage on the attack roll. You cant attack a target beyond the weapons long range."
special:
- "Refer to Player's Handbook."

View File

@ -17,7 +17,7 @@ enchanted:
- 0 - 0
- weapon - weapon
magical: magical:
- 'striking, smacking' - 'legend, legendary strking, legendary smacking, legendary strikes'
- '+3' - '+3'
- This magical weapon grants +3 to attack and damage rolls. - This magical weapon grants +3 to attack and damage rolls.
- '{damage_type}' - '{damage_type}'

View File

@ -17,7 +17,7 @@ enchanted:
- 0 - 0
- weapon - weapon
magical: magical:
- 'striking, smacking' - 'precision, precise striking, precise smacking, precise strikes'
- '+2' - '+2'
- This magical weapon grants +2 to attack and damage rolls. - This magical weapon grants +2 to attack and damage rolls.
- '{damage_type}' - '{damage_type}'

View File

@ -32,7 +32,7 @@ enchanted:
- null - null
- weapon - weapon
magical: magical:
- 'striking, smacking' - 'honed striking, honed smacking, honed strikes'
- '+1' - '+1'
- This magical weapon grants +1 to attack and damage rolls. - This magical weapon grants +1 to attack and damage rolls.
- '{damage_type}' - '{damage_type}'

View File

@ -17,7 +17,7 @@ enchanted:
- 0 - 0
- weapon - weapon
magical: magical:
- 'striking, smacking' - 'might, mighty strking, mighty smacking, mighty strikes'
- '+3' - '+3'
- This magical weapon grants +3 to attack and damage rolls. - This magical weapon grants +3 to attack and damage rolls.
- '{damage_type}' - '{damage_type}'

View File

@ -252,8 +252,11 @@ class GeneratorSource:
( (
item.rarity['sort_order'], item.rarity['sort_order'],
[ [
item.name, item.rarity['rarity'], item.name,
item.summary, ', '.join(item.get('properties', [])) item.rarity['rarity'],
item.summary,
', '.join(item.get('properties', [])),
item.id
] ]
) )
for item in self.generator.random(count=count, challenge_rating=self.cr) for item in self.generator.random(count=count, challenge_rating=self.cr)
@ -286,6 +289,7 @@ class RollTable(rolltable.types.RollTable):
'Name', 'Name',
'Rarity', 'Rarity',
'Summary', 'Summary',
'Properties' 'Properties',
'ID',
] ]
self._header_excludes = [] self._header_excludes = []

View File

@ -1,4 +1,6 @@
import random import random
import base64
import hashlib
from functools import cached_property from functools import cached_property
@ -32,9 +34,9 @@ class Weapon(types.Item):
def _name_template(self, with_adjectives: bool, with_nouns: bool) -> str: def _name_template(self, with_adjectives: bool, with_nouns: bool) -> str:
num_properties = len(self.properties) num_properties = len(self.properties)
options = [] options = []
if with_nouns: if with_nouns and not with_adjectives:
options.append(('{name} of {nouns}', 0.5)) options.append(('{name} of {nouns}', 0.5))
if with_adjectives: if with_adjectives and not with_nouns:
options.append(('{adjectives} {name}', 0.5)) options.append(('{adjectives} {name}', 0.5))
if with_nouns and with_adjectives: if with_nouns and with_adjectives:
if num_properties == 1: if num_properties == 1:
@ -60,22 +62,34 @@ class Weapon(types.Item):
def add_word(key, obj, source): def add_word(key, obj, source):
obj.append(source[key].random().strip()) obj.append(source[key].random().strip())
seen_nouns = dict()
for prop_name in set(list(nouns.keys()) + list(adjectives.keys())): for prop_name in set(list(nouns.keys()) + list(adjectives.keys())):
if prop_name in nouns and prop_name in adjectives:
val = random.random() if prop_name in nouns and prop_name not in adjectives:
if val <= 0.4: if prop_name not in seen_nouns:
add_word(prop_name, random_nouns, nouns) add_word(prop_name, random_nouns, nouns)
seen_nouns[prop_name] = True
elif prop_name in adjectives and prop_name not in nouns:
add_word(prop_name, random_adjectives, adjectives)
if prop_name in nouns and prop_name in adjectives:
# if the property has both nouns and adjectives, select one
# or the other or both, for the weapon name. Both leads to
# spurious names like 'thundering dagger of thunder', so we
# we reduce the likelihood of this eventuality so it is an
# occasionl bit of silliness, not consistently silly.
val = random.random()
if val <= 0.4 and prop_name not in seen_nouns:
add_word(prop_name, random_nouns, nouns)
seen_nouns[prop_name] = True
elif val <= 0.8: elif val <= 0.8:
add_word(prop_name, random_adjectives, adjectives) add_word(prop_name, random_adjectives, adjectives)
else: else:
add_word(prop_name, random_nouns, nouns) add_word(prop_name, random_nouns, nouns)
add_word(prop_name, random_adjectives, adjectives) add_word(prop_name, random_adjectives, adjectives)
elif prop_name in nouns:
add_word(prop_name, random_nouns, nouns)
elif prop_name in adjectives:
add_word(prop_name, random_adjectives, adjectives)
random_nouns = ' '.join(random_nouns) random_nouns = ' and '.join(random_nouns)
random_adjectives = ' '.join(random_adjectives) random_adjectives = ' '.join(random_adjectives)
return (random_nouns, random_adjectives) return (random_nouns, random_adjectives)
@ -131,7 +145,7 @@ class Weapon(types.Item):
@property @property
def summary(self): def summary(self):
return f"{self.to_hit} to hit, {self.range} ft., {self.targets} targets. {self.damage_dice}" return f"{self.to_hit} to hit, {self.range} ft., {self.targets} tgts. {self.damage_dice}"
@property @property
def details(self): def details(self):
@ -146,6 +160,13 @@ class Weapon(types.Item):
f"\n{self.description}\n" f"\n{self.description}\n"
]) ])
@property
def id(self):
sha1bytes = hashlib.sha1(''.join([
self._name, self.to_hit, self.damage_dice,
]).encode())
return base64.urlsafe_b64encode(sha1bytes.digest()).decode('ascii')[:10]
class WeaponGenerator(types.ItemGenerator): class WeaponGenerator(types.ItemGenerator):
item_class = Weapon item_class = Weapon