Skip to content

Commit

Permalink
add: Created a simulation function for the Yayoi period.
Browse files Browse the repository at this point in the history
  • Loading branch information
AsPJT committed May 24, 2024
1 parent d45d5b2 commit 8cb2b8b
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 68 deletions.
4 changes: 2 additions & 2 deletions Library/PAX_MAHOROBA/LocationPoint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,9 +678,9 @@ namespace paxs {
// if (lli.lpe == MurMur3::calcHash("agent1"))
{
// const std::size_t pop_original = settlement.getFarmingPopulation(); // settlement.getPopulation();
const float pop_original = settlement.getFarmingPopulation() / float(settlement.getPopulation()) * 80.0f; // settlement.getPopulation();
const float pop_original = settlement.getFarmingPopulation() / float(settlement.getPopulation()) * 75.0f; // settlement.getPopulation();

const std::uint_least8_t pop = (pop_original >= 80) ? 80 : static_cast<std::uint_least8_t>(pop_original);
const std::uint_least8_t pop = (pop_original >= 75) ? 75 : static_cast<std::uint_least8_t>(pop_original);
paxg::Circle(draw_pos,
1.0f + (settlement.getPopulation() / 40.0f)//2.0f
).draw(getColor(pop));
Expand Down
4 changes: 2 additions & 2 deletions Library/PAX_SAPIENTICA/Simulation/Chromosome.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace paxs {
/// @brief 染色体
class Chromosome {
public:
static constexpr std::uint_least8_t chromosome_length = 46;
static constexpr std::uint_least8_t chromosome_length = 2;// 46;
Chromosome() = default;

std::uint_least8_t get(const std::uint_least8_t index) const noexcept {
Expand All @@ -53,7 +53,7 @@ namespace paxs {
return os;
}

std::uint_least8_t getGender() const noexcept {
constexpr std::uint_least8_t getGender() const noexcept {
return gender;
}

Expand Down
2 changes: 1 addition & 1 deletion Library/PAX_SAPIENTICA/Simulation/Genome.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace paxs {
yDNA = value;
}

std::uint_least8_t getGender() const noexcept {
constexpr std::uint_least8_t getGender() const noexcept {
return chromosome.getGender();
}

Expand Down
9 changes: 4 additions & 5 deletions Library/PAX_SAPIENTICA/Simulation/JapanProvinces.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ namespace paxs {
std::uint_least8_t region_id; // 対応する地方区分ID
std::uint_least32_t settlement_population_min_ad200;
std::uint_least32_t settlement_population_max_ad200;
std::uint_least32_t population_ad200;
std::uint_least32_t population_ad725;
std::uint_least32_t population[4];
};

/// @brief A class that represents a prefecture in Japan.
Expand Down Expand Up @@ -79,8 +78,8 @@ namespace paxs {
ryoseikoku.region_id = static_cast<std::uint_least8_t>(std::stoi(ryoseikoku_tsv[i][2]));
ryoseikoku.settlement_population_min_ad200 = std::stoi(ryoseikoku_tsv[i][3]);
ryoseikoku.settlement_population_max_ad200 = std::stoi(ryoseikoku_tsv[i][4]);
ryoseikoku.population_ad200 = std::stoi(ryoseikoku_tsv[i][5]);
ryoseikoku.population_ad725 = std::stoi(ryoseikoku_tsv[i][6]);
ryoseikoku.population[0/*ad200*/] = std::stoi(ryoseikoku_tsv[i][5]);
ryoseikoku.population[1/*ad725*/] = std::stoi(ryoseikoku_tsv[i][6]);
ryoseikoku_list.emplace_back(ryoseikoku);
} catch (const std::invalid_argument&) {
PAXS_WARNING("Failed to read Ryoseikoku TSV file: " + ryoseikoku_tsv_path + " at line " + std::to_string(i));
Expand Down Expand Up @@ -133,7 +132,7 @@ namespace paxs {
std::uint_least32_t getRyoseikokuPopulationAd200(const std::uint_least8_t id) const noexcept {
for (const auto& ryoseikoku : ryoseikoku_list) {
if (ryoseikoku.id == id) {
return ryoseikoku.population_ad200;
return ryoseikoku.population[0/*ad200*/];
}
}
PAXS_WARNING("Failed to get Ryoseikoku population: " + std::to_string(id));
Expand Down
28 changes: 19 additions & 9 deletions Library/PAX_SAPIENTICA/Simulation/Settlement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ namespace paxs {
// 結婚可能かどうか
if (agents[i].isAbleToMarriage() && agents[i].getGender() == SimulationConstants::getInstance()->female) {
if (!isMarried(agents[i].getAge())) continue;
// 妊娠していたら婚姻しない(婚姻可能と定義すると再婚者のデータで上書きされ子供への継承が不自然になる)
if (agents[i].getBirthIntervalCount() > 0) continue;

marriageable_female_index.emplace_back(i);
}
Expand Down Expand Up @@ -273,7 +275,7 @@ namespace paxs {
/// @brief 事前更新
void preUpdate(KanakumaLifeSpan& kanakuma_life_span, std::uint_least64_t& count) noexcept {
birth(kanakuma_life_span);
emigration(kanakuma_life_span, count);
//emigration(kanakuma_life_span, count);
}

/// @brief On update.
Expand Down Expand Up @@ -399,18 +401,26 @@ namespace paxs {
if (agent.getBirthIntervalCount() > 0) {
std::uint_least8_t count = agent.decrementBirthIntervalCount();
if (count == 0) {
// 死産
if (random_dist(*gen) < 0.11f) continue;
// 死産率 100 %の場合は出産しない
if (SimulationConstants::getInstance()->stillbirth_rate >= 1.0f) continue;
else if (SimulationConstants::getInstance()->stillbirth_rate > 0.0f) {
// 死産
if (random_dist(*gen) < SimulationConstants::getInstance()->stillbirth_rate) continue;
}
// TODO: 直す
if (!agent.isMarried()) continue;
//if (!agent.isMarried()) continue;
Genome genome = Genome::generateFromParents(agent.cgetGenome(), agent.cgetPartnerGenome());
children.emplace_back(Agent(
UniqueIdentification<std::uint_least64_t>::generate(),
0, // TODO: 名前ID
UniqueIdentification<std::uint_least32_t>::generate(),
//0, // TODO: 名前ID
0,
kanakuma_life_span.setLifeSpan(genome.getGender(), *gen),
genome,
(((*gen)() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
(agent.cgetFarming() > 0 && agent.cgetPartnerFarming() > 0) ? 255 :(
(agent.cgetFarming() == 0 && agent.cgetPartnerFarming() == 0) ? 0 : (
(random_dist(*gen) < SimulationConstants::getInstance()->child_agriculture_priority) ? 255 : 0
)),
//(((*gen)() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
(((*gen)() % 2) == 0) ? agent.cgetHunterGatherer() : agent.cgetPartnerHunterGatherer()
));
}
Expand Down Expand Up @@ -439,8 +449,8 @@ namespace paxs {
static_cast<int>(set_lifespan - 1) }; // 性別の乱数分布

agents.emplace_back(Agent(
UniqueIdentification<std::uint_least64_t>::generate(),
0, // TODO: 名前ID
UniqueIdentification<std::uint_least32_t>::generate(),
//0, // TODO: 名前ID
lifespan_dist(*gen),
set_lifespan,
genome,
Expand Down
33 changes: 17 additions & 16 deletions Library/PAX_SAPIENTICA/Simulation/SettlementAgent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,18 @@ namespace paxs {

SettlementAgent() = default;

explicit SettlementAgent(const std::uint_least64_t id, const std::uint_least32_t& name_id,
explicit SettlementAgent(const std::uint_least32_t id, //const std::uint_least32_t& name_id,
const std::uint_least32_t age, const std::uint_least32_t life_span, const Genome& genome,
std::uint_least8_t farming_, // 農耕文化
std::uint_least8_t hunter_gatherer_ // 狩猟採集文化
) noexcept
: id(id), name_id(name_id), gender(genome.getGender()), age(age), life_span(life_span), genome(genome),
: id(id), //name_id(name_id),
age(age), life_span(life_span), genome(genome),
farming(farming_), hunter_gatherer(hunter_gatherer_) {}

/// @brief Get the id.
/// @brief idを取得
constexpr std::uint_least64_t getId() const noexcept { return id; }
constexpr std::uint_least32_t getId() const noexcept { return id; }

/// @brief Is the agent dead?
/// @brief エージェントが死んでいるかどうかを返す
Expand All @@ -61,7 +62,7 @@ namespace paxs {

/// @brief Get the agent's age.
/// @brief エージェントの性別を取得する
constexpr std::uint_least8_t getGender() const noexcept { return gender; }
constexpr std::uint_least8_t getGender() const noexcept { return genome.getGender(); }

/// @brief Increment the agent's age.
/// @brief エージェントの年齢をインクリメントする
Expand Down Expand Up @@ -91,8 +92,8 @@ namespace paxs {

constexpr bool operator==(const SettlementAgent& a) const noexcept {
return id == a.id &&
name_id == a.name_id &&
gender == a.gender &&
//name_id == a.name_id &&
//gender == a.gender &&
age == a.age &&
life_span == a.life_span &&
genome == a.genome &&
Expand All @@ -108,7 +109,7 @@ namespace paxs {

/// @brief Set the agent's marriage status.
/// @brief 結婚する
void marry(const std::uint_least64_t partner_id_, const Genome& partner_genome_,
void marry(const std::uint_least32_t partner_id_, const Genome& partner_genome_,
std::uint_least8_t partner_farming_, // 結婚相手の農耕文化
std::uint_least8_t partner_hunter_gatherer_ // 結婚相手の狩猟採集文化
) noexcept {
Expand All @@ -123,10 +124,10 @@ namespace paxs {
/// @brief エージェントが結婚可能かどうかを返す
bool isAbleToMarriage() const noexcept {
float age_f = static_cast<float>(age) / SimulationConstants::getInstance()->steps_per_year;
return age_f > (gender ?
return age_f > (genome.getGender() ?
SimulationConstants::getInstance()->male_marriageable_age_min :
SimulationConstants::getInstance()->female_marriageable_age_min) &&
age_f < (gender ?
age_f < (genome.getGender() ?
SimulationConstants::getInstance()->male_marriageable_age_max :
SimulationConstants::getInstance()->male_marriageable_age_max) &&
!is_married;
Expand All @@ -142,16 +143,16 @@ namespace paxs {

/// @brief Get the partner's ID.
/// @brief 結婚相手のIDを取得
std::uint_least64_t getPartnerId() const noexcept { return partner_id; }
std::uint_least32_t getPartnerId() const noexcept { return partner_id; }

/// @brief Divorce.
/// @brief 離婚
void divorce() noexcept {
is_married = false;
partner_id = 0;
// partner_genome = nullptr;
partner_farming = 0;
partner_hunter_gatherer = 0;
//partner_farming = 0;
//partner_hunter_gatherer = 0;
}

std::uint_least8_t getBirthIntervalCount() const noexcept { return birth_interval_count; }
Expand All @@ -160,7 +161,7 @@ namespace paxs {

protected:
bool is_married = false; // 結婚しているかどうか
std::uint_least8_t gender; // 性別: 0 -> 女性, 1 -> 男性
//std::uint_least8_t gender; // 性別: 0 -> 女性, 1 -> 男性
std::uint_least8_t birth_interval_count = 0; // 出産の間隔のカウント

std::uint_least8_t farming = 0; // 農耕文化
Expand All @@ -170,10 +171,10 @@ namespace paxs {

std::uint_least32_t age; // 年齢
std::uint_least32_t life_span; // 寿命
std::uint_least32_t name_id; // 名前のID
//std::uint_least32_t name_id; // 名前のID

std::uint_least64_t id; // ID
std::uint_least64_t partner_id = 0; // 結婚相手のID
std::uint_least32_t id; // ID
std::uint_least32_t partner_id = 0; // 結婚相手のID

Genome genome; // ゲノム
Genome partner_genome; // 結婚相手のゲノム
Expand Down
82 changes: 50 additions & 32 deletions Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ namespace paxs {
/// @details 集落をクリアし、地域ごとに指定されたエージェント数になるようにランダムに配置する
void init() {
settlement_grids.clear();
randomizeSettlements();
initRandomizeSettlements();
randomizeSettlements(0, 0, 255);
}

/// @brief Run the simulation for the specified number of steps.
Expand Down Expand Up @@ -130,6 +131,8 @@ namespace paxs {
}
}

randomizeSettlements(1, 255, 0);

auto delete_agent = [this](const std::uint_least64_t agent_id, const std::uint_least32_t settlement_id, const Vector2 key) {
auto it = settlement_grids.find(key.toU64());
if (it != settlement_grids.end()) {
Expand Down Expand Up @@ -203,31 +206,34 @@ namespace paxs {

std::uint_least64_t emigration_count = 0;

/// @brief Randomly place settlements.
/// @brief 集落をランダムに配置する
void randomizeSettlements() noexcept {
// 陸の位置のリストを取得
std::vector<std::uint64_t> land_positions;

struct Live {
// 可住地重みリスト
std::vector<int> live_probabilities;
// 可住地の位置
std::vector<std::uint64_t> habitable_land_positions;

void emplaceBack(const int live_probabilities_, const std::uint64_t habitable_land_positions_) {
live_probabilities.emplace_back(live_probabilities_);
habitable_land_positions.emplace_back(habitable_land_positions_);
}
};
std::unique_ptr<std::array<Live, 90>> live_list;

/// @brief ()
/// @brief 集落をランダムに配置する前の初期化処理
bool initRandomizeSettlements() {
std::cout << "Randomize settlements..." << std::endl;

// 陸の位置のリストを取得
std::vector<std::uint64_t> land_positions;
environment->getLandPositions(land_positions);

struct Live {
// 可住地重みリスト
std::vector<int> live_probabilities;
// 可住地の位置
std::vector<std::uint64_t> habitable_land_positions;
live_list = std::unique_ptr<std::array<Live, 90>>(new std::array<Live, 90>());

void emplaceBack(const int live_probabilities_, const std::uint64_t habitable_land_positions_) {
live_probabilities.emplace_back(live_probabilities_);
habitable_land_positions.emplace_back(habitable_land_positions_);
}
};

std::unique_ptr<std::array<Live, 90>> live_list(new std::array<Live, 90>());
if (live_list.get() == nullptr) {
std::cout << "Low memory" << std::endl;
return; // 処理失敗
return false; // 処理失敗
}

for (const std::uint64_t land_position : land_positions) {
Expand Down Expand Up @@ -259,14 +265,24 @@ namespace paxs {
(*live_list)[ryoseikoku_id].emplaceBack(live_probability, land_position);
}
}
return true;
}

/// @brief Randomly place settlements.
/// @brief 集落をランダムに配置する
void randomizeSettlements(
std::size_t ad200,
std::uint_least8_t farming,
std::uint_least8_t hunter_gatherer
) noexcept {

// 令制国と人口のマップ
std::unordered_map<std::uint_least8_t, std::uint_least32_t> ryoseikoku_population_map;
for (auto& ryoseikoku : japan_provinces->cgetRyoseikokuList()) {
if (ryoseikoku.population_ad200 == 0) {
if (ryoseikoku.population[ad200/*ad200*/] == 0) {
continue;
}
ryoseikoku_population_map[ryoseikoku.id] = ryoseikoku.population_ad200;
ryoseikoku_population_map[ryoseikoku.id] = ryoseikoku.population[ad200/*ad200*/];
}

int all_population = 0;
Expand Down Expand Up @@ -329,14 +345,15 @@ namespace paxs {

std::uniform_int_distribution<> lifespan_dist{ 0, static_cast<int>(set_lifespan - 1) }; // 性別の乱数分布

settlement.setAgent(Agent(UniqueIdentification<std::uint_least64_t>::generate(),
0, // TODO: 名前ID
settlement.setAgent(Agent(UniqueIdentification<std::uint_least32_t>::generate(),
//0, // TODO: 名前ID
lifespan_dist(gen),
set_lifespan,
genome,
0, // ((gen() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
255 // ((gen() % 2) == 0) ? agent.cgetHunterGatherer() : agent.cgetPartnerHunterGatherer()
farming, // ((gen() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
hunter_gatherer // ((gen() % 2) == 0) ? agent.cgetHunterGatherer() : agent.cgetPartnerHunterGatherer()
), static_cast<std::size_t>(i));
if (farming > 0) ++emigration_count; // 農耕カウント
}

// 令制国の人口を減らす
Expand All @@ -356,8 +373,8 @@ namespace paxs {
live.habitable_land_positions.pop_back();
}
}
StatusDisplayer::displayProgressBar(all_population, all_population);
std::cout << std::endl;
//StatusDisplayer::displayProgressBar(all_population, all_population);
//std::cout << std::endl;

// 令制国の人口が残っている場合は、ランダムに配置
for (auto& ryoseikoku_population : ryoseikoku_population_map) {
Expand All @@ -382,20 +399,21 @@ namespace paxs {
std::uniform_int_distribution<> lifespan_dist{ 0, static_cast<int>(set_lifespan - 1) }; // 性別の乱数分布

agents[i] = Agent(
UniqueIdentification<std::uint_least64_t>::generate(),
0, // TODO: 名前ID
UniqueIdentification<std::uint_least32_t>::generate(),
//0, // TODO: 名前ID
lifespan_dist(gen),
set_lifespan,
genome,
0, // ((gen() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
255 // ((gen() % 2) == 0) ? agent.cgetHunterGatherer() : agent.cgetPartnerHunterGatherer()
farming, // ((gen() % 2) == 0) ? agent.cgetFarming() : agent.cgetPartnerFarming(),
hunter_gatherer // ((gen() % 2) == 0) ? agent.cgetHunterGatherer() : agent.cgetPartnerHunterGatherer()
);
if (farming > 0) ++emigration_count; // 農耕カウント
}
settlement.addAgents(agents);
}
}

std::cout << "Done." << std::endl;
//std::cout << "Done." << std::endl;
}

/// @brief 指定した令制国のIDの集落グリッドを取得
Expand Down
Loading

0 comments on commit 8cb2b8b

Please sign in to comment.