1
00:00:04,960 --> 00:00:07,360
Hi, welcome to this new video.

2
00:00:07,360 --> 00:00:08,680
We are going to continue

3
00:00:08,680 --> 00:00:11,240
working on our
ecosystem project.

4
00:00:11,240 --> 00:00:13,500
We are writing the behavior,

5
00:00:13,500 --> 00:00:16,080
the internal brain of
a herbivore class,

6
00:00:16,080 --> 00:00:20,775
which is an animal that
eats our food class.

7
00:00:20,775 --> 00:00:24,675
We're finally at the
point where our animal,

8
00:00:24,675 --> 00:00:26,575
this herbivore has reached,

9
00:00:26,575 --> 00:00:29,630
can move towards the
food when it's hungry,

10
00:00:29,630 --> 00:00:31,685
and it gets there.

11
00:00:31,685 --> 00:00:35,925
There's interaction here that

12
00:00:35,925 --> 00:00:40,035
we basically transition
a behavior change.

13
00:00:40,035 --> 00:00:42,120
The consumption of the food

14
00:00:42,120 --> 00:00:44,820
triggers a change in
the decision tree.

15
00:00:44,820 --> 00:00:48,080
What actually happens is that
when we're seeking food,

16
00:00:48,080 --> 00:00:50,700
we reach that food
and eating that food

17
00:00:50,700 --> 00:00:53,680
not only kills that entry of

18
00:00:53,680 --> 00:00:57,570
the food supply and
actually takes us

19
00:00:57,570 --> 00:01:01,820
back into the evaluation
of the decision tree.

20
00:01:01,820 --> 00:01:04,020
What we're going to try to
implement is a sequence

21
00:01:04,020 --> 00:01:06,380
in which the herbivore,

22
00:01:06,380 --> 00:01:11,750
once it eats, gets sleepy
and it goes and takes a nap.

23
00:01:11,750 --> 00:01:14,605
We're going to transition
the rest state.

24
00:01:14,605 --> 00:01:16,360
The rest state will have

25
00:01:16,360 --> 00:01:20,320
a certain amount of frames
that it's going to be resting.

26
00:01:20,320 --> 00:01:23,660
Of course, if you had some
very expressive designs

27
00:01:23,660 --> 00:01:24,940
for these different states,

28
00:01:24,940 --> 00:01:27,940
you can actually add
sprites or images,

29
00:01:27,940 --> 00:01:31,105
wander states maybe,
like a movement,

30
00:01:31,105 --> 00:01:34,585
action, and then resting
state is sleeping action.

31
00:01:34,585 --> 00:01:36,210
But that's what we're
going to do, we're

32
00:01:36,210 --> 00:01:37,725
going to make awake false.

33
00:01:37,725 --> 00:01:40,470
It's going to go to
rest and hungry false,

34
00:01:40,470 --> 00:01:41,760
so you're not hungry anymore.

35
00:01:41,760 --> 00:01:45,110
When you wake up, you're
going to be full of energy

36
00:01:45,110 --> 00:01:46,830
to start over and maybe going to

37
00:01:46,830 --> 00:01:48,690
wander and eventually get tired,

38
00:01:48,690 --> 00:01:51,515
going to seeking food,
and going back to awake.

39
00:01:51,515 --> 00:01:53,835
With that in mind,
let's start writing

40
00:01:53,835 --> 00:01:57,970
the eat food in range function,

41
00:01:57,970 --> 00:02:00,425
which is what we're
going to do today.

42
00:02:00,425 --> 00:02:02,330
The first thing I wanted to do,

43
00:02:02,330 --> 00:02:06,155
and I think I mentioned that
at the end of last video,

44
00:02:06,155 --> 00:02:10,260
is looking at our move function.

45
00:02:11,840 --> 00:02:15,530
It's fine. I'm in the herbivore
class just for reference.

46
00:02:15,530 --> 00:02:19,390
I'm continuing with the work
we've been doing so far,

47
00:02:19,390 --> 00:02:22,830
the code that we've written
so far in this week.

48
00:02:22,830 --> 00:02:25,770
If we move down, and here it is,

49
00:02:25,770 --> 00:02:30,415
the move function
currently doesn't take

50
00:02:30,415 --> 00:02:35,340
any factor, any intensity.

51
00:02:35,340 --> 00:02:36,740
I wanted to make a difference

52
00:02:36,740 --> 00:02:41,880
between the movement of

53
00:02:41,880 --> 00:02:44,940
wander and the movement
of seeking food.

54
00:02:44,940 --> 00:02:48,590
Let's just add here
something called a factor,

