1
00:00:05,480 --> 00:00:06,654
Hi, welcome to this new video.

2
00:00:06,654 --> 00:00:11,436
We're going to continue working on our
ecosystem simulation, and at this point,

3
00:00:11,436 --> 00:00:15,584
we're going to be starting to talk
about how do we remove herbivores from

4
00:00:15,584 --> 00:00:16,534
the system.

5
00:00:16,534 --> 00:00:19,318
What would be the conditions for
them to die, right?

6
00:00:19,318 --> 00:00:23,611
We could create a condition in
which they die out of the lifespan,

7
00:00:23,611 --> 00:00:28,718
reaching kind of a point where we think
that's kind of the end of their life.

8
00:00:28,718 --> 00:00:33,730
But we could also start thinking of
how we can connect ideas of feeding or

9
00:00:33,730 --> 00:00:37,404
like achieving a resource
like our food system, and

10
00:00:37,404 --> 00:00:42,342
how starvation might happen if that
resource is not around, right?

11
00:00:42,342 --> 00:00:47,263
So we really want to create kind of
a symbiosis between our different classes

12
00:00:47,263 --> 00:00:49,174
at this point, right?

13
00:00:49,174 --> 00:00:54,122
So what would be our starvation or
death from starvation function?

14
00:00:54,122 --> 00:00:58,622
As we have done before, we're going to
create a variable that is going to be our

15
00:00:58,622 --> 00:01:02,904
patient value, that is only going to
start counting once the animal is in

16
00:01:02,904 --> 00:01:05,266
sick food state or hungry, right?

17
00:01:05,266 --> 00:01:07,431
Maybe when it's in that state,

18
00:01:07,431 --> 00:01:13,114
it will start gradually building up
a sense of maybe desperation for food.

19
00:01:13,114 --> 00:01:19,418
That's perhaps how resilient the animal
would maintain the search for food.

20
00:01:19,418 --> 00:01:24,115
If it doesn't find any food, especially
when there's a lot of competition,

21
00:01:24,115 --> 00:01:26,473
it might end up in a dead state, right?

22
00:01:26,473 --> 00:01:29,554
We're going to remove those
entities from the system.

23
00:01:29,554 --> 00:01:35,770
So with this in mind, let's just jump into
the code and see how to implement this.

24
00:01:35,770 --> 00:01:37,770
So let's recap where we're at.

25
00:01:37,770 --> 00:01:41,066
We're actually continuing
from our last video.

26
00:01:41,066 --> 00:01:44,433
If you remember, in the last video,
we have our herbivore,

27
00:01:44,433 --> 00:01:48,114
only a single herbivore in the screen,
it's wandering around.

28
00:01:48,114 --> 00:01:51,303
You can see in the console, at some point
it transitions to seeking food, and

29
00:01:51,303 --> 00:01:52,934
at that point transitions to resting.

30
00:01:54,914 --> 00:01:57,914
So what I would like to do is
kind of bring back a few things.

31
00:01:57,914 --> 00:02:04,634
We're going to create a transition
first from resting to wandering, right?

32
00:02:04,634 --> 00:02:06,434
We don't have that yet.

33
00:02:06,434 --> 00:02:11,118
And now that when we have that complete
circularity, we're going to introduce

34
00:02:11,118 --> 00:02:15,754
the possibility of this herbivore
to die of starvation, right?

35
00:02:15,754 --> 00:02:18,924
And we're also going to bring back
many herbivores to the system.

36
00:02:18,924 --> 00:02:24,392
So let's start with the, I'm here in the
herbivore class, which is again the class

37
00:02:24,392 --> 00:02:29,548
that we've been working through the weeks,
through the different lessons.

38
00:02:29,548 --> 00:02:33,822
If we go down to the rest function,
you see that right now we

39
00:02:33,822 --> 00:02:38,596
have a placeholder that says,
just print line, I'm resting.

40
00:02:38,596 --> 00:02:40,180
And that's what we can
see here in the console.

41
00:02:40,180 --> 00:02:44,364
Our herbivore is in fact only resting,
right?

