-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathperson.py
105 lines (89 loc) · 4.5 KB
/
person.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import random
import uuid
from person_gene import PersonGene
import constants as const
import numpy as np
class Person:
def __init__(
self,
genes: dict[str, PersonGene],
age: int,
death_age: int,
max_offspring: int,
parents):
self._genes: dict[str, PersonGene] = genes
self.is_male_sex = random.choice([True, False])
self.age = age
self.death_age = death_age
self.max_offspring = max_offspring # Only for females this matters really
self.reproductive_age = np.random.normal(13, 0.5)
self.max_reproductive_age = np.random.normal(45, 0.5) if not self.is_male_sex else np.random.normal(70, 1)
self.parents: tuple[Person, Person] = parents # This causes a lot of deeply nested objects, consider removing
self.name = str(uuid.uuid4())
# Make the existing number of offspring linearly proportional to age upon creation...
self.number_of_offspring = int(self.age * max_offspring/(self.max_reproductive_age - self.reproductive_age))
def __repr__(self):
return str(self.__dict__)
def increment_number_of_offspring(self):
self.number_of_offspring = self.number_of_offspring + 1
def randomly_mutate_genes(self):
for (gene_name, gene) in self._genes.items():
self._genes[gene_name].randomly_mutate()
def mate(self, person):
"""
Mate with a parter of opposite sex
:param person: The partner
:return:
"""
if self.is_male_sex and person.is_male_sex:
raise Exception("Cannot make children having the same sex... (No need to get triggered, it's a fact)")
offspring_genes = {}
for (gene_name, gene) in self._genes.items():
parent_1_gene: PersonGene = person.get_gene(gene_name)
parent_2_gene: PersonGene = self.get_gene(gene_name)
parent_1_selected_gene = parent_1_gene.select_either_gene_randomly()
parent_2_selected_gene = parent_2_gene.select_either_gene_randomly()
offspring_gene = PersonGene(gene_name, parent_1_selected_gene, parent_2_selected_gene)
offspring_genes[gene_name] = offspring_gene
max_offspring_offspring = np.random.normal(2, 1) # TODO: make this a function of the population's resources
# if offspring_genes[const.MORE_LIKELY_FOR_EXTRA_CHILD_GENE].exhibits_trait():
# max_offspring_offspring = max_offspring_offspring + 0.1
# TODO: Extra child gene likelihood makes the population explode too much.
# Need a mechanism to punish having too many offspring
if offspring_genes[const.CANNOT_REPRODUCE_GENE].exhibits_trait():
max_offspring_offspring = 0
death_age = np.random.normal((person.death_age + self.death_age) / 2)
if offspring_genes[const.PREMATURE_DEATH_GENE].exhibits_trait():
death_age = np.random.normal(const.PREMATURE_DEATH_AGE, 1)
parents = (self, person)
offspring = Person(offspring_genes, 0, death_age, round(max_offspring_offspring), parents)
self.increment_number_of_offspring()
person.increment_number_of_offspring()
# print(f"OMG It's a {'boy' if is_new_offspring_male else 'girl'}!!!")
return offspring
def get_gene(self, trait) -> PersonGene:
return self._genes[trait]
def increment_age(self, num_years=1):
self.age += num_years
def died_of_old_age(self):
return self.age > self.death_age
def person_exhibits_combined_trait(self, exhibiting_gene_configuration: dict[str, bool]):
pass
def exhibits_gene_trait(self, trait: str):
return self.get_gene(trait).exhibits_trait()
@staticmethod
def get_random_person(death_age=100, age=0, max_offspring=5):
person_genes = {
const.CANNOT_REPRODUCE_GENE: PersonGene.get_random_gene(const.CANNOT_REPRODUCE_GENE),
const.MORE_LIKELY_FOR_EXTRA_CHILD_GENE: PersonGene.get_random_gene(const.MORE_LIKELY_FOR_EXTRA_CHILD_GENE),
const.HAS_BLONDE_HAIR_GENE: PersonGene.get_random_gene(const.HAS_BLONDE_HAIR_GENE),
const.EARLY_BALDING_GENE: PersonGene.get_random_gene(const.EARLY_BALDING_GENE),
const.PREMATURE_DEATH_GENE: PersonGene.get_random_gene(const.PREMATURE_DEATH_GENE)
# Add more genes of choice
}
return Person(
person_genes,
age=age,
death_age=death_age,
max_offspring=max_offspring,
parents=None)