示例#1
0
def read_vanilla():
    nationalunits = {}
    _read_vanilla_unit_nation_map_file(
        "data/VanillaLeaderMaps/fort_leader_types_by_nation.csv",
        nationalunits)
    _read_vanilla_unit_nation_map_file(
        "data/VanillaLeaderMaps/coast_leader_types_by_nation.csv",
        nationalunits)
    _read_vanilla_unit_nation_map_file(
        "data/VanillaLeaderMaps/nonfort_leader_types_by_nation.csv",
        nationalunits)

    _read_vanilla_cap_only_site_recruits(nationalunits)

    # Get their info
    unitdata = {}
    with open("data/BaseU.csv", "r") as datacsv:
        reader = csv.DictReader(datacsv, delimiter="\t")
        for line in reader:
            unitdata[int(line["id"])] = copy.copy(line)

    for unitid in unitdata:
        dataline = unitdata[unitid]
        mage: NationalMage = NationalMage()
        for index, key in enumerate(["F", "A", "W", "E", "S", "D", "N", "B"]):
            if dataline[key] != "":
                mage.add_magic_path(2**index, int(dataline[key]))

        for n in range(1, 7):
            if dataline[f"mask{n}"] == "":
                break
            mask = int(dataline[f"mask{n}"]) >> 7
            chance = int(dataline[f"rand{n}"])
            instances = int(dataline[f"nbr{n}"])
            link = int(dataline[f"link{n}"])
            for i in range(instances):
                mage.add_magic_random(
                    MagePathRandom(chance=chance, link=link, paths=mask))

        mage.name = dataline[f"name"]

        if mage.is_mage():
            vanillamages[unitid] = mage

    for nationid, units in nationalunits.items():
        if nationid not in nations:
            nations[nationid] = Nation(nationid)
        for unitid in units:
            if unitid in vanillamages:
                mage = vanillamages[unitid]
                if mage.is_mage():
                    nations[nationid].add_mage(mage)
示例#2
0
def _roll_path_for_national_spell(nation: Nation) -> int:
    pathweights = nation.get_pathweights()
    totalweights = 0
    for i, weight in pathweights.items():
        totalweights += weight
    if totalweights == 0:
        raise ValueError(f"Failed calculating national spell path weights.\n"
                         f"Nation: {nation.to_text()}\n"
                         f"Weights: {pprint.pformat(pathweights)}\n"
                         f"Total Weight: {totalweights}")
    initialroll = roll = random.randrange(0, totalweights, 1)
    for path, weight in pathweights.items():
        if roll < weight:
            DebugLogger.debuglog(f"Selected path {utils.pathstotext(path)} from weights {pathweights.items()}, "
                               f"rolled {initialroll}",
                                 debugkeys.NATIONALSPELLGENERATION,
                                 debugkeys.NATIONALSPELLGENERATIONWEIGHTING)
            return path
        roll -= weight
    raise ValueError(f"Attempted and failed to roll for weighted path\n  Rolled {initialroll}\n  Total weight: "
                     f"{totalweights}\n  Weights: {pprint.pformat(pathweights)}\n")
