예제 #1
0
def _parse_spell(spell_source, default, spell_list):
    spell = copy.copy(default)
    m = re.match("(.*) \((.*)\)", spell_source)
    count = 1
    if m:
        spell["name"] = m.groups()[0]
        notes = [s.strip() for s in split(m.groups()[1])]
        while len(notes) > 0:
            note = notes.pop(0)
            if note.startswith("DC "):
                dc = note[3:]
                dc_notes = None
                if dc.find(";"):
                    parts = split(dc, char=";")
                    dc = parts.pop(0)
                    dc_notes = parts
                dc = int(dc)
                spell["dc"] = {"value": dc}
                if dc_notes:
                    spell["dc"]["notes"] = dc_notes
            elif note.isdigit():
                count = int(note)
            else:
                spell["notes"] = note
    else:
        spell["name"] = spell_source
    if spell["name"].endswith("D"):
        spell["name"] = spell["name"][:-1]
        spell["domain"] = True
    if spell["name"].endswith("M"):
        spell["name"] = spell["name"][:-1]
        spell["mythic"] = True
    for i in range(count):
        spell_list["spells"].append(spell)
예제 #2
0
def _parse_spell(spell_source, default, spell_list):
	spell = copy.copy(default)
	m = re.match("(.*) \((.*)\)", spell_source)
	count = 1
	if m:
		spell["name"] = m.groups()[0]
		notes = [s.strip() for s in split(m.groups()[1])]
		while len(notes) > 0:
			note = notes.pop(0)
			if note.startswith("DC "):
				dc = note[3:]
				dc_notes = None
				if dc.find(";"):
					parts = split(dc, char=";")
					dc = parts.pop(0)
					dc_notes = parts
				dc = int(dc)
				spell["dc"] = {"value": dc}
				if dc_notes:
					spell["dc"]["notes"] = dc_notes
			elif note.isdigit():
				count = int(note)
			else:
				spell["notes"] = note
	else:
		spell["name"] = spell_source
	if spell["name"].endswith("D"):
		spell["name"] = spell["name"][:-1]
		spell["domain"] = True
	if spell["name"].endswith("M"):
		spell["name"] = spell["name"][:-1]
		spell["mythic"] = True
	for i in range(count):
		spell_list["spells"].append(spell)
예제 #3
0
def _handle_saves(statblock, token, data):
	content = " ".join([l.strip() for l in data["lines"]])
	saves = statblock.setdefault("saves", {})
	parts = [s.strip() for s in split(content, char=";")]
	saves_source = [s.strip() for s in split(parts.pop(0))]
	modifiers = ";".join(parts)
	for save in saves_source:
		m = re.match("^(.*) ([-+]?\d+)$", save)
		if m:
			name, value = m.groups()
			name = name.lower()
			value = int(value)
			if name == "ref":
				name = "reflex"
			elif name == "fort":
				name = "fortitude"
			saves[name] = create("save", name=name, value=value)
			add_situational_modifiers(saves[name], modifiers)
			continue
		m = re.match("^(.*) ([-+]?\d+) \((.*)\)$", save)
		if m:
			name, value, specific_modifiers = m.groups()
			name = name.lower()
			value = int(value)
			if name == "ref":
				name = "reflex"
			elif name == "fort":
				name = "fortitude"
			saves[name] = create("save", name=name, value=int(m.groups()[1]))
			add_situational_modifiers(saves[name], modifiers)
			add_situational_modifiers(saves[name], specific_modifiers, value)
			continue
		raise Exception("Don't know how to parse saves: %s" % content)
예제 #4
0
def _handle_saves(statblock, token, data):
    content = " ".join([l.strip() for l in data["lines"]])
    saves = statblock.setdefault("saves", {})
    parts = [s.strip() for s in split(content, char=";")]
    saves_source = [s.strip() for s in split(parts.pop(0))]
    modifiers = ";".join(parts)
    for save in saves_source:
        m = re.match("^(.*) ([-+]?\d+)$", save)
        if m:
            name, value = m.groups()
            name = name.lower()
            value = int(value)
            if name == "ref":
                name = "reflex"
            elif name == "fort":
                name = "fortitude"
            saves[name] = create("save", name=name, value=value)
            add_situational_modifiers(saves[name], modifiers)
            continue
        m = re.match("^(.*) ([-+]?\d+) \((.*)\)$", save)
        if m:
            name, value, specific_modifiers = m.groups()
            name = name.lower()
            value = int(value)
            if name == "ref":
                name = "reflex"
            elif name == "fort":
                name = "fortitude"
            saves[name] = create("save", name=name, value=int(m.groups()[1]))
            add_situational_modifiers(saves[name], modifiers)
            add_situational_modifiers(saves[name], specific_modifiers, value)
            continue
        raise Exception("Don't know how to parse saves: %s" % content)
예제 #5
0
	def _handle_list_intern(statblock, token, data):
		lines = data['lines']
		content = " ".join([line.strip() for line in lines])
		fields = split(content, ";")
		if len(fields) > 1:
			raise Exception("; not yet supported in %s: %s" % (token, json.dumps(content)))
		parts = [create(object_type, name=part.strip()) for part in split(content)]
		name_token = token.lower().replace(" ", "_")
		statblock[name_token] = parts
예제 #6
0
def _handle_skills(statblock, token, data):
	lines = data['lines']
	content = " ".join([line.strip() for line in lines]).split(";")
	skills_line = content.pop(0)
	skills = {}
	for skill_line in split(skills_line):
		skill_line = skill_line.strip()
		name = None
		bonus = None
		m = re.match("^([A-Za-z ]*) ([+-]?[0-9]+)$", skill_line)
		if m:
			name = m.groups()[0]
			skill_name = name.lower().replace(" ", "_")
			bonus = int(m.groups()[1])
			skills[skill_name] = create("skill", value=bonus, name=name)
			continue
		m = re.match("^([A-Za-z ]*) \((.*?)\) ([+-]?[0-9]+)$", skill_line)
		if m:
			name = m.groups()[0]
			skill_name = name.lower().replace(" ", "_")
			subtype = m.groups()[1]
			bonus = int(m.groups()[2])
			subtype = subtype.replace(", and ", ", ").replace(" or ", ", ")
			for st in subtype.split(","):
				skills["%s_%s" % (skill_name, st.strip().replace(" ", "_"))] = create(
					"skill", value=bonus, name=name, subskill=st.strip())
			continue
		m = re.match("^([A-Za-z ]*) ([+-]?[0-9]+) \((.*?)\)$", skill_line)
		if m:
			name = m.groups()[0]
			skill_name = name.lower().replace(" ", "_")
			bonus = int(m.groups()[1])
			skill = create("skill", value=bonus, name=name)
			skills[skill_name] = skill
			modifiers = m.groups()[2]
			add_situational_modifiers(skill, modifiers, bonus)
			continue

	for line in content:
		if line.strip().startswith("Racial Modifiers "):
			line = line.replace("Racial Modifiers ", "")
			bonuses = split(line)
			for bonus in bonuses:
				m = re.match("([+-]?[0-9]+) (.*)", bonus.strip())
				if m:
					b = int(m.groups()[0])
					skill_name = m.groups()[1]
					skill = skills.setdefault(skill_name, create("skill", name=name))
					add_modifier(skill, create_modifier("racial", value=b))
				else:
					raise Exception("Can't parse: %s" % line)
		else:
			raise Exception("Unknown skill subsection: %s" % line)
	statblock["skills"] = skills
예제 #7
0
def _handle_weapons(statblock, token, data):
    content = " ".join([d.strip() for d in data["lines"]])
    section = statblock.setdefault(token, [])
    if content.find(" or "):
        content.replace(" or ", "`")
    for weapon_set_source in split(content, char="`"):
        weapon_set_source = weapon_set_source.replace("`", " or ")
        weapon_set = []
        section.append(weapon_set)
        for weapon in split(weapon_set_source):
            weapon = weapon.strip()
            m = re.match("(\d+) (.*) ([0-9/+-]+) \((.*)\)", weapon)
            if m:
                count = int(m.groups()[0])
                name = m.groups()[1]
                if name.endswith("s"):
                    name = name
                to_hit = m.groups()[2]
                damage = m.groups()[3]
                w = _generate_weapon(name, to_hit, damage)
                w["count"] = count
                weapon_set.append(w)
                continue
            m = re.match("(.*) ([0-9/+-]+) \((.*)\)", weapon)
            if m:
                name = m.groups()[0]
                to_hit = m.groups()[1]
                damage = m.groups()[2]
                w = _generate_weapon(name, to_hit, damage)
                weapon_set.append(w)
                continue
            m = re.match("(.*) ([0-9/+-]+)", weapon)
            if m:
                name = m.groups()[0]
                to_hit = m.groups()[1]
                w = _generate_weapon(name, to_hit)
                weapon_set.append(w)
                continue
            m = re.match("(.*) ([0-9/+-]+)", weapon)
            if m:
                name = m.groups()[0]
                to_hit = m.groups()[1]
                w = _generate_weapon(name, to_hit)
                weapon_set.append(w)
                continue
            m = re.match("(.*) \((.*)\)", weapon)
            if m:
                name = m.groups()[0]
                damage = m.groups()[1]
                w = _generate_weapon(name, "", damage)
                weapon_set.append(w)
                continue
            raise Exception("Don't know how to parse weapon: %s" %
                            json.dumps(weapon))
예제 #8
0
 def _handle_list_intern(statblock, token, data):
     lines = data['lines']
     content = " ".join([line.strip() for line in lines])
     fields = split(content, ";")
     if len(fields) > 1:
         raise Exception("; not yet supported in %s: %s" %
                         (token, json.dumps(content)))
     parts = [
         create(object_type, name=part.strip()) for part in split(content)
     ]
     name_token = token.lower().replace(" ", "_")
     statblock[name_token] = parts