42
00:02:44,364 --> 00:02:46,044
But I'm going to need
a few variables first.

43
00:02:46,044 --> 00:02:47,940
Let's create a few variables
that we will need.

44
00:02:47,940 --> 00:02:52,238
We did have hunger_level,
hunger_threshold.

45
00:02:52,238 --> 00:02:56,760
Let's create a few variables
that would be useful to

46
00:02:56,760 --> 00:03:01,910
calculate the starvation and
also the rest level, right?

47
00:03:01,910 --> 00:03:05,806
So imagine you're resting and you're kind
of regenerating a sense of kind fo rest.

48
00:03:05,806 --> 00:03:08,674
So let's call first self.rest_level.

49
00:03:11,134 --> 00:03:15,314
And that's going to be, we're going to
start with something like 0, I think.

50
00:03:16,784 --> 00:03:20,136
Let's just go with 0 for now.

51
00:03:20,136 --> 00:03:25,284
And we're also going to
use self.rest_threshold.

52
00:03:27,544 --> 00:03:31,135
And we're going to put
a number 50 here for

53
00:03:31,135 --> 00:03:35,688
now so that the sleeping time
is not going to be too much.

54
00:03:35,688 --> 00:03:39,344
This is basically how long to sleep for.

55
00:03:39,344 --> 00:03:43,249
If you want that nap to be
very long after eating,

56
00:03:43,249 --> 00:03:46,442
you will have to increase this number.

57
00:03:46,442 --> 00:03:49,834
But we're going to spend a bit of
time in calibration after this video.

58
00:03:49,834 --> 00:03:55,903
And I will come back here where we're
going to create the starvation level and

59
00:03:55,903 --> 00:04:00,333
the starvation threshold,
which is going to be a similar

60
00:04:00,333 --> 00:04:04,522
technique to calculate
the starvation function.

61
00:04:04,522 --> 00:04:06,594
But for now, let's do the rest.

62
00:04:06,594 --> 00:04:11,524
So resting, we have basically this
function here, which is a placeholder.

63
00:04:11,524 --> 00:04:19,404
And we're going to say
self.rest_level += 1, right?

64
00:04:19,404 --> 00:04:22,244
So we increase this as a counter.

65
00:04:22,244 --> 00:04:28,113
And if the self.rest_level

66
00:04:28,113 --> 00:04:37,039
is bigger than the self.rest_threshold,

67
00:04:40,605 --> 00:04:42,424
Right, what happens?

68
00:04:42,424 --> 00:04:44,176
That's not how you spell threshold.

69
00:04:44,176 --> 00:04:46,524
There we go, threshold.

70
00:04:49,304 --> 00:04:50,872
We are going to do a few things.

71
00:04:50,872 --> 00:04:52,520
We're going to change the state, right?

72
00:04:52,520 --> 00:05:01,212
So we're going to say self.isAwake = True,
right?

73
00:05:01,212 --> 00:05:02,444
So we wake up.

74
00:05:02,444 --> 00:05:05,504
So we are rested enough, we wake up.

75
00:05:06,964 --> 00:05:10,188
We're also going to reset the rest_level.

76
00:05:10,188 --> 00:05:13,104
So now the rest_level goes back to 0.

77
00:05:17,404 --> 00:05:21,310
And finally, and
perhaps the most important part,

78
00:05:21,310 --> 00:05:23,972
is that we reset the tree, right?

79
00:05:23,972 --> 00:05:28,107
What we do here in other functions,
like whenever we want to reset

80
00:05:28,107 --> 00:05:33,292
the calculation of the decision tree, we
go back and recalculate that the current

81
00:05:33,292 --> 00:05:37,864
node of the tree, the decision tree,
will become a new calculation.

82
00:05:37,864 --> 00:05:41,701
So this would kind of cascade through
the tree, check, is it awake?

83
00:05:41,701 --> 00:05:46,008
Now, it's true, it's going to
transition back to a wandering state or

84
00:05:46,008 --> 00:05:50,032
a sick food state,
depending on if it's hungry or not hungry.