示例#3
0
def read_mods(modstring):
    global monsterids, weaponids, spellids, eventcodes, montagids, siteids, enchantids, vanillamages
    mods = modstring.strip().split(",")
    monsterids = [3499]
    weaponids = [799]
    siteids = [1499]
    spellids = [1299]
    eventcodes = [-299]
    montagids = [1000]
    enchantids = [500]
    for mod in mods:
        mod = mod.strip()
        if mod == "":
            continue
        with open(mod, "r", encoding="u8") as f:
            currentsite: Union[Site, None] = None
            sites: Dict[int, Site] = {}
            sitenames: Dict[str, int] = {}
            # TODO Sites that are defined after nations with them as startsite

            nationstartsites: Dict[Nation, List[Union[int, str]]] = {}
            sitecommanders: Dict[Site, List[Union[int, str]]] = {}

            currentnation: Union[Nation, None] = None
            currentunit: Union[NationalMage, None] = None

            units: Dict[int, NationalMage] = {}

            for line in f:
                if "--" in line:
                    line = line[0:line.find("--")].strip()
                line = line.strip()
                if line == "": continue

                m = re.match("#newmonster (\\d+)", line)
                if m is None:
                    m = re.match("#selectmonster (\\d+)", line)
                if m is not None:
                    unitid = int(m.groups()[0])
                    print(f"Parsed newmonster {unitid}")
                    if unitid not in units:
                        units[unitid] = NationalMage()
                        units[unitid].id = unitid
                        monsterids.append(unitid)
                    currentunit = units[unitid]
                elif line.startswith("#newmonster"):
                    newid = max(monsterids) + 1
                    units[newid] = NationalMage()
                    monsterids.append(newid)
                    currentunit = units[newid]
                    currentunit.id = newid

                m = re.match("#montag (\\d+)", line)
                if m is not None:
                    newid = int(m.groups()[0])
                    montagids.append(newid)
                    print(f"Parsed montag {newid}")

                m = re.match("#code (.+)", line)
                if m is None:
                    m = re.match("#code2 (.+)", line)
                if m is None:
                    m = re.match("#codedelay (.+)", line)
                if m is None:
                    m = re.match("#codedelay2 (.+)", line)
                if m is not None:
                    newid = int(m.groups()[0])
                    eventcodes.append(newid)
                    print(f"Parsed event code {newid}")

                m = re.match("#newspell (\\d+)", line)
                if m is None:
                    m = re.match("#selectspell (\\d+)", line)
                if m is not None:
                    newid = int(m.groups()[0])
                    spellids.append(newid)
                    print(f"Parsed spell {newid}")
                elif line.startswith("#newspell"):
                    newid = max(spellids) + 1
                    print(f"Parsed spell with implied id {newid}")
                    spellids.append(newid)

                m = re.match("#newweapon (\\d+)", line)
                if m is None:
                    m = re.match("#selectweapon (\\d+)", line)
                if m is not None:
                    newid = int(m.groups()[0])
                    weaponids.append(newid)
                elif line.startswith("#newweapon"):
                    newid = max(weaponids) + 1
                    weaponids.append(newid)

                m = re.match("#newsite\\W+(\\d+)", line)
                if m is None:
                    m = re.match("#selectsite\\W+(\\d+)", line)
                if m is not None:
                    newid = int(m.groups()[0])
                    if newid not in sites:
                        sites[newid] = Site(newid)
                        sites[newid].id = newid
                        siteids.append(newid)
                    currentsite = sites[newid]
                elif line.startswith("#newsite"):
                    newid = max(siteids) + 1
                    sites[newid] = Site(newid)
                    sites[newid].id = newid
                    siteids.append(newid)
                    currentsite = sites[newid]

                m = re.match("#selectnation (\\d+)", line)
                if m is not None:
                    nationid = int(m.groups()[0])
                    print(f"Parsed selectnation {nationid}")
                    if nationid not in nations:
                        nations[nationid] = Nation(nationid)
                    currentnation = nations[nationid]

                m = re.match("#newnation", line)
                if m is not None:
                    newid = -1
                    while newid in nations:
                        newid -= 1
                    print(f"Parsed newnation, assigned id {newid}")
                    if newid not in nations:
                        nations[newid] = Nation(newid)
                    currentnation = nations[newid]

                m = re.match("#name [\"](.+)[\"]", line)
                if m is not None:
                    name = m.groups()[0]
                    if currentsite is not None:
                        print(f"Attach site name {name} to {currentsite}")
                        currentsite.name = name
                        sitenames[name] = currentsite.id
                    elif currentnation is not None:
                        print(f"Attach nation name {name} to {currentnation}")
                        currentnation.name = name
                    elif currentunit is not None:
                        print(f"Attach unit name {name} to {currentunit}")
                        currentunit.name = name

                m = re.match("#era\\W+(.+)", line)
                if m is not None:
                    currentnation.era = int(m.groups()[0])
                    print(
                        f"Set Era for nation {currentnation.id} to {currentnation.era}"
                    )

                m = re.match("#homecom (\\d+)", line)
                if m is not None:
                    unitid = int(m.groups()[0])
                    if currentsite is None:
                        raise ValueError(
                            f"Attempt to assign home com {unitid} to nonexistent site"
                        )
                    if currentsite not in sitecommanders:
                        sitecommanders[currentsite] = []
                    sitecommanders[currentsite].append(unitid)
                    print(f"Assign Commander {unitid} to site {currentsite}")

                m = re.match("#startsite [\"](.+)[\"]", line)
                if m is not None:
                    name = m.groups()[0]
                    if currentnation not in nationstartsites:
                        nationstartsites[currentnation] = []
                    nationstartsites[currentnation].append(name)

                    print(
                        f"Assign startsite {name} as belonging to {currentnation}"
                    )

                m = re.match("#addreccom (\\d+)", line)
                if m is not None:
                    unitid = int(m.groups()[0])
                    print(
                        f"{unitid} is a recruitable commander of {currentnation}"
                    )
                    if currentnation is None:
                        print(
                            f"Warning: {unitid} is set as a recruited commander, but no nation selected - ignored as"
                            f" this is likely a poptype addition")
                    else:
                        if unitid in units:
                            currentnation.add_mage(units[unitid])
                        else:
                            if unitid in vanillamages:
                                currentnation.add_mage(vanillamages[unitid])
                            else:
                                print(
                                    f"{unitid} appears to be a non-mage non-modded unit, ignored"
                                )

                if line.strip() == "#disableoldnations":
                    print(f"found disableoldnations")
                    for x in range(0, 120):
                        if x in nations:
                            del nations[x]

                if line.strip() == "#end":
                    print(f"Found #end")
                    currentnation = None
                    currentsite = None
                    currentunit = None

                for enchCommand in [
                        "req_noench", "req_ench", "req_myench",
                        "req_friendlyench", "req_hostileench", "req_enchdom"
                ]:
                    m = re.match(f"#{enchCommand}\\W+(.*)", line)
                    if m is not None:
                        print(
                            f"Found enchantment ID from event mod command: {line}"
                        )
                        enchantids.append(int(m.groups()[0]))

                m = re.match("#copystats (\\d+)", line)
                if m is not None:
                    uid = int(m.groups()[0])
                    print(f"Found #copystats {uid} for unit")
                    if uid in vanillamages and vanillamages[uid] is not None:
                        vanillamages[uid].copystats(currentunit)
                        print(f"Successfully copied over paths: {currentunit}")

                m = re.match("#magicskill (\\d+) (\\d+)", line)
                if m is not None:
                    # In normal dominions modding, path flags are 0-7, just for this I converted them into their
                    # 2^n bitmask form
                    path = 2**int(int(m.groups()[0]))
                    level = int(m.groups()[1])
                    print(
                        f"Give guaranteed path {path} of strength {level} to current commander"
                    )
                    currentunit.add_magic_path(path, level)

                m = re.match("#custommagic (\\d+) (\\d+)", line)
                if m is not None:
                    mask = int(m.groups()[0]) >> 7
                    chancemask = int(m.groups()[1])
                    if chancemask > 100:
                        chance = 100
                        link = int(chancemask / 100)
                    else:
                        link = 1
                        chance = chancemask
                    random = MagePathRandom(paths=mask,
                                            chance=chance,
                                            link=link)
                    print(f"Give random path {mask} to current commander")
                    currentunit.add_magic_random(random)

            for nation in nationstartsites:
                for siteid in nationstartsites[nation]:
                    if siteid in sitenames:
                        nation.sites.append(sites[sitenames[siteid]])
                    else:
                        if siteid in sites:
                            nation.sites.append(sites[siteid])
                            print(
                                f"Added start site {site} to nation {nation}")
                        else:
                            print(
                                f"Nation has start site with ID {siteid}, this site was not found, ignored"
                            )

            for site in sitecommanders:
                for unitid in sitecommanders[site]:
                    if unitid in units:
                        site.mages.append(units[unitid])
                    elif unitid in vanillamages:
                        site.mages.append(vanillamages[unitid])
                    else:
                        print(
                            f"Site {site} had commander {unitid} added, but this seems to not be a mage: skipped"
                        )