예제 #9
0
def _handle_weapons(statblock, token, data):
	content = " ".join([d.strip() for d in data["lines"]])
	section = statblock.setdefault(token, [])
	if content.find(" or "):
		content.replace(" or ", "`")
	for weapon_set_source in split(content, char="`"):
		weapon_set_source = weapon_set_source.replace("`", " or ")
		weapon_set = []
		section.append(weapon_set)
		for weapon in split(weapon_set_source):
			weapon = weapon.strip()
			m = re.match("(\d+) (.*) ([0-9/+-]+) \((.*)\)", weapon)
			if m:
				count = int(m.groups()[0])
				name = m.groups()[1]
				if name.endswith("s"):
					name = name
				to_hit = m.groups()[2]
				damage = m.groups()[3]
				w = _generate_weapon(name, to_hit, damage)
				w["count"] = count
				weapon_set.append(w)
				continue
			m = re.match("(.*) ([0-9/+-]+) \((.*)\)", weapon)
			if m:
				name = m.groups()[0]
				to_hit = m.groups()[1]
				damage = m.groups()[2]
				w = _generate_weapon(name, to_hit, damage)
				weapon_set.append(w)
				continue
			m = re.match("(.*) ([0-9/+-]+)", weapon)
			if m:
				name = m.groups()[0]
				to_hit = m.groups()[1]
				w = _generate_weapon(name, to_hit)
				weapon_set.append(w)
				continue
			m = re.match("(.*) ([0-9/+-]+)", weapon)
			if m:
				name = m.groups()[0]
				to_hit = m.groups()[1]
				w = _generate_weapon(name, to_hit)
				weapon_set.append(w)
				continue
			m = re.match("(.*) \((.*)\)", weapon)
			if m:
				name = m.groups()[0]
				damage = m.groups()[1]
				w = _generate_weapon(name, "", damage)
				weapon_set.append(w)
				continue
			raise Exception("Don't know how to parse weapon: %s" % json.dumps(weapon))
예제 #10
0
def _handle_languages(statblock, token, data):
	lines = data['lines']
	content = " ".join([line.strip() for line in lines])
	fields = split(content, ";")
	languages = split(fields[0])
	final = []
	for language in languages:
		final.append(create("language", name=language.strip()))
	if len(fields) > 1:
		others = split(fields[1])
		for other in others:
			final.append(create("language", "other", name=other.strip()))
	elif len(fields) > 2:
		raise Exception("I don't know how to handle this language list: %s" % json.dumps(content))
	statblock["languages"] = final
예제 #11
0
def _handle_cl(section, lines):
    line = lines.pop(0)
    m = re.match("\((CL .*?)\)", line)
    if m:
        cl = m.groups()[0]
        pieces = split(cl, char=";")
        for piece in pieces:
            piece = piece.strip()
            m = re.match("CL (\d+)[snrt][tdh]", piece)
            if m:
                section["caster_level"] = create("caster_level",
                                                 value=int(m.groups()[0]))
                continue
            m = re.match("(\d+)% spell failure", piece)
            if m:
                section["spell_failure"] = create("spell_failure",
                                                  value=int(m.groups()[0]))
                continue
            m = re.match("concentration ([+-]?\d+)", piece)
            if m:
                section["concentration"] = create("concentration",
                                                  value=int(m.groups()[0]))
                continue
            section["notes"] = line
        parts = line.split(")")
        parts.pop(0)
        line = ")".join(parts).strip()
        if line == "":
            return lines
        else:
            lines.insert(0, line)
            return lines
    raise Exception("Spell block has unexpected format: %s" % line)
예제 #12
0
def _handle_spell_notes(section, lines):
    retlines = []
    for line in lines:
        append = True
        for s in [
                "Thassilonian Specialization", "Thassilonian Specialist",
                "Opposition Schools", "Prohibited Schools ", "D ", "Domain ",
                "Domains ", "Patron ", "Bloodline ", "Mystery ", "M "
        ]:
            if line.startswith(s):
                if s not in ["D ", "M "]:
                    data = line[len(s):].strip()
                    key = s.lower().strip()
                    if data.find(",") > -1:
                        data = [d.strip() for d in split(data)]
                    if s == "Domain ":
                        key = "domains"
                        data = [data]
                    if s == "Thassilonian Specialist":
                        key = "thassilonian specialization"
                    section[key] = data
                append = False
        if append:
            retlines.append(line)
    return retlines
예제 #13
0
def _handle_attack(statblock, token, data):
	lines = data['lines']
	content = " ".join([line.strip() for line in lines])
	fields = [field.strip() for field in split(content, char=";")]
	for field in fields:
		m = re.match("(.*?) ([+-]?[0-9]+) \((.*?)\)", field)
		if m:
			name = m.groups()[0]
			name, subtype, abbrev = _get_attack_fields(name)
			bonus = int(m.groups()[1])
			modifiers = m.groups()[2]
			section = create(
				"attack", subtype, name=name, value=bonus, abbrev=abbrev)
			add_situational_modifiers(section, modifiers, bonus)
			statblock[name] = section
			continue
		m = re.match("(.*?) ([+-]?[0-9]+)", field)
		if m:
			name = m.groups()[0]
			name, subtype, abbrev = _get_attack_fields(name)
			bonus = int(m.groups()[1])
			statblock[name] = create(
				"attack", subtype, name=name, value=bonus, abbrev=abbrev)
		m = re.match("(.*?) -", field)
		if m:
			name = m.groups()[0]
			name, subtype, abbrev = _get_attack_fields(name)
			statblock[name] = create(
				"attack", subtype, name=name, value=None, abbrev=abbrev)
예제 #14
0
def _handle_cl(section, lines):
	line = lines.pop(0)
	m = re.match("\((CL .*?)\)", line)
	if m:
		cl = m.groups()[0]
		pieces = split(cl, char=";")
		for piece in pieces:
			piece = piece.strip()
			m = re.match("CL (\d+)[snrt][tdh]", piece)
			if m:
				section["caster_level"] = create(
					"caster_level", value=int(m.groups()[0]))
				continue
			m = re.match("(\d+)% spell failure", piece)
			if m:
				section["spell_failure"] = create(
					"spell_failure", value=int(m.groups()[0]))
				continue
			m = re.match("concentration ([+-]?\d+)", piece)
			if m:
				section["concentration"] = create(
					"concentration", value=int(m.groups()[0]))
				continue
			section["notes"] = line
		parts = line.split(")")
		parts.pop(0)
		line = ")".join(parts).strip()
		if line == "":
			return lines
		else:
			lines.insert(0, line)
			return lines
	raise Exception("Spell block has unexpected format: %s" % line)
예제 #15
0
def _handle_gear(statblock, token, data):
	lines = data['lines']
	content = " ".join([line.strip() for line in lines])
	gear = statblock.setdefault("gear", {})
	items = split(content)
	subgear = gear.setdefault(token, [])
	for item in items:
		subgear.append(create("gear", name=item.strip()))
예제 #16
0
def _split_spell_fields(lines):
	retlines = []
	for line in lines:
		if line.find(";") > -1:
			parts = split(line, char=";")
			for part in parts:
				retlines.append(part.strip())
		else:
			retlines.append(line)
	return retlines
예제 #17
0
def _split_spell_fields(lines):
    retlines = []
    for line in lines:
        if line.find(";") > -1:
            parts = split(line, char=";")
            for part in parts:
                retlines.append(part.strip())
        else:
            retlines.append(line)
    return retlines
예제 #18
0
def _handle_ac(statblock, token, data):
    content = " ".join([l.strip() for l in data["lines"]])
    parts = split(content, char=";")
    ac = statblock.setdefault("ac", {})
    ac_part = parts.pop(0)
    try:
        _handle_ac_components(ac, ac_part)
    except Exception, e:
        sys.stderr.write("%s\n" % json.dumps(content, indent=2))
        raise e
예제 #19
0
def _handle_ac(statblock, token, data):
	content = " ".join([l.strip() for l in data["lines"]])
	parts = split(content, char=";")
	ac = statblock.setdefault("ac", {})
	ac_part = parts.pop(0)
	try:
		_handle_ac_components(ac, ac_part)
	except Exception, e:
		sys.stderr.write("%s\n" % json.dumps(content, indent=2))
		raise e
예제 #20
0
def _handle_defensive_abilities(statblock, data):
	abilities = [s.strip() for s in split(data[20:])]
	da_s = statblock.setdefault("defensive abilities", {})
	for ability in abilities:
		m = re.match("^(.*) ([-+]?\d+)$", ability)
		if m:
			name = m.groups()[0]
			bonus = int(m.groups()[1])
			da_s["name"] = create("defensive_ability", name=name, value=bonus)
		else:
			da_s["name"] = create("defensive_ability", name=ability)
예제 #21
0
def _handle_defensive_abilities(statblock, data):
    abilities = [s.strip() for s in split(data[20:])]
    da_s = statblock.setdefault("defensive abilities", {})
    for ability in abilities:
        m = re.match("^(.*) ([-+]?\d+)$", ability)
        if m:
            name = m.groups()[0]
            bonus = int(m.groups()[1])
            da_s["name"] = create("defensive_ability", name=name, value=bonus)
        else:
            da_s["name"] = create("defensive_ability", name=ability)
예제 #22
0
def _handle_senses(statblock, parts):
	retlines = []
	while len(parts) > 0:
		part = parts.pop()
		if part.strip().startswith("Senses "):
			content = part[7:]
			sections = [p.strip() for p in split(content)]
			statblock["senses"] = [create("sense", name=s) for s in sections]
		else:
			retlines.append(part)
	return retlines
예제 #23
0
def add_situational_modifiers(statblock, modifiers, bonus=0):
	for modifier in split(modifiers):
		m = re.match("([+-]?[0-9]+) (.*)", modifier.strip())
		if m:
			value = int(m.groups()[0]) - bonus
			situation = m.groups()[1]
			add_modifier(statblock, create_modifier(
				subtype="situational", value=value, situation=situation))
		else:
			add_modifier(statblock, create_modifier(
				subtype="situational", situation=modifier))