55
00:02:49,790 --> 00:02:55,420
and we're going to say
that the self.velocity.

56
00:02:55,580 --> 00:02:58,840
We're going to normalize,

57
00:03:04,100 --> 00:03:08,160
and we're going to
multiply it by the factor.

58
00:03:08,160 --> 00:03:12,880
I know I'm overriding the
diversity of movement.

59
00:03:12,880 --> 00:03:15,060
I'm going to just basically be

60
00:03:15,060 --> 00:03:20,155
dictating the velocity speed
through this function now.

61
00:03:20,155 --> 00:03:23,350
I think that for this case,

62
00:03:24,470 --> 00:03:27,920
it's a little bit more
cartoony, if you want.

63
00:03:27,920 --> 00:03:29,330
It's going to feel
like wandering.

64
00:03:29,330 --> 00:03:32,800
It's a small, slow behavior
at a certain factor,

65
00:03:32,800 --> 00:03:38,870
but then it creates an
acceleration when seeking food.

66
00:03:38,870 --> 00:03:40,380
There's kind of
how do you convey

67
00:03:40,380 --> 00:03:42,060
that expressivity of seeking

68
00:03:42,060 --> 00:03:44,400
food is something
a bit more urgent?

69
00:03:44,400 --> 00:03:47,475
What we're doing is normalizing

70
00:03:47,475 --> 00:03:50,280
the velocity and
multiplying by this factor.

71
00:03:50,280 --> 00:03:52,060
The challenge now is that

72
00:03:52,060 --> 00:03:54,630
whenever we use
the function move,

73
00:03:54,630 --> 00:03:59,115
we will need to
provide a factor.

74
00:03:59,115 --> 00:04:01,090
Here within one direction,

75
00:04:01,090 --> 00:04:04,695
we're going to make that one.

76
00:04:04,695 --> 00:04:07,035
We have two instances of move;

77
00:04:07,035 --> 00:04:09,500
one in wander which is going
to be a movement of one,

78
00:04:09,500 --> 00:04:12,220
and one in seeking food,

79
00:04:12,220 --> 00:04:15,270
which I think is down here,

80
00:04:15,270 --> 00:04:16,815
seeking food, move 3.

81
00:04:16,815 --> 00:04:19,795
That's the difference
we're doing at the moment.

82
00:04:19,795 --> 00:04:22,495
Now, let's finally write,

83
00:04:22,495 --> 00:04:25,190
maybe after seeking food.

84
00:04:31,340 --> 00:04:35,260
Here, we can say eat food.

85
00:04:36,350 --> 00:04:40,800
We basically return
this function as well.

86
00:04:40,800 --> 00:04:43,620
Let's just write it
together once more.

87
00:04:43,620 --> 00:04:54,240
Find or eat _food_ in_range.

88
00:04:54,240 --> 00:04:57,930
We're going to take the self,

89
00:04:57,930 --> 00:05:09,085
the closest _food
and they eat_range.

90
00:05:09,085 --> 00:05:13,745
Just to give some flexibility
to this function,

91
00:05:13,745 --> 00:05:19,050
we want to make the
difference vector

92
00:05:20,300 --> 00:05:25,750
between the closest _food,

93
00:05:27,170 --> 00:05:31,935
which is going to be an
object, meaning a class.

94
00:05:31,935 --> 00:05:33,690
We're going to ask

95
00:05:33,690 --> 00:05:38,320
to request the position
vector of that object.

96
00:05:40,250 --> 00:05:43,950
Let's create a copy of that and

97
00:05:43,950 --> 00:05:49,065
substract the self
thought position.

98
00:05:49,065 --> 00:05:51,180
Again, the substraction

99
00:05:51,180 --> 00:05:53,325
between the two points
that we're evaluating,

100
00:05:53,325 --> 00:06:01,360
and again, distance
equals diff.magnitude.

101
00:06:01,550 --> 00:06:09,105
If the distance is smaller
than the eating range,

102
00:06:09,105 --> 00:06:10,740
which is going to
be specified by

103
00:06:10,740 --> 00:06:12,990
the function the eat_ range.

104
00:06:12,990 --> 00:06:15,765
We could say something. This
is a very small number,

105
00:06:15,765 --> 00:06:18,990
but it's good that we have
some capacity to tune it.

106
00:06:18,990 --> 00:06:23,830
Think of it like if you're
within five pixels.

107
00:06:27,920 --> 00:06:30,480
Let's just put a note here,

108
00:06:30,480 --> 00:06:39,615
remove the food from the
list or kill the food.

109
00:06:39,615 --> 00:06:49,140
Then let's just say
self.hunger_level equals zero.

