def _update_children(self, prosp): mortality = self._mortality["children"] * Utils.opposite(prosp) n_children = self._children [dead, grown] = Utils.rsplit(n_children, mortality) [men, women] = Utils.rsplit(grown, self._grown_rates["men-women"]) # print("Dead children: " + str(dead)) return [-dead, men, women, 0, 0]
def _get_men_availability_factor(young_men, young_women): if young_women > 0: men_factor = young_men / young_women res = (men_factor * 0.5) / 2 return Utils.saturate(Utils.saturate(res, 1.0), men_factor * 3) else: return 0
def _update_births(self, prosp): n_young_men = self._young_men n_young_women = self._young_women men_availability_factor = self._get_men_availability_factor(n_young_men, n_young_women) women_fertility = n_young_women * self._grown_rates["women-fertility"] * Utils.perturbate_high(prosp) births = round(women_fertility * men_availability_factor) return [births, 0, 0, 0, 0]
def migrate(group, world, information, verbose): """ This event checks if a group migrates from it's current position. If the event occurs a fact is added to the group. :param group: The group to check. :param world: The world. :param information: A dictionary with the information for the events. :param verbose: True if the event has to register into facts, False otherwise """ if random.random() < chance_to_migrate(group, world, information["occupied_positions"]): positions = land_cells_around(world, group.position, group.migration_radius, information["occupied_positions"]) prosperity = ([Utils.perturbate_low(group.get_prosperity(world, p)), p] for p in positions) best = max(prosperity) group.position = best[1] fact = "{} is moving to better lands {}.".format(group.name, best[1]) if verbose: if information["turn"] in group.facts: group.facts[information["turn"]].append(fact) else: group.facts[information["turn"]] = [fact] if information["turn"] in group.file_facts: group.file_facts[information["turn"]]['pos'] = best[1] else: group.file_facts[information["turn"]] = {'pos': best[1]}
def chance_to_discover_agriculture(group, world): if group.nomadism != "nomadic" and not ("Agriculture" in group.activities): agr_prosp = group.get_base_prosperity_per_activity("Agriculture", world, group.position) p = (agr_prosp - 0.75) * 6.0 p *= discovery_population_factor(group.total_persons, 200) return Utils.saturate(max(0.0, p), 0.3) else: return 0
def chance_to_become_sedentary(group): if group.nomadism == "semi-sedentary" and "Agriculture" in group.activities: prosperity = group.prosperity if prosperity > 0.72: return Utils.saturate((prosperity - 0.75) / 1.5, 0.2) else: return 0 else: return 0
def get_prosperity_per_activity(self, world, position): """ This function returns the prosperity of each activity of group in the given position. :param world: The world in which the group lives. :param position: The position to check. :return: A list with the prosperity for each activity of the group. """ prosperity = [] for activity in self.activities: base = self.get_base_prosperity_per_activity(activity, world, position) crowding = self._get_crowding_per_activity(activity) prosperity.append(Utils.saturate(base * crowding, 1.0)) return prosperity
def chance_to_develop_trade(group, occupied_positions): if group.nomadism == "sedentary" and not group.knows_trade: neighbours = groups_around(group.position, group.trade_radius, occupied_positions) if neighbours > 0: prosperity = group.prosperity if prosperity > 0.8: return Utils.saturate((prosperity - 0.78) / 1.3, 0.3) else: return 0.05 else: return 0 else: return 0
def _update_old(self, prosp): mortality_men = Utils.saturate(self._mortality["old-men"] * Utils.opposite(prosp), 1.0) mortality_women = Utils.saturate(self._mortality["old-women"] * Utils.opposite(prosp), 1.0) n_old_men = self._old_men n_old_women = self._old_women [m_dead, m_alive] = Utils.rsplit(n_old_men, mortality_men) [w_dead, w_alive] = Utils.rsplit(n_old_women, mortality_women) # print("Dead old men: " + str(m_dead) + " dead old women: " + str(w_dead)) return [0, 0, 0, -m_dead, -w_dead]
def _update_young(self, prosp): mortality_men = self._mortality["young-men"] * Utils.opposite(prosp) mortality_women = self._mortality["young-women"] * Utils.opposite(prosp) n_young_men = self._young_men n_young_women = self._young_women [m_dead, m_alive] = Utils.rsplit(n_young_men, mortality_men) [w_dead, w_alive] = Utils.rsplit(n_young_women, mortality_women) [m_grown, m_rest] = Utils.rsplit(m_alive, self._grown_rates["old-men"]) [w_grown, w_rest] = Utils.rsplit(w_alive, self._grown_rates["old-women"]) # print("Dead young men: " + str(m_dead) + " dead young women: " + str(w_dead)) return [0, -1 * (m_dead + m_grown), -1 * (w_dead + w_grown), m_grown, w_grown]
def __init__(self, position, tribe, default, id): """ This will create a group in the given position, and with the given parameters. The tribe parameters will be merged with the default ones. :param position: The position to set the group. :param tribe: A dictionary containing all the custom parameters for the group. :param default: A dictionary containing all the default parameters for all the groups. """ self._position = position self.id = id mix_tribe = copy.deepcopy(tribe) def_tribe = copy.deepcopy(default) mix_tribe = Utils.update(mix_tribe, def_tribe) self._tribe = mix_tribe self.name = eval(mix_tribe["Name"])(mix_tribe["Name-rules"]) self.type = mix_tribe["Type"] self._children = random.randrange(0, mix_tribe["Max-initial-population"]["children"]) self._young_men = random.randrange(0, mix_tribe["Max-initial-population"]["young-men"]) self._young_women = random.randrange(0, mix_tribe["Max-initial-population"]["young-women"]) self._old_men = random.randrange(0, mix_tribe["Max-initial-population"]["old-men"]) self._old_women = random.randrange(0, mix_tribe["Max-initial-population"]["old-women"]) self.activities = mix_tribe["Start-activities"] self._max_populations = mix_tribe["Max-population-for-activity"] self._biomes_prosperity_per_activity = mix_tribe["Biomes-prosperity-per-activity"] self._crowding_per_activity = mix_tribe["Crowding-for-activity"] self._mortality = mix_tribe["Mortality-rates"] self._grown_rates = mix_tribe["Grown-rates"] self._last_prosperity = 0 self.nomadism = "nomadic" self._events = mix_tribe["Events"] self._migration_radius = mix_tribe["Migration-radius"] self._migration_rate = mix_tribe["Migration-rate"] self.facts = {} self.file_facts = {} self._wealth = 0 self._wealth_base_multiplier = mix_tribe["Wealth-base-multiplier"] self._trade_radius = mix_tribe["Trade-base-radius"] self.knows_trade = False self.file_facts[0] = {'pos': self._position, 'nomadism': 'nomadic'}
def groups_around_info(pos, radius, groups): rad = range(-radius, radius + 1) positions = itertools.product(rad, rad) occupied = [g.position for g in groups] g_positions = [Utils.add_list(pos, p) for p in positions if Utils.add_list(pos, p) in occupied and not p == (0, 0)] return [g for g in groups if g.position in g_positions]
def groups_around(pos, radius, occupied_positions): rad = range(-radius, radius + 1) positions = itertools.product(rad, rad) return len([p for p in positions if Utils.add_list(pos, p) in occupied_positions and not p == (0, 0)])
def land_cells_around(world, pos, radius, occupied_positions): rad = range(-radius, radius + 1) positions = itertools.product(rad, rad) filtered = (Utils.add_list(pos, p) for p in positions if inside_world(world, Utils.add_list(pos, p))) land = (p for p in filtered if is_land(world, p)) return (p for p in land if p not in occupied_positions)
def chance_to_become_semi_sedentary(group): prosperity = group.prosperity if group.nomadism == "nomadic" and prosperity > 0.6: return Utils.saturate((prosperity - 0.75) / 1.5, 0.1) else: return 0
def chance_to_trade(group, information): if group.knows_trade: neighbours = groups_around_info(group.position, group.trade_radius, information["groups"]) chance = Utils.saturate(len(neighbours) / (group.trade_radius * group.trade_radius - 1), 0.8) return [chance, neighbours] return [0, 0]