Created
June 25, 2020 10:37
-
-
Save justinabrahms/e52c9824bd37e2860704311aea00c341 to your computer and use it in GitHub Desktop.
item parser for avendar.net
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from hashlib import sha256 | |
class Item(object): | |
def __init__(self, item): | |
self.item = item | |
def __str__(self): | |
return self.item['name'] | |
def __repr__(self): | |
return '"' + self.item['name'] + '"' | |
def __hash__(self): | |
return hash(self.item['name']) | |
with open('./old-items.txt', 'r') as f: | |
old_text = f.read() | |
with open('./new-items.txt', 'r') as f: | |
new_text = f.read() | |
objects = set() | |
merge = lambda a, b: {**a,**b} | |
def get_objects__old_format(text): | |
object_lines = [] | |
current_lines = [] | |
for line in text.splitlines(): | |
if line.strip() != "": | |
current_lines.append(line) | |
else: | |
object_lines.append(current_lines) | |
current_lines = [] | |
name = re.compile(r"Object: '(?P<title>[\w -\\\']+)' is type (?P<armor_type>\w+).") | |
weapon_type = re.compile("Weapon type is (?P<weapon_type>\w+).") | |
damage = re.compile("Damage is (?P<dice_count>\d+)d(?P<dice_size>\d+) \(average (?P<avg>\d+)\).?") | |
# @@@ check it parses negative stoo | |
affect = re.compile("Affects (?P<stat>[\w ]+) by (?P<amount>[\d-]+).?") | |
comment = re.compile(r"[/\\]+(?P<comment>.*)") | |
armor = re.compile("Armor class is (?P<pierce>\d+) pierce, (?P<bash>\d+) bash, (?P<slash>\d+) slash, and (?P<magic>\d+) vs. magic.") | |
extra_flags = re.compile("Extra flags (?P<flags>[\w -]+)") | |
material = re.compile("Material is (?P<material>\w+).") | |
weight = re.compile("Weight is (?P<weight>[\d.]+\d+), level is (?P<level>\d+).") | |
weapons_flags = re.compile("Weapons flags: (?P<weapon_flags>[\w-]+)") | |
spells = re.compile("Level (?P<level>\d+) spells of: (?P<spells>.*).") | |
charges = re.compile("Has (?P<charges>\d+) charges of level (?P<level>\d+) (?P<spell>.*).") | |
capacity = re.compile("Capacity: (?P<capacity>\d+)#? Maximum weight: (?P<max_weight>\d+)#? flags: (?P<container_flags>.*)") | |
weight_multi = re.compile("Weight multiplier: (?P<weight_multiplier>\d+)%") | |
regexen = [ | |
name, weapon_type, damage, comment, armor, extra_flags, | |
material, weight, weapons_flags, spells, charges, capacity, | |
weight_multi, | |
] | |
special_regexen = [affect] | |
for lines in objects: | |
current_object = {} | |
for line in lines: | |
line = line.strip() | |
if 'You have become better at' in line: | |
continue | |
if "chant softly" in line: | |
continue | |
if "rush of knowledge" in line: | |
continue | |
found = False | |
for regex in regexen: | |
if not found and regex.match(line): | |
current_object = merge(current_object, regex.match(line).groupdict()) | |
found = True | |
if affect.match(line): | |
found = True | |
if 'affects' not in current_object: | |
current_object['affects'] = {} | |
group = affect.match(line).groupdict() | |
current_object['affects'][group['stat']] = group['amount'] | |
if not found: | |
if 'comment' not in current_object: | |
current_object['comment'] = [] | |
current_object['comment'].append(line) | |
if current_object != {}: | |
objects.add(Item(current_object)) | |
def get_objects__new_format(text): | |
object_lines = [] | |
current_lines = [] | |
for line in new_text.splitlines(): | |
if line.strip() == "": | |
if current_lines != []: | |
object_lines.append(current_lines) | |
current_lines = [] | |
else: | |
continue | |
else: | |
# print("line: ", line) | |
# print(len(current_lines)) | |
current_lines.append(line) | |
num_re = r"[\d.]+" | |
pipe_re = lambda x,y,z: f".*{x}:\s+(?P<{y.replace(' ', '_')}>{z})\s+\|" | |
simple_number = lambda x: re.compile(pipe_re(x, x.lower(), num_re)) | |
simple_str = lambda x: re.compile(pipe_re(x, x.lower(), r"[\w, -]+?")) | |
# pipe_re = lambda x, y, z: ".*" | |
name = re.compile(pipe_re( "Object", "name", r'[\w, "\'-]+?')) | |
weight = simple_number("Weight") | |
size = simple_number("Size") | |
level = simple_number("Level") | |
material = simple_str("Material") | |
item_type = simple_str("Type") | |
spell = simple_str("Spell") | |
flags = simple_str("Flags") | |
size = simple_str("Size") | |
capacity = simple_str("Capacity") | |
multiplier = simple_str("Multiplier") | |
wear = simple_str("Wear") | |
weapon_type = re.compile(pipe_re("Weapon type", 'weapon_type', r'[\w, -/]+?')) | |
weapon_flags = simple_str("Weapon flags") | |
damage_type = simple_str("Damage type") | |
damage_dice = re.compile(r'.*Damage dice:\s+(?P<dice_count>\d+)d(?P<dice_size>\d+) \(average (?P<average>[\d.]+)\).*') | |
ac_pierce = re.compile(pipe_re("AC vs pierce", "ac_pierce", num_re)) | |
ac_bash = re.compile(pipe_re("AC vs bash", "ac_bash", num_re)) | |
ac_slash = re.compile(pipe_re("AC vs slash" , "ac_slash", num_re)) | |
ac_magic = re.compile(pipe_re("AC vs magic", "ac_magic", num_re)) | |
# = simple_str("") | |
# = simple_str("") | |
regexen = [ | |
name, weight, size, level, material, item_type, spell, flags, size, | |
multiplier, capacity, wear, weapon_type, weapon_flags, damage_type, | |
damage_dice, damage_dice, ac_pierce, ac_bash, ac_slash, ac_magic | |
] | |
affect = re.compile('.*Affects (?P<stat>[\w ]+) by (?P<amount>[\d-]+).*') | |
for obj_lines in object_lines: | |
current_object = {} | |
for line in obj_lines: | |
if '+------' in line: | |
continue | |
elif '| -----' in line: | |
continue | |
found = False | |
for regex in regexen: | |
if not found and regex.match(line): | |
current_object = merge(current_object, regex.match(line).groupdict()) | |
found = True | |
if affect.match(line): | |
found = True | |
if 'affects' not in current_object: | |
current_object['affects'] = {} | |
group = affect.match(line).groupdict() | |
current_object['affects'][group['stat']] = group['amount'] | |
if not found: | |
if 'comments' not in current_object: | |
current_object['comments'] = [] | |
current_object['comments'].append(line) | |
objects.add(Item(current_object)) | |
get_objects__old_format(old_text) | |
get_objects__new_format(new_text) | |
from pprint import pprint | |
# print("Known: ", len(objects)) | |
def best_items_with_affect(affect, limit=20): | |
print("affect: ", affect) | |
looking_for = set() | |
for i in objects: | |
item = i.item | |
if 'affects' not in item: | |
continue | |
if affect not in item['affects']: | |
continue | |
looking_for.add(i) | |
return sorted(looking_for, key=lambda x: x.item['affects'][affect], reverse=True)[0:limit] | |
# pprint(['comments' in x and x['comments'] for x in looking_for]) | |
# pprint(looking_for) | |
# print(len(looking_for)) | |
# items = sorted(looking_for, key=lambda x: x.item['affects']['hit roll'], reverse=True)[0:20] | |
# for item in items: | |
# print(f"{item.item['affects']['hit roll']}: {item.item['name']} {item.item['comments']}") | |
affect = 'saves' | |
for item in best_items_with_affect(affect, limit=30): | |
try: | |
affect_score = item.item['affects'][affect] | |
except: | |
print(item.item) | |
print(f"{affect_score}: {item.item['name']} {item.item['comments']}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment