Hi. Welcome to this new lesson. This is the fourth video of our complex systems project, which is the final project of this specialization. We have been working on a Langton sank algorithm. By all means, I invite you to go and revisit some of those videos. We are going to continue working on the code that we started a few videos back. Let's see where we're at, and what comes next. Let's just run the code. We have a grid class. We're writing everything in an object oriented fashion. We have a grid class and we have an at class. We have two instances of the ants. The ant is an entity, it's an agent that operates on top of the grid. Currently, it's just not doing much, just appearing there showing itself with this red color. What we're going to start doing today is starting to create some behaviors for this class. We're going to make the entities move based on their direction. Obviously, as they move, they might reach the boundary condition, they might reach out of bounds. We're going to deal with that as we go. Let's go into the script in. We actually wrote here that we wanted to work on the ant behavior. Let's do just that. We are going to do that just below here. Let's just create a bit of space for us to work. Let's create a function called the definition of ant behavior. There we go. The ant behavior in itself is going to be a series of functions. Things like basically, the following the Langton and algorithm. The Langton and algorithm has a series of requirements of behaving differently based on the information of the grid. But for now, we are just going to create a few functions. Let's start with move forward. We're going to have rotate 90 degrees clockwise, count clockwise, and also change the grid data. There's a few things that we might need to do within this ant behavior. Let's start with the move forward. I'm going to create, let's just write a few other things and rotate. Flip cells. Those are things that we might want to do within this function. Let's create the move forward script first. They move forward. It could be quite easy if we didn't have a direction. But let's just consider the direction. We're going to do the this direction matters. You're going to provide the direction. The direction is basically a value between zero and three, 0, 1, 2, 3, and that would represent the direction, the axis of movement or the axis in which the ant is facing. Let's just do an if direction is zero. Then self.x+=1. The moving of the ant is just basically changing its index to +1 in an entity. Let's just do an elif statement for all the other conditions that we have here. Let's just copy paste this. If the direction is one, the direction that we're going to be moving is in y+1. This elif is going to be repeated four times. If the direction is two, then x is minus one. Finally, if the direction is three, then, sorry, y is minus one. Zero would be moving towards the right, one would be moving down, two would be moving to the left, and three would be moving up. That's what move forward would mean based on a direction that it's a value that we already have declare. We can say here. Let's just use move forward function. Move forward and self.direction. That's great. We actually have our first line of behavior that should allow us to see our ants moving in the screen. Let's just see how we could actually get this going. Because our classes actually are being drawn in to our setup function and effectively, they're not being drawn every frame differently. Let's just break this up. Here I'm going to define draw and here the ant Actually, in the draw function, let's just draw the background. Well, we will need to redraw the grid. Let's just cut this and put it here. We want to redraw the grid every frame and we also want to execute our ant every frame. The only thing that we actually doing only once is the initiation of the data. If you actually do this initiation of the data, which is the grid class, if you initialize the data, every frame, you're going to be basically having your grid switching its data. Every frame, you're going to have new data, or as a matter of fact, you might be adding new data to that class. That would actually create quite a bit of error. If you want to reset the data, make sure that you include. I'm just thinking of this as we go but in this data, if you wanted to initiate the data, you might want to put a safety measure, which is data that clear. Reset the data from scratch every time you call this function, so that you're not just adding more and more data every frame. But this function is only meant to be run once in the setup. Then we can actually execute the drawing of the grid and the running of the ends, which already should contain. Let's review what's there and the run contains the drawing of the ant, and it should contain non behavior, but you see we haven't really turned it on yet. It's just that self behavior, Now we have the run function, which is basically our outline of all the things that the ant will be doing includes to displaying yourself and moving. Let's see. If we try to run this, we're running into an issue. Let's just see where is the issue. Let's just coming out this for a moment. It's certainly within the aunt because as we turn this off, this is totally fine. As we bring one of those in, we have our crash. Let's see what are we doing wrong. Well, here we go. Self. move forward. This is potentially one of the issues, let's see. We have that working here. You can see, we do run into an H condition. Let's just try our second aunt. These two ants because they have the direction of, let's just give one aunt the direction of zero. This one should move to the right, and then this one should move down. You can see that both aunts actually do work. Let's just comment out this aunts for a second. There seems to be something as we reach the edge condition. There seems to be like a grid displacement. I think what we're doing when we're getting to this edge condition, we run into an error. Because we're trying to access an information in the grid that doesn't exist. Let's just write something that would stay within bounds or there's different ways of thinking of the data. What happens when you reach the edge condition. Let's just write a definition for what to do in those cases. Stay within pounds. We're going to say if self.x is smaller than zero, what happens? Self.x equals self.grid object.columns-1. What does this line say? It's saying, well, if my x value, if I'm moving left in x, and I reach zero, well, why don't I then appear on the other side by defining my new x, it's going to be the size of the grid. The final index of the grid because we start at zero, we have to add this -1 at the end. But it's basically the size of the grid -1, which is the left most unit. We're doing like a wrap space if you play something like Pac Man, you probably are familiar with something like this. Like you go on one side and you appear on the other side. That's what we're actually doing. We're actually wrapping the world. It's infinite in the sense that you can move infinitely in one direction and appear on the side on the other side of the screen. Let's copy this line a few times. I was getting this ventation problem because we don't really need these parentheses here. These are going to be for if statements for all the four conditions of. This is going to be the inverted version. If we're bigger or equal, than the size of the column then x becomes zero. The left most boundary, if we reached the right most boundary, we go back to zero. Then these two, now we can add two more for the y variable. Instead of columns, we add rows and then this function. Now, we have the definition. This is making sure that we're not running into an error if we get to the boundary. We would like to add it in the add behavior, maybe towards the end. This is stay within bounds, and let's just not forget that we need that self.stay within bounds. As we run the script, you'll see that there's something not as expected. The behavior of the seems to be working well, but there seems to be some kind of virtual artifacts here. There's some, ants that stick to the right. The grid seems to be displaced. So what's wrong? I actually spend a bit of time trying to find this. The first thing I would like to test is to make sure that we can draw a background here in the back. That should get rid of some of the problem. As you can see, we can get rid of the edge condition, but it just seems that the grid is not longer well placed. Well, there's something we did with the end that we actually change the default form by which the rectangles are drawn in the screen. We're using the form rectangle center. By default processing would actually assume that you're using a different style of drawing, which is using the corner. What we need to do here is just make sure that we actually go back to our grid, and when we draw the rectangle off the grid, we type the same thing, but we do corner. Here. Because the grid is drawn with a different style, which is the corner style. The calculation was done for that using the default. That's why the grid was actually working well initially. But as we transition to a different kind of drawing style with the ant, then the grid in the next frame. The first frame is actually executed correctly, but the second frame is trying to draw the grid in a displaced position. So we lose the perfect alignment that we had originally. Let's see. You see we have it corrected now. We have our ants starting in particular two different positions. One is moving down, one is moving to the right. Both of them have a stay within bounds. Function, so we're not running into any errors. This is the foundation for what is going to be our ant behavior. Things are working very well. We have one final video missing. We're going to really write most of the functionality of the ant within that video. I'll see you then.