Hi. Welcome to this new video on our ecosystem simulation series. This is Week 3. We're going to continue working on the behavior of our herbivore class. We're going to be looking at the seeking food function. This is very similar to some of the things that we have done with particles. So you might be familiar with that if you've done already Week 2. The seek food behavior, it's going to detect food particles or food entities within range, and it's going to operate by finding the closest one. We're going to redo an algorithm that we've written already, which is finding closest entity. Basically at that point, you reorient, look to the target and start walking towards the target. We're not going to write just yet the eating food, the transferring of killing that food and absorbing a transition as well of behavior after getting that energy of obtaining that food. But we're just going to write the boilerplate behavior for seek food using the closest food calculation. Let's do that. I know this is becoming one of relatively complex class. That's why it's important that your naming conventions are right. Remember that when we were writing here in the herbivore class. If I navigate all the way down to wander, we had turned off this exit state after maybe spending 200 frames wandering, we get hungry. The herbivore will get hungry. Right now, I think that's set to hunger threshold, 300. Let's do a little bit higher. Let's do 400 frames. We want to see that our herbivore is in wander state, starts moving, doing its thing, and eventually, it should get to seeking food. Let's just wait for it. Now it's currently in seeking food mode. It shouldn't be moving anymore. This means that we drop completely the calling of the functions that are associated with wander. This is why it's important that we break down those behaviors, because we don't want to be mixing them up. We want to be able to address very specifically wander. Let's resolve that well. Let's move into seek food. As much as the code might be longer, if each one of these building blocks are understandable, we should be able to handle the complexity of a rather complex class. Still the behavior is very simple. It's not that the behavior is really complex. But if you're new to coding, maybe starting to engage with a project that has more and more functions, might be a little bit more daunting. I just want to be mindful of what is the strategy that we're taking towards this. We do have the seek food function. This is what we're going to be working with right now. Let's write an outline of what we want this function to do. We want to find the closest food. Let's just also look at the food. Basically, orient yourself to the food, and then move towards the food. Then later, we're going to eat it. Probably, we're going to write some transitions as well like, at that point, you might not be hungry anymore and you transition to where your hungry state should be false. We could also say, well, after eating, maybe you get tired, so we could say, you're not awakening once you go to take a nap. You eat something and maybe you take a nap, and there's a resting state. Then the resting state comes back. Once you've recovered from resting, you wake up and you start over again. That could be the cycle that we're going to build at the moment. Let's start by defining closest food, which is, again, an algorithm that we have written before. Define find closest food. We usually do this by starting with a closest distance, with a very high number, maybe that's not too high, and the closest ID. Let's start with a -1, and for i, and food. We're going to do this technique now that we're a bit more advanced in programming where we're going to just be able to use the enumerate. This way, using this function, we can actually look through all the food entities here. The herbivore is going through all the food entities available. Well, first of all, do we have access to the old foods? Let's just double check that, because I don't remember if we actually wrote that into our herbivore class. We don't have a reference to that. That's new here. Let's just make a variable, all_foods. We're going to have to provide that from outside. This is going to change the way we construct. Once we construct the variable, we need to be passing on the collection of the foods, basically, the collection of, let's just call it all_food. Sounds weird as a plural. All_food. When we go into the construction of the herbivore. Herbivore equals new_herbivore. We need to provide the all_food list here in the constructor, we need to make sure that we do that. Also, if you would do it through this function, which we were doing before, we would also need to provide it here, because now the constructor would require the all_food list in order to execute. Let's make sure we do that. Let's go back to our herbivore. Now that the herbivore has visibility to the food collection, we can continue doing what we were doing. I was getting ahead of myself in terms of accessing something that I assumed we had already, which is the all_food. Let's just spell that correctly, the all_food variable. The way we've done this in the past is using a difference vector. We take self.position.copy. We copy the position, and we substract the food position. We should have called this position, but we call it vector_position. We need to sometimes remember that I would rather keep the convention that all our classes have a position. But for some reason, I wrote vector_position at the time. We could refactor this, meaning, change the naming conventions of variable. You can do that with I think command F in the Mac or Control F and just change all the instances of a particular variable. But we're not going to do that here yet in distance. We're going to say diff.magnitude. The magnitude we created the substract vector between the position of the herbivore and the position of the food. We create that vector, we calculate the magnitude of that vector, and that gives us the distance. If the distance is smaller than the closest distance, well, then the closest distance becomes the distance and the closest ID becomes i. We use the enumerate to be able to have both access to the i, the index of the list and then food, which is the entry, the item that we're evaluating. This is a way of having this loop giving us both of those pieces of information which we needed for the calculation of the index. Again, we did spend a bit more time looking at this algorithm before, so I would refer you to that video where we go a little bit in a further explanation of how this works. Closest_food. The closest_food now is going to be the self.all food, using the closest ID. That is the actual food element. We're using the closest ID. Here, what I would like to make sure that we are going to draw it just because I would like to evaluate, have some visual confirmation. Self.position.x and self.position.y. Here, let's use the closest_food.vec_position.x, closest_food.vec_position.y. Then we also want to return because what we want to pass on to the rest of the algorithm is the closest_food. Let's just for good measure, test that this part of the algorithm is working. We're replacing this outline. Is a pseudo-code kind of intention with the actual algorithm. Hopefully, when we start seeking for food, we're going to basically find the closest_food and draw a line towards that entry. We are running into some issues, let's see. One of my most common mistakes, I think it's forgetting the self. Let's see if that helps. We're still wondering, we can see that in the console down here, and now we transition to seeking food and we draw a line to the closest food. It's dynamic. It's being calculated every frame so, if for some reason there's food entry, you see like this one that is closer, that's updated. That's actually working well. We have that in place. Let's do one more, which is look towards target. Let's define look towards. This is going to be a generic function that takes a target vector, and it's going to calculate the difference. Taking the target vector, let's create a copy of that, and do a substruction to the position. What we're doing here is, again, similar idea; creating a substruction between our position and that foot position or the target position, we're going to create a vector between those two with substruction. We're going to calculate the current magnitude. It's going to be the magnitude of our velocity. This vector, we can normalize it and scale it by the magnitude of the velocity and finally, assign that. What we're doing here is because we're associating the velocity vector as the orientation of the herbivore, we're saying, create a vector that's the vector between the two units, store the magnitude of your velocity, and now we're going to match that vector that orient the herbivore towards this target. We give it that magnitude, and then that new vector becomes the velocity. We're overriding the velocity completely for this new vector that actually looks into the direction of the food. I think I spelled wrong normalize. There we go. Normalize. Now we have this function, self.look_towards, the target, in this case. We need to provide in the function. We're going to say that the closest food equals, because remember that this function defined closest returns value, returns the closest food, so we're going to say the closest food is the execution of define closest_food function, and now we can use the vector of position of that food, so closest_food.position.vec_position. The position of the food, we basically need to give a vector, and the vector we're looking at is from the food, which is the closest food we're looking at the vector position. The only thing that we should see at this point, is that our agent actually or herbivore orients itself towards that food, which is the closest food, and the other one, we already written it, so self.move. We have this function already. The move is just moving in the direction of your velocity. Let's see if we can get it to move towards the closest food. In wondering mode, we are engaging with a different behavior. At some point, we transition, and you can see, now the herbivore, it's actually moving towards that closest food. Here, because we're not eating it yet, it's just stuck, keeps on moving around that target. We can try it again. But, yeah, this is working pretty well. We have basically the wonder behavior and then the seeking food behavior. What I would like to do in the next video is maybe start giving it a bit of expressivity. Maybe when you're seeking food you're actually moving a little bit faster. You're having a sense of urgency and maybe there's competition, and maybe two different herbivores are going for the same food supply, so moving faster may get a bit more expressive in terms of the behaviors that we're separating it from the wonder behavior. Which is more like, oh, I'm just relaxed wandering around, and then at some point, I get hungry, I really want to just go and get my food. We'll leave it here. We'll continue building up on these behaviors in the next video, so I'll see you then.