85
00:05:50,032 --> 00:05:53,724
Most likely after eating and
going to a rest,

86
00:05:53,724 --> 00:05:57,604
our herbivore will be,
in fact, not hungry.

87
00:05:57,604 --> 00:06:01,156
So it would probably default back
to a wandering state, right?

88
00:06:01,156 --> 00:06:03,790
So, but again, it's important to debug and

89
00:06:03,790 --> 00:06:06,724
make sure that your behavior
is as you expected.

90
00:06:06,724 --> 00:06:08,870
Sometimes you might,
depending on the order of things,

91
00:06:08,870 --> 00:06:10,604
you might be getting a different result.

92
00:06:10,604 --> 00:06:12,404
So we are in a wandering state.

93
00:06:12,404 --> 00:06:14,068
Let's just check that this is working.

94
00:06:14,068 --> 00:06:15,252
Seeking food.

95
00:06:15,252 --> 00:06:19,064
Now it's resting,
going back to wandering, right?

96
00:06:19,064 --> 00:06:20,296
And now it's wandering around.

97
00:06:20,296 --> 00:06:21,920
It's not necessarily seeking that food.

98
00:06:21,920 --> 00:06:22,832
It's not hungry yet.

99
00:06:22,832 --> 00:06:25,960
Got hungry, went and
eat, now wanders around.

100
00:06:25,960 --> 00:06:28,401
So the wander state is
more like a curiosity,

101
00:06:28,401 --> 00:06:30,336
kind of hanging out kind of state.

102
00:06:30,336 --> 00:06:34,232
The seeking food is a state
of chasing that food.

103
00:06:34,232 --> 00:06:36,176
So we have that circularity, right?

104
00:06:36,176 --> 00:06:41,064
It loops around three different states.

105
00:06:41,064 --> 00:06:46,041
Let's bring back in the World_Manager,
remember that we actually

106
00:06:46,041 --> 00:06:50,812
created a single herbivore with
this function as a placeholder.

107
00:06:50,812 --> 00:06:55,510
So I'm going to remove all that because
now I actually would like to create

108
00:06:55,510 --> 00:06:57,204
herbivores over time.

109
00:06:57,204 --> 00:07:02,148
And we did that thing with this function
here that we had commented out, right?

110
00:07:02,148 --> 00:07:04,864
So every 80 frames we
create a new herbivore.

111
00:07:06,404 --> 00:07:08,644
Let's just see how that would work.

112
00:07:08,644 --> 00:07:14,004
So we have one here, and
every time we create a new herbivore,

113
00:07:14,004 --> 00:07:18,244
this is a pretty high rate
of population growth.

114
00:07:19,864 --> 00:07:23,812
And you can see all of them are kind of
eating the food supply that is available

115
00:07:23,812 --> 00:07:24,784
close to them.

116
00:07:24,784 --> 00:07:29,682
At some point,
they will run out of food because

117
00:07:29,682 --> 00:07:33,944
the food kind of grows at its own rate.

118
00:07:33,944 --> 00:07:39,344
But suddenly more and more herbivores are
getting hungry and they're not being fed.

119
00:07:40,604 --> 00:07:44,204
And eventually, they're going to reach
a point where they cannot find the food.

120
00:07:44,204 --> 00:07:49,904
They're kind of chasing, chasing, chasing,
and they're not going to find their food.

121
00:07:51,484 --> 00:07:53,981
At that point,
we should be killing them, or

122
00:07:53,981 --> 00:07:57,796
basically they should be dying from
not really having enough food.

123
00:07:57,796 --> 00:08:00,511
So that's where our starvation
function is going to kick in, right?

124
00:08:00,511 --> 00:08:05,740
So let's just make sure that we go all
the way up here to the herbivore node,

125
00:08:05,740 --> 00:08:10,975
and let's create another variable that
is going to be our starvation value.

126
00:08:19,968 --> 00:08:24,118
And it's going to start at 0, and

127
00:08:24,118 --> 00:08:33,899
starvation_threshold, It's
going to say 100.

128
00:08:33,899 --> 00:08:38,417
So for 100 frames,
if our herbivore looks for food for