예제 #24
0
def _handle_senses(statblock, parts):
    retlines = []
    while len(parts) > 0:
        part = parts.pop()
        if part.strip().startswith("Senses "):
            content = part[7:]
            sections = [p.strip() for p in split(content)]
            statblock["senses"] = [create("sense", name=s) for s in sections]
        else:
            retlines.append(part)
    return retlines
예제 #25
0
def _handle_hp(statblock, token, data):
	content = " ".join([l.strip() for l in data["lines"]])
	parts = [s.strip() for s in split(content, char=";")]
	hp_source = parts.pop(0)
	hp = statblock.setdefault("hit_points", create("hit_points"))
	hp_source = hp_source.replace(" each", "")
	m = re.match("(\d+) \((.*)\)", hp_source)
	if m:
		hit_points, hit_dice = m.groups()
		hp["value"] = int(hit_points)
		m = re.match("(\d+) HD; ([0-9d+]+)([-+]\d+)", hit_dice)
		if m:
			hd, dice, plus = m.groups()
			hp["hit_dice"] = create("hit_dice", value=int(hd))
			hp["dice"] = dice
			hp["plus"] = create("hp_plus", value=int(plus))
		else:
			m = re.match("([0-9]+)d([0-9]+)([-+]\d+)", hit_dice)
			if m:
				count, d_type, plus = m.groups()
				hp["hit_dice"] = create("hit_dice", value=int(count))
				hp["dice"] = "%sd%s" % (count, d_type)
				hp["plus"] = create("hp_plus", value=int(plus))
			else:
				m = re.match("([0-9]+)d([0-9]+)", hit_dice)
				if m:
					count, d_type = m.groups()
					hp["hit_dice"] = create("hit_dice", value=int(count))
					hp["dice"] = "%sd%s" % (count, d_type)
				else:
					raise Exception(
						"Don't know how to parse hit dice: %s" % json.dumps(content))
	else:
		raise Exception(
			"Don't know how to parse hp: %s" % json.dumps(content))
	if len(parts) > 0:
		healing = [h.strip() for h in split(parts.pop(0))]
		_handle_healing(hp, healing)
	if len(parts) > 0:
		raise Exception(
			"Don't know how to parse hp line: %s" % json.dumps(content))
예제 #26
0
def _parse_ac_modifiers(pieces):
    parts = [p.strip() for p in split(pieces)]
    results = {}
    for part in parts:
        m = re.match("^([-+]?\d+) (.*)", part)
        if m:
            bonus = int(m.groups()[0])
            name = m.groups()[1]
            results[name] = bonus
            continue
        raise Exception("Don't know how to parse: %s" % pieces)
    return results
예제 #27
0
def _parse_ac_modifiers(pieces):
	parts = [p.strip() for p in split(pieces)]
	results = {}
	for part in parts:
		m = re.match("^([-+]?\d+) (.*)", part)
		if m:
			bonus = int(m.groups()[0])
			name = m.groups()[1]
			results[name] = bonus
			continue
		raise Exception("Don't know how to parse: %s" % pieces)
	return results
예제 #28
0
def _handle_hp(statblock, token, data):
    content = " ".join([l.strip() for l in data["lines"]])
    parts = [s.strip() for s in split(content, char=";")]
    hp_source = parts.pop(0)
    hp = statblock.setdefault("hit_points", create("hit_points"))
    hp_source = hp_source.replace(" each", "")
    m = re.match("(\d+) \((.*)\)", hp_source)
    if m:
        hit_points, hit_dice = m.groups()
        hp["value"] = int(hit_points)
        m = re.match("(\d+) HD; ([0-9d+]+)([-+]\d+)", hit_dice)
        if m:
            hd, dice, plus = m.groups()
            hp["hit_dice"] = create("hit_dice", value=int(hd))
            hp["dice"] = dice
            hp["plus"] = create("hp_plus", value=int(plus))
        else:
            m = re.match("([0-9]+)d([0-9]+)([-+]\d+)", hit_dice)
            if m:
                count, d_type, plus = m.groups()
                hp["hit_dice"] = create("hit_dice", value=int(count))
                hp["dice"] = "%sd%s" % (count, d_type)
                hp["plus"] = create("hp_plus", value=int(plus))
            else:
                m = re.match("([0-9]+)d([0-9]+)", hit_dice)
                if m:
                    count, d_type = m.groups()
                    hp["hit_dice"] = create("hit_dice", value=int(count))
                    hp["dice"] = "%sd%s" % (count, d_type)
                else:
                    raise Exception("Don't know how to parse hit dice: %s" %
                                    json.dumps(content))
    else:
        raise Exception("Don't know how to parse hp: %s" % json.dumps(content))
    if len(parts) > 0:
        healing = [h.strip() for h in split(parts.pop(0))]
        _handle_healing(hp, healing)
    if len(parts) > 0:
        raise Exception("Don't know how to parse hp line: %s" %
                        json.dumps(content))
