def readNewUnitsFromDir(dir): from Services.utils import newunits out = newunits for f in os.listdir(dir): if f.endswith(".txt"): c = readNewUnitFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError(f"NewUnit named {key} already exists and was redefined in {f}") out[key] = c[key]
def readUnitModListFile(fp): "Read one file and return all the spell modifiers within." out = {} curreff = None with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "": continue if line.startswith("--"): continue if line.startswith("#newunitmodlist"): if curreff is not None: raise ParseError( f"{fp} line {lineno}: Unexpected #newunitmodlist (still parsing previous effect)" ) m = re.match("#newunitmodlist\W+\"(.*)\"\W*$", line) if m is None: raise ParseError( f"{fp} line {lineno}: Expected an effect name, none was found" ) curreff = UnitModList() curreff.name = m.groups()[0] else: if curreff is None: raise ParseError( f"{fp} line {lineno}: Expected a #newunitmodlist line") m = re.match(f'#allowedunitmod "(.*)"', line) if m is not None: pval = m.groups()[0] curreff.allowedunitmods.append(pval) continue if line.startswith("#end"): out[curreff.name] = curreff curreff = None continue raise ParseError( f"{fp} line {lineno}: Unrecognised content: {line}") return out
def readWeaponModsFromDir(dir): out = weaponmods for f in os.listdir(dir): if f.endswith(".txt"): c = readWeaponModFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError( f"WeaponMod named {key} already exists and was redefined in {f}" ) out[key] = c[key]
def readEffectsFromDir(dir): out = utils.spelleffects new = [] for f in os.listdir(dir): if f.endswith(".txt"): c = readEffectFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError( f"Spell named {key} already exists and was redefined in {f}" ) out[key] = c[key] if c[key].spelltype == -1: raise ParseError( f"{f}: Spell Effect {key} was given no spell type") new.append(key) o = {} for key in new: o[key] = out[key] return o
def readSecondariesFromDir(dir): out = secondaries for f in os.listdir(dir): if f.endswith(".txt"): c = readSecondaryFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError( f"SpellSecondaryEffect named {key} already exists and was redefined in {f}" ) out[key] = c[key]
def readUnitModListsFromDir(dir): out = unitmodlists for f in os.listdir(dir): if f.endswith(".txt"): c = readUnitModListFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError( f"UnitModList named {key} already exists and was redefined in {f}" ) out[key] = c[key]
def readMagicSitesFromDir(dir): from Services.utils import magicsites out = magicsites for f in os.listdir(dir): if f.endswith(".txt"): c = readMagicSiteFile(os.path.join(dir, f)) for key in c: if key in out: raise ParseError( f"MagicSite named {key} already exists and was redefined in {f}" ) out[key] = c[key]
def readEventSetsFromDir(dir): out = eventsets for dirpath, dirnames, files in os.walk(dir): for f in files: print(f) if f.endswith(".txt"): c = readEventSet(os.path.join(dirpath, f)) if c is None: continue if c.name in out: raise ParseError( f"EventSet named {c.name} already exists and was redefined in {f}" ) out[c.name] = c if c.modulegroup is not None: if c.modulegroup not in eventmodulegroups: eventmodulegroups[c.modulegroup] = [] eventmodulegroups[c.modulegroup].append(c)
def readWeaponModFile(fp): "Read one file and return all the weapon modifiers within." out = {} curreff = None with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "": continue if line.startswith("--"): continue if line.startswith("#newweaponmod"): if curreff is not None: raise ParseError( f"{fp} line {lineno}: Unexpected #newweaponmod (still parsing previous effect)" ) m = re.match("#newweaponmod\W+\"(.*)\"\W*$", line) if m is None: raise ParseError( f"{fp} line {lineno}: Expected a weapon mod name, none was found" ) curreff = WeaponMod() curreff.name = m.groups()[0] else: if curreff is None: raise ParseError( f"{fp} line {lineno}: Expected a #newweaponmod line") sorted = False # Params to simply copy for simple in secondary_params_int: if fileparserutils.parsesimpleint(simple, line, curreff): sorted = True break if sorted: continue for simple in secondary_params_str: m = re.match(f"#{simple}" + "\\W+?\"(.*)\"\\W*", line) if m is not None: pval = m.groups()[0] setattr(curreff, simple, pval) sorted = True continue if sorted: continue for simple in secondary_params_float: m = re.match(f"#{simple}\W+?([-.0-9]*)\W*$", line) if m is not None: pval = float(m.groups()[0]) setattr(curreff, simple, pval) sorted = True continue if sorted: continue if line.startswith("#req"): m = re.match( '#req2\\W+([0-9]*)[ \t]([<>=!]+)\\W+(.+)[ \t]+([<>=!]+)\\W*([0-9]*)', line) if m is not None: cond = NameCond() cond.val2 = m.groups()[0] cond.op2 = m.groups()[1] cond.param = m.groups()[2] cond.op = m.groups()[3] cond.val = m.groups()[4] cond.text = "" curreff.reqs.append(cond) continue m = re.match('#req\\W+(.+)[ \t]+([<>&=!]+)\\W*([0-9]*)', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #req") cond = NameCond() cond.param = m.groups()[0] cond.op = m.groups()[1] cond.val = m.groups()[2] cond.text = "" curreff.reqs.append(cond) continue if line.startswith("#set"): m = re.match('#set\\W+(.*?)\\W*?([-0-9.]+)$', line) if m is not None: param = m.groups()[0] val = int(m.groups()[1]) curreff.setcommands.append([param, val]) continue raise ParseError(f"{fp} line {lineno}: bad #set") if line.startswith("#extracommand"): m = re.match('#extracommand\\W+(.*?)$', line) if m is not None: param = m.groups()[0] curreff.extracommands.append(param) continue raise ParseError(f"{fp} line {lineno}: bad #extracommand") if line.startswith("#mult"): m = re.match('#mult\\W+(.*?)\\W*?([-0-9.]+)$', line) if m is not None: param = m.groups()[0] val = int(m.groups()[1]) curreff.multcommands.append([param, val]) continue raise ParseError(f"{fp} line {lineno}: bad #mult") if line.startswith("#end"): out[curreff.name] = curreff curreff = None continue raise ParseError( f"{fp} line {lineno}: Unrecognised content: {line}") return out
def readEffectFile(fp): "Read one file and return all the spell effects within." try: lineno = None out = {} curreff = None with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "": continue if line.startswith("--"): continue if line.startswith("#neweffect"): if curreff is not None: raise ParseError( f"{fp} line {lineno}: Unexpected #neweffect (still parsing previous effect)" ) m = re.match("#neweffect\W+\"(.*)\"\W*$", line) if m is None: raise ParseError( f"{fp} line {lineno}: Expected an effect name, none was found" ) curreff = SpellEffect(fp) curreff.name = m.groups()[0] currPriority = 0 else: if curreff is None: raise ParseError( f"{fp} line {lineno}: Expected a #neweffect line") sorted = False # Params to simply copy for simple in simple_params_int: if fileparserutils.parsesimpleint( simple, line, curreff): sorted = True break if sorted: continue for simple in simple_params_str: m = re.match(f"#{simple}" + "\\W+?\"(.*)\"\\W*", line) if m is not None: pval = m.groups()[0] setattr(curreff, simple, pval) sorted = True continue if sorted: continue for simple in simple_params_float: m = re.match(f"#{simple}\W+?([-.0-9]*)\W*$", line) if m is not None: pval = float(m.groups()[0]) setattr(curreff, simple, pval) sorted = True continue if sorted: continue if line.startswith("#priority"): m = re.match("#priority\\W+?([-0-9]*)\\W*$", line) if m is not None: currPriority = int(m.groups()[0]) continue if line.startswith("#namecond"): m = re.match( '#namecond2\\W+([0-9]*)[ \t]([<>=!]+)\\W+(.+)[ \t]+([<>&=!]+)\\W*([0-9]*)\\W+(.*?)\\W+"(.*)"', line) if m is not None: paths = fileparserutils.parsepathalias( m.groups()[5]) for path in utils.breakdownflagcomponents(paths): cond = NameCond() cond.val2 = m.groups()[0] cond.op2 = m.groups()[1] cond.param = m.groups()[2] cond.op = m.groups()[3] cond.val = m.groups()[4] cond.path = path cond.text = m.groups()[6] if cond.path not in curreff.nameconds: curreff.nameconds[cond.path] = {} if currPriority not in curreff.nameconds[ cond.path]: curreff.nameconds[ cond.path][currPriority] = [] curreff.nameconds[ cond.path][currPriority].append(cond) continue m = re.match( '#namecond\\W+(.+)[ \t]+([<>=&!]+)\\W*([0-9]*)\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #namecond or #namecond2" ) paths = fileparserutils.parsepathalias(m.groups()[3]) for path in utils.breakdownflagcomponents(paths): cond = NameCond() cond.param = m.groups()[0] cond.op = m.groups()[1] cond.val = m.groups()[2] cond.path = path cond.text = m.groups()[4] if cond.path not in curreff.nameconds: curreff.nameconds[cond.path] = {} if currPriority not in curreff.nameconds[ cond.path]: curreff.nameconds[cond.path][currPriority] = [] curreff.nameconds[cond.path][currPriority].append( cond) continue if line.startswith("#descrcond"): m = re.match( '#descrcond2\\W+([0-9]*)[ \t]([<>=!]+)\\W+(.+)[ \t]+([<>&=!]+)\\W*([0-9]*)\\W+(.*?)\\W+"(.*)"', line) if m is not None: paths = fileparserutils.parsepathalias( m.groups()[5]) for path in utils.breakdownflagcomponents(paths): cond = NameCond() cond.val2 = m.groups()[0] cond.op2 = m.groups()[1] cond.param = m.groups()[2] cond.op = m.groups()[3] cond.val = m.groups()[4] cond.path = path cond.text = m.groups()[6] if cond.path not in curreff.descrconds: curreff.descrconds[cond.path] = {} if currPriority not in curreff.descrconds[ cond.path]: curreff.descrconds[ cond.path][currPriority] = [] curreff.descrconds[ cond.path][currPriority].append(cond) continue m = re.match( '#descrcond\\W+(.+)[ \t]+([<>&=!]+)\\W*([0-9]*)\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #descrcond") paths = fileparserutils.parsepathalias(m.groups()[3]) for path in utils.breakdownflagcomponents(paths): cond = NameCond() cond.param = m.groups()[0] cond.op = m.groups()[1] cond.val = m.groups()[2] cond.path = path cond.text = m.groups()[4] if cond.path not in curreff.descrconds: curreff.descrconds[cond.path] = {} if currPriority not in curreff.descrconds[ cond.path]: curreff.descrconds[ cond.path][currPriority] = [] curreff.descrconds[cond.path][currPriority].append( cond) continue if line.startswith("#descr"): m = re.match('#descr\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #descr") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): curreff.descriptions[path] = m.groups()[1] continue if line.startswith("#pathskipchance"): m = re.match('#pathskipchance\\W+(.*?)\\W+([0-9]*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #pathskipchance") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): skipchance = int(m.groups()[1]) curreff.pathskipchances[path] = skipchance continue if line.startswith("#name"): m = re.match('#name\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #name") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): if path not in curreff.names: curreff.names[path] = [] curreff.names[path].append(m.groups()[1]) continue if line.startswith("#end"): out[curreff.name] = curreff curreff = None continue raise ParseError( f"{fp} line {lineno}: Unrecognised content: {line}") return out except: if lineno is not None: raise ParseError(f"Failed to read {fp}, failed at line {lineno}") else: raise ParseError(f"Failed to read {fp}, undetermined line")
def readNewUnitFile(fp): "Read one file and return all the new units within." out = {} curreff = None with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "": continue if line.startswith("--"): continue if line.startswith("#newunit"): if curreff is not None: raise ParseError(f"{fp} line {lineno}: Unexpected #newunit (still parsing previous effect)") m = re.match("#newunit\W+\"(.*)\"\W*$", line) if m is None: raise ParseError(f"{fp} line {lineno}: Expected an unit name, none was found") curreff = NewUnit.NewUnit() curreff.name = m.groups()[0] else: if curreff is None: raise ParseError(f"{fp} line {lineno}: Expected a #newunit line") sorted = False # Params to simply copy for simple in modifier_params_int: if fileparserutils.parsesimpleint(simple, line, curreff): sorted = True break if sorted: continue for simple in modifier_params_str: m = re.match(f"#{simple}" + "\\W+?\"(.*)\"\\W*", line) if m is not None: pval = m.groups()[0] setattr(curreff, simple, pval) sorted = True continue if sorted: continue for simple in modifier_params_float: m = re.match(f"#{simple}\W+?([-.0-9]*)\W*$", line) if m is not None: pval = float(m.groups()[0]) setattr(curreff, simple, pval) sorted = True continue if sorted: continue if line.startswith("#raw"): m = re.match('#raw\\W+"(.*)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #raw") curreff.rawcmds.append(m.groups()[0].strip()) continue if line.startswith("#setstr"): m = re.match('#setstr\\W+(.*?)\\W*?"(.+)"', line) if m is not None: param = m.groups()[0] val = m.groups()[1] curreff.setcmds.append([param, val]) continue raise ParseError(f"{fp} line {lineno}: bad #setstr") if line.startswith("#set"): m = re.match('#set\\W+(.*?)\\W*?([-0-9]+)', line) if m is not None: param = m.groups()[0] val = int(m.groups()[1]) curreff.setcmds.append([param, val]) continue raise ParseError(f"{fp} line {lineno}: bad #set") if line.startswith("#addweapon"): m = re.match('#addweapon\\W+(.*?)\\W*$', line) if m is not None: val = int(m.groups()[0]) curreff.addweapons.append(val) continue raise ParseError(f"{fp} line {lineno}: bad #addweapon") if line.startswith("#addnewweapon"): m = re.match('#addnewweapon\\W+"(.*)"\\W*', line) if m is not None: val = m.groups()[0] curreff.addnewweapons.append(val) continue raise ParseError(f"{fp} line {lineno}: bad #addnewweapon") if line.startswith("#end"): out[curreff.name] = curreff curreff = None continue raise ParseError(f"{fp} line {lineno}: Unrecognised content: {line}") return out
def readEventSet(fp): "Read one file and return its event set." out = None curreff = None parsingrawmodcode = False with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "" and not parsingrawmodcode: continue if line.startswith("--") and not parsingrawmodcode: continue if line.startswith("#neweventset"): if curreff is not None: raise ParseError( f"{fp} line {lineno}: Unexpected #neweventset (only 1 per file!)" ) m = re.match("#neweventset\W+\"(.*)\"\W*$", line) if m is None: raise ParseError( f"{fp} line {lineno}: Expected an eventset name, none was found" ) curreff = EventSet() curreff.name = m.groups()[0] else: if parsingrawmodcode: curreff.rawdata += (line + "\n") continue sorted = False # Params to simply copy for simple in secondary_params_int: if fileparserutils.parsesimpleint(simple, line, curreff): sorted = True break if sorted: continue for simple in secondary_params_str: m = re.match(f"#{simple}" + "\\W+?\"(.*)\"\\W*", line) if m is not None: pval = m.groups()[0] setattr(curreff, simple, pval) sorted = True continue if sorted: continue for simple in secondary_params_float: m = re.match(f"#{simple}\W+?([-.0-9]*)\W*$", line) if m is not None: pval = float(m.groups()[0]) setattr(curreff, simple, pval) sorted = True continue if sorted: continue m = re.match(f'#allowedunitmod "(.*)"', line) if m is not None: pval = m.groups()[0] curreff.allowedunitmods.append(pval) sorted = True continue if line.startswith("#scaleparam_mult"): m = re.match('#scaleparam_mult\\W+"(.*)"\\W+?([0-9-.]*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #scaleparam_mult") curreff.scaleparammults[m.groups()[0]] = float( m.groups()[1]) continue if line.startswith("#scaleparam"): m = re.match('#scaleparam\\W+"(.*)"\\W+?([0-9-.]*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #scaleparam") curreff.scaleparams[m.groups()[0]] = float(m.groups()[1]) continue # the trailing space here is NEEDED # or this trips all the other #module* params and tries to RE them and fails if line.startswith("#module "): m = re.match('#module\\W+"(.*?)"\\W+?"(.*?)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #module") curreff.modules[m.groups()[0]] = m.groups()[1] continue if line.startswith("#textrepl"): m = re.match('#textrepl\\W+"(.*?)"\\W+?"(.*?)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #textrepl") curreff.textrepls[m.groups()[0]] = m.groups()[1] continue if line.startswith("#incompatible"): m = re.match('#incompatible\\W+"(.*?)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #incompatible") curreff.incompatibilities.append(m.groups()[0]) continue if line.startswith("#noun"): m = re.match('#noun\\W+"(.*?)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #noun") curreff.nouns.append(m.groups()[0]) continue if line.startswith("#verb"): m = re.match('#verb\\W+"(.*?)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #noun") curreff.verbs.append(m.groups()[0]) continue if line.startswith("#req"): m = re.match( '#req2\\W+([0-9]*)[ \t]([<>=!]+)\\W+(.+)[ \t]+([<>=!]+)\\W*?([0-9]+)', line) if m is not None: cond = NameCond() cond.val2 = m.groups()[0] cond.op2 = m.groups()[1] cond.param = m.groups()[2] cond.op = m.groups()[3] cond.val = m.groups()[4] cond.text = "" curreff.reqs.append(cond) continue m = re.match('#req\\W+(.+)[ \t]+([<>&=!]+)\\W*?([0-9]+)', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #req") cond = NameCond() cond.param = m.groups()[0] cond.op = m.groups()[1] cond.val = m.groups()[2] cond.text = "" curreff.reqs.append(cond) continue if line.startswith("#dummymonstername"): m = re.match('#dummymonstername\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #dummymonstername") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): if path not in curreff.dummymonsternames: curreff.dummymonsternames[path] = [] curreff.dummymonsternames[path].append(m.groups()[1]) continue if line.startswith("#effectnumberforunits"): m = re.match('#effectnumberforunits\\W+(.*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #effectnumberforunits") curreff.effectnumberforunits.append(int(m.groups()[0])) continue if line.startswith("#selectunitmod"): m = re.match('#selectunitmod\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #selectunitmod") if curreff.selectunitmods is None: curreff.selectunitmods = [] curreff.selectunitmods.append(m.groups()[0]) continue if line.startswith("#end"): out = curreff parsingrawmodcode = True continue raise ParseError( f"{fp} line {lineno}: Unrecognised content: {line}") return out
def readMagicSiteFile(fp): "Read one file and return all the magic sites within." out = {} curreff = None with open(fp, "r") as f: for lineno, line in enumerate(f): line = line.strip() if line == "": continue if line.startswith("--"): continue if line.startswith("#newsite"): if curreff is not None: raise ParseError( f"{fp} line {lineno}: Unexpected #newsite (still parsing previous effect)" ) m = re.match("#newsite\W+\"(.*)\"\W*$", line) if m is None: raise ParseError( f"{fp} line {lineno}: Expected a site name, none was found" ) curreff = MagicSite.MagicSite() curreff.name = m.groups()[0] else: if curreff is None: raise ParseError( f"{fp} line {lineno}: Expected a #newsite line") sorted = False # Params to simply copy for simple in modifier_params_int: if fileparserutils.parsesimpleint(simple, line, curreff): sorted = True break if sorted: continue for simple in modifier_params_str: m = re.match(f"#{simple}" + "\\W+?\"(.*)\"\\W*", line) if m is not None: pval = m.groups()[0] setattr(curreff, simple, pval) sorted = True continue if sorted: continue for simple in modifier_params_float: m = re.match(f"#{simple}\W+?([-.0-9]*)\W*$", line) if m is not None: pval = float(m.groups()[0]) setattr(curreff, simple, pval) sorted = True continue if sorted: continue m = re.match(f'#allowedunitmod "(.*)"', line) if m is not None: pval = m.groups()[0] curreff.allowedunitmods.append(pval) sorted = True continue if line.startswith("#scaleparam"): m = re.match('#scaleparam\\W+"(.*)"\\W+?([0-9-.]*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #scaleparam") curreff.scaleparams[m.groups()[0]] = float(m.groups()[1]) continue if line.startswith("#name"): m = re.match('#name\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError(f"{fp} line {lineno}: bad #name") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): if path not in curreff.names: curreff.names[path] = [] curreff.names[path].append(m.groups()[1]) continue if line.startswith("#dummymonstername"): m = re.match('#dummymonstername\\W+(.*?)\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #dummymonstername") paths = fileparserutils.parsepathalias(m.groups()[0]) for path in utils.breakdownflagcomponents(paths): if path not in curreff.dummymonsternames: curreff.dummymonsternames[path] = [] curreff.dummymonsternames[path].append(m.groups()[1]) continue if line.startswith("#selectunitmod"): m = re.match('#selectunitmod\\W+"(.*)"', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #selectunitmod") if curreff.selectunitmods is None: curreff.selectunitmods = [] curreff.selectunitmods.append(m.groups()[0]) continue if line.startswith("#effectnumberforunits"): m = re.match('#effectnumberforunits\\W+(.*)', line) if m is None: raise ParseError( f"{fp} line {lineno}: bad #effectnumberforunits") curreff.effectnumberforunits.append(int(m.groups()[0])) continue if line.startswith("#end"): out[curreff.name] = curreff curreff = None continue raise ParseError( f"{fp} line {lineno}: Unrecognised content: {line}") return out