129
00:08:38,417 --> 00:08:43,424
100 frames and it doesn't find food,
it will die, right?

130
00:08:44,484 --> 00:08:49,452
So now that we have those variables,
let's just put them in action.

131
00:08:49,452 --> 00:08:54,900
We're going to be looking
into the seek_food function.

132
00:08:54,900 --> 00:08:57,504
That's basically where we want
the starvation to kick in.

133
00:08:58,684 --> 00:09:01,782
So sick food, why do we want
to do it in the seeking food?

134
00:09:01,782 --> 00:09:05,732
Because we want to make sure that
while we're looking for food,

135
00:09:05,732 --> 00:09:09,366
the particular kind of movement
that is faster, right?

136
00:09:09,366 --> 00:09:12,470
We're exerting more energy for
looking food.

137
00:09:12,470 --> 00:09:13,598
It's kind of a desperate mode.

138
00:09:13,598 --> 00:09:18,194
It's like we're competing against other
herbivores for food at this point.

139
00:09:19,334 --> 00:09:22,462
At this point,
we're going to kick in a sense of like,

140
00:09:22,462 --> 00:09:25,502
now you're a countdown of starvation,
right?

141
00:09:25,502 --> 00:09:30,593
So we would do the same technique again of

142
00:09:30,593 --> 00:09:36,332
self.starvation _value += 1, right?

143
00:09:36,332 --> 00:09:38,964
So your starvation will start growing.

144
00:09:38,964 --> 00:09:43,001
And if that starvation_value,

145
00:09:45,341 --> 00:09:50,583
It's bigger than the starvation_threshold,

146
00:09:50,583 --> 00:09:55,964
which we,
I think we said 100 frames, right?

147
00:09:56,984 --> 00:10:01,636
We're going to call a function like die,
[LAUGH] right?

148
00:10:01,636 --> 00:10:06,936
And we don't have that function yet,
so let's create it.

149
00:10:06,936 --> 00:10:12,504
So def die(), it's going to take self.

150
00:10:12,504 --> 00:10:18,496
And here how we have done this before,
like food actually can remove itself.

151
00:10:18,496 --> 00:10:21,464
It could be eaten, so it could be removed.

152
00:10:21,464 --> 00:10:25,546
We need to make sure that we
have a reference to, currently,

153
00:10:25,546 --> 00:10:30,544
the herbivore has a reference
to the all_food variable, right?

154
00:10:30,544 --> 00:10:34,129
So it can understand where all the food
elements are, but it doesn't understand

155
00:10:34,129 --> 00:10:36,923
its position in relation to
a population of other herbivores,

156
00:10:36,923 --> 00:10:39,280
especially because those
are part of a list as well.

157
00:10:39,280 --> 00:10:42,617
So we're going to do here all_herbivores,

158
00:10:46,258 --> 00:10:51,228
And so all_herbivores will be
a passing of the list that

159
00:10:51,228 --> 00:10:56,304
contains all the herbivores,
or death is going to be like,

160
00:10:56,304 --> 00:11:01,320
you're no longer computed
as part of that collection.

161
00:11:01,320 --> 00:11:03,644
You're removed from that
collection in a way.

162
00:11:04,904 --> 00:11:11,104
So let's also, when we did self.all_food,
where is that all_food?

163
00:11:11,104 --> 00:11:12,048
There, here.

164
00:11:12,048 --> 00:11:14,924
So let's do the same thing.

165
00:11:18,884 --> 00:11:24,028
self.all_herbivores = all_herbivores,
right?

166
00:11:24,028 --> 00:11:28,307
So if we do that, because we changed
the construction of the class,

167
00:11:28,307 --> 00:11:32,510
we need to make sure that whenever
we're creating the class here,

168
00:11:32,510 --> 00:11:36,868
we're constructing a herbivore,
we're passing on all_food.

169
00:11:36,868 --> 00:11:44,401
We also have to pass all_herivores,
which is the list, right?

170
00:11:44,401 --> 00:11:50,549
And the constructor demands
a series of arguments, right?

