From dfce4d0398a8bafbb7ad7a31345af181c0269c09 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 15 Apr 2021 15:23:23 -0400 Subject: Added spells --- parser/scrapeToJson.py | 70 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 6 deletions(-) (limited to 'parser/scrapeToJson.py') diff --git a/parser/scrapeToJson.py b/parser/scrapeToJson.py index d9444c7..24980a1 100755 --- a/parser/scrapeToJson.py +++ b/parser/scrapeToJson.py @@ -4,7 +4,7 @@ import json import re import utils -def processMonster(data, weapons, armors): +def processMonster(data, weapons, armors, spells): names2names = {'ac': 'Armor Class', 'hp': 'Hit Points', 'speed': 'Speed', 'saves': 'Saving Throws', 'd_resistances': 'Damage Resistances?', 'd_vulnerabilities': 'Damage Vulnerabilities', 'd_immunities': 'Damage Immunities', 'c_immunities': 'Condition Immunities', 'senses': 'Senses', 'langs': 'Languages', 'skills': 'Skills'} desc = {} for name in names2names: @@ -74,7 +74,8 @@ def processMonster(data, weapons, armors): found = True bonus = armorDict['ac'] typ = armorDict['type'] - desc['inventory'].append(armorDict) + #desc['inventory'].append(armorDict) + desc['inventory'].append({'name': a, 'type': 'armor', 'text': '{} armor'.format(a)}) break if not found: print('Cound not identify armor: {}'.format(a)) @@ -188,8 +189,6 @@ def processMonster(data, weapons, armors): if isOr and toAppend['dmg_type'] == details['damage'][-1]['dmg_type'] and toAppend['dmg_die_sides'] == details['damage'][-1]['dmg_die_sides'] + 2: details['properties'].append('versatile') else: - if isOr: - print('We got here for {}!!!!!!!!!!!!!!'.format(desc['name'])) details['damage'].append(toAppend) details['text'] = re.search('(?s)(_Hit:_ (?:\d+ [^\.]*\.)?)(.*)', action['text']).group(2).strip() if len(details['damage']) == 0: @@ -198,7 +197,66 @@ def processMonster(data, weapons, armors): for name, value in utils.formatWeapon(action['name'], details['range'][0], details['range'][1], details['reach'], details['damage'][0]['dmg_type'], details['damage'][0]['dmg_die_count'], details['damage'][0]['dmg_die_sides'], action['text']).items(): action['attack'][name] = value if action['attack']['type'] != 'unknown': - desc['inventory'].append(action['attack']) + #desc['inventory'].append(action['attack']) + desc['inventory'].append({'name': action['attack']['name'], 'type': 'weapon', 'text': action['text']}) + elif 'spellcasting' in action['name']: + action['type'] = 'spellcasting' + print('{} has spellcasting!'.format(desc['name'])) + abilities = ['Intelligence', 'Wisdom', 'Charisma'] + for ability in abilities: + if ability in action['text']: + if 'spellcasting_ability' in action: + print('Uh oh, both {} and {} present!'.format(action['spellcasting_ability'], ability)) + exit(1) + action['spellcasting_ability'] = ability.lower()[:3] + if 'spellcasting_ability' not in action: + print('Uh oh, no spellcasting ability!') + exit(1) + # Interpretation of slots differs if is innate or not + action['innate'] = 'innate' in action['text'] + # Now, break down by level + action['levels'] = [] + def getSpells(text): + names = [] + [names.extend(m.split(', ')) for m in re.findall('(?<=\*\*_).*?(?=_\*\*)', text)] + #ret = [] + for name in names: + found = False + for spell in spells: + if spell['name'] == name: + #ret.append(spell) + found = True + break + if not found: + print('Could not find spell: {}!!!!!!!!!!!!'.format(name)) + #return ret + return names + # Sometimes it is in the name (as is case with mephits) + if '/day' in action['name']: + slots = int(re.search('(?<=\()\d+', action['name']).group(0)) + spellNames = getSpells(action['text']) + action['levels'].append({'slots': slots, 'spells': spellNames}) + else: + # Repair pit fiend + m = re.match('(?sm)^(.+) \d+/day each: ', action['text']) + if m: + action['text'] = re.sub(re.escape(m.group(0)), m.group(0) + '**_', action['text']) + action['text'] = re.sub(re.escape(m.group(1)), m.group(1) + '_**\n', action['text']) + for line in action['text'].split('\n')[1:]: + line = line.lower() + if all(string not in line for string in ['(', '/day', 'at will']): + continue + #print('Searching line {}'.format(line)) + # If it's "at will", then slots = 0 + if 'at will' in line: + slots = 0 + else: + slots = int(re.search('(\d+)( slot|/day)', line).group(1)) + spellNames = getSpells(line) + action['levels'].append({'slots': slots, 'spells': spellNames}) + + action['name'] = 'spellcasting' + # Remove weapon actions from features (they were just added to inventory) desc['features'] = [a for a in desc['features'] if 'attack' not in a or a['attack']['type'] == 'unknown'] # Get rid of precalculated passive perception @@ -233,4 +291,4 @@ for monster in Path('../../5thSRD/docs/gamemaster_rules/monsters/').glob('*.md') data = f.read() Path('monsters/').mkdir(exist_ok=True) with open('monsters/' + monster.stem + '.json', 'w') as f: - json.dump(processMonster(data, weapons, armors), f, indent=2) + json.dump(processMonster(data, weapons, armors, spells), f, indent=2) -- cgit v1.2.3