I'm going to end the week with our most elaborate world program yet. What we saw earlier was that cats have a mind of their own. When they get to the edge of the box, they just keep walking off the screen. Cows on the other hand, cows are a docile creature. When they get to the fence they turn around and they go back the other way. So, we're going to do a cow animation now. And you can kind of see the key way it's going to be different, right? A cat only has a position, it always goes the same direction, but a cow has two changing properties. Its position and its direction. So, this is going to be a compound data problem. It's going to be a how to design worlds problem with compound data. This is a long video, you may not want to watch it all at one sitting. But a world problem is a long problem and compound data makes it a bit longer, and there is a couple of very interesting points that happen here along the way. So, I would encourage you to be sure to watch this whole video through. Again, a good thing to do might be to stop it every now and then, and try to work a bit of it on your own, getting ahead of the video. But don't do that when you get to the render cow function, because there's a special thing going on there that we need to talk about. What I have open here in Doctor Racket is the starter file. We're also providing intermediate solutions at different points along the way of developing the whole solution. And as I said, I'll be dropping into different places in this as we go. So, here's the problem statement worked out in a bit more detail. We're going to have a cow that walks back and forth across the screen, and when it gets to the edge, it changes direction and goes back the other way. And we're giving you a couple nice images of cows, which we got from Brown. Of course, with any world program, the first step is to do an analysis. I have the analysis already worked out. And here it is, and mostly it's like the analysis of a cat program. A lot of the constant information is the same: the width, the height, the center y, the background. One difference is here the cow has two images: the image where it's facing to the right and the image where it's facing to the left. That's one difference. The most important difference is is reflected in the center picture and also in the changing information, which is the key here. There are two changing information values associated with the cow. The cow's x coordinates and the cow's direction and speed. We're going to call the direction edx for the change in x. So, that is how we're going to name label the velocity, which is, which is the change in the position. Another difference shows up here in the third image, where I've made a detailed note to myself describing what's going to happen when the cow gets to the edge. So, what I'm saying here is that if the cows center, cow x, tries to go past width or past 0, then we're going to reset it. So, here the decision I'm making, is that I'm going to let the cow get all the way up to the edge of the box but not outside. The big-bang options are relatively straight forward, there's on-tick, to-draw, and on-key. So, now I'm going to jump to the v zero solution, and in all of these solution files, you can see a list of kind of where each one is in it. You might choose not to read that, so that you don't get too far ahead. What you might want to do now is try to do some of this yourself and then use these solution files to catch yourself up, or watch the video to catch yourself up, or follow along with me either way. So, look here is the constants, and the constants are relatively straightforward. There's the width, the height, the center y. There's two cow images and the background. Nothing really new there. Now, I'm going to go on to the data definition for the changing world state. On looking at the analysis, I see that there's two pieces of changing information. Two changing information values that naturally belong together. And so, that tells me that I want to use a compound data definition. So, when you use a compound data definition, the first thing we have to do is a structure definition for it. So, let me make a structure, and I guess I'll just call it cow. And it has two fields, and I'll call one x for the x coordinate and one dx for the current rate of change in the x coordinate. And I will say cow is make cow. Now, we know that this cow nicely stays in the box. So, that means we know that the x-coordinate is bounded a certain way in this world program. So, what I'm going to do here is I'm going to say, Natural 0, width, as a way of saying that the cow's x-coordinate stays within the boundaries of the box. Now, we don't know of any bounds on dx, on the velocity of the cow, but let's just decide that it's going to be at least be an an integer. That'll make some things simpler. So, we'll say that this is an integer. We'll say that the interpretation of a cow is that, if you have a cow make cow with an x and a dx. Then that's a cow with x coordinate x and velocity dx. We'll say that the x is the center of the cow. We'll say that x is in screen coordinates or pixels. And we'll say that dx is in pixels per tick. So that if dx is three, for example, that means that on each clock tick the cow moves three pixels, where its x value gets bigger by three. Now, here we're to start to see with some examples get a bit more interesting. I'm going to make a couple of them, let's say C1. Let's say this is a cow that its current position is 10, and that its current dx is 3. And I'll just label this one to help me understand the interpretation at position 10 moving left to right. And here's another one. And this one is at 20, and it's moving the other way. So, this is a case where as the data definition becomes more complicated, the examples become more useful to really understand how the data definition works, and what the interpretation is. Now, of course, I have to do the template and template rules used. But what I'm going to do to speed this video up a little bit, is I'm kind of going to pull, pull the next stage of the roast out of the oven ready done. I'll go to cowabunga v1. And it already has the complete data definition here, everything that we just did plus the template and template rules used. Next step is going to be to set up the main function, and all the wish list entries for the big bang option handlers. And since that's straightforward again, I'm going to jump ahead to go to cowabunga V2 that has all that. You might want to not do that, and go ahead and develop that yourself as a way of checking your work. I'm going to jump ahead now though. So, here I'm in cowabunga V2, and it's got the data definition we did before. And it's got a main function that calls big bang with the three handlers: on-tick, to-draw, and on-key. And I've given those functions the names: next cow, render cow, and handle key. And here's the wish list entries. The signatures are formulaic, of course. Once we know that the changing real state is represented by type called cow, all these signatures come automatically. But I did spend some time thinking about the purposes that I put in here. So, I said for next cow that it increases the cow x by dx, and it bounces off the edges just to remind me that when the cow gets to the edge it has to turn around. In this one I said, place the appropriate cow image on MTS at its current position and center-Y. And appropriate here is reminding me that sometimes I use the cow that faces right, and sometimes I use the cow that faces left. And for handle-key, I put reverse the direction of cow travel when the Spacebar is pressed. At this point we're set up to go, and all that has to happen is to complete the design of these three functions. There are a couple of interesting things that happen in the design of these functions though. So, I'm going to go ahead and work through next cow and render cow in more detail, so that you could see how that plays out. So, now I need to work my wish list until it's done. And the first WishList entry is for next cow, so let me start with that. I've already got the signature, purpose, and stub, I need to work on the examples. So, let's see, examples are going to look something like this. Next-cow, they're always going to consume some sort of cow, and they're always going to produce some sort of cow. So, that's kind of the skeleton of an example. Let's try to fill them in some. Let's see, a simple case is that the cow is somewhere in the middle of the screen. Let's just assume that 20 is less than the full width. And it's moving at a velocity of three, which means it's moving three pixels to the right each time. And that means that on the next tick that cow should be at 20 plus 3, and still moving at the same velocity. So, that's a cow in the middle moving left to right. Let's do a cow in the middle that's moving right to left. Let's see that cow would just be at minus 20 and three, and still moving right to left. So, that's those two cases, these are middle cases. I said in the analysis that we would let the cow go all the way up to the edge of the box but without changing direction. So, let's do that case next. Let me make some copies of this x before I added it. So, let's see, we might have a cow moving from left to right that's just about to get all the way to to the edge of the box. So, that might be a cow for example that's at width minus three and moving three pixels to the right per tick. So, that cow after this tick will be all the way to width, and still think it's moving towards the right. It hasn't bounced yet, because we said were going to let it get all the way to the edge. It'll bounce the next time. And another cow might be, let's see, it might be at three moving with speed minus three. And that means that when this tick is done it will be all the way at zero, and still think it's going to head towards the left even though its not. You know, bounce on the next tick. So, these are somewhere, these were, how we would describe these cases. These are cases where it's going to reaches, the cow reaches the very edge. And now it seems like there's going to be two more cases for when the cow would actually pass the edge. Let's see, there's a case where the cow might be at, let's say width minus 2, moving 3 to the right each time. And what are we going to do with that cow? Well, let's put it all the way at the edge but now headed back towards the center. It needs to change its direction now. So, we'll change its direction to that. Basically make it reverse its direction, because it was, it had, it would, it actually tried to leave the box. So now, its going to be at the edge, but its going to be headed towards the center of the box again. And the corresponding case of course is that there's a cow at two that's headed towards the left. And we'll say no, no, no, you can't leave the box, you stay at the edge of the box, and now you're heading the other way. So, these are cows that these two counts. They try these cases, try to pass the edge. And let's see all those are well formed. They are well formed. And you can see that it's a little bit complicated. That's a feature of this design method, which is that I'm working out all these complex boundary cases before I actually get to coding the general purpose function. I've got some concrete examples to help me understand the function. And, I've got tests for when I get the function going. So, now let's see, let's go get the template. There's the template for a cow. And I've got these notes here in the template. I'll make a note to myself it says I took template from Cow. I'll rename this function to next cow. And I've got note for myself that it says the template has two fields and it also tells me the types of fields to remind me what's going on there. Now, let's think about the examples for a second. What do the examples tell us in terms of how many cases of examples are there are. In all four of these cases, the cow really keeps doing whatever it was doing. Here it goes from 20 to 23, and its direction doesn't change. Here it goes from 20 to 17, and its direction doesn't change. Here it goes from width minus three to width, its direction doesn't change. Here it goes from 3 to 0, but its direction doesn't change. These four are all really the same case, they're just the keep doing what you're doing case. But these two are different, this is the case where the cow tries to leave the right hand edge of the box. And this is the case where the cow tries to leave the left hand edge of the box. So, my next step in building the template for this function is I'm going to give myself a three case cond. Okay. I'm going to say cond, and then in each case, now that I know what these types are, I'll just delete this note. And then in each case, I'll give myself two copies of the template to work with, the question version and the answer version. And I'll have three of these. So now, let me see how do I think about these cases. Well, this case here is the case where if the cow kept going, it would leave the box by the right edge. It would go too far. What does that mean it we go too far? Well, it means that if I took the cow's current x position and I added the dx to it, this expression here is what the cows position would be if it just kept going. In, in this case, what happens is that, if the cow just kept going, then it's position would be greater than width. The cow would leave the right edge of the box, and of course we don't want the cow to do that. We want the cow to be a nice docile creature that stays inside the box. And so, instead of letting it leave the box, we're going to say, no, no, no, no, you're going to be a new cow that is going to be right at the edge of the box in your new velocity. We will basically do the opposite of your current velocity. And in Racket, if you call the minus primitive with a single argument, it just changes the sign of the number. So, if you call minus with three, it gives you minus three. If you call minus with minus six, it gives you six. So, this changes the direction of the cow, and this puts it right at the edge of the box. So, that's this case here. So now, let's look at this case here. Well, this is the case where if you let the cow just keep going, this is the cow that just keeps going, then it would end up outside the left edge of the box. Its position would end up less than zero, and of course we don't want the cow to do that. We want it to stay in the box. So, we're going to say, no, instead we're going to have a cow that's at the very left edge of the box. And once again, we're just going to flip its direction around. So, that's this case. And now, all these other cases are just the cow keeps doing whatever it was doing. So, we don't need a question here, we'll just put an else. And we'll say, well the new cow is a cow that keeps doing whatever it was doing, that's plus cow of x and cow dx. This is the same expression used here and here to see where will the cow end up if we just let it keep going. Well, this cow is going to just keep going. And its new dx is just going to be the same as its old dx, because it's just going to keep going. Let's try all our tests now. Whoops, make is wrong, this is supposed to be make cow. All six test paths. Now look, this is in some sense the most complicated function we've designed so far. Now, it's complicated entirely due to domain knowledge. It's complicated, because the geometry of an object moving back and forth across a box, and handling the edge conditions right is a bit complicated. But notice something important. If you break it down into all of these six examples, and then you realize that those six examples are really just three cases, then it isn't complicated. The design method really worked for us here. It told us to do the examples first, which broke the problem down, and helped us then take the template and put structure onto it. Here's an example of the design method making a moderately difficult problem a lot easier. What I've done now is to jump to the v3 version of the cowabunga solution. That has the next-cow solution, which we just developed a few minutes ago. And I've actually done a bit more than that. I've started doing the design for the render-cow function. Just to save time, I did the first part of the design already. So I've got the signature, the purpose, the stab, and I did the examples. And the examples for this function are actually relatively straightforward. If I render a cow that's at position 99 and has a positive velocity. In other words, it's, it's facing towards the right edge of the screen. Then, what this function needs to do is to place an image of the right facing cow at x position 99 at y position center y onto the background MTS. And I need two tests for this function, because sometimes it places a cow facing right and sometimes it places a cow facing left. And so, I've got a second test here where the cow is going in the different direction. And to be honest, this test would actually be a little bit better if I changed the x coordinate just to be sure that I couldn't accidentally have put in by accident 99 into the actual solution. So, let's just make this be you know, 33, and we'll make that be 33. And now those are two pretty good examples, they vary both the direction that the cow is facing and the x coordinate. So, I've already got the template, let's just start filling this in. Let's see, both examples tell me that I'm going to place an image. And sometimes it's one image and sometimes it's another image. Let me just put dots there for a second. And I always place the image at the cow's x coordinate. And I always place the image at center y. And I always place the image on the background. That's all of it, except for this part here where I have to decide exactly which image to place. Now, there's two choices here. One choice is I could Start to put an if expression here that would choose which cow image to use. Well, I'm going to do something slightly different, and it's going to be something that we'll talk a lot about in the course as we go forward. Which is I'm going to say to myself you know, this function is actually doing two things. This function is deciding which image to use and putting it in the proper place. Two tasks. And as a general rule, we don't want functions that do two tasks. We want each function to do one task. So, what I'm going to do is I'm going to wish for a helper. I'm going to say you know, it really would be great here if there was a function called choose-image. And I could call that function with a cow, and it would give me back the right image to use. If I had that, then I would be done. And so, I'm just going to wish for that to exist. And I have to wish in a little bit more detail. I'll wish in a little more detail by writing a WishList entry for it. So I'll say cow to image, produce. Now, what does it need to do, well, it needs to choose the right cow. Produce RCOW or LCOW depending on direction cow is going. And the reason I write this signature on purpose right now, and I write it in detail right now, is that right now after I just finished wishing for this function, I know what I want it to do. So, I'm going to take the trouble to write down what I want it to do. And then I'm going to say, oh, but this doesn't exist yet. I hope it will some day, and I'll make a stub. Choose-image and sends a cow, and it's got to produce some image. I could make it produce the blank image. In this case, I'll just make the stub produce the right cow. And now I run this to see if it's well-formed. And it is well-formed. And what we're going to see paradoxically is that one of these two render cow tests actually passed. The first one actually passed just because it's choose image stub always produces the right facing cow. So now, I've basically done render-cow. If somebody goes and fulfills this wish that I made for choose image. And that somebody is going to be me a little bit later when I say to myself, hey, what what work remains to be done. Let me search for bang, bang, bang, oh, I need this function choose-image. Okay, great. Let me do it. Lets see what does it do, it consumes a cow, it produces an image. It produces either the right cow or the left cow depending on the direction the cow is going. So, I'm going to speed this up a bit. I've got two examples. One example for when the cow is moving left to right so, it's facing toward the right. Another example for when the cow is moving the other way, and so, I need the left cow image. I'm going to go and get the template from cow. And now, let's see, there's two cases. So I'll use an if, and the question is whether the dx of the cow is greater than zero. If it is, I use the right-facing cow, otherwise I use the left-facing cow. And there's a bit of an issue here I have to deal with, which is what to do if cow dx is actually zero. And in that case, I'm just going to go ahead and decide to use the left-facing cow. Now when I run it, I get that all my tests pass. And that includes the three tests for choose-image, but it also includes the two tests for render-cow, because choose-image is a helper for render-cow. So now, render-cow is working completely, because choose-image is working completely. Let me just recap what happened there. We were in the middle of coding the function render-cow. And we knew it had to place an image, and we knew where it was going to place the image, and we knew it had to decide what image it was going to place. And that's when this idea about each function should only do one task came up. What I did was I decided you know, deciding where to put the image, and deciding what the image is, it's two tasks. I'm going to delegate one of the tasks to a new helper function, choose-image in this case. We're going to talk a lot more about this idea of helper functions as we go along. And in some cases, we're going to give you very clear cut and dried rules for when to use helper function. This is not one of those cut and dried cases. In this case, you have to kind of decide that choose image is its own separate task. And some programmers wouldn't make a separate function for choose-image, because it's so small. But this is a reasonable place to use a helper function, because there really is a separate task here. And as we work through this part of this course, we want you to look out for places where there is a separate task and it makes sense to use a separate function. What is clear is that when I go back to read this function, and I go to read render cow, it says okay, let's see. I'm going to place an image and somebody else is going to choose the image, and I'm going to put it at the cow's x coordinate, Center Y and MTS. That's very clear to me. It says, I'm placing the image and somebody else is choosing the image. And now, when I go down here and re-choose the image, it says, well. If the dx is greater than zero, it's right facing, otherwise it's left facing. This code is easy to read. And at this point, I have all of my handlers done except for handle key. So, I actually can run this program at this point. And I could say, main, make cow. The cow that starts at the left edge and is moving three ticks, three pixels per tick. And there's our little cow. I'll leave it to you to finish the key handler, as I said the solution is there in cowabunga v five. And the problem description also talks about a fun little thing you can do, where if you take the cow image and you take each image and rotate it a couple degrees left and a couple degrees right. And then you take a speed that's for example, an odd number. And you arrange to use different cow images depending on whether the position is an odd or an even number. You can make the cow appear to waddle as it crosses the screen, and that looks kind of neat. And there's all sorts of other fun stuff you can do here. Just go ahead and have some fun with this cow program, that will be good practice for doing this week's homework assignment.