示例#4
0
def _generate_spells_for_nation(nation: Nation, researchmod: int, spelleffects: Dict[str, SpellEffect],
                                alreadygeneratedeffectsatlevels: Dict[int, List[str]], generatedspells: List[Spell],
                                targetnumberofnationalspells: int, options: Dict[str, str]):
    DebugLogger.debuglog(f"Generating spells for nation: {nation.to_text()}",
                         debugkeys.NATIONALSPELLGENERATION)
    if not nation.has_mages():
        _writetoconsole(f"Skipping nation {nation.to_text()} because no national mages were found\n")
        return
    availableeffectpool = copy.copy(spelleffects)
    while len(nation.nationalspells) < targetnumberofnationalspells:
        primarypath: int = _roll_path_for_national_spell(nation)
        DebugLogger.debuglog(f"Attempting to generate for primary path {utils.pathstotext(primarypath)}\n",
                             debugkeys.NATIONALSPELLGENERATION)

        # Select a commander to generate this spell for
        commander: NationalMage = nation.get_commander_with_path(primarypath)

        # calculate if blood shall be allowed as path in the spell
        allowblood = commander.can_have_blood()

        # Select effect for spell
        DebugLogger.debuglog(f"Selecting national spell effect\n", debugkeys.NATIONALSPELLGENERATION)

        researchlevel = _select_research_level(researchmod, alreadygeneratedeffectsatlevels)
        try:
            choseneffect = _choose_effect(
                effectpool=availableeffectpool,
                primarypath=primarypath,
                alreadygeneratedeffectsatlevels=alreadygeneratedeffectsatlevels,
                researchlevel=researchlevel
            )
            # Only one attempt an effect per nation
            del availableeffectpool[choseneffect.name]
        except ValueError:
            raise ValueError(
                f"Couldn't make a national spell for nation {nation.name} (ID:{nation.id})\n"
                f"Primarypath={utils.pathstotext(primarypath)}\n"
                f"Researchlevel={researchlevel}\n "
                f"Available effects: {availableeffectpool}\n"
                f"No effect available\n")

        DebugLogger.debuglog(
            f"Try generating national spell for nation {nation.id} with effect {choseneffect.name}, "
            f"primarypath={utils.pathstotext(primarypath)}, secondaries={commander.get_total_possible_paths_mask()}, there are "
            f"{len(availableeffectpool)} effects available\n", debugkeys.NATIONALSPELLGENERATION)
        spell = _try_to_generate_a_national_spell(
            nation=nation,
            spelleffect=choseneffect,
            researchlevel=researchlevel,
            primarypath=primarypath,
            allowblood=allowblood,
            options=options,
            secondarypathoptions=commander.get_total_possible_paths_mask()
        )
        if spell is None:
            DebugLogger.debuglog(f"Failed to generate spell for effect {choseneffect.name}\n",
                                 debugkeys.NATIONALSPELLGENERATION)
        else:
            generatedspells.append(spell)
            nation.register_national_spell(spell)
            NationalSpellGenerationInfoCollector.numberofgeneratedspells += 1
            DebugLogger.debuglog("Spell successfully generated\n", debugkeys.NATIONALSPELLGENERATION)