def getStates(hoi4path): stateMap = {} for filename in os.listdir(hoi4path + "history/states/"): stateData = open(hoi4path + "history/states/" + filename).read() stateData = stateData.replace("=\n{", "={") stateData = stateData.replace("=\n\t{", "={") stateData = stateData.replace("=\n\t\t{", "={") stateData = stateData.replace("=\n\t\t\t{", "={") stateData = stateData.replace("=\n\t\t\t\t{", "={") stateData = re.sub(r"#[^\n]*?\n", r"\n", stateData) state = naive_parser.ParseSaveData(stateData) stateId = int(naive_parser.drill(state, "state", "id")) provinces = naive_parser.drill(state, "state", "provinces", "").split(" ") provinceIds = [] for province in provinces: if not province: continue provinceIds.append(int(province)) for province in provinceIds: stateMap[province] = stateId return stateMap
def getGovernment(self, empire): governmentSet = naive_parser.ParseSaveFile("files/governments.txt") empire.ideology = empire.ideology.replace("_neutral", "") government = Dotdict({}) if naive_parser.drill(governmentSet, "governments", empire.ideology): government.authority = naive_parser.drill(governmentSet, "governments", empire.ideology, "authority") government.ethics = naive_parser.splitstrings( naive_parser.drill(governmentSet, "governments", empire.ideology, "ethics", "")) government.civics = naive_parser.splitstrings( naive_parser.drill(governmentSet, "governments", empire.ideology, "civics", "")) else: print("WARNING: Did not recognise " + empire.longTag() + "'s \"" + empire.ideology + "\" ideology. Falling back to generic democracy.") government.authority = "auth_democratic" government.ethics = [ "ethic_egalitarian", "ethic_pacifist", "ethic_xenophobe" ] government.civics = [ "civic_parliamentary_system", "civic_environmentalist" ] return government
def stringlist_drill(*args): output = [] theStrings = naive_parser.drill(*args) if theStrings: for line in theStrings['']: output += ClunkyStringSplit(line) return output
def Load(self): parser = naive_parser.Parser(self.savefile) self.topNations = parser.getTopNations() self.smallNations = parser.getSmallNations() self.gini = parser.getGiniCoeff() self.totalScore = parser.getTotalScore() self.seed = int(naive_parser.drill(self.savefile, "game_unique_seed")) currentDate = naive_parser.drill(self.savefile, "date") currentDate = currentDate.replace('"', '') self.currentDate = [int(n) for n in currentDate.split(".")] self.defcon = Config().defconResults if self.defcon: self.CreateEventsFromDefcon() else: self.CreateEvents()
def getStates(): stateMap = {} statepath = config.Config().getModdedHoi4File("history/states/") for filename in os.listdir(statepath): stateData = open(statepath + filename).read() stateData = stateData.replace("=\n{", "={") stateData = stateData.replace("=\n\t{", "={") stateData = stateData.replace("=\n\t\t{", "={") stateData = stateData.replace("=\n\t\t\t{", "={") stateData = stateData.replace("=\n\t\t\t\t{", "={") stateData = re.sub(r"#[^\n]*?\n", r"\n", stateData) if not stateData: continue state = naive_parser.ParseSaveData(stateData) if 0 == len(state.keys()): print("WARNING: \"" + statepath + filename + "\" could not be parsed. Skipping.") continue stateId = int(naive_parser.drill(state, "state", "id")) provinces = naive_parser.drill(state, "state", "provinces", "").split(" ") provinceIds = [] for province in provinces: if not province: continue provinceIds.append(int(province)) for province in provinceIds: stateMap[province] = stateId return stateMap
def __init__(self): BorgSingleton.__init__(self) if hasattr(self, 'loaded'): return self.loaded = True self.configfile = naive_parser.ParseSaveFile("configuration.txt") config = naive_parser.drill(self.configfile, "configuration") if getattr(sys, 'frozen', False): # running in a bundle self.converterDir = self.makeSanePath( os.path.dirname(sys.executable)) else: # running live self.converterDir = self.makeSanePath( os.path.dirname(os.path.realpath(__file__))) print("Running from: " + self.converterDir) self.savefileName = naive_parser.unquote( naive_parser.drill(config, "savefile")) self.hoi4Path = naive_parser.unquote( naive_parser.drill(config, "HoI4directory")) self.hoi4ModPath = naive_parser.unquote( naive_parser.drill(config, "HoI4ModDirectory")) self.stellarisModPath = naive_parser.unquote( naive_parser.drill(config, "StellarisModdirectory")) self.useDefconResults = naive_parser.unquote( naive_parser.drill(config, "useDefconResults")) if self.useDefconResults == "y" or self.useDefconResults == "yes": self.defconResults = naive_parser.unquote( naive_parser.drill(config, "defconResults")) else: self.defconResults = False self.modName = "outputMod" self.baseModPath = self.converterDir + self.modName + "_base/" self.outputPath = self.converterDir + self.modName + "/" self.outputModFile = self.converterDir + self.modName + ".mod" if self.stellarisModPath: self.stellarisModPath = self.makeSanePath(self.stellarisModPath) self.finalPath = self.stellarisModPath + self.modName + "/" self.finalModFile = self.stellarisModPath + self.modName + ".mod" else: self.finalPath = "" self.finalModFile = "" if not self.isSane(): sys.exit(0)
def __init__(self): print("Parsing configuration") self.configfile = naive_parser.ParseSaveFile("configuration.txt") self.savefile = naive_parser.drill(self.configfile, "configuration", "savefile") self.hoi4path = naive_parser.drill(self.configfile, "configuration", "HoI4directory") self.targetdir = naive_parser.drill(self.configfile, "configuration", "StellarisModdirectory") print("Save file: " + self.savefile) print("HoI4 location: " + self.hoi4path) print("Stellaris mod path: " + self.targetdir) self.savefile = reformatPath(self.savefile, False) self.hoi4path = reformatPath(self.hoi4path, True) self.targetdir = reformatPath(self.targetdir, True) if not self.savefile: print("Error: Could not parse save file.") sys.exit(1) if not self.hoi4path: print("Error: Could not parse HoI4 path.") sys.exit(1) if not self.targetdir: print( "Warning: Could not parse Stellaris mod path. Mod will only be created in the converter directory." ) for path in [self.savefile, self.hoi4path, self.targetdir]: if not os.path.exists(path): print("Error: Could not find " + path) sys.exit(1)
def Load(self): parser = naive_parser.Parser(self.savefile, self.hoi4path) self.topNations = parser.getTopNations() self.smallNations = parser.getSmallNations() self.gini = parser.getGiniCoeff() self.totalScore = parser.getTotalScore() self.seed = int(naive_parser.drill(self.savefile, "game_unique_seed")) currentDate = naive_parser.drill(self.savefile, "date") currentDate = currentDate.replace('"', '') self.currentDate = [int(n) for n in currentDate.split(".")] self.events = [] climateChange = 0 self.nuclearWar = 0 self.earthOwnedBy = "" climateAuthority = "" self.earthType = "pc_continental" self.empires = [] for nation in self.topNations: self.empires.append(Empire(nation)) if len(self.empires) == 1: self.events.append(Event("Hegemon", self.empires[0].tag)) self.earthOwnedBy = self.empires[0].tag climateAuthority = self.empires[0].tag elif self.empires[ 0].score / self.totalScore > 0.5: # largest nation has 50% if self.empires[1].score / self.empires[ 0].score > 0.5: # next largest is pretty big self.events.append( Event("ColdWar", self.empires[0].tag, self.empires[1].tag)) self.events.append( Event("MinorNuclearWar", self.empires[0].tag, self.empires[1].tag)) self.events.append( Event("MinorNuclearWarLose", self.empires[1].tag)) self.events.append( Event("MinorNuclearWarWin", self.empires[0].tag)) self.nuclearWar = 1 self.earthOwnedBy = self.empires[0].tag self.empires[0].nuclear = True self.empires[1].nuclear = True self.empires[1].population *= 0.25 else: # next largest is pretty small self.events.append( Event("EconomicCollapse", self.empires[1].tag)) self.empires[1].industry *= 0.75 self.events.append(Event("Hegemon", self.empires[0].tag)) self.earthOwnedBy = self.empires[0].tag else: # largest nation does not have 50% if self.empires[ 0].score / self.totalScore > 0.3: # someone's large-ish if self.empires[1].score / self.empires[ 0].score > 0.5: # next largest is pretty big if len(self.empires) == 2: # only two nations self.events.append( Event("ColdWar", self.empires[0].tag, self.empires[1].tag)) elif (self.empires[2].score / self.empires[1].score > 0.5): # and next after that is pretty big too self.events.append( Event("EconomicProblems", self.empires[2].tag)) self.empires[2].industry *= 0.9 self.events.append( Event("ColdWar", self.empires[0].tag, self.empires[1].tag)) self.events.append( Event("ColdWarStaysCold", self.empires[0].tag, self.empires[1].tag)) self.events.append(Event("Squabbling")) else: # and next after that is pretty small self.events.append( Event("EconomicCollapse", self.empires[2].tag)) self.empires[2].industry *= 0.75 self.events.append( Event("ColdWar", self.empires[0].tag, self.empires[1].tag)) if self.empires[0].government == self.empires[ 1].government and self.empires[ 0].government != "fascist": self.events.append( Event("ColdWarStaysCold", self.empires[0].tag, self.empires[1].tag)) self.events.append(Event("Squabbling")) else: self.events.append( Event("NuclearWar", self.empires[0].tag, self.empires[1].tag)) self.nuclearWar = 2 self.events.append( Event("NuclearWarLose", self.empires[0].tag, self.empires[1].tag)) self.empires[0].nuclear = True self.empires[1].nuclear = True self.empires[0].population *= 0.25 self.empires[1].population *= 0.25 else: # next largest is pretty small self.events.append( Event("EconomicCollapse", self.empires[1].tag)) self.empires[1].industry *= 0.75 self.events.append(Event("Hegemon", self.empires[0].tag)) self.earthOwnedBy = self.empires[0].longTag() else: # everyone's tiny self.events.append(Event("Squabbling")) if self.gini > 0.4: if climateAuthority: self.events.append( Event("GovernmentClimateControl", climateAuthority)) elif self.gini > 0.6: climateChange = 2 else: climateChange = 1 else: self.events.append(Event("CleanIndustrialization")) self.events.append(Event("Migrations")) if self.nuclearWar == 2: self.events.append(Event("TombWorld")) self.events.append(Event("EscapeLaunches")) self.earthType = "pc_nuked" elif self.nuclearWar == 1: if climateChange == 0: self.events.append(Event("NuclearWinter")) self.events.append(Event("EscapeLaunches")) self.earthType = "pc_arctic" elif climateChange == 1: self.events.append(Event("SeaLevelsRise")) self.events.append(Event("Launches")) self.earthType = "pc_ocean" elif climateChange == 2: self.events.append(Event("NuclearIndustrialDesert")) self.events.append(Event("EscapeLaunches")) self.earthType = "pc_desert" else: if climateChange == 0: self.earthType = "pc_continental" self.events.append(Event("Launches")) pass elif climateChange == 1: self.events.append(Event("SeaLevelsRise")) self.events.append(Event("Launches")) self.earthType = "pc_ocean" elif climateChange == 2: self.events.append(Event("GlobalWarming")) self.events.append(Event("EscapeLaunches")) self.earthType = "pc_arid" #for event in self.events: # print(event) colourMap = properties.getColours(self.hoi4path) for empire in self.empires: if empire.tag in colourMap: empire.colour = colourMap[empire.tag] empire.GoIntoSpace()
def GetHistory(self): tagToName = {} tagToAdj = {} cityNames = getCountryNames.getCityNames() countryNames = getCountryNames.getCountryNames() for empire in self.topNations + self.smallNations: tagBlank = empire.longTag() tagDef = empire.longTag() + "_DEF" tagAdj = empire.longTag() + "_ADJ" if tagDef in countryNames: name = countryNames[tagDef] else: name = countryNames[tagBlank] name = name.replace("The", "the") tagToName[empire.tag] = name if tagAdj in countryNames: adj = countryNames[tagAdj] else: adj = countryNames[tagBlank] tagToAdj[empire.tag] = adj numpy.random.seed(self.seed) startYear = self.currentDate[0] + 5 endYear = 2200 yearRange = endYear - startYear eventCount = numpy.random.randint(8, 12) nationCount = len(self.topNations) + len(self.smallNations) if nationCount == 1: # only one nation - so events about "nations" won't make much sense deleteKeys = [] for key in self.eventStrings: if "nation" in self.eventStrings[key].lower(): deleteKeys.append(key) for key in deleteKeys: del self.eventStrings[key] realEvents = [] for event in self.events: if event.eventType in self.eventStrings: realEvents.append(Event(event.eventType, *event.tags)) if event.eventType + "0" in self.eventStrings: realEvents.append(Event(event.eventType + "0", *event.tags)) for i in range(1, 10): if event.eventType + str(i) in self.eventStrings and (numpy.random.random() < 0.7): realEvents.append(Event(event.eventType + str(i), *event.tags)) randomEventCount = eventCount - len(realEvents) randomEventKeys = [] for eventKey in sorted(self.eventStrings): if "Random" in eventKey: randomEventKeys.append(eventKey) randomEvents = [] skips = 0 while len(randomEvents) < randomEventCount: skips += 1 if skips > 100: break chosenEvent = Event(numpy.random.choice(randomEventKeys)) if chosenEvent not in randomEvents: randomEvents.append(chosenEvent) randomEvents.sort() if randomEventCount > 0: jump = eventCount // randomEventCount insertPoint = 2 - jump if jump == 1: insertPoint = 0 for randomEvent in randomEvents: insertPoint += jump realEvents.insert(insertPoint, randomEvent) # Tried just having linear gaps between years; it doesn't feel right. We # need a pretty dense cold-war 20th century and a pretty sparse 22nd # century. Log scales to the rescue! logNudge = 80 yearLogScale = numpy.logspace( numpy.log10(logNudge), numpy.log10( yearRange + logNudge), num=len(realEvents) + 1) yearLogScale = [x - logNudge for x in yearLogScale] defconResultsText = "" if self.defcon: def scoreSort(tag): try: return self.defcon[tag].score except AttributeError: return 0 survivorTags = [] okTags = [] oblitTags = [] for tag in sorted(self.defcon, key=scoreSort): if not type(tag) is str: continue survivors = float(naive_parser.drill(self.defcon, tag, "survivors")) if survivors > 80: survivorTags.append(tag) elif survivors > 40: okTags.append(tag) else: oblitTags.append(tag) # We've only got 3 "survived" messages and 2 "is basically ok" messages. while len(survivorTags) > 3: okTags.append(survivorTags.pop()) while len(okTags) > 2: okTags.pop() def nameOfTagOrFaction(name): if name in tagToName: return tagToName[name] return "the "+name.title() for n in range(len(survivorTags)): nationName = "the "+survivorTags[n] if survivorTags[n] in tagToName: nationName = tagToName[survivorTags[n]] defconResultsText += self.eventStrings["DefconSurvive"+str(n+1)] + " " defconResultsText = defconResultsText.replace("&NATION_1&", nameOfTagOrFaction(survivorTags[n])) for n in range(len(okTags)): defconResultsText += self.eventStrings["DefconOk"+str(n+1)] + " " defconResultsText = defconResultsText.replace("&NATION_1&", nameOfTagOrFaction(okTags[n])) if len(oblitTags) == 1: defconResultsText += self.eventStrings["DefconObliterated1"] + " " defconResultsText = defconResultsText.replace("&NATION_1&", nameOfTagOrFaction(oblitTags[0])) elif len(oblitTags) > 1: for n in range(len(oblitTags)-1): defconResultsText += nameOfTagOrFaction(oblitTags[n]) + ", " defconResultsText += "and " + self.eventStrings["DefconObliteratedPl1"] defconResultsText = defconResultsText.replace("&NATION_1&", nameOfTagOrFaction(oblitTags[-1])) historyString = "" for e in range(len(realEvents)): year = int(numpy.floor(startYear + yearLogScale[e])) yearJump = (yearLogScale[e + 1] - yearLogScale[e]) // 2 if yearJump > 1: year += numpy.random.randint(-yearJump // 2, yearJump // 2) if year < startYear: year = startYear + 1 if year > endYear: year = endYear - 1 event = realEvents[e] print(event) replaces = {} replaces["&YEAR&"] = str(year) replaces["&DECADE&"] = str(year // 10) + "0s" replaces["&NATION_1&"] = tagToName[event.tags[0]] if len(event.tags) > 0 else "" replaces["&NATION_2&"] = tagToName[event.tags[1]] if len(event.tags) > 1 else "" replaces["&NATION_3&"] = tagToName[event.tags[2]] if len(event.tags) > 2 else "" replaces["&NATION_4&"] = tagToName[event.tags[3]] if len(event.tags) > 3 else "" replaces["&NATION_5&"] = tagToName[event.tags[4]] if len(event.tags) > 4 else "" replaces["&NATION_6&"] = tagToName[event.tags[5]] if len(event.tags) > 5 else "" replaces["&NATION_1_ADJ&"] = tagToAdj[event.tags[0]] if len(event.tags) > 0 else "" replaces["&NATION_2_ADJ&"] = tagToAdj[event.tags[1]] if len(event.tags) > 1 else "" replaces["&NATION_3_ADJ&"] = tagToAdj[event.tags[2]] if len(event.tags) > 2 else "" replaces["&NATION_4_ADJ&"] = tagToAdj[event.tags[3]] if len(event.tags) > 3 else "" replaces["&NATION_5_ADJ&"] = tagToAdj[event.tags[4]] if len(event.tags) > 4 else "" replaces["&NATION_6_ADJ&"] = tagToAdj[event.tags[5]] if len(event.tags) > 5 else "" replaces["&DEFCONRESULTS&"] = defconResultsText if len(cityNames) > 0: replaces["&RANDOM_SMALL_CITY&"] = numpy.random.choice(cityNames) else: replaces["&RANDOM_SMALL_CITY&"] = "Vienna" if len(self.smallNations) > 0: replaces["&RANDOM_SMALL_NATION&"] = tagToName[numpy.random.choice(self.smallNations).tag] else: replaces["&RANDOM_SMALL_NATION&"] = "Secret Denmark" eventline = self.eventStrings[event.eventType] for replaceString in replaces: eventline = eventline.replace(replaceString, replaces[replaceString]) historyString += eventline + "\n" historyString = historyString.replace(". the", ". The") historyString = historyString.replace(": the", ": The") print(historyString) return historyString
def getColours(): hoi4ColourData = naive_parser.ParseSaveFile( config.Config().getModdedHoi4File("common/countries/colors.txt")) stellarisGreyData = { "grey": [0.65, 0.05, 0.35], "dark_grey": [0.65, 0.05, 0.22], "black": [0.5, 0.3, 0.05] } stellarisColourData = { "grey": [0.65, 0.05, 0.35], "dark_grey": [0.65, 0.05, 0.22], "black": [0.5, 0.3, 0.05], "dark_brown": [0.07, 0.6, 0.23], "brown": [0.07, 0.6, 0.4], "beige": [0.1, 0.4, 0.6], "yellow": [0.11, 0.8, 0.8], "light_orange": [0.09, 1.0, 0.8], "orange": [0.06, 0.9, 0.7], "red_orange": [0.01, 0.75, 0.7], "red": [0.0, 0.95, 0.5], "burgundy": [0.95, 0.8, 0.35], "pink": [0.88, 0.61, 0.5], "purple": [0.74, 0.65, 0.61], "dark_purple": [0.74, 0.71, 0.37], "indigo": [0.71, 0.85, 0.5], "dark_blue": [0.64, 0.85, 0.45], "blue": [0.64, 0.7, 0.6], "light_blue": [0.6, 0.6, 0.7], "turquoise": [0.49, 0.6, 0.6], "dark_teal": [0.5, 0.6, 0.3], "teal": [0.42, 0.6, 0.5], "light_green": [0.35, 0.5, 0.60], "green": [0.32, 0.6, 0.40], "dark_green": [0.33, 0.6, 0.27], } hsvSet = {} nameSet = {} for tag in hoi4ColourData: colour = naive_parser.drill(hoi4ColourData, tag, "color", "") rgb = ("." not in colour) colour = [float(x) for x in colour.replace(" ", " ").split(" ")] if rgb: colour = list(colorsys.rgb_to_hsv(*colour)) colour[2] = colour[2] / 255 hsvSet[tag] = colour minDist = 9999 bestColour = "red" if colour[1] < 0.2: colourData = stellarisGreyData else: colourData = stellarisColourData for stellarisColour in colourData: stellarisHsv = colourData[stellarisColour] newDist = colourDistance(colour, stellarisHsv) if newDist < minDist: minDist = newDist bestColour = stellarisColour nameSet[tag] = bestColour return nameSet
def getClimates(): climateMap = {} stateMap = getStates() strategicRegionsPath = config.Config().getModdedHoi4File( "map/strategicregions/") for filename in os.listdir(strategicRegionsPath): climateData = naive_parser.ParseSaveFile(strategicRegionsPath + filename) provinces = naive_parser.drill(climateData, "strategic_region", "provinces", "").split(" ") periodses = naive_parser.drill(climateData, "strategic_region", "weather") if "period" not in periodses: continue periods = periodses["period"] yearTemperatures = [] yearRain = [] yearSnow = [] yearSand = [] if len(periods) == 0: continue for period in periods: temperatureRange = naive_parser.drill(period, "temperature", "").split(" ") maxTemp = temperatureRange[1].replace("\"", "") minTemp = temperatureRange[0].replace("\"", "") temperature = float(maxTemp) - float(minTemp) yearTemperatures.append(temperature) lightRain = naive_parser.unquote( naive_parser.drill(period, "rain_light")) heavyRain = naive_parser.unquote( naive_parser.drill(period, "rain_heavy")) snow = naive_parser.unquote(naive_parser.drill(period, "snow")) blizzard = naive_parser.unquote( naive_parser.drill(period, "blizzard")) sandstorm = naive_parser.unquote( naive_parser.drill(period, "sandstorm")) yearRain.append(float(lightRain) + float(heavyRain) * 2) yearSnow.append(float(snow) + float(blizzard) * 3) yearSand.append(float(sandstorm)) averageTemperature = sum(yearTemperatures) / len(yearTemperatures) averageRain = sum(yearRain) / len(yearRain) averageSnow = sum(yearSnow) / len(yearSnow) averageSand = sum(yearSand) / len(yearSand) climate = "pc_arid" if averageSand > 0.05: climate = "pc_desert" elif averageSnow > 0.3: climate = "pc_arctic" elif averageSnow > 0.1: climate = "pc_tundra" elif averageTemperature > 10.0: climate = "pc_arid" elif averageTemperature < 4.7: climate = "pc_savannah" else: climate = "pc_alpine" for province in provinces: if not province: continue provinceId = int(province) if provinceId in stateMap: stateId = stateMap[provinceId] climateMap[stateId] = climate return climateMap