예제 #29
0
def _handle_space(statblock, token, data):
    content = " ".join([d.strip() for d in data["lines"]])
    space = content
    if content.find(";"):
        parts = split(space, char=";")
        space = parts.pop(0)
        for part in parts:
            part = part.strip()
            if part.startswith("Reach "):
                statblock["reach"] = part[6:]
            else:
                raise Exception("Space token not recognized: %" % content)
    statblock["space"] = space
예제 #30
0
def _handle_space(statblock, token, data):
	content = " ".join([d.strip() for d in data["lines"]])
	space = content
	if content.find(";"):
		parts = split(space, char=";")
		space = parts.pop(0)
		for part in parts:
			part = part.strip()
			if part.startswith("Reach "):
				statblock["reach"] = part[6:]
			else:
				raise Exception("Space token not recognized: %" % content)
	statblock["space"] = space
예제 #31
0
def add_situational_modifiers(statblock, modifiers, bonus=0):
    for modifier in split(modifiers):
        m = re.match("([+-]?[0-9]+) (.*)", modifier.strip())
        if m:
            value = int(m.groups()[0]) - bonus
            situation = m.groups()[1]
            add_modifier(
                statblock,
                create_modifier(subtype="situational",
                                value=value,
                                situation=situation))
        else:
            add_modifier(
                statblock,
                create_modifier(subtype="situational", situation=modifier))
예제 #32
0
def parse_senses(lines):
	retlines = []
	for statblock in yield_statblocks(lines, retlines):
		source = statblock.setdefault("source", {})
		basics = statblock.setdefault("basics", {})
		senses_source = source.setdefault("senses", {})
		content = " ".join([sense.strip() for sense in senses_source.get("lines", [])])
		if content != "":
			parts = [part.strip() for part in split(content, ";")]
			parts = _handle_initiative(basics, parts)
			parts = _handle_senses(basics, parts)
			parts = _handle_perception(statblock, parts)
			if len(parts) > 0:
				raise Exception("Senses line contains unknown parts: %s" % content)
		del source["senses"]
	return retlines
예제 #33
0
def _parse_alignment(statblock, data):
	content = " ".join([l.strip() for l in data["lines"]])
	if content.find("(") > -1:
		content, subtypes = content.split("(")
		subtypes = subtypes[:-1]
		statblock["creature_subtypes"] = [s.strip() for s in split(subtypes)]
	parts = content.split()
	align = parts.pop(0)
	if not validate_alignment(align):
		raise Exception("Don't recognize alignment: %s" % align)
	statblock["alignment"] = create("alignment", value=align)
	statblock["size"] = create_size(parts.pop(0))
	creature_type = " ".join(parts)
	if not validate_creature_type(creature_type):
		raise Exception("Creature Type unrecognized: %s" % creature_type)
	statblock["creature_type"] = creature_type
예제 #34
0
def _add_spells(line, section, level=None, freq=None, freq_period=None):
	parts = line.split("-")
	parts.pop(0)
	spells = [s.strip() for s in split("-".join(parts))]
	spell = create("spell")
	spell_list = create("spell_list", spells=[])
	if level != None:
		spell_list["level"] = level
		spell["level"] = level
	if freq:
		spell_list["frequency"] = freq
	if freq_period:
		spell_list["frequency period"] = freq_period
	for spell_source in spells:
		_parse_spell(spell_source, spell, spell_list)
	section["spell_lists"].append(spell_list)
예제 #35
0
def _handle_defenses(statblock, token, data):
	content = " ".join([l.strip() for l in data["lines"]])
	chunks = [s.strip() for s in split(content, char=";")]
	for da in chunks:
		if da.startswith("Defensive Abilities "):
			_handle_defensive_abilities(statblock, da)
		elif da.startswith("DR "):
			_handle_dr(statblock, da)
		elif da.startswith("Immune "):
			handle_list("immune")(statblock, "immune", {"lines": [da[7:]]})
		elif da.startswith("Resist "):
			_handle_resist(statblock, da)
		elif da.startswith("SR "):
			_handle_sr(statblock, da)
		else:
			raise Exception("I don't recognize this defense: %s" % json.dumps(da))
예제 #36
0
def _parse_armor(ac, line):
	parts = [l.strip() for l in split(line)]
	ac["base"] = {
		"value": int(parts.pop(0)), "name": "base", "type": "armor_class"}
	while len(parts) > 0:
		p = parts.pop()
		if p.startswith("touch"):
			ac["touch"] = {
				"value": int(p.replace("touch", "")),
				"name": "touch", "type": "armor_class"}
		elif p.startswith("flat-footed"):
			ac["flat-footed"] = {
				"value": int(p.replace("flat-footed", "")),
				"name": "flat-footed", "type": "armor_class"}
		else:
			raise Exception("I don't know how to parse armor: %s" % line)
