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
|
#!/bin/usr/env python
"""
Script to rudementarally model spiders colonising new terrain, and the effect
that could have on increasing the nutrient levels.
"""
import matplotlib.pyplot as plt
import numpy as np
import time
class Terrain:
""" Terrain class represents the terrain over which the model is run.
field: Shape of the terrain, and nutrient values
field_mask: mask for various attributes of the field (bit mask?)
"""
def __init__(self, size_x=10, size_y=10):
""" Create a new field of size_x by size_y """
self.field = np.zeros(shape=(size_x, size_y), dtype=int)
self.field_mask = np.ones(shape=(size_x, size_y), dtype=bool)
def print_terrain(self):
""" Display the field """
print(f"Terrain:\n"
f"{self.field}\n"
# f"Terrain mask:\n"
# f"{self.field_mask}\n"
)
def get_terrain(self):
""" Return the terrain """
return self.field
def update_nutrients(self, x, y, nutrients):
""" change nutrient values on the terrain """
self.field[x][y] += nutrients
def size(self):
""" return size of the terrain """
return self.field.shape
class Critter:
""" Basic class for a creature that can appear, modify the terrain, and
procreate or die. """
def __init__(self, nutrient_value=1, pos_x=0, pos_y=0, lifespan=10):
self.nutrient_value = nutrient_value
self.pos_x = pos_x
self.pos_y = pos_y
self.lifespan = lifespan # built in (max?) life
self.life = lifespan # dynamic life left
def live(self):
""" Live another tick, decrement lifespan, and resolve """
# print("Living another tick")
self.life -= 1
if not self.life:
self.life = 'dead'
return self.life
def get_lifespan(self):
""" return how long a creature is supposed to liv """
return self.lifespan
def get_position(self):
""" Return the position of the critter """
return self.pos_x, self.pos_y
def expire(self):
""" Death of the critter """
return self.nutrient_value
def immigrate():
""" check for immigrants """
pass
def actions():
""" actions taken """
pass
def update():
pass
def main():
""" main function, do stuff """
board = Terrain(100, 100)
print(f"The board has a width of {board.size()[0]}, and a height of"
f" {board.size()[1]}.")
spiders = []
spider_count = 0
for tick in range(0, 1_000_000):
if np.random.rand() < 0.2:
spiders.append(Critter(nutrient_value=1,
pos_x=np.random.randint(0, board.size()[0]),
pos_y=np.random.randint(0, board.size()[1]),
lifespan=10))
print(f"Spider created at {tick}!", end='\r')
spider_count += 1
for spider in spiders:
state = spider.live()
if state == 'dead':
board.update_nutrients(*spider.get_position(), spider.expire())
spiders.remove(spider)
# print("A spider died.")
print(f"There are {len(spiders)} spiders remaining"
f" of {spider_count} total.")
xy = [x.get_position() for x in spiders]
print(*zip(*xy))
plt.scatter(*zip(*xy), c="pink")
plt.imshow(board.get_terrain(), cmap='jet', interpolation="nearest")
plt.show()
if __name__ == '__main__':
main()
|