def create_city(self, name=''): if name == '': name = self.language.make_name_word() x, y = self.get_average_city_position() candidates = self.get_city_candidate_cells() candidate = utility.weighted_random_choice(candidates, lambda _, cell: 1.0 / ( utility.distance_squared((cell.x, cell.y), (x, y)) + 1.0)) self.cities.append(city.City(self, name, candidate, self.parent)) self.chance_add_new_name(self.cities[-1].name) self.parent.event_log.add_event('CityFounded', {'nation_a': self.id, 'city_a': self.cities[-1].name}, self.parent.get_current_date()) self.cities[-1].army = self.army_structure.copy().zero() self.money -= CITY_FOUND_COST self.mod_morale(city.MORALE_INCREMENT) if self.parent.cells[self.cities[-1].position[0]][self.cities[-1].position[1]].owner is None: self.parent.change_cell_ownership(self.cities[-1].position[0], self.cities[-1].position[1], self.cities[-1], new_type='city') religion_populations = self.get_nation_religion_populations() if len(religion_populations) > 0: religion, _ = utility.weighted_random_choice(religion_populations, lambda i, (_, adherents): adherents) religion.adherents[self.cities[-1].name] = self.cities[-1].population
def history_step(self): self.name.history_step(self) # we lost our capital somehow if not self.has_capital(): # choose a new capital from our cities, weighted by population if len(self.cities) > 0: # Just to be sure new_capital = utility.weighted_random_choice(self.cities, weight=lambda i, v: v.population) new_capital.make_capital() else: self.mod_morale(city.CAPITAL_CITY_MORALE_BONUS) self.handle_treaties() for curCity in self.cities: # It's more likely to found a new city when this city is near population capacity # Because as there's no more space, people want to go to a new city try: found_city_chance = max(1, int( len(self.cities) ** 4 * math.math.log(curCity.population_capacity - curCity.population))) except: # Log is negative found_city_chance = max(1, len(self.cities) ** 4) if random.randint(0, found_city_chance) == 0 and self.money > CITY_FOUND_COST: self.create_city() if self.current_research is None or self.current_research.is_unlocked(): if self.current_research is not None and self.current_research.is_unlocked(): self.parent.event_log.add_event('TechResearch', {'nation_a': self.id, 'tech_a': self.current_research.name}, self.parent.get_current_date()) available = self.tech.get_available_research() if len(available) > 0: self.current_research = random.choice(available) else: # There's nothing left to research self.current_research = None else: self.current_research.do_research(random.randint(1, int(math.log(curCity.population + 1) ** 2 + 1))) for cell in curCity.cells: for building in cell.buildings: research_rate = building.get_research_rate() if research_rate > 0: self.current_research.do_research(random.randint(1, research_rate)) self.handle_rearming() self.handle_people() self.age += 1 # More cities means less happiness self.mod_morale(-(len(self.cities) ** 2 + 1))
def build_buildings(self): improvement_chance = int((self.building_count() + 1) / (math.sqrt(self.owner.population) + 1)) if random.randint(0, improvement_chance + 1) == 0: available_buildings = filter(lambda b: b.get_size() <= self.get_available_building_capacity(), self.buildings) if len(available_buildings) > 0: build_building = utility.weighted_random_choice(available_buildings, weight=lambda _, b: 1.0 / b.get_cost()) if self.owner.nation.money > build_building.get_cost(): self.owner.nation.money -= build_building.get_cost() build_building.number += 1
def build_buildings(self): improvement_chance = int((self.building_count() + 1) / (math.sqrt(self.owner.population) + 1)) if random.randint(0, improvement_chance + 1) == 0: available_buildings = filter( lambda b: b.get_size() <= self.get_available_building_capacity( ), self.buildings) if len(available_buildings) > 0: build_building = utility.weighted_random_choice( available_buildings, weight=lambda _, b: 1.0 / b.get_cost()) if self.owner.nation.money > build_building.get_cost(): self.owner.nation.money -= build_building.get_cost() build_building.number += 1
def handle_army_dispatch(self): # Determine if we want to launch an attack with this city's army for city in self.cities: if len(self.at_war) > 0 and city.army.size() > 0: enemy = random.choice(self.at_war) # Make sure our enemy actually still exists. if len(enemy.cities) > 0 and enemy in self.parent.nations: attacking_city = utility.weighted_random_choice(enemy.cities, weight=lambda _, v: 1.0 / utility.distance( city.position, v.position)) if random.randint(0, max(20, city.army.size() + city.population // 8 - attacking_city.population // 3 - attacking_city.army.size())) > 20: if random.randint(0, len(self.moving_armies) ** 3) == 0: fx, fy = city.position dx, dy = attacking_city.position # Conscript some levies to join the army. if city.population // 3 > 1: conscript_max = max(city.population // 4, 3) conscript_min = min(city.population // 8, 2) conscripted = int( random.randint(conscript_min, conscript_max) * self.get_conscription_bonus()) else: conscripted = 0 city.population -= conscripted city.army.add_to(city.army.name, conscripted) action = self.parent.do_attack(self, city, enemy, attacking_city) self.moving_armies.append( Group(self.parent, self.id, city.army, (fx, fy), (dx, dy), self.color, lambda s: False, action, is_army=True, has_boat=(city.resources['boats'] > 0))) self.parent.event_log.add_event('ArmyDispatched', {'nation_a': self.id, 'nation_b': enemy.id, 'city_a': city.name, 'city_b': attacking_city.name, 'reason': 'attack', 'army_size': city.army.size()}, self.parent.get_current_date()) city.army = city.army.zero()
def create_city(self, name=''): if name == '': name = self.language.make_name_word() x, y = self.get_average_city_position() candidates = self.get_city_candidate_cells() candidate = utility.weighted_random_choice( candidates, lambda _, cell: 1.0 / (utility.distance_squared( (cell.x, cell.y), (x, y)) + 1.0)) self.cities.append(city.City(self, name, candidate, self.parent)) self.chance_add_new_name(self.cities[-1].name) self.parent.event_log.add_event('CityFounded', { 'nation_a': self.id, 'city_a': self.cities[-1].name }, self.parent.get_current_date()) self.cities[-1].army = self.army_structure.copy().zero() self.money -= CITY_FOUND_COST self.mod_morale(city.MORALE_INCREMENT) if self.parent.cells[self.cities[-1].position[0]][ self.cities[-1].position[1]].owner is None: self.parent.change_cell_ownership(self.cities[-1].position[0], self.cities[-1].position[1], self.cities[-1], new_type='city') religion_populations = self.get_nation_religion_populations() if len(religion_populations) > 0: religion, _ = utility.weighted_random_choice( religion_populations, lambda i, (_, adherents): adherents) religion.adherents[ self.cities[-1].name] = self.cities[-1].population
def choice(self, options, amount=1): def weight(_, v): if v in self.custom_weights: return self.custom_weights[v] else: return 1 converted = {} for i in xrange(len(options)): if isinstance(options[i], list): converted[utility.tuplize(options[i])] = options[i] options[i] = utility.tuplize(options[i]) chosen_item = utility.weighted_random_choice(options, weight=weight) if chosen_item in self.custom_weights: self.custom_weights[chosen_item] += amount else: self.custom_weights[chosen_item] = 1 + amount if chosen_item in converted: return converted[chosen_item] else: return chosen_item
def __init__(self, person, role=None): self.person = person # Measured in months self.length = 0 self.custom_weights = {} self.art = [] if role is not None: self.role = role else: # Could possibly change roles. This is less likely if the person has spent more time in a particular role, and if they have created more works. # If it's our first run, then our role is only determined by our religion, otherwise, religion plays a more minor role as the person becomes more cemented. role_weights = person.get_role_weights() self.role = utility.weighted_random_choice(PERSON_ROLES.keys(), lambda _, role: role_weights[role]) base_create_chance = PERSON_ROLES[self.role]['art_create_chance'] base_create_variance = PERSON_ROLES[self.role]['art_create_variance'] self.art_create_chance = base_create_chance + random.randint(-base_create_variance, base_create_variance) custom_tags = {'role': [self.role]} if (self.art_create_chance - base_create_variance // 10) > base_create_chance: custom_tags['creation_rate'] = ['prolific', 'productive', 'creative'] elif (self.art_create_chance + base_create_chance // 10) < base_create_chance: custom_tags['creation_rate'] = ['quiet', 'lazy', 'unproductive', 'barren'] else: custom_tags['creation_rate'] = ['normal', 'average', 'standard'] if self.role in ART_CATEGORIES.keys(): gen = Form(PERIOD_FORMS, custom_tags=custom_tags) else: gen = Form(NORMAL_FORMS, custom_tags=custom_tags) self.name = gen.generate(nation=self.person.nation, creator=self.person)[0]
def get_random_religion(self): religion_populations = self.get_religion_populations() weight = lambda _, (religion, adherents): adherents religion, _ = utility.weighted_random_choice(religion_populations, weight=weight) return religion
def generate_tags(self, actual_forms, nation=None, creator=None): # So that tags are generated in the correct order. tag_order = [] for form in actual_forms: for part in form: if part.startswith('tag:'): tag_order.append(part.split(':')[1]) for tag in tag_order: base = self.tags[tag] # () allow you to group text without using any actual tag # For example, <test:(<animal>'s hair)> allows you to give the name 'test' to 'lion's hair' while '<(' in base: i = base.find('<(') # Get the full tag and remove the brackets group = utility.get_container(base, '<', '>', i) base = base.replace(group, group[2:-2]) # Remove the containing stuff # Checks if tags exist. Replaces the tag's text with the first tag that exists. Otherwise replaces it with nothing. while '<tagexists' in base: i = base.find('<tagexists') section = utility.get_container(base, '<', '>', i) check_tags = section[1:-1].split(';')[1:] replacement = '' for tag_name in check_tags: if tag_name in self.chosen_tags: replacement = self.chosen_tags[tag_name] base = base.replace(section, replacement) while '|' in base: start_pos, end_pos = utility.find_container_of( base, '<', '>', '|') choice_section = base[start_pos + 1:end_pos] choice = utility.separate_container(choice_section, '<', '>', '|') valid_choice = filter(is_valid(nation), choice) base = base.replace('<' + choice_section + '>', self.choice(valid_choice), 1) while ',' in base: start_pos, end_pos = utility.find_container_of( base, '<', '>', ',') select_section = base[start_pos + 1:end_pos] select = utility.separate_container(select_section, '<', '>', ',') valid_select = filter(is_valid(nation), select) search = '<' + select_section + '>' replacement = '<{}>'.format('> <'.join( random.sample(valid_select, random.randint(1, len(valid_select))))) base = base.replace(search, replacement) base = base.replace('<> ', '') base = base.replace('<>', '') while '<paint>' in base: base = base.replace('<paint>', self.choice(PAINTS), 1) while '<medium>' in base: base = base.replace('<medium>', self.choice(MEDIUMS), 1) while '<sketch>' in base: base = base.replace('<sketch>', self.choice(SKETCHING), 1) while '<material>' in base: base = base.replace('<material>', self.choice(MATERIALS), 1) while '<animal>' in base: base = base.replace('<animal>', self.choice(ANIMALS), 1) while '<nature>' in base: base = base.replace('<nature>', self.choice(NATURE), 1) while '<philosophy>' in base: base = base.replace('<philosophy>', self.choice(PHILOSOPHIES), 1) while '<nation>' in base: if nation is not None: base = base.replace( '<nation>', str(self.choice(nation.parent.nations).name), 1) else: base = base.replace('<nation>', '') while '<notable_person>' in base: if nation is not None: base = base.replace( '<notable_person>', self.choice(nation.notable_people).name, 1) else: base = base.replace('<notable_person>', '') while '<notable_person_role>' in base: if nation is not None: person = self.choice(nation.notable_people) base = base.replace( '<notable_person_role>', '{} the {}'.format(person.name, person.periods[-1].role), 1) else: base = base.replace('<notable_person_role>', '') while '<god>' in base: if nation is not None: religion_populations = nation.get_nation_religion_populations( ) if len(religion_populations) > 0: religion, _ = utility.weighted_random_choice( religion_populations, weight=lambda i, (_, adherents): adherents) base = base.replace('<god>', self.choice(religion.gods).name, 1) else: base = base.replace('<god>', '') else: base = base.replace('<god>', '') while '<name>' in base: if nation is not None: base = base.replace('<name>', nation.language.generate_name(), 1) else: base = base.replace('<name>', '') while '<art>' in base: if nation is not None and len(nation.culture.art) > 0: base = base.replace( '<art>', '\'{}\''.format( self.choice(nation.culture.art).subject), 1) else: base = base.replace('<art>', '') while '<art_creator>' in base: if nation is not None and len(nation.culture.art) > 0: art = self.choice(nation.culture.art) base = base.replace( '<art_creator>', '{}\'s \'{}\''.format(art.creator.name, art.subject), 1) else: base = base.replace('<art_creator>', '') while '<place>' in base: if nation is not None and len( nation.parent.get_all_cities()) > 0: base = base.replace( '<place>', self.choice(nation.parent.get_all_cities()).name, 1) else: base = base.replace('<place>', '') while '<nation_place>' in base: if nation is not None and len(nation.cities) > 0: base = base.replace('<nation_place>', self.choice(nation.cities).name, 1) else: base = base.replace('<nation_place>', '') while '<battle>' in base: if nation is not None and len( nation.parent.battle_history) > 0: battle = self.choice(nation.parent.battle_history) battle_bases = [ '<The Battle of|The Battle for|>{}'.format( battle.location.name) ] base = base.replace( '<battle>', gen_simple_form(self.choice(battle_bases)), 1) else: base = base.replace('<battle>', '') while '<treaty>' in base: if nation is not None and len(nation.parent.treaties) > 0: treaty = self.choice( nation.parent.treaties).get_treaty_name( nation.parent.get_current_date(), nation) base = base.replace('<treaty>', treaty) else: base = base.replace('<treaty>', '') while '<nation_treaty>' in base: if nation is not None and len(nation.treaties) > 0: treaty = self.choice(nation.treaties).get_treaty_name( nation.parent.get_current_date(), nation) base = base.replace('<nation_treaty>', treaty) else: base = base.replace('<nation_treaty>', '') while '<weapon>' in base: base = base.replace( '<weapon>', self.choice(equipment_list.weapon_list).name, 1) while '<armor>' in base: base = base.replace( '<armor>', self.choice(equipment_list.armor_list).name, 1) while '<color>' in base: base = base.replace('<color>', self.choice(COLORS), 1) while '<flower>' in base: base = base.replace('<flower>', self.choice(FLOWERS), 1) while '<scientific_subject>' in base: base = base.replace('<scientific_subject>', self.choice(SCIENTIFIC_SUBJECTS), 1) while '<n>' in base: base = base.replace('<n>', self.choice(NOUNS), 1) while '<v>' in base: base = base.replace('<v>', self.choice(VERBS), 1) while '<prep>' in base: base = base.replace('<prep>', self.choice(PREPOSITIONS), 1) while '<adj>' in base: base = base.replace('<adj>', self.choice(ADJECTIVES), 1) if creator is not None: if '<self>' in base: base = base.replace('<self>', creator.name) if '<self_role>' in base: base = base.replace( '<self_role>', '{} the {}'.format(creator.name, creator.periods[-1].role)) randoms = re.findall(r'<rand(.*?);(.*?);(.*?)>', base) for rand_type, minimum, maximum in randoms: if rand_type == 'int': minimum, maximum = int(minimum), int(maximum) res = random.randint(minimum, maximum) elif rand_type == 'om': # Float minimum, maximum = float(minimum), float(maximum) res = random.random() * (maximum - minimum) + minimum base = base.replace( '<rand{};{};{}>'.format(rand_type, minimum, maximum), str(res)) # So we can access the previously used tags remaining_tags = re.findall(r'<(.*?)>', base) for check_tag in remaining_tags: if check_tag in self.chosen_tags: base = base.replace('<' + check_tag + '>', self.chosen_tags[check_tag]) elif check_tag in self.custom_tags: base = base.replace( '<' + check_tag + '>', self.choice(self.custom_tags[check_tag])) while True: try: i = base.index('<article>') base = base[:i] + base[i + len('<article>'):] next_word = re.sub(r'<.*?>', '', base) article = 'the ' for word in COUNTABLE_WORDS: if next_word.startswith(word): article = random.choice(['<indef>', 'the ']) break base = base[:i] + article + base[i:] except: break while True: try: i = base.index('<indef>') base = base[:i] + base[i + len('<indef>'):] test = re.sub(r'<.*?>', '', str(base)) if test[i].lower() in 'aeiou': article = 'an ' else: article = 'a ' base = base[:i] + article + base[i:] except: break while True: try: i = base.index('<cap>') base = base[:i] + base[i + len('<cap>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i].upper() + base[i + 1:] except: break while True: try: i = base.index('<lower>') base = base[:i] + base[i + len('<lower>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i].lower() + base[i + 1:] except: break while True: try: i = base.index('<all_lower>') base = base[:i] + base[i + len('<all_lower>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i:].lower() except: break while True: try: i = base.index('<titlecase>') base = base[:i] + base[i + len('<titlecase>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + utility.titlecase(test[i:]) except: break while True: try: i = base.index('<pl>') base = base[:i] + base[i + len('<pl>'):] test = re.sub(r'<.*?>', '', str(base[i:])) words = test.split() if len(words) > 0: next_word = words[0] if next_word in COUNTABLE_WORDS: if next_word in IRREGULAR_PLURALS: pluralized = IRREGULAR_PLURALS[next_word] else: pluralized = str(next_word) if next_word.endswith( 's') or next_word.endswith( 'x') or next_word.endswith( 'ch') or next_word.endswith( 'sh'): pluralized += 'es' elif next_word.endswith('y'): pluralized = pluralized[:-1] + 'ies' else: pluralized += 's' base = base.replace(next_word, pluralized) except: break conjugate = re.findall(r'<conj;(.*?);(.*?);(.*?);(.*?)>', base) for person, tense, number, verb in conjugate: conjugated = self.do_conjugate(verb, person, tense, number) base = base.replace( '<conj;{};{};{};{}>'.format(person, tense, number, verb), conjugated) conjugate = re.findall(r'<conj;(.*?);(.*?)>', base) for conj_type, verb in conjugate: conjugated = self.do_conjugate_type(verb, conj_type) base = base.replace('<conj;{};{}>'.format(conj_type, verb), conjugated) base = base.replace(' ', ' ').strip() self.chosen_tags[tag] = base
def history_step(self): self.name.history_step(self) # we lost our capital somehow if not self.has_capital(): # choose a new capital from our cities, weighted by population if len(self.cities) > 0: # Just to be sure new_capital = utility.weighted_random_choice( self.cities, weight=lambda i, v: v.population) new_capital.make_capital() else: self.mod_morale(city.CAPITAL_CITY_MORALE_BONUS) self.handle_treaties() for curCity in self.cities: # It's more likely to found a new city when this city is near population capacity # Because as there's no more space, people want to go to a new city found_city_chance = max( 1, int( len(self.cities)**2 * float(curCity.population_capacity) / curCity.population)) if random.randint( 0, found_city_chance) == 0 and self.money > CITY_FOUND_COST: self.create_city() if self.current_research is None or self.current_research.is_unlocked( ): if self.current_research is not None and self.current_research.is_unlocked( ): self.parent.event_log.add_event( 'TechResearch', { 'nation_a': self.id, 'tech_a': self.current_research.name }, self.parent.get_current_date()) available = self.tech.get_available_research() if len(available) > 0: self.current_research = random.choice(available) else: # There's nothing left to research self.current_research = None else: self.current_research.do_research( random.randint( 1, int(math.log(curCity.population + 1)**2 + 1))) for cell in curCity.cells: for building in cell.buildings: research_rate = building.get_research_rate() if research_rate > 0: self.current_research.do_research( random.randint(1, research_rate)) self.handle_rearming() self.handle_people() self.age += 1 # More cities means less happiness self.mod_morale(-(len(self.cities)**2 + 1))
def handle_army_dispatch(self): # Determine if we want to launch an attack with this city's army for city in self.cities: if len(self.at_war) > 0 and city.army.size() > 0: enemy = random.choice(self.at_war) # Make sure our enemy actually still exists. if len(enemy.cities) > 0 and enemy in self.parent.nations: attacking_city = utility.weighted_random_choice( enemy.cities, weight=lambda _, v: 1.0 / utility.distance( city.position, v.position)) if random.randint( 0, max( 20, city.army.size() + city.population // 8 - attacking_city.population // 3 - attacking_city.army.size())) > 20: if random.randint(0, len(self.moving_armies)**3) == 0: fx, fy = city.position dx, dy = attacking_city.position # Conscript some levies to join the army. if city.population // 3 > 1: conscript_max = max(city.population // 4, 3) conscript_min = min(city.population // 8, 2) conscripted = int( random.randint(conscript_min, conscript_max) * self.get_conscription_bonus()) else: conscripted = 0 city.population -= conscripted city.army.add_to(city.army.name, conscripted) action = self.parent.do_attack( self, city, enemy, attacking_city) self.moving_armies.append( Group(self.parent, self.id, city.army, (fx, fy), (dx, dy), self.color, lambda s: False, action, is_army=True, has_boat=(city.resources['boats'] > 0))) self.parent.event_log.add_event( 'ArmyDispatched', { 'nation_a': self.id, 'nation_b': enemy.id, 'city_a': city.name, 'city_b': attacking_city.name, 'reason': 'attack', 'army_size': city.army.size() }, self.parent.get_current_date()) city.army = city.army.zero()
def generate_tags(self, actual_forms, nation=None, creator=None): # So that tags are generated in the correct order. tag_order = [] for form in actual_forms: for part in form: if part.startswith('tag:'): tag_order.append(part.split(':')[1]) for tag in tag_order: base = self.tags[tag] # () allow you to group text without using any actual tag # For example, <test:(<animal>'s hair)> allows you to give the name 'test' to 'lion's hair' while '<(' in base: i = base.find('<(') # Get the full tag and remove the brackets group = utility.get_container(base, '<', '>', i) base = base.replace(group, group[2:-2]) # Remove the containing stuff # Checks if tags exist. Replaces the tag's text with the first tag that exists. Otherwise replaces it with nothing. while '<tagexists' in base: i = base.find('<tagexists') section = utility.get_container(base, '<', '>', i) check_tags = section[1:-1].split(';')[1:] replacement = '' for tag_name in check_tags: if tag_name in self.chosen_tags: replacement = self.chosen_tags[tag_name] base = base.replace(section, replacement) while '|' in base: start_pos, end_pos = utility.find_container_of(base, '<', '>', '|') choice_section = base[start_pos + 1:end_pos] choice = utility.separate_container(choice_section, '<', '>', '|') valid_choice = filter(is_valid(nation), choice) base = base.replace('<' + choice_section + '>', self.choice(valid_choice), 1) while ',' in base: start_pos, end_pos = utility.find_container_of(base, '<', '>', ',') select_section = base[start_pos + 1:end_pos] select = utility.separate_container(select_section, '<', '>', ',') valid_select = filter(is_valid(nation), select) search = '<' + select_section + '>' replacement = '<{}>'.format( '> <'.join(random.sample(valid_select, random.randint(1, len(valid_select))))) base = base.replace(search, replacement) base = base.replace('<> ', '') base = base.replace('<>', '') while '<paint>' in base: base = base.replace('<paint>', self.choice(PAINTS), 1) while '<medium>' in base: base = base.replace('<medium>', self.choice(MEDIUMS), 1) while '<sketch>' in base: base = base.replace('<sketch>', self.choice(SKETCHING), 1) while '<material>' in base: base = base.replace('<material>', self.choice(MATERIALS), 1) while '<animal>' in base: base = base.replace('<animal>', self.choice(ANIMALS), 1) while '<nature>' in base: base = base.replace('<nature>', self.choice(NATURE), 1) while '<philosophy>' in base: base = base.replace('<philosophy>', self.choice(PHILOSOPHIES), 1) while '<nation>' in base: if nation is not None: base = base.replace('<nation>', str(self.choice(nation.parent.nations).name), 1) else: base = base.replace('<nation>', '') while '<notable_person>' in base: if nation is not None: base = base.replace('<notable_person>', self.choice(nation.notable_people).name, 1) else: base = base.replace('<notable_person>', '') while '<notable_person_role>' in base: if nation is not None: person = self.choice(nation.notable_people) base = base.replace('<notable_person_role>', '{} the {}'.format(person.name, person.periods[-1].role), 1) else: base = base.replace('<notable_person_role>', '') while '<god>' in base: if nation is not None: religion_populations = nation.get_nation_religion_populations() if len(religion_populations) > 0: religion, _ = utility.weighted_random_choice(religion_populations, weight=lambda i, (_, adherents): adherents) base = base.replace('<god>', self.choice(religion.gods).name, 1) else: base = base.replace('<god>', '') else: base = base.replace('<god>', '') while '<name>' in base: if nation is not None: base = base.replace('<name>', nation.language.generate_name(), 1) else: base = base.replace('<name>', '') while '<art>' in base: if nation is not None and len(nation.culture.art) > 0: base = base.replace('<art>', '\'{}\''.format(self.choice(nation.culture.art).subject), 1) else: base = base.replace('<art>', '') while '<art_creator>' in base: if nation is not None and len(nation.culture.art) > 0: art = self.choice(nation.culture.art) base = base.replace('<art_creator>', '{}\'s \'{}\''.format(art.creator.name, art.subject), 1) else: base = base.replace('<art_creator>', '') while '<place>' in base: if nation is not None and len(nation.parent.get_all_cities()) > 0: base = base.replace('<place>', self.choice(nation.parent.get_all_cities()).name, 1) else: base = base.replace('<place>', '') while '<nation_place>' in base: if nation is not None and len(nation.cities) > 0: base = base.replace('<nation_place>', self.choice(nation.cities).name, 1) else: base = base.replace('<nation_place>', '') while '<battle>' in base: if nation is not None and len(nation.parent.battle_history) > 0: battle = self.choice(nation.parent.battle_history) battle_bases = ['<The Battle of|The Battle for|>{}'.format(battle.location.name)] base = base.replace('<battle>', gen_simple_form(self.choice(battle_bases)), 1) else: base = base.replace('<battle>', '') while '<treaty>' in base: if nation is not None and len(nation.parent.treaties) > 0: treaty = self.choice(nation.parent.treaties).get_treaty_name(nation.parent.get_current_date(), nation) base = base.replace('<treaty>', treaty) else: base = base.replace('<treaty>', '') while '<nation_treaty>' in base: if nation is not None and len(nation.treaties) > 0: treaty = self.choice(nation.treaties).get_treaty_name(nation.parent.get_current_date(), nation) base = base.replace('<nation_treaty>', treaty) else: base = base.replace('<nation_treaty>', '') while '<weapon>' in base: base = base.replace('<weapon>', self.choice(equipment_list.weapon_list).name, 1) while '<armor>' in base: base = base.replace('<armor>', self.choice(equipment_list.armor_list).name, 1) while '<color>' in base: base = base.replace('<color>', self.choice(COLORS), 1) while '<flower>' in base: base = base.replace('<flower>', self.choice(FLOWERS), 1) while '<scientific_subject>' in base: base = base.replace('<scientific_subject>', self.choice(SCIENTIFIC_SUBJECTS), 1) while '<n>' in base: base = base.replace('<n>', self.choice(NOUNS), 1) while '<v>' in base: base = base.replace('<v>', self.choice(VERBS), 1) while '<prep>' in base: base = base.replace('<prep>', self.choice(PREPOSITIONS), 1) while '<adj>' in base: base = base.replace('<adj>', self.choice(ADJECTIVES), 1) if creator is not None: if '<self>' in base: base = base.replace('<self>', creator.name) if '<self_role>' in base: base = base.replace('<self_role>', '{} the {}'.format(creator.name, creator.periods[-1].role)) randoms = re.findall(r'<rand(.*?);(.*?);(.*?)>', base) for rand_type, minimum, maximum in randoms: if rand_type == 'int': minimum, maximum = int(minimum), int(maximum) res = random.randint(minimum, maximum) elif rand_type == 'om': # Float minimum, maximum = float(minimum), float(maximum) res = random.random() * (maximum - minimum) + minimum base = base.replace('<rand{};{};{}>'.format(rand_type, minimum, maximum), str(res)) # So we can access the previously used tags remaining_tags = re.findall(r'<(.*?)>', base) for check_tag in remaining_tags: if check_tag in self.chosen_tags: base = base.replace('<' + check_tag + '>', self.chosen_tags[check_tag]) elif check_tag in self.custom_tags: base = base.replace('<' + check_tag + '>', self.choice(self.custom_tags[check_tag])) while True: try: i = base.index('<article>') base = base[:i] + base[i + len('<article>'):] next_word = re.sub(r'<.*?>', '', base) article = 'the ' for word in COUNTABLE_WORDS: if next_word.startswith(word): article = random.choice(['<indef>', 'the ']) break base = base[:i] + article + base[i:] except: break while True: try: i = base.index('<indef>') base = base[:i] + base[i + len('<indef>'):] test = re.sub(r'<.*?>', '', str(base)) if test[i].lower() in 'aeiou': article = 'an ' else: article = 'a ' base = base[:i] + article + base[i:] except: break while True: try: i = base.index('<cap>') base = base[:i] + base[i + len('<cap>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i].upper() + base[i + 1:] except: break while True: try: i = base.index('<lower>') base = base[:i] + base[i + len('<lower>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i].lower() + base[i + 1:] except: break while True: try: i = base.index('<all_lower>') base = base[:i] + base[i + len('<all_lower>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + test[i:].lower() except: break while True: try: i = base.index('<titlecase>') base = base[:i] + base[i + len('<titlecase>'):] test = re.sub(r'<.*?>', '', str(base)) base = base[:i] + utility.titlecase(test[i:]) except: break while True: try: i = base.index('<pl>') base = base[:i] + base[i + len('<pl>'):] test = re.sub(r'<.*?>', '', str(base[i:])) words = test.split() if len(words) > 0: next_word = words[0] if next_word in COUNTABLE_WORDS: if next_word in IRREGULAR_PLURALS: pluralized = IRREGULAR_PLURALS[next_word] else: pluralized = str(next_word) if next_word.endswith('s') or next_word.endswith('x') or next_word.endswith( 'ch') or next_word.endswith('sh'): pluralized += 'es' elif next_word.endswith('y'): pluralized = pluralized[:-1] + 'ies' else: pluralized += 's' base = base.replace(next_word, pluralized) except: break conjugate = re.findall(r'<conj;(.*?);(.*?);(.*?);(.*?)>', base) for person, tense, number, verb in conjugate: conjugated = self.do_conjugate(verb, person, tense, number) base = base.replace('<conj;{};{};{};{}>'.format(person, tense, number, verb), conjugated) conjugate = re.findall(r'<conj;(.*?);(.*?)>', base) for conj_type, verb in conjugate: conjugated = self.do_conjugate_type(verb, conj_type) base = base.replace('<conj;{};{}>'.format(conj_type, verb), conjugated) base = base.replace(' ', ' ').strip() self.chosen_tags[tag] = base