예제 #37
0
def _add_spells(line, section, level=None, freq=None, freq_period=None):
    parts = line.split("-")
    parts.pop(0)
    spells = [s.strip() for s in split("-".join(parts))]
    spell = create("spell")
    spell_list = create("spell_list", spells=[])
    if level != None:
        spell_list["level"] = level
        spell["level"] = level
    if freq:
        spell_list["frequency"] = freq
    if freq_period:
        spell_list["frequency period"] = freq_period
    for spell_source in spells:
        _parse_spell(spell_source, spell, spell_list)
    section["spell_lists"].append(spell_list)
예제 #38
0
def _parse_alignment(statblock, data):
    content = " ".join([l.strip() for l in data["lines"]])
    if content.find("(") > -1:
        content, subtypes = content.split("(")
        subtypes = subtypes[:-1]
        statblock["creature_subtypes"] = [s.strip() for s in split(subtypes)]
    parts = content.split()
    align = parts.pop(0)
    if not validate_alignment(align):
        raise Exception("Don't recognize alignment: %s" % align)
    statblock["alignment"] = create("alignment", value=align)
    statblock["size"] = create_size(parts.pop(0))
    creature_type = " ".join(parts)
    if not validate_creature_type(creature_type):
        raise Exception("Creature Type unrecognized: %s" % creature_type)
    statblock["creature_type"] = creature_type
예제 #39
0
def _handle_defenses(statblock, token, data):
    content = " ".join([l.strip() for l in data["lines"]])
    chunks = [s.strip() for s in split(content, char=";")]
    for da in chunks:
        if da.startswith("Defensive Abilities "):
            _handle_defensive_abilities(statblock, da)
        elif da.startswith("DR "):
            _handle_dr(statblock, da)
        elif da.startswith("Immune "):
            handle_list("immune")(statblock, "immune", {"lines": [da[7:]]})
        elif da.startswith("Resist "):
            _handle_resist(statblock, da)
        elif da.startswith("SR "):
            _handle_sr(statblock, da)
        else:
            raise Exception("I don't recognize this defense: %s" %
                            json.dumps(da))
예제 #40
0
def _handle_resist(statblock, data):
    resists = [s.strip() for s in split(data[7:])]
    for resist in resists:
        m = re.match("(.*) (\d+) \((.*)\)", resist)
        if m:
            name, value, notes = m.groups()
            resist_section = statblock.setdefault("resistances", [])
            resist_section.append(
                create("resistance", name=name, value=int(value), notes=notes))
            continue
        m = re.match("(.*) (\d+)", resist)
        if m:
            name, value = m.groups()
            resist_section = statblock.setdefault("resistances", [])
            resist_section.append(
                create("resistance", name=name, value=int(value)))
            continue
        raise Exception("Don't know how to parse resist: %s" % data)
예제 #41
0
def _handle_resist(statblock, data):
	resists = [s.strip() for s in split(data[7:])]
	for resist in resists:
		m = re.match("(.*) (\d+) \((.*)\)", resist)
		if m:
			name, value, notes = m.groups()
			resist_section = statblock.setdefault("resistances", [])
			resist_section.append(create(
				"resistance", name=name, value=int(value), notes=notes))
			continue
		m = re.match("(.*) (\d+)", resist)
		if m:
			name, value = m.groups()
			resist_section = statblock.setdefault("resistances", [])
			resist_section.append(create(
				"resistance", name=name, value=int(value)))
			continue
		raise Exception("Don't know how to parse resist: %s" % data)
예제 #42
0
def parse_senses(lines):
    retlines = []
    for statblock in yield_statblocks(lines, retlines):
        source = statblock.setdefault("source", {})
        basics = statblock.setdefault("basics", {})
        senses_source = source.setdefault("senses", {})
        content = " ".join(
            [sense.strip() for sense in senses_source.get("lines", [])])
        if content != "":
            parts = [part.strip() for part in split(content, ";")]
            parts = _handle_initiative(basics, parts)
            parts = _handle_senses(basics, parts)
            parts = _handle_perception(statblock, parts)
            if len(parts) > 0:
                raise Exception("Senses line contains unknown parts: %s" %
                                content)
        del source["senses"]
    return retlines
예제 #43
0
def _handle_sr(statblock, data):
	sr_s = [s.strip() for s in split(data[3:])]
	for sr in sr_s:
		m = re.match("(\d+) \((.*)\)", sr)
		if m:
			value, notes = m.groups()
			sr_section = statblock.setdefault("spell_resistances", [])
			sr_section.append(create(
				"spell_resistance", value=int(value), notes=notes))
			continue
		m = re.match("(\d+) (.*)", sr)
		if m:
			value, notes = m.groups()
			sr_section = statblock.setdefault("spell_resistances", [])
			sr_section.append(create(
				"spell_resistance", value=int(value), notes=notes))
			continue
		resist_section = statblock.setdefault("spell_resistances", [])
		resist_section.append(create("spell_resistance", value=int(sr)))