110
00:06:49,140 --> 00:06:50,955
We reset the hunger.

111
00:06:50,955 --> 00:06:52,710
Let's make sure that we
have those variables

112
00:06:52,710 --> 00:06:54,315
here written in the same way.

113
00:06:54,315 --> 00:06:57,330
Hunger_level, it's going
to go down to zero.

114
00:06:57,330 --> 00:06:59,710
IsHungry.

115
00:07:05,660 --> 00:07:08,190
Hunger_level here.

116
00:07:08,190 --> 00:07:10,785
Hunger_level has
come back to zero,

117
00:07:10,785 --> 00:07:17,580
isHungry is going to
go back to false.

118
00:07:24,410 --> 00:07:26,580
Sorry. Awake is going to be

119
00:07:26,580 --> 00:07:28,080
false and hungry is
going to be false.

120
00:07:28,080 --> 00:07:31,245
Awake means that it's
going to go to sleep.

121
00:07:31,245 --> 00:07:34,410
At this point, we can do
what we did in wander,

122
00:07:34,410 --> 00:07:37,690
which is because this
is a transition,

123
00:07:38,420 --> 00:07:44,250
where do we have
the wander_state?

124
00:07:44,250 --> 00:07:47,820
Here. This line is
the important line,

125
00:07:47,820 --> 00:07:50,010
which is that it triggers

126
00:07:50,010 --> 00:07:53,850
the reevaluation of
the decision tree,

127
00:07:53,850 --> 00:07:59,220
because we separated
our eating function

128
00:07:59,220 --> 00:08:04,605
out of the others current_node.

129
00:08:04,605 --> 00:08:08,460
Basically repeal the decision
tree means start over,

130
00:08:08,460 --> 00:08:11,775
start going through
the top root node

131
00:08:11,775 --> 00:08:15,825
and evaluate with the new
data that we've changed.

132
00:08:15,825 --> 00:08:20,685
We're not longer going to be
in the seeking food state,

133
00:08:20,685 --> 00:08:24,195
that this is the
transition action.

134
00:08:24,195 --> 00:08:25,980
The only thing that
we're missing here is

135
00:08:25,980 --> 00:08:27,990
actually removing
food from the list.

136
00:08:27,990 --> 00:08:30,640
I would like to do that

137
00:08:31,610 --> 00:08:36,340
by writing a function

138
00:08:36,410 --> 00:08:40,710
that I would call something
like remove self.

139
00:08:40,710 --> 00:08:44,880
I think that the problem with

140
00:08:44,880 --> 00:08:49,185
our current food system

141
00:08:49,185 --> 00:08:52,890
is that they don't have any
references to other food.

142
00:08:52,890 --> 00:08:55,845
It doesn't have a reference
to self within a collection,

143
00:08:55,845 --> 00:08:58,410
so it's just an entity that has

144
00:08:58,410 --> 00:09:02,025
very little power to remove
itself from the collection.

145
00:09:02,025 --> 00:09:06,640
Let's do an all food
reference here so that

146
00:09:06,640 --> 00:09:11,610
all our foods are aware of
who they are in a collection.

147
00:09:11,610 --> 00:09:19,010
Self.all _food equals all_food.

148
00:09:19,010 --> 00:09:21,590
Once you do that, you

149
00:09:21,590 --> 00:09:23,120
need to make sure
that in the world,

150
00:09:23,120 --> 00:09:28,295
whenever you're creating
food like here, all_food,

151
00:09:28,295 --> 00:09:34,830
we need to pass the self
total food collection.

152
00:09:35,920 --> 00:09:40,565
New_food equals that.
The constructor now,

153
00:09:40,565 --> 00:09:44,810
the constructor requires
reference to the list.

154
00:09:44,810 --> 00:09:47,210
That's everything.

155
00:09:47,210 --> 00:09:49,925
But that means that
now we could actually

156
00:09:49,925 --> 00:09:57,120
the food class we could
write a very short function,

157
00:09:57,430 --> 00:10:05,190
which I'm going to
call remove_self.

158
00:10:07,750 --> 00:10:10,130
The remove_self is going to

159
00:10:10,130 --> 00:10:26,690
say self.all_food.remove, self.

160
00:10:26,690 --> 00:10:27,815
Remove yourself from
the collection.

161
00:10:27,815 --> 00:10:29,840
This is going to be
a useful function

162
00:10:29,840 --> 00:10:32,195
if you want to create a state,

163
00:10:32,195 --> 00:10:33,980
which we've done already,

164
00:10:33,980 --> 00:10:37,770
something like if the H

165
00:10:42,010 --> 00:10:45,740
is bigger or equal
than the lifespan,

