Skip to content

Instantly share code, notes, and snippets.

@justinabrahms
Created June 25, 2020 10:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinabrahms/e52c9824bd37e2860704311aea00c341 to your computer and use it in GitHub Desktop.
Save justinabrahms/e52c9824bd37e2860704311aea00c341 to your computer and use it in GitHub Desktop.
item parser for avendar.net
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