171
00:11:50,549 --> 00:11:56,464
And now we're passing the list of
herbivores to the herbivore class, right?

172
00:11:57,644 --> 00:11:59,684
So that's our node.

173
00:11:59,684 --> 00:12:03,748
So now that we have all the herbivores
referenced, we can actually die or

174
00:12:03,748 --> 00:12:05,460
kind of kill the herbivore.

175
00:12:05,460 --> 00:12:10,696
This function here, as we have discussed,

176
00:12:10,696 --> 00:12:16,779
or the same way in which we
have done it for the food,

177
00:12:16,779 --> 00:12:26,104
right, which is
self.all_herbivores.remove(self), right?

178
00:12:26,104 --> 00:12:30,778
And with that function now written,

179
00:12:30,778 --> 00:12:37,423
we can do self.die within the seek_food,
right?

180
00:12:37,423 --> 00:12:41,694
So if the starvation level reaches,
we're going to find a dead state,

181
00:12:41,694 --> 00:12:44,036
removing yourself from the system.

182
00:12:44,036 --> 00:12:47,068
So you would imagine that
the more herbivores you have in

183
00:12:47,068 --> 00:12:48,892
the system competing for food.

184
00:12:48,892 --> 00:12:52,568
Some of them will be maybe further away
from food and will transition to look for

185
00:12:52,568 --> 00:12:55,620
another piece of food, and
eventually some of them will die.

186
00:12:55,620 --> 00:13:00,401
So they will start creating kind of this
dynamic equilibrium between the amount of

187
00:13:00,401 --> 00:13:03,728
food available and
the amount of herbivores available,

188
00:13:03,728 --> 00:13:08,303
because the herbivores are not going to
be able to sustain population growth that

189
00:13:08,303 --> 00:13:11,104
doesn't have any food supply, right?

190
00:13:11,104 --> 00:13:16,824
So let's just see if our
simulation is running correctly.

191
00:13:16,824 --> 00:13:19,769
So we have herbivores running around,

192
00:13:19,769 --> 00:13:25,104
they're getting hungry, and
they start eating the food.

193
00:13:25,104 --> 00:13:30,648
And eventually some of them,
we currently don't have a very clear way.

194
00:13:30,648 --> 00:13:33,844
You see one of them,
I think, disappeared here.

195
00:13:33,844 --> 00:13:37,640
You might want to create a state,
not just remove them from the system, but

196
00:13:37,640 --> 00:13:40,452
you see that some of them just disappear,
they die.

197
00:13:40,452 --> 00:13:43,676
Our death is kind of pretty quick and
pretty brutally.

198
00:13:43,676 --> 00:13:48,292
You don't see them really
hanging around in any way.

199
00:13:48,292 --> 00:13:50,636
They just disappear.

200
00:13:50,636 --> 00:13:52,588
So we remove them from the computation.

201
00:13:52,588 --> 00:13:57,016
What we could actually do, if you wanted
to graphically see them stay around,

202
00:13:57,016 --> 00:14:01,781
you can actually reduce their speed, maybe
as they get tired, or you could actually

203
00:14:01,781 --> 00:14:06,814
leave them in a dead state as part of a
computation, but maybe without an emotion.

204
00:14:06,814 --> 00:14:11,110
So it could be visible that
how many of your animals

205
00:14:11,110 --> 00:14:14,734
are actually not surviving, right?

206
00:14:14,734 --> 00:14:17,802
But we're going to spend a bit of time
in the next video really calibrating and

207
00:14:17,802 --> 00:14:18,766
also visualizing.

208
00:14:18,766 --> 00:14:23,421
There's a lot of data going on here that
it might be important to visualize so that

209
00:14:23,421 --> 00:14:28,154
we could actually visually debug if our
system is performing the way we intended.

210
00:14:29,184 --> 00:14:31,080
We're going to leave this video here,
and I'll see you in the next one.

211
00:14:31,080 --> 00:14:32,648
We're going to be doing
that visualization.

212
00:14:32,648 --> 00:14:33,148
I'll see you then.