166
00:10:45,740 --> 00:10:47,705
which I think we
never completed.

167
00:10:47,705 --> 00:10:50,390
We wrote, so let's
just use it now.

168
00:10:50,390 --> 00:11:00,030
If we are bigger than the
lifespan, self.remove_self.

169
00:11:05,410 --> 00:11:08,075
Basically, the line in
which you would just

170
00:11:08,075 --> 00:11:10,310
remove yourself from the list.

171
00:11:10,310 --> 00:11:14,165
Now that we have a reference
to that, our grow function.

172
00:11:14,165 --> 00:11:16,055
This is interesting
because in a way,

173
00:11:16,055 --> 00:11:19,535
if you have a species
that dies too quickly,

174
00:11:19,535 --> 00:11:25,160
might not be within its prime
to offer the calories or

175
00:11:25,160 --> 00:11:28,010
the nutrients for the
herbivore to actually

176
00:11:28,010 --> 00:11:32,880
be consumed and potentially
go out of its hunger state.

177
00:11:33,510 --> 00:11:36,850
The new function that
we are accessing here

178
00:11:36,850 --> 00:11:40,350
in the food, let's
just copy that.

179
00:11:40,350 --> 00:11:42,680
We're going to invoke
it from the herbivore.

180
00:11:42,680 --> 00:11:46,490
Remember that here when the
herbivore eats the food,

181
00:11:46,490 --> 00:11:50,060
instead of the herbivore
removing it from the collection,

182
00:11:50,060 --> 00:11:52,340
let's say, it's going

183
00:11:52,340 --> 00:12:00,600
to call the
closest_food.remove_self.

184
00:12:02,920 --> 00:12:09,300
That's the check that
we're doing that right.

185
00:12:11,500 --> 00:12:15,230
Closest _food.remove_self,
brilliant.

186
00:12:15,230 --> 00:12:20,330
Now, when we call the
sick food function,

187
00:12:20,330 --> 00:12:26,075
we can call this
eat food in range.

188
00:12:26,075 --> 00:12:33,360
Here, this would be
self.eat_food _in_range.

189
00:12:35,890 --> 00:12:38,390
We have the closest_food.

190
00:12:38,390 --> 00:12:40,650
We have to provide that.

191
00:12:41,410 --> 00:12:44,315
I don't know why I
spelled that like that.

192
00:12:44,315 --> 00:12:51,425
Food_in_range with
the radius of five.

193
00:12:51,425 --> 00:12:52,925
I'm going to give five pixels,

194
00:12:52,925 --> 00:12:54,530
so a very short radius.

195
00:12:54,530 --> 00:12:56,570
If the closest_food is within

196
00:12:56,570 --> 00:13:00,990
five pixels or five units
from the herbivore,

197
00:13:01,390 --> 00:13:05,210
and it's in the
six food function,

198
00:13:05,210 --> 00:13:07,670
you are going to
delete the food,

199
00:13:07,670 --> 00:13:17,165
and the herbivore will
transition to be not awake.

200
00:13:17,165 --> 00:13:18,680
Basically, go to sleep.

201
00:13:18,680 --> 00:13:21,530
Let's see if we're
running into any errors.

202
00:13:21,530 --> 00:13:25,085
We're wandering. We're seeking.

203
00:13:25,085 --> 00:13:27,095
No, not seeking yet.
We're still wandering.

204
00:13:27,095 --> 00:13:32,180
We're seeking food.
Basically, it went

205
00:13:32,180 --> 00:13:33,470
towards the food, it ate

206
00:13:33,470 --> 00:13:35,765
the food, and now it's resting.

207
00:13:35,765 --> 00:13:38,345
Our rest state doesn't
have any exit.

208
00:13:38,345 --> 00:13:41,420
We don't have any transition,
so this is where we're at.

209
00:13:41,420 --> 00:13:45,155
We're little by little
starting to build a loop,

210
00:13:45,155 --> 00:13:49,400
if you want, a decision
tree nested within that.

211
00:13:49,400 --> 00:13:52,805
There's state machine for
the wandering behavior.

212
00:13:52,805 --> 00:13:55,040
We're finally going full circle,

213
00:13:55,040 --> 00:13:56,930
where we could have
not only one agent,

214
00:13:56,930 --> 00:13:59,255
but many potentially
eating the food,

215
00:13:59,255 --> 00:14:03,260
resting, then trying to
get more food as well.

216
00:14:03,260 --> 00:14:05,270
We'll leave this here,
and we're going to

217
00:14:05,270 --> 00:14:07,890
continue in the next
video. I'll see you there.