-
Notifications
You must be signed in to change notification settings - Fork 0
/
game.py
154 lines (121 loc) · 3.98 KB
/
game.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
"""
This module defines the Game class, which is the simulation.
"""
import random
class Game:
"""
A singular isolated community of only hawks and doves with
varying initial parameters. This is also referred to a single
"simulation" or "game."
"""
def __init__(self, birds, p_doves, carrying_cap, r):
"""
Game of hawks and doves
"""
self.doves = int((birds * p_doves)//1)
self.hawks = birds - self.doves
self.carrying_cap = carrying_cap
self.r = r
self.chosen_doves = 0
self.chosen_hawks = 0
self.game_matrix = [
[(0, None), (1, 0.25)],
[(1, 0.25), (None, 11/12)]
]
def choose_pair(self):
"""
Chooses up to 2 random birds and return them
returns [Optional 0|1, Optional 0|1]
"""
# Calculate true number of hawks and doves
doves = self.doves - self.chosen_doves
hawks = self.hawks - self.chosen_hawks
# Return list with single element if only 1 available, empty list if none
if doves + hawks < 2:
if doves == 1:
return [1]
elif hawks == 1:
return [0]
else:
return []
# Chose 2 random birds
chosen = []
for _ in range(2):
doves = self.doves - self.chosen_doves
hawks = self.hawks - self.chosen_hawks
if random.random() < doves/(doves + hawks):
chosen.append(1)
self.chosen_doves += 1
else:
chosen.append(0)
self.chosen_hawks += 1
# Return result
return chosen
def generate_pairs(self):
"""
Randomly pairs entire bird population and returns pairs
returns list([Optional 0|1, Optional 0|1])
"""
# Reset chosen counts
self.chosen_doves = 0
self.chosen_hawks = 0
# Generate all pairs
pairs = []
for _ in range(int((self.carrying_cap+1)//2)):
pairs.append(self.choose_pair())
# Return result
return pairs
def evaluate_pair(self, pair):
"""
Evaluates the given pair and determines the number of surviving hawks and doves
pair [Optional 0|1, Optional 0|1]: the pair of birds
returns [surviving hawks 0|1|2, suriving doves 0|1|2]
"""
# Edge cases of empty and single-element pairs
if len(pair) == 0:
return [0, 0]
elif len(pair) == 1:
survived = [0, 0]
survived[pair[0]] = 1
return survived
# Generate survival probabilities
matrix_cell = self.game_matrix[pair[0]][pair[1]]
hawk_survival_prob = matrix_cell[0]
dove_survival_prob = matrix_cell[1]
# Randomly die
survived = [0, 0]
for i in pair:
if i == 0:
if random.random() < hawk_survival_prob:
survived[0] += 1
elif i == 1:
if random.random() < dove_survival_prob:
survived[1] += 1
# Return result
return survived
def kill_birds(self):
"""
Pairs birds and kills birds that randomly died
"""
# Generate all pairs
pairs = self.generate_pairs()
# Count surviving birds
survived = [0, 0]
for pair in pairs:
live_hawks, live_doves = self.evaluate_pair(pair)
survived = [survived[0] + live_hawks, survived[1] + live_doves]
# Update counts
self.hawks = survived[0]
self.doves = survived[1]
def exponential_growth(self):
"""
Allows all birds to increase in population exponentially
"""
self.doves += self.r*self.doves
self.hawks += self.r*self.hawks
def day(self):
"""
Updates the number of birds after 1 day
"""
self.exponential_growth()
self.kill_birds()