예제 #44
0
def _handle_sr(statblock, data):
    sr_s = [s.strip() for s in split(data[3:])]
    for sr in sr_s:
        m = re.match("(\d+) \((.*)\)", sr)
        if m:
            value, notes = m.groups()
            sr_section = statblock.setdefault("spell_resistances", [])
            sr_section.append(
                create("spell_resistance", value=int(value), notes=notes))
            continue
        m = re.match("(\d+) (.*)", sr)
        if m:
            value, notes = m.groups()
            sr_section = statblock.setdefault("spell_resistances", [])
            sr_section.append(
                create("spell_resistance", value=int(value), notes=notes))
            continue
        resist_section = statblock.setdefault("spell_resistances", [])
        resist_section.append(create("spell_resistance", value=int(sr)))
예제 #45
0
def _parse_classes(creature, parts):
	class_parts = []
	while parts[-1][0].isdigit():
		class_parts.insert(0, parts.pop())
	if len(class_parts) > 0:
		class_parts.insert(0, parts.pop())
	if parts[-1] == "of":
		class_parts.insert(0, parts.pop())
		class_parts.insert(0, parts.pop())
	class_source = " ".join(class_parts)
	classes = [s.strip() for s in split(class_source, char="/")]
	cc = None
	for pc_class in classes:
		m = re.match("^(.*) (\d+)$", pc_class)
		if m:
			name, value = m.groups()
			cc = creature.setdefault("classes", [])
			cc.append(create("class", name=name, value=int(value)))
		else:
			raise Exception("I don't recognize class: %s" % pc_class)
예제 #46
0
def _parse_classes(creature, parts):
    class_parts = []
    while parts[-1][0].isdigit():
        class_parts.insert(0, parts.pop())
    if len(class_parts) > 0:
        class_parts.insert(0, parts.pop())
    if parts[-1] == "of":
        class_parts.insert(0, parts.pop())
        class_parts.insert(0, parts.pop())
    class_source = " ".join(class_parts)
    classes = [s.strip() for s in split(class_source, char="/")]
    cc = None
    for pc_class in classes:
        m = re.match("^(.*) (\d+)$", pc_class)
        if m:
            name, value = m.groups()
            cc = creature.setdefault("classes", [])
            cc.append(create("class", name=name, value=int(value)))
        else:
            raise Exception("I don't recognize class: %s" % pc_class)
예제 #47
0
def _handle_spell_notes(section, lines):
	retlines = []
	for line in lines:
		append = True
		for s in ["Thassilonian Specialization", "Thassilonian Specialist", "Opposition Schools", "Prohibited Schools ", "D ", "Domain ", "Domains ", "Patron ", "Bloodline ", "Mystery ", "M "]:
			if line.startswith(s):
				if s not in ["D ", "M "]:
					data = line[len(s):].strip()
					key = s.lower().strip()
					if data.find(",") > -1:
						data = [d.strip() for d in split(data)]
					if s == "Domain ":
						key = "domains"
						data = [data]
					if s == "Thassilonian Specialist":
						key = "thassilonian specialization"
					section[key] = data
				append = False
		if append:
			retlines.append(line)
	return retlines
예제 #48
0
def _parse_armor(ac, line):
    parts = [l.strip() for l in split(line)]
    ac["base"] = {
        "value": int(parts.pop(0)),
        "name": "base",
        "type": "armor_class"
    }
    while len(parts) > 0:
        p = parts.pop()
        if p.startswith("touch"):
            ac["touch"] = {
                "value": int(p.replace("touch", "")),
                "name": "touch",
                "type": "armor_class"
            }
        elif p.startswith("flat-footed"):
            ac["flat-footed"] = {
                "value": int(p.replace("flat-footed", "")),
                "name": "flat-footed",
                "type": "armor_class"
            }
        else:
            raise Exception("I don't know how to parse armor: %s" % line)
예제 #49
0
def _handle_attributes(statblock, token, data):
	lines = data['lines']
	content = " ".join([line.strip() for line in lines])
	for field in split(content):
		field = field.strip()
		m = re.match("^([A-Za-z]+) ([-0-9]+)$", field)
		if m:
			stat = m.groups()[0]
			stat, abbrev = _get_attribute_name(stat)
			value = m.groups()[1]
			if value == "-":
				value = None
			else:
				value = int(value)
			mod = "%s_mod" % abbrev
			mod_value = None
			if value:
				mod_value = int(value - 10) / 2
			statblock[abbrev] = create(
				"attribute", name=stat, value=value, abbrev=abbrev, mod=create(
					"attribute_modifier", name=mod, value=mod_value))
		else:
			raise Exception("Cannot parse Attributes: %s" % json.dumps(content))
예제 #50
0
def _handle_speed(statblock, token, data):
    content = " ".join([d.strip() for d in data["lines"]])
    statblock["speed"] = [
        create("movement", name=c.strip()) for c in split(content)
    ]
예제 #51
0
def _handle_speed(statblock, token, data):
	content = " ".join([d.strip() for d in data["lines"]])
	statblock["speed"] = [create("movement", name=c.strip()) for c in split(content)]