-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimpleLife.py
208 lines (160 loc) · 7.6 KB
/
simpleLife.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"""
Simple implementation of Game of Life.
Author : Vladislav Plotnikov
"""
import sys, argparse
import uuid
from operator import attrgetter
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from conwayGameOfLife import randomGrid
from helpers.consts import *
from helpers.helper import create2dimFieldOfCells, polygon_of_cells_2_colors_2d
from structures.agent import Agent
from structures.field import Field
class Simulation:
def __init__(self,
n=N,
max_food=MAX_FOOD_IN_CELL,
agents=INITIAL_AGENTS_COUNT,
part_foody_cells=PART_OF_CELLS_WITH_FOOD,
update_interval=UPDATE_INTERVAL,
) -> None:
self.n_dim = n
self.max_food = max_food
self.agents_in_game = agents
self.foody_cells = part_foody_cells
self.upd_interval = update_interval
self.agents_alive = set()
def clean(self, ax):
'''
remove all agents from field
param 1 - ax object (return by plt.subplot())
'''
# loop over all lines on the axis "ax" to remove
for line in ax.lines:
line.set_marker(None)
def drawAgents(self, alive_agents, ax):
'''
draw all agents
param 1 - list of alive agents (cells)
param 2 - ax object (return by plt.subplot())
return - nothing
'''
for agent in alive_agents:
x, y = agent.x, agent.y
ax.plot(x, y, marker="o", markersize=5, markeredgecolor="red", markerfacecolor="green")
# TODO : implement field update. How to renew food?
'''
params : state of game as input
'''
def update(self, frameNum, img, grid_np, grid, field, ax):
# copy grid since we require 8 neighbors for calculation
# and we go line by line
# redraw previous state before new move !
print("[STATE-BEFORE]Currently alive agents {} . Total quantity = {}".format(self.agents_alive,
len(self.agents_alive)))
print("[STATE-BEFORE]Currently alive agents {} . ".format(list(map(lambda x: x.name, self.agents_alive))))
self.clean(ax)
self.drawAgents(self.agents_alive, ax)
print('[DEBUG] Quantity of acting ACTORS = {}'.format(len(self.agents_alive)))
print('[DEBUG-STATE] {}/{} . {} - max allowed agents quantity '.format(len(self.agents_alive), field.max_agents,
field.max_agents))
new_agents = set()
updated_agents = set()
dead_agents = set()
# each alive agent will act ordered by age
for agent in self.agents_alive:
result = agent.act(field)
# process results before next step
for key, value in result.items():
if key == "field" and value is not None:
updated_agents.add(result['agent'])
elif key == "agent" and value is not None:
# update fields of existing agent by new values
updated_agents.add(result['agent'])
elif key == "new_agent" and value is not None:
new_agents.add(result['new_agent'])
elif key == "die" and value == True:
dead_agents.add(agent)
print("[DEBUG] >>>>>>>>>> DEAD AGENTS ", dead_agents)
print("[DEBUG] >>>>>>>>>> DEAD AGENTS {} . ".format(
list(map(lambda x: x.name, dead_agents))))
if len(new_agents) > 0 or len(updated_agents) > 0:
print('[STATE-MIDDLE] Before overriding list of agents : {} . '
'Total quantity = {}'.format(self.agents_alive, len(self.agents_alive)))
print("[STATE-MIDDLE]Currently alive agents {} . ".format(list(map(lambda x: x.name, self.agents_alive))))
self.agents_alive = updated_agents.union(new_agents)
field.agents = len(self.agents_alive)
if len(dead_agents) > 0:
#remove_dead = self.agents_alive - dead_agents
self.agents_alive = self.agents_alive - dead_agents
print('[STATE-MIDDLE.2] REMOVE DEAD AGENTS : {} . '
'Total quantity = {}'.format(dead_agents, len(dead_agents)))
print("[STATE-MIDDLE.2]Currently dead agents {} . ".format(list(map(lambda x: x.name, dead_agents))))
field.agents = len(self.agents_alive)
print("[STATE-AFTER]Currently alive agents {} . Total quantity = {}".format(self.agents_alive,
len(self.agents_alive)))
print("[STATE-AFTER]Currently alive agents {} . ".format(list(map(lambda x: x.name, self.agents_alive))))
# newGrid = grid.copy()
# newGrid_np = grid_np.copy()
# -- verify field. Updated colors . If food in cell ended - turn it off.
field.check_cells_food_state()
polygon_arr_cells, polygon_arr_np = field.create_food(2)
#field.create_food(field.agents)
# field update - each turn - random update
#polygon, polygon_arr = create2dimFieldOfCells(self.n_dim)
#polygon_arr_np = np.array(polygon_arr)
newGrid_np = polygon_arr_np.copy()
img.set_data(newGrid_np)
grid[:] = newGrid_np[:]
return img, 1
def run(self):
"""
1 - init field with food
2 - create 1 agent . add it ti list of alive agent
3 - start sim:
_1 - agent check for food, eat once or move towards to food or randomly
"""
field = Field(self.n_dim, self.max_food, self.agents_in_game, self.foody_cells)
#polygon, polygon_arr = field.polygon, field.polygon_arr
polygon = field.polygon
polygon_colors = polygon_of_cells_2_colors_2d(polygon)
agent = Agent(uuid.uuid4(), self.n_dim, MAX_PHISICAL_HEALTH, MAX_MENTAL_HEALTH, SPLIT_COEFFICIENT_PHISICAL,
MAX_PHISICAL_HEALTH, MAX_MENTAL_HEALTH)
self.agents_alive.add(agent)
polygon_colors_np = np.array(polygon_colors) # move polygon to NP array.
fig, ax = plt.subplots() # draw initial field
print("[DEBUG] INITIAL FIELD COLOR STATE ", polygon_colors_np)
img = ax.imshow(polygon_colors_np, interpolation='nearest')
ani = animation.FuncAnimation(fig, self.update,
fargs=(img, polygon_colors_np, polygon_colors, field, ax),
frames=10,
interval=self.upd_interval,
save_count=50) # set up animation
# # of frames?
# set output file
plt.show()
def main():
# sys.argv[0] is the script name itself and can be ignored
# parse arguments
parser = argparse.ArgumentParser(description="Runs Artificial Conway's Game of Life simulation.")
parser.add_argument('--grid-size', dest='N', required=False)
parser.add_argument('--mov-file', dest='movfile', required=False)
parser.add_argument('--interval', dest='interval', required=False)
args = parser.parse_args()
# set grid size
N_size = N
if args.N and int(args.N) > 8:
N_size = int(args.N)
# set animation update interval
updateInterval = 10000
if args.interval:
updateInterval = int(args.interval)
# declare grid
# grid = np.array([])
sim = Simulation(N_size)
sim.run()
if __name__ == '__main__':
main()