spell_templates working
Merged together cylinders+circles+spheres and squares+cubes for the purpose of printing templates. Also added additional filtering to remove spells just mentioning shining light, and ignoring self-targetting spells.
This commit is contained in:
parent
632a8c4f1b
commit
96624631b2
@ -1,14 +1,31 @@
|
||||
import collections
|
||||
import pprint
|
||||
import re
|
||||
import typing
|
||||
import dnd5etools.db.spells
|
||||
import dnd5etools.scripts.argparse
|
||||
|
||||
|
||||
area_size_re = re.compile(r"\d+-foot")
|
||||
sphere_size_re = re.compile(r"(?P<size>\d+)-foot-radius sphere")
|
||||
cylinder_size_re = re.compile(r"(?P<size>\d+)-foot-radius, \d+-foot-high cylinder")
|
||||
cube_size_re = re.compile(r"(?P<size>\d+)-foot cube")
|
||||
cone_size_re = re.compile(r"(?P<size>\d+)-foot cone")
|
||||
area_size_re = re.compile(r"\d+-foot", flags=re.IGNORECASE)
|
||||
light_size_re = re.compile(r"(light|light\|\w+\}) in a \d+-foot", flags=re.IGNORECASE)
|
||||
circle_size_re = re.compile(
|
||||
r"(?P<size>\d+)-foot-radius[ -](sphere|circle)", flags=re.IGNORECASE
|
||||
)
|
||||
radius_size_re = re.compile(r"(?P<size>\d+)-foot radius", flags=re.IGNORECASE)
|
||||
circle_diam_size_re = re.compile(
|
||||
r"(?P<size>\d+)-foot-diameter[ -](sphere|circle)", flags=re.IGNORECASE
|
||||
)
|
||||
cylinder_size_re = re.compile(
|
||||
r"(?P<size>\d+)-foot-radius, \d+-foot[ -](high|tall) cylinder", flags=re.IGNORECASE
|
||||
)
|
||||
alt_cylinder_size_re = re.compile(
|
||||
r"\d+-foot[ -](high|tall), (?P<size>\d+)-foot-radius cylinder", flags=re.IGNORECASE
|
||||
)
|
||||
square_size_re = re.compile(r"(?P<size>\d+)-foot[ -](cube|square)", flags=re.IGNORECASE)
|
||||
cone_size_re = re.compile(r"(?P<size>\d+)-foot cone", flags=re.IGNORECASE)
|
||||
line_size_re = re.compile(
|
||||
r"\d+-foot-wide, (?P<size>\d+)-foot[ -]long line", flags=re.IGNORECASE
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
@ -23,38 +40,63 @@ def main():
|
||||
all_template_spells = []
|
||||
for code in codes:
|
||||
all_template_spells += filter(is_template_spell, db.get_spell_list(code).spells)
|
||||
# pprint.pprint(all_template_spells)
|
||||
spheres = set()
|
||||
cylinders = set()
|
||||
cubes = set()
|
||||
cones = set()
|
||||
num_matches = 0
|
||||
circles = collections.defaultdict(list)
|
||||
squares = collections.defaultdict(list)
|
||||
cones = collections.defaultdict(list)
|
||||
lines = collections.defaultdict(list)
|
||||
for spell in all_template_spells:
|
||||
found = False
|
||||
for search_re, dest in [
|
||||
(sphere_size_re, spheres),
|
||||
(cylinder_size_re, cylinders),
|
||||
(cube_size_re, cubes),
|
||||
(line_size_re, lines),
|
||||
(circle_size_re, circles),
|
||||
(cylinder_size_re, circles),
|
||||
(circle_diam_size_re, circles),
|
||||
(alt_cylinder_size_re, circles),
|
||||
(square_size_re, squares),
|
||||
(cone_size_re, cones),
|
||||
(radius_size_re, circles),
|
||||
]:
|
||||
m = search_re.search(spell.description)
|
||||
if m is not None:
|
||||
dest.add(m.group("size"))
|
||||
size = int(m.group("size"))
|
||||
if search_re not in (
|
||||
cone_size_re,
|
||||
square_size_re,
|
||||
circle_diam_size_re,
|
||||
line_size_re,
|
||||
):
|
||||
size *= 2
|
||||
dest[size].append(spell.name)
|
||||
found = True
|
||||
num_matches += 1
|
||||
break
|
||||
if not found:
|
||||
print(spell)
|
||||
print("spheres", spheres)
|
||||
print("cylinders", cylinders)
|
||||
print("cubes", cubes)
|
||||
print("cones", cones)
|
||||
print(f"{num_matches} matched from {len(all_template_spells)}")
|
||||
print("circles/diameter")
|
||||
print_sizes(circles, " ")
|
||||
print("squares/size")
|
||||
print_sizes(squares, " ")
|
||||
print("cones/size")
|
||||
print_sizes(cones, " ")
|
||||
print("lines/length")
|
||||
print_sizes(lines, " ")
|
||||
|
||||
|
||||
def is_template_spell(spell: dnd5etools.db.spells.Spell) -> bool:
|
||||
num_area_sizes = 0
|
||||
for _ in area_size_re.finditer(spell.description):
|
||||
num_area_sizes += 1
|
||||
num_light_sizes = 0
|
||||
for _ in light_size_re.finditer(spell.description):
|
||||
num_light_sizes += 1
|
||||
return (
|
||||
len(spell.area_type) > 0
|
||||
and not "Wall" in spell.name
|
||||
and has_timed_duration(spell)
|
||||
and spell.range.type != dnd5etools.db.spells.SpellRangeType.Emanation
|
||||
and area_size_re.search(spell.description) is not None
|
||||
and spell.range.type != dnd5etools.db.spells.SpellRangeType.Emanation
|
||||
and spell.range.distance_type != "self"
|
||||
and num_area_sizes > 0
|
||||
and num_light_sizes < num_area_sizes
|
||||
)
|
||||
|
||||
|
||||
@ -63,3 +105,9 @@ def has_timed_duration(spell: dnd5etools.db.spells.Spell) -> bool:
|
||||
if sd.type != dnd5etools.db.spells.DurationType.Instant:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def print_sizes(sizes_dict: typing.Mapping[int, int], indent: str) -> None:
|
||||
for s in sorted(sizes_dict.items(), key=lambda kv: len(kv[1]), reverse=True):
|
||||
print(f"{indent} {s[0]}ft => {len(s[1])}")
|
||||
print(f"{indent}{indent}{s[1]}")
|
||||
|
Loading…
x
Reference in New Issue
Block a user