Don't do this at work
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Montes, Tiago
In this talk I reframe a computer programming workshop for kids I delivered earlier this year, exploring and sharing my experience throughout that journey, from preparation to delivery, by recreating a simple yet engaging enough game. With that I'll both demonstrate several Python related techniques and tools many may not be aware of, on one hand, and, on the other, extract provocative questions about general learning processes, especially when targeted at professional developers. I promise zero slides and a somewhat fast-paced live (re)coding session, intertwined with comments on good/bad techniques, along with a surprising exploration of the turtle module in the Standard Library - it is more capable than you think. I wrap up with a self-code review and with thoughts on how such a game could be improved, what implications that could have for both beginners and seasoned professionals: should you do this at work? Targeting 10 minute Q&A / discussion by the end!
 Let me try to extend a thank you to a bunch of other people, like all the volunteers, all the organizers. This is a huge endeavor, so thank you to them. The sponsors, thank you very much. Please if you can, next time, more money. The often forgotten technical people, like Mateo out there that are doing sound, video, stage lighting and stage support, let's have a quick hand for all these people. Thank you. So hello, my name is Thiago, I come from Lisbon in sunny Portugal, which I invite you to visit. Welcome. And this story starts back in January when a very dear friend of mine came to me, knowing that I do these kinds of things professionally, and he asked me, Thiago, would you organize an introduction to programming with Python workshop for my oldest kid, along with a few of his friends from school? Well, these kids are about 12 years old, and of course I said yes, knowing two things from the start. The first one is that working with kids is a very serious business, so an appropriately serious amount of preparation was in order. And the other thing was that I wouldn't be able to reuse none of the materials, tools, sizes, whatever that I normally use when I train professional developers. And here we go. So instead I need to go for a much more informal approach, like a learn by doing approach in a friendly, fun, if somewhat chaotic environment where kids would be really engaged into the thing without, you know, kind of barriers. So we would go for a learn by doing in lots of many code along sessions, where I would explain maybe a simple concept, type a few lines of Python, maybe one, maybe two, and they tap along and run it, and we would do that repeatedly until we reached like a mini project that was fun and they could then explore. And then we did that three or four times, and I wanted the last project to be something they would be really proud of. They would take home and share with their friends and family, you know, and it would need to be a game. Now we're having a problem with projection, may I plug in and plug in, do you need anything, Mathew? Are we okay? Okay. I'll move on. I'll move on. You won't be able to see the code if it's not projecting, but I'll keep talking, don't worry. So we need it. Thank you. So given that we were starting from the turtle module, I wanted to see if we could build the game with a turtle module. And if you don't know the turtle module, let me show it to you. Hopefully. I'll try that. I'll try that. So the turtle module implements, as the name implies, turtle graphics. And turtle graphics are a thing that back from the 1960s, where you get a canvas, okay, and a turtle. This is from a programming environment called logo back then. And you get a canvas and a turtle, and essentially you can say things like turtle, go forward, a certain amount, and you see the turtle goes forward, okay? And then you can say, well, dear turtle, can you please turn left? Then the dust on left. Do we need to make a break to fix this? No problem. There's no problem at all. We can try and see what's going on. So there's this certain amount of primitives that we can tell the turtle to do, like you see. It's stable now, so it's just a glitch. So now we turn the turtle, we say go forward, and now it goes forward in a different direction. It keeps drawing the line, so it's pretty intuitive. It behaves pretty much like a pencil on a sheet of paper. And pretty much like a pencil, you can say, well, turtle, go up, okay? It should be fly, because the turtle should fly for kids, but it's forward, no problem. If we now say go forward, now it goes forward, but doesn't draw the line, so it nicely animates. This could be useful for a game, I said. Oh, this can be useful. And then there's other fun things that we can do. We can tell it go forward a negative amount of distance, whatever, and it goes backward, which is kind of intuitive, maybe. And more, if we bring it down again, such that it goes back to drawing lines as it moves, we can also tell the turtle to go to a specific point in the canvas, and it will go there directly in a straight line, regardless of being facing whatever it is. So it's now kind of facing up, but you tell it to go to the origin, which is the point where it started in the center of the canvas, and there it goes. It draws a straight line, okay? So the question is, could we build a game with this? And again, the answer is yes, and let me show you, okay? What do I want to do? I want to start with something like, what's Python 3.7, maybe? Shall we? Let's do that. It says here, game.py. And we will make it executable. And don't worry about this. You really don't care about this. What you care is this. So we'll import it to a module, okay? And we'll run it. It's like this. And if you run this, this main loop thing here is just like keeping the canvas window open, okay? So let's pimp it up just a bit. And we can pimp it up by setting up a screen thing that's here, okay? And we say start x600 to shift the canvas more towards the right hand side of the screen. And we'd like to work with the known width and height. So 640 should be enough for anyone. Mr. Bill Gates has said that. So let's go with that. And let's give it a nice orange background color. And if you haven't made any horrible mistake, we now have a nice orange canvas. So what kind of game do we build with an orange canvas? Well, given that Minecraft in Fortnite were taken, okay, so we went to a different crowd. And in our game, there will be two characters, a player, player control character, aptly named player, and a beast. So it's the player and the beast. And these characters move around in a grid somehow constrained in the grid. And the purpose is you control the player, you need to capture the beast. The beast runs away randomly, okay? Pretty simple, much better than all those other fancy stuff. So we will start by drawing a grid to help us out with this. So bear with me for a minute. This will define the grid size, which is the grid size, each cell size. The grid span, which is the, how many cells we will have from the center of the canvas. And we'll use this one grid max, which will be used all around. So this would be grid size times grid grid, no grid size, okay, go and grid, mad grid span. And we'll draw the grid using a line function that draws arbitrary lines. So let's go here and here. Well, we know these, we can say total up and then we go to the starting point, like X1, Y1. And we duplicate these ones, say go down and now go to the end point. Okay, so this would be two and two. And now we can iterate over the range for, for I in range of minus grid span to grid span, okay, plus one, because there's always this plus one, isn't there? Scale I equals I times grid size. And now we'll draw a line from minus grid max. See, leftmost edge, let's say of the grid, scale I, and to grid max, scale I. If you run this, and if I haven't made any horrible mistake, there you go, they're slowly trying to draw grid. So let's, let's speed it up, okay? Let's speed it up. Hang on, hang on. We're just starting, okay? Let's keep having some fun. So we can say something that's not very intuitive at all if you look at the dots, but the speeds, they tell you in the dots it's from zero to ten, from one to ten, ten being the fastest. But if you tell it to zero, it's even faster, okay? So go, you go zero. You can hide the total, and you can tell it, like, give it a nice, you know, dark orange background color, because too much, the background, the nice orange color for the line, let's make it thicker, you know, for, for effects, whatever. And by the way, let's swap these coordinates here, okay? And we get the vertical lines as well, and we get a grid, a much finer looking grid. Right. So this is a grid. So we need the players, the characters, okay? And one very interesting thing in the total module is that we can have as many turtles as we like, okay? We don't get just one. So how do we create a turtle? Like this. Let's see. You go player equals turtle, that's a module, and there's a total class, and that's it. And you get a new turtle, and you can have as many as you like. There's your turtle. Not a very engaging character in the game, okay? You're 12-year-old, you want to see something more engaging. So there's yet another thing that the total module can do, which is very cool, okay? If I can properly copy this line, of course. So that would be, you can register a shape and give it a file, okay? Have on desk. That would be playerGIF. I'll tell you about the file in a moment. And then once you do that, you can tell the player turtle to use that shape. Once you do this, you get this guy. And now the kids always go, oh, I like this. I know how to move this guy. Move and go to and forward, okay? So let me tell you about these files in a quick minute. So I brought along these two files here, which I obtained from OpenGameArt.org. Go there, lots of cool stuff. Thanks to the authors. And the other thing we want to do, of course, is to control this player character with a keyboard. So how can we do that? Well, here's another trick that the total module has for us. So that's a two-step process. Okay, we say something like this. OnKey, func, and then up. And the idea is the listen function tells the main loop, okay, when it enters the main loop to keep listening for keyboard events. And this other call, onKey, tells the main loop to call the function func every time the up key on my keyboard is pressed, okay? So we will need four of these because we want to control the player in all directions down, left, left, and right, right, right. And as for func, let's go a bit funky, okay, here. I'll go with a lambda. Don't worry too much for now. I'm just being generic here, okay? And when we move up and down, x doesn't change. When we move left and right, y doesn't change. When we move up, y is positive. Down is y is negative. x is negative, and right, x is positive. Now if we just need to create the move player function, don't you like the justs that we keep introducing our speech? Just, just, it seems as if it's obvious. It's not, okay? Especially when working with beginners. So we will create the move player like this. So it takes delta x and delta y. So we'll try to move the player relatively to where it is. So if we knew where the player is, we don't, okay? We could do something like player go to, remember this one, wherever you are, plus the delta x, x times the grid size, right? And wherever you are, the y axis plus the delta y times the grid size. And if we knew the player position, if only we knew the player position. Okay, that's it. Okay? Only we knew it. And you go like this, and now if I hit my keyboard, oh, there it goes, okay? It's drawing a line because guess what? That's what Terval Zoo here, okay? But we know how to fix that, okay? Because we have the player fly or up method. If we do this, then it moves nicely, okay? It can go crazy, but we don't really care, okay? It moves. What's missing? Well, the other character, the beast, right? So we might feel tempted to like copy and paste these. We won't do that. You don't copy and paste code. Don't. We'll do a few of that, but we'll get to that. But so we'll instead create an actor function that will create an actor or a character for us, okay? And the way to do that could be, one possible way would be, let's say, this image, okay? An image. Then we'll return this thing that we're creating here. I don't like that. It's called player because it doesn't make much sense any longer. So let's call it T. And see that player is actor. PlayerGalp, okay? And this should work, okay? And now we can just copy it over and say beast. And we have player and the beast. And there's the beast. Okay? It's sitting there still. So let's make it move around. So we could create maybe a moveBeast function, okay? Let's see. Find a moveBeast function here that will move it kind of randomly. And for minus grid, span to blah, blah, blah, you know, this is the boring part. Sorry for that. But, you know, there's no fun without pain, I guess. So we can say beast. Now go to guru. Okay? And we can say it's not that easy today. X times grid size. And Y times grid size, I guess. And now this function just moves the beast at some point in random, the grid. We'll call it right before starting here. And the other thing we're going to do is we'll need to import the random module right because we're using the random function. So there it goes. Okay? So it's there. Let's start it again. It's where it goes, okay? So, okay, it goes there. Now the idea is that we'll move the player. And as we move, we need to see, did we capture the beast? Yes or no? And when we'll capture the beast, the beast will do like a, let's call it a small dance as if it's stunned by being caught. Then it turns away again. So the way to do that is, let's say, every time we move the player, we will attempt a capture, say, a capture, capture. Okay? And what's that? So attempting a capture might be something like, well, if the player position is, you know, equal to the beast position, right? Then beast do a dance. Doing a dance might be drawing a circle, which is yet another method of turtles that, you know, appropriately named, draws a circle. But if it's raised, it won't draw it. Just do a little dance. We'll reduce the step to make it faster. And then you say, move, beat, so go away from wherever you are. And let's see how it goes. If I save this and run it. So dance goes away. Cool. But it's really not challenging because as we move, the beast is just sitting there. So it needs to be a bit more challenging. So maybe whenever we move, there's some odds that the beast will try to cheat trick us. So we might say something like, well, else, if we didn't capture, okay, so maybe if random dot random, this is, will give us a random number between zero and one. Okay, we call it lower than move beast odds. We'll just move the beast. So the bigger this number is, the bigger the odds are the beast moving around the tricking out. So we'll set this, call it the game difficulty constant here. And we'll say, well, let's make it one in five, zero point two. So let's see how it goes. So dangerous. This is random in a live coding scenario. So it might never happen. But it did. You see, I'll just move around and see if the beast, okay, the beast. It's very dumb sometimes if you really want to capture it, you'll see there's some artificial intelligence here. The random number knows. I know that. I've been playing this and the kids know too. So if you take a look at this, okay, so the game is already cool. Okay, you can play it around. But there's a very serious problem in this game and that's it never ends. And with kids, you need games to end because at some point we'll be telling kids come over it's dinner time and they say, hey, dad, let me just finish the game. It doesn't finish. So it must finish. Okay. So we'll introduce the concept of say, energy or karma, which will again be visually represented by yet another turtle, of course. And we'll have like a turtle center and top of the grid. The turtle will move slowly towards the left as the player moves. Okay. And if it ever reaches the leftmost edge, the player loses. And on the other hand, whenever the player captures the beast, the karma will move like a chunk towards the right. And if it ever reaches the rightmost edge, the player wins. Okay. So let's build this step by step. So we need a new turtle, a new karma turtle. So let's go there. Well, just, yeah, this is the time for copying and pasting, right? We can copy and paste this karma. But oh, come on. I don't have a karma dot gift image on this. So what am I to do? Well, it turns out that if you look at our actor function. It creates a turtle, registers a shape, loads it from desk, and then tells the turtle to use it. Okay. It turns out there are a few built-in shapes in the turtle module that don't require registering. Okay. And one of those is called Circle, which we'll use here, which will fail to register because register tried to open a file on desk. So we'll say, well, if the image ends with, you know, dot gift, then register it. Otherwise, assume it's a built-in shape and just go ahead and do it. And there's our karma turtle. It's not at the right place. And it's kind of dark. Nobody wants a dark karma, right? So let's make it shiny a bit. So one thing I'd like to do is something like maybe color equals gold. I don't know. And for that, we'll add a, like, a keyword argument here defaulting to black so that I don't need to go back and change all the other code and say, this is the turtle I created locally and say color, color. Okay. And this should work. And then we'll tell the karma turtle to go to zero. That's horizontal center. And then when max, which is the top of the grid and just a little bit further up and that thing, whenever you need it a little bit further up in a crazy number, you go with 42 and nothing can go wrong. So there you go. There's our karma turtle. Okay. So we need to move depending on the result of the game. And if you remember, even though it's a circle, it's facing towards the right hand side. Okay. So we'll use that forward positive number forward negative as a trick to move it left or right. So that moving the karma turtle is just a matter of saying karma go forward this number. Okay. So to do that, we'll create a, an update karma function somewhere here. Let's say, well, well, well, well, well, well, maybe here. Maybe here. Yeah. Maybe here. So let's call update karma. It takes a delta karma, which will be positive or negative, depending. And we'll say go forward delta karma. That's it. Okay. And now in our attempt to capture, we say, well, this is a captured case. So we'll say update karma with a karma value of a capture and we'll set this variable to a positive value. And then this is the case where we moved but didn't capture. So we'll go there and say karma move and we'll set these two here. Maybe let's say this one is a hundred and maybe this one, this one, I know it needs to be negative. So let's go minus 20 say and we'll get, go get back to our code and let's run it and see if it moves. Okay. Slowly towards the left, right? Slowly towards the left. And now it should jump towards the right hand side. Okay. This is working. Good. So all we need to do now is to find our boundary conditions, detect them until game over, you won, game over, you lost. And we do that by checking the karma position, the horizontal position after every move. So we'll grab the karma x and karma y. We already know that these karma y equals karma position, right? But we really don't care about the y. So let's go like this. Okay. That's a throwaway variable. And we say, well, if karma was my keyboard, karma x is greater than or equal to grid max, then let's say end game, we'll give it a, this is winning. So let's say, yay, victory. Congratulations. You won. And otherwise we can say, well, if it's negative, if it's below negative grid max, so this is certainly a defeat. So let's go, I defeat, sorry for that. Try again. Where end game or the end game function is a function that takes a message and uses the right method of turtles that just displays text strings besides the turtles. We don't have much control, but it's good enough. We have control on over the alignment, the horizontal alignment, which we'll try to center on the turtle. We will override default font because the default font is actually too tiny for this kind of game. And I thought, why not go with Hovetica for two reasons? Okay. So it's a hallmark of Swiss design and it seemed appropriate. And you really can't go wrong. Nobody was ever fired by using Hovetica. So don't be creative with your fonts. Use Hovetica and you'll be fine. Okay. So if you, I don't want to go off rail, but I love typography. So don't use other things. Don't be creative. So this should work. Okay. So just write some message and we're going to test this by cheating a bit. So because we don't have that much time, so we're just going to say, well, let's win this really quickly. We'll always win really quickly. And here we go. So we move. We're about to win anyway. I don't really care. I'll go up and down. I went victory. Great. So it seems to work. The text is in black. I'd rather have it in white. But if you recall the turtles, the font color is black. So I'll change it to white. And there's another thing. That's a much more serious thing because if I head up, you see, the game is still on. Okay. And why is that? Look at our curve. So we said in game, what does in game does? We thought in game meant everything's done. But all we did in game, sorry for that, is we wrote the text message. But originally when we set up the keyboard things, we told listen and whenever this keys press do this and this, call the move, it's still doing it. It's still doing that. We haven't told it, stop doing that. So ideally we would do turtle and lesson. So forget about the keyboard. Just be still. We cut to that. The turtle module doesn't have that. So we'll hack it away in a very ugly approach. It works so I don't care. Up, down, left, left and right. And I'll tell you a bit about why I think this is really bad later. But if we have the time, okay. On key, we'll go the on key again. But now we'll say, well, for these keys, use the none function. So it means forget about anything you knew about this key. And we want the player turtle to be white. You remember that. And this should be pretty fast and cool like this. So let's see. Okay. Down. I want to win really quickly. Yes. We're in cheat mode because we are the cosers. We can do anything. Right? It's very powerful. Victory. Good. And now I'll bang on my keyboard to see if it works. Okay. I'm banging. This is one of those Apple computers, but one of those oldests that used to come out with real keyboard. Okay. And this is kind of flaky. That's not the case. So Tim, please fix the keyboard. Okay. Thank you. This is working. And what I'm going to do is cheat the other way around to check that my losing condition is being properly checked. And we're nearly done. Okay. So let's go minus, what's minus 82? Why not? Let's make it go faster. Go go faster. Faster for kids is great. So don't capture the beast. We want to lose this really quickly. And defeat and bang on our keyboard. So the game is nearly done. Okay. This was my original plan for the game, but the kids came and said, yes, but we need a score. Okay. We need the motive to come back to the game and do better. That makes a lot of sense. Okay. So they came up with this very simple and effective idea. And what they came up with is, well, if we counted the number of steps that the player does along the game, and you just need to print them at the end. So if you win, you want to win with as few steps as possible. Okay. That's reasonable. It's a better score. And if you lose, I don't know, ask the kids. Okay. So there's a score. Let's implement that really quickly. And the way to do that is one way to do that, because there's no single way to do things. We'll do it like this. Well, player steps equals zero. Start counting steps at zero. Okay. When things start. And then every time the player moves, this is the function. You will just increment it. Plus one. Okay. And then if you remember, there's a method here in game that writes a message with the you won, you lost. We'll just copy and paste that and use a comma turtle to write a different message. We'll use a funky f string. F strings are so cool. Don't you like them? Yeah. Player steps. We'll make it slightly smaller. And this should be it. Let's see. Three statements of Python. We've implemented a score. Isn't Python cool? The three steps. So let's cheat the other way around. Let's instead remove the cheat and go for a real quick run of the game to get a feel. And I won't go until the end. This is one of those games that may never end. So dangerous for the dinner thing with the kids. But it seems to work. It's fun engaging enough. And I won't play it anymore. I won't bore you. Because if you play it, you'll have fun. But just watching it is boring. So let's step back for a minute. What we have here. So we have 100 lines of Python code. Created pretty much, you know, make it up as you go along. Okay. Yeah, I don't care. Just create a function. Oh, that's not cool. And what I'd like to do now is do a quick review of this code. I'll highlight a few things. I don't have time to go over all of it, of course. Highlighting maybe good ideas, bad ideas. Would you do this at work? Yes or no? Okay. So let's get here. So these variables are constants. These are a very good practice. The character movements and the grid drawing, they're all based on these constants. So if we need to change something, let's say, if I go five here, five, can I go five, please? Five? Yeah, there you go. Five. Then it all still works. Okay. So this is clearly something that you would do at work. It's a good practice. Okay. To have common constants or variables. And same can be said for these. It's the game difficulty. Okay. This is a good thing. Then I'm going to take a look at these. This is kind of a mess. So this loop draws the grid, but it's difficult to read. I wouldn't want something like this in my serious, sustainable code. Maybe it's the variable names I selected. I don't know. But I don't like this very much. It's hard to read. It's lots of John Tree. I hate it. But it works. There you go. And then there's this line. This line deserves a mention because it could have been written as fmh of minus 40 blah, blah, blah equals to dot k of, blah, blah, blah. These are semantically equivalent. And I claim that the first one that I used is much better for two reasons. First reason, readability. Read that says if image ends with that, so it's clear for you to your brain. It's dark to your brain. This string ends with that string. Whereas in the other one, whether you're a beginner or an experienced professional, something like this is going on more consciously or subconsciously. What's that? Oh, that's the colon thing. The colon thing is a slice. It's from there to there. What's the there on the right? There's nothing there on the right-hand side. So that's still the end of the string. What about minus four? So that's four from the end. Does it include the fourth from the end or is it from the fifth or from the month? It's a mess. This happens in a split second for advanced developers. And it takes a long time for beginners. It's not readable. And then there's this. If you change at some point, you want to use JPEG images. Then this line of code still works. And the other one doesn't any longer because image of minus four till the end is four characters long and dot JPEG is five characters long. So you need to change in two places. You need to change your code in both sides of the comparison. So it's clearly a worse solution. So go with ends with and starts with. It's simpler. I don't know. Just use ends with and starts with. Keep it simple. Now this deserves some mention too. What's going on here? So we're calling the active function that creates a turtle ready to use. So we're ready to play with it. And then we're slapping a dot steps attribute there to counter steps. It's our solution to tracking the player steps. And it's effective, simple. So let's review this. So in general, everything in Python is an object. And Python objects have a type and have attributes. Now again, in general, any piece of code can create, destroy, rebind or reassign values to any attribute in any object. There's no protections. There are some exceptions to this, but this is the fundamental model of the way Python works. So in general, this is not really a good idea because we're poking around it, objects that might behave differently. So this isn't something you would do at work, but it's possible. And again, with great power comes great responsibility. So use these kinds of things wisely. But I wouldn't want this in any serious, sustainable code. We would need to find different solutions to that. Now I'll highlight just one more thing, two more things for the sake of time. So we can step back furthermore. And again, this statement could have been written as comma position of zero or bracket zero. And again, I say that the one I use is better for two reasons. First again, readability. Maybe for some people that funky thing with the comma, comma and the score blah blah blah is somewhat strange. But you'll quickly get used to that. What I claim is that this line has the comma position in parenthesis and brackets and blah. So it's slightly harder to read. I'll grant you that might be a personal opinion. But check this. When you look at this code, you wonder, well, could I have used 42 instead of zero? Maybe that comma position is a dictionary-like thing. Maybe could I have used key there? You don't know. The only way to answer these questions is to look at the function documentation. Or God forbid, look at the source code. You worried about your update comma function. You don't want to know about the others. Whereas here, you know that that comma position thing, I'll short it to right-hand side is iterable. That's a funky thing. And we won't go into that. Think less like maybe it's a bunch of things. It's a bunch of things. If you want to know more, we'll talk in the quarters. And it's iterable and it has two elements. It's guaranteed to have that because there are two things here, comma separated. Otherwise this code wouldn't work. And by the way, if we're using that underscore, that's a variable like any other. But it's a way of saying we don't really care about what's here. So we also know that we care about the first. So it's clearly, first, no, first, Tiago. So it's clear other than readability, the line that I used gives you three facts immediately. And the other line leaves you with a few questions. So again, I say this is better. There's a very interesting article by Trey Hunter. I think. Trey Hunter, he's a trainer too, I think. Go read it. And come to me, I can point you to that. It's very interesting on this idea. Let's wrap up our code review to move on to some different thoughts. Now just go here. This is the most horrible two lines I've written here in my understanding. And why? Because there's repetition. The up, down, left and right string constants are repeated here. And you see in this code that sets up the keyword initially. And that's really a no, no, no, no, no. So possible solutions would be to define constants with these values, wrap them in a list in a dictionary, create an enum, something like that. This is really, you wouldn't do this at work. I would be angry or disappointed if someone said Tiago just created the best looking code. Now I think we can improve that. So let's forget about the code for a minute. So this is the code. Now here are a few thoughts. Well the Python scenario is amazing. It has a bunch of functionality. And quite often it does surprise you. It has its smelling corners, it does. But if you dig deeper into a given module, you're bound to be surprised and you're bound to find useful functions, tidbits, examples, okay? That was the case with the turtle module. I didn't know you could do this with the turtle module. Keyboard input, multiple turtles, GIF images. I can do a bunch, okay? I can nearly serve a breakfast with the turtle module. I don't know. So there have been recent discussions on the standard library and they're very relevant, I think. But the fact of the matter is that the standard library is bound to change in the long term, okay? But in the near term, it will stay pretty much as it is. And knowing it and using it is a very valuable skill. Don't rush into it. It takes time, but it pays back. So I learn a lot. Every time I go into the docs, go docs, Python, or the library reference. That's it. You go there, there's a bunch of cool things. And then, of course, there's this, you know, I'll read my own slides. Don't do this. Direct in your face. Python is effective and fun, and it is. And maybe the reason why so many of us are here today. Because one day we said, oh, this is Python. Maybe if I just, hmm, funny. Oh, cool. Oh, I like this. I want more. And then 15 years later, here we are. I don't know if you're relate to this. This is what happened to me. And having fun is obviously the best way to learn new things, and the kids did learn a few things. While the workshop was back in March, and certainly three months after the fact, or four, whatever, they probably don't know much Python now. But there's one thing they learned. They will never forget. And that is that they're gaming consoles, they're tablets, they're electronic devices. They're all programmable. They have seen the lights in a way. They know there's a way to make the machine do something they want. So maybe in 5, 10, 20, 40 years time, they're faced with some kind of software that just doesn't feel right for some reason. They know, no, I'll fix it. And I'll go pick up back on that path. And this is a very powerful thing to know that you can't really unlearn. Okay? And this was my main objective with the kids. These machines, you are the master. So you can make them do whatever you want. Okay? So if you want, go do that. Now what if you're a professional seasoned developer, four years experience, you've done it all. You've never done it all. Okay? That's my opinion. There's always something else to do. Now, would you do this at work? That's something like this. Exactly this. This silly game. Would you do it? Well, could you learn something from it? Would say extending it to network-based gameplay. Would you learn socket programming, IP addressing, IPv6, by the way, at DNS, I don't know, Bluetooth? Would you learn that there's no way, no technology, no protocol, no whatever that guarantees that when you send a message out through the network, there's no guarantee that you'll ever get back a response. So you need to use timers and timeouts and things. Would you learn something from it? Would that compel you to write a low-level event loop managing network traffic, keyboard input, internal animation, and sound, by the way, why not? And would that help you understand different models of concurrent programming with coroutines and learning about the async and await keywords that are so mysterious to many? Would that be helpful in something else that you do? Would you learn about race conditions? This game here has race conditions. You might say, oh, I don't care about race conditions because I do data analysis. And you don't need network code to have race conditions. You don't need to have a web-driven code to have race conditions. All you need to have is concurrency. And concurrency is everywhere, more and more. But tuning your mind into grasping what the race condition is and kind of smelling it from the distance and knowing how to avoid and improve your code to avoid those because they are very difficult to diagnose and fix. But if your mind is kind of tuned into that, you've learned a very valuable skill, OK, and so on and so forth, OK? So I clearly say, yes, you should do this at work. Go ahead and tell your boss, yeah, what are you doing? I'm doing a silly game. Are you crazy? No, I'm not crazy. I'm learning the best way possible because I'm having a bunch of fun. But don't do, don't just do this at work, OK? You balance it out, OK? Now the part in fun is this. It came to me as I evolved and parted away from the workshop as that learning and having fun, hopefully learning while having fun, OK, is probably the best way to grow into better versions of ourselves. And I think in the end that's what it's all about. I mean, I've had a bunch of fun since January, thinking, discussing, working long nights. It was a lot of work, but a bunch of fun for, why did I do it? For love, I don't know, for passion, for friendship, for kids. But I learned a lot too, OK? I'm still figuring out all that I learned from this experience, and I humbly hope that all of this, what shall I call it? This is not to talk, this is some silliness, some fun, that it might motivate you and inspire you to think, maybe to put away some time, some energy or karma, if you will, and dedicate it to learning and having fun with whichever silly, however silly, whatever, who are they to say, oh, this is silly, you do whatever you like. So to dedicate some time and energy to having fun and learning, and if you need to choose, if you can't have both, OK, go for fun, OK? If you can't have learning and fun, go for fun. So this is it. Thank you very much. I hope you go out and have a lot of fun. Thank you. Thank you, Tiago, for this very entertaining talk. Thank you. We have a few minutes for questions. Yes, I'm happy to address anything about the code, the kids, the method, and catch me out there. I'll be happy to discuss all of this at any time, OK? Go ahead. Thank you. I really love the message that we have about providing kids the ability to think, yeah, I can tweak this in the future. I really don't know how it works, but I know that it can be fixed. So my question is, how would you address it to adults if you had to do something like this, like 20-something or 30-something? That's a great question. I haven't thought about that much, but this is a thought that crossed my mind a lot of times. Working with kids is serious business, and you heard me say that, because kids are very wide open. So you can pretty much kind of drive them the way you want, OK? So that's a huge responsibility, OK? So they're more malleable, so to speak, OK? That's what I meant, that kids, working with kids is very serious, OK? Because you can't mold them some way. I don't know how I would do it adults, because as we grow up, we tend to become stiffer. But in the end, it's about showing and not telling. If you show people something that resonates with them, they will resonate with that and go from there. So from an educational standpoint, I would say that it's about finding what resonates with your target audience. And certainly what resonates with kids is a game like this. And if I went to this with an adult, this wouldn't probably be interesting. It wouldn't resonate. I'd say that that's the key idea. But I'm happy to discuss this more. OK. It works. Thank you very much. It was great. It was very important, I think. But I have a neat pick. Go ahead. This pattern where you use a single underscore for a variable that you don't use, have you ever had to use getText? GetText, yes. Sure. Yeah, getText is a way, is a module in the standard library that helps you internationalize or translate your code to different languages, OK? And it does a hack. It uses this underscore variable that becomes a function. So you convert all your strings that you say to the user, say, hello, user. And then you wrap it up with underscore and parenthesis. And then in another file, we say, well, hello, user is, hola, oclizador, hola, oswario, blah, blah, blah, blah, and all the languages. And then it does that for you. So thank you, Radhmer. That's a great point. That's like a counterpoint, OK, this code that we've seen is much more advanced than what we did with the kids. We didn't do any kind of lambdas. We didn't do loops. So they went like draw line, draw line, draw line, draw line, draw line, draw line, draw line. So we went for the basics. Thank you. That's a great nitpick. And I'd like to know how to solve that. I don't know. I would like to. That's why I'm asking. I have no idea. I never thought about it. I never thought about it. I go with a double underscore variable, I don't know. Good idea. Thanks, Radhmer. So it's gone red. Yeah, I'm sorry. OK, so let's talk out there, OK? Yeah, you can. Very short question. Go. How long did it take for the kids to reach this level of? OK, we did eight hours, OK, two hours, two hours, two hours, two hours across two days. So two hours in the morning, and we went slowly, OK, from I'm happy to share the materials. I have all the materials, all the step by step lessons, OK? But when they got here, they were comfortable enough to vary some, change some conditions, play around, OK? But this was like a bit too sophisticated for what they were comfortable with. So it was kind of a balance between having fun, being proud, look what I did, but I don't completely understand it, OK? OK. Thank you. Thank you again. Thank you.
 Let me try to extend a thank you to a bunch of other people, like all the volunteers,  all the organizers.  This is a huge endeavor, so thank you to them.  The sponsors, thank you very much.  Please if you can, next time, more money.  The often forgotten technical people, like Mateo out there that are doing sound, video,  stage lighting and stage support, let's have a quick hand for all these people.  Thank you.  So hello, my name is Thiago, I come from Lisbon in sunny Portugal, which I invite you to  visit.  Welcome.  And this story starts back in January when a very dear friend of mine came to me, knowing  that I do these kinds of things professionally, and he asked me, Thiago, would you organize  an introduction to programming with Python workshop for my oldest kid, along with a few  of his friends from school?  Well, these kids are about 12 years old, and of course I said yes, knowing two things  from the start.  The first one is that working with kids is a very serious business, so an appropriately  serious amount of preparation was in order.  And the other thing was that I wouldn't be able to reuse none of the materials, tools,  sizes, whatever that I normally use when I train professional developers.  And here we go.  So instead I need to go for a much more informal approach, like a learn by doing approach in  a friendly, fun, if somewhat chaotic environment where kids would be really engaged into the  thing without, you know, kind of barriers.  So we would go for a learn by doing in lots of many code along sessions, where I would  explain maybe a simple concept, type a few lines of Python, maybe one, maybe two, and  they tap along and run it, and we would do that repeatedly until we reached like a mini  project that was fun and they could then explore.  And then we did that three or four times, and I wanted the last project to be something  they would be really proud of.  They would take home and share with their friends and family, you know, and it would  need to be a game.  Now we're having a problem with projection, may I plug in and plug in, do you need anything,  Mathew?  Are we okay?  Okay.  I'll move on.  I'll move on.  You won't be able to see the code if it's not projecting, but I'll keep talking, don't  worry.  So we need it.  Thank you.  So given that we were starting from the turtle module, I wanted to see if we could build  the game with a turtle module.  And if you don't know the turtle module, let me show it to you.  Hopefully.  I'll try that.  I'll try that.  So the turtle module implements, as the name implies, turtle graphics.  And turtle graphics are a thing that back from the 1960s, where you get a canvas, okay,  and a turtle.  This is from a programming environment called logo back then.  And you get a canvas and a turtle, and essentially you can say things like turtle, go forward,  a certain amount, and you see the turtle goes forward, okay?  And then you can say, well, dear turtle, can you please turn left?  Then the dust on left.  Do we need to make a break to fix this?  No problem.  There's no problem at all.  We can try and see what's going on.  So there's this certain amount of primitives that we can tell the turtle to do, like you  see.  It's stable now, so it's just a glitch.  So now we turn the turtle, we say go forward, and now it goes forward in a different direction.  It keeps drawing the line, so it's pretty intuitive.  It behaves pretty much like a pencil on a sheet of paper.  And pretty much like a pencil, you can say, well, turtle, go up, okay?  It should be fly, because the turtle should fly for kids, but it's forward, no problem.  If we now say go forward, now it goes forward, but doesn't draw the line, so it nicely animates.  This could be useful for a game, I said.  Oh, this can be useful.  And then there's other fun things that we can do.  We can tell it go forward a negative amount of distance, whatever, and it goes backward,  which is kind of intuitive, maybe.  And more, if we bring it down again, such that it goes back to drawing lines as it moves,  we can also tell the turtle to go to a specific point in the canvas, and it will go there  directly in a straight line, regardless of being facing whatever it is.  So it's now kind of facing up, but you tell it to go to the origin, which is the point  where it started in the center of the canvas, and there it goes.  It draws a straight line, okay?  So the question is, could we build a game with this?  And again, the answer is yes, and let me show you, okay?  What do I want to do?  I want to start with something like, what's Python 3.7, maybe?  Shall we?  Let's do that.  It says here, game.py.  And we will make it executable.  And don't worry about this.  You really don't care about this.  What you care is this.  So we'll import it to a module, okay?  And we'll run it.  It's like this.  And if you run this, this main loop thing here is just like keeping the canvas window  open, okay?  So let's pimp it up just a bit.  And we can pimp it up by setting up a screen thing that's here, okay?  And we say start x600 to shift the canvas more towards the right hand side of the screen.  And we'd like to work with the known width and height.  So 640 should be enough for anyone.  Mr. Bill Gates has said that.  So let's go with that.  And let's give it a nice orange background color.  And if you haven't made any horrible mistake, we now have a nice orange canvas.  So what kind of game do we build with an orange canvas?  Well, given that Minecraft in Fortnite were taken, okay, so we went to a different crowd.  And in our game, there will be two characters, a player, player control character, aptly named  player, and a beast.  So it's the player and the beast.  And these characters move around in a grid somehow constrained in the grid.  And the purpose is you control the player, you need to capture the beast.  The beast runs away randomly, okay?  Pretty simple, much better than all those other fancy stuff.  So we will start by drawing a grid to help us out with this.  So bear with me for a minute.  This will define the grid size, which is the grid size, each cell size.  The grid span, which is the, how many cells we will have from the center of the canvas.  And we'll use this one grid max, which will be used all around.  So this would be grid size times grid grid, no grid size, okay, go and grid, mad grid  span.  And we'll draw the grid using a line function that draws arbitrary lines.  So let's go here and here.  Well, we know these, we can say total up and then we go to the starting point, like X1,  Y1.  And we duplicate these ones, say go down and now go to the end point.  Okay, so this would be two and two.  And now we can iterate over the range for, for I in range of minus grid span to grid  span, okay, plus one, because there's always this plus one, isn't there?  Scale I equals I times grid size.  And now we'll draw a line from minus grid max.  See, leftmost edge, let's say of the grid, scale I, and to grid max, scale I.  If you run this, and if I haven't made any horrible mistake, there you go, they're slowly  trying to draw grid.  So let's, let's speed it up, okay?  Let's speed it up.  Hang on, hang on.  We're just starting, okay?  Let's keep having some fun.  So we can say something that's not very intuitive at all if you look at the dots, but the speeds,  they tell you in the dots it's from zero to ten, from one to ten, ten being the fastest.  But if you tell it to zero, it's even faster, okay?  So go, you go zero.  You can hide the total, and you can tell it, like, give it a nice, you know, dark orange  background color, because too much, the background, the nice orange color for the line, let's make  it thicker, you know, for, for effects, whatever.  And by the way, let's swap these coordinates here, okay?  And we get the vertical lines as well, and we get a grid, a much finer looking grid.  Right.  So this is a grid.  So we need the players, the characters, okay?  And one very interesting thing in the total module is that we can have as many turtles  as we like, okay?  We don't get just one.  So how do we create a turtle?  Like this.  Let's see.  You go player equals turtle, that's a module, and there's a total class, and that's it.  And you get a new turtle, and you can have as many as you like.  There's your turtle.  Not a very engaging character in the game, okay?  You're 12-year-old, you want to see something more engaging.  So there's yet another thing that the total module can do, which is very cool, okay?  If I can properly copy this line, of course.  So that would be, you can register a shape and give it a file, okay?  Have on desk.  That would be playerGIF.  I'll tell you about the file in a moment.  And then once you do that, you can tell the player turtle to use that shape.  Once you do this, you get this guy.  And now the kids always go, oh, I like this.  I know how to move this guy.  Move and go to and forward, okay?  So let me tell you about these files in a quick minute.  So I brought along these two files here, which I obtained from OpenGameArt.org.  Go there, lots of cool stuff.  Thanks to the authors.  And the other thing we want to do, of course, is to control this player character with a  keyboard.  So how can we do that?  Well, here's another trick that the total module has for us.  So that's a two-step process.  Okay, we say something like this.  OnKey, func, and then up.  And the idea is the listen function tells the main loop, okay, when it enters the main  loop to keep listening for keyboard events.  And this other call, onKey, tells the main loop to call the function func every time  the up key on my keyboard is pressed, okay?  So we will need four of these because we want to control the player in all directions down,  left, left, and right, right, right.  And as for func, let's go a bit funky, okay, here.  I'll go with a lambda.  Don't worry too much for now.  I'm just being generic here, okay?  And when we move up and down, x doesn't change.  When we move left and right, y doesn't change.  When we move up, y is positive.  Down is y is negative.  x is negative, and right, x is positive.  Now if we just need to create the move player function, don't you like the justs that we  keep introducing our speech?  Just, just, it seems as if it's obvious.  It's not, okay?  Especially when working with beginners.  So we will create the move player like this.  So it takes delta x and delta y.  So we'll try to move the player relatively to where it is.  So if we knew where the player is, we don't, okay?  We could do something like player go to, remember this one, wherever you are, plus the delta  x, x times the grid size, right?  And wherever you are, the y axis plus the delta y times the grid size.  And if we knew the player position, if only we knew the player position.  Okay, that's it.  Okay?  Only we knew it.  And you go like this, and now if I hit my keyboard, oh, there it goes, okay?  It's drawing a line because guess what?  That's what Terval Zoo here, okay?  But we know how to fix that, okay?  Because we have the player fly or up method.  If we do this, then it moves nicely, okay?  It can go crazy, but we don't really care, okay?  It moves.  What's missing?  Well, the other character, the beast, right?  So we might feel tempted to like copy and paste these.  We won't do that.  You don't copy and paste code.  Don't.  We'll do a few of that, but we'll get to that.  But so we'll instead create an actor function that will create an actor or a character for  us, okay?  And the way to do that could be, one possible way would be, let's say, this image, okay?  An image.  Then we'll return this thing that we're creating here.  I don't like that.  It's called player because it doesn't make much sense any longer.  So let's call it T. And see that player is actor.  PlayerGalp, okay?  And this should work, okay?  And now we can just copy it over and say beast.  And we have player and the beast.  And there's the beast.  Okay?  It's sitting there still.  So let's make it move around.  So we could create maybe a moveBeast function, okay?  Let's see.  Find a moveBeast function here that will move it kind of randomly.  And for minus grid, span to blah, blah, blah, you know, this is the boring part.  Sorry for that.  But, you know, there's no fun without pain, I guess.  So we can say beast.  Now go to guru.  Okay?  And we can say it's not that easy today.  X times grid size.  And Y times grid size, I guess.  And now this function just moves the beast at some point in random, the grid.  We'll call it right before starting here.  And the other thing we're going to do is we'll need to import the random module right because  we're using the random function.  So there it goes.  Okay?  So it's there.  Let's start it again.  It's where it goes, okay?  So, okay, it goes there.  Now the idea is that we'll move the player.  And as we move, we need to see, did we capture the beast?  Yes or no?  And when we'll capture the beast, the beast will do like a, let's call it a small dance  as if it's stunned by being caught.  Then it turns away again.  So the way to do that is, let's say, every time we move the player, we will attempt a  capture, say, a capture, capture.  Okay?  And what's that?  So attempting a capture might be something like, well, if the player position is, you  know, equal to the beast position, right?  Then beast do a dance.  Doing a dance might be drawing a circle, which is yet another method of turtles that, you  know, appropriately named, draws a circle.  But if it's raised, it won't draw it.  Just do a little dance.  We'll reduce the step to make it faster.  And then you say, move, beat, so go away from wherever you are.  And let's see how it goes.  If I save this and run it.  So dance goes away.  Cool.  But it's really not challenging because as we move, the beast is just sitting there.  So it needs to be a bit more challenging.  So maybe whenever we move, there's some odds that the beast will try to cheat trick us.  So we might say something like, well, else, if we didn't capture, okay, so maybe if random  dot random, this is, will give us a random number between zero and one.  Okay, we call it lower than move beast odds.  We'll just move the beast.  So the bigger this number is, the bigger the odds are the beast moving around the tricking  out.  So we'll set this, call it the game difficulty constant here.  And we'll say, well, let's make it one in five, zero point two.  So let's see how it goes.  So dangerous.  This is random in a live coding scenario.  So it might never happen.  But it did.  You see, I'll just move around and see if the beast, okay, the beast.  It's very dumb sometimes if you really want to capture it, you'll see there's some artificial  intelligence here.  The random number knows.  I know that.  I've been playing this and the kids know too.  So if you take a look at this, okay, so the game is already cool.  Okay, you can play it around.  But there's a very serious problem in this game and that's it never ends.  And with kids, you need games to end because at some point we'll be telling kids come over  it's dinner time and they say, hey, dad, let me just finish the game.  It doesn't finish.  So it must finish.  Okay.  So we'll introduce the concept of say, energy or karma, which will again be visually represented  by yet another turtle, of course.  And we'll have like a turtle center and top of the grid.  The turtle will move slowly towards the left as the player moves.  Okay.  And if it ever reaches the leftmost edge, the player loses.  And on the other hand, whenever the player captures the beast, the karma will move like  a chunk towards the right.  And if it ever reaches the rightmost edge, the player wins.  Okay.  So let's build this step by step.  So we need a new turtle, a new karma turtle.  So let's go there.  Well, just, yeah, this is the time for copying and pasting, right?  We can copy and paste this karma.  But oh, come on.  I don't have a karma dot gift image on this.  So what am I to do?  Well, it turns out that if you look at our actor function.  It creates a turtle, registers a shape, loads it from desk, and then tells the turtle to  use it.  Okay.  It turns out there are a few built-in shapes in the turtle module that don't require registering.  Okay.  And one of those is called Circle, which we'll use here, which will fail to register because  register tried to open a file on desk.  So we'll say, well, if the image ends with, you know, dot gift, then register it.  Otherwise, assume it's a built-in shape and just go ahead and do it.  And there's our karma turtle.  It's not at the right place.  And it's kind of dark.  Nobody wants a dark karma, right?  So let's make it shiny a bit.  So one thing I'd like to do is something like maybe color equals gold.  I don't know.  And for that, we'll add a, like, a keyword argument here defaulting to black so that I  don't need to go back and change all the other code and say, this is the turtle I created  locally and say color, color.  Okay.  And this should work.  And then we'll tell the karma turtle to go to zero.  That's horizontal center.  And then when max, which is the top of the grid and just a little bit further up and that  thing, whenever you need it a little bit further up in a crazy number, you go with 42 and nothing  can go wrong.  So there you go.  There's our karma turtle.  Okay.  So we need to move depending on the result of the game.  And if you remember, even though it's a circle, it's facing towards the right hand side.  Okay.  So we'll use that forward positive number forward negative as a trick to move it left or right.  So that moving the karma turtle is just a matter of saying karma go forward this number.  Okay.  So to do that, we'll create a, an update karma function somewhere here.  Let's say, well, well, well, well, well, well, maybe here.  Maybe here.  Yeah.  Maybe here.  So let's call update karma.  It takes a delta karma, which will be positive or negative, depending.  And we'll say go forward delta karma.  That's it.  Okay.  And now in our attempt to capture, we say, well, this is a captured case.  So we'll say update karma with a karma value of a capture and we'll set this variable to  a positive value.  And then this is the case where we moved but didn't capture.  So we'll go there and say karma move and we'll set these two here.  Maybe let's say this one is a hundred and maybe this one, this one, I know it needs to  be negative.  So let's go minus 20 say and we'll get, go get back to our code and let's run it and  see if it moves.  Okay.  Slowly towards the left, right?  Slowly towards the left.  And now it should jump towards the right hand side.  Okay.  This is working.  Good.  So all we need to do now is to find our boundary conditions, detect them until game over, you  won, game over, you lost.  And we do that by checking the karma position, the horizontal position after every move.  So we'll grab the karma x and karma y.  We already know that these karma y equals karma position, right?  But we really don't care about the y.  So let's go like this.  Okay.  That's a throwaway variable.  And we say, well, if karma was my keyboard, karma x is greater than or equal to grid max,  then let's say end game, we'll give it a, this is winning.  So let's say, yay, victory.  Congratulations.  You won.  And otherwise we can say, well, if it's negative, if it's below negative grid max, so this  is certainly a defeat.  So let's go, I defeat, sorry for that.  Try again.  Where end game or the end game function is a function that takes a message and uses  the right method of turtles that just displays text strings besides the turtles.  We don't have much control, but it's good enough.  We have control on over the alignment, the horizontal alignment, which we'll try to  center on the turtle.  We will override default font because the default font is actually too tiny for this  kind of game.  And I thought, why not go with Hovetica for two reasons?  Okay.  So it's a hallmark of Swiss design and it seemed appropriate.  And you really can't go wrong.  Nobody was ever fired by using Hovetica.  So don't be creative with your fonts.  Use Hovetica and you'll be fine.  Okay.  So if you, I don't want to go off rail, but I love typography.  So don't use other things.  Don't be creative.  So this should work.  Okay.  So just write some message and we're going to test this by cheating a bit.  So because we don't have that much time, so we're just going to say, well, let's win  this really quickly.  We'll always win really quickly.  And here we go.  So we move.  We're about to win anyway.  I don't really care.  I'll go up and down.  I went victory.  Great.  So it seems to work.  The text is in black.  I'd rather have it in white.  But if you recall the turtles, the font color is black.  So I'll change it to white.  And there's another thing.  That's a much more serious thing because if I head up, you see, the game is still on.  Okay.  And why is that?  Look at our curve.  So we said in game, what does in game does?  We thought in game meant everything's done.  But all we did in game, sorry for that, is we wrote the text message.  But originally when we set up the keyboard things, we told listen and whenever this  keys press do this and this, call the move, it's still doing it.  It's still doing that.  We haven't told it, stop doing that.  So ideally we would do turtle and lesson.  So forget about the keyboard.  Just be still.  We cut to that.  The turtle module doesn't have that.  So we'll hack it away in a very ugly approach.  It works so I don't care.  Up, down, left, left and right.  And I'll tell you a bit about why I think this is really bad later.  But if we have the time, okay.  On key, we'll go the on key again.  But now we'll say, well, for these keys, use the none function.  So it means forget about anything you knew about this key.  And we want the player turtle to be white.  You remember that.  And this should be pretty fast and cool like this.  So let's see.  Okay.  Down.  I want to win really quickly.  Yes.  We're in cheat mode because we are the cosers.  We can do anything.  Right?  It's very powerful.  Victory.  Good.  And now I'll bang on my keyboard to see if it works.  Okay.  I'm banging.  This is one of those Apple computers, but one of those oldests that used to come out  with real keyboard.  Okay.  And this is kind of flaky.  That's not the case.  So Tim, please fix the keyboard.  Okay.  Thank you.  This is working.  And what I'm going to do is cheat the other way around to check that my losing condition  is being properly checked.  And we're nearly done.  Okay.  So let's go minus, what's minus 82?  Why not?  Let's make it go faster.  Go go faster.  Faster for kids is great.  So don't capture the beast.  We want to lose this really quickly.  And defeat and bang on our keyboard.  So the game is nearly done.  Okay.  This was my original plan for the game, but the kids came and said, yes, but we need a  score.  Okay.  We need the motive to come back to the game and do better.  That makes a lot of sense.  Okay.  So they came up with this very simple and effective idea.  And what they came up with is, well, if we counted the number of steps that the player  does along the game, and you just need to print them at the end.  So if you win, you want to win with as few steps as possible.  Okay.  That's reasonable.  It's a better score.  And if you lose, I don't know, ask the kids.  Okay.  So there's a score.  Let's implement that really quickly.  And the way to do that is one way to do that, because there's no single way to do things.  We'll do it like this.  Well, player steps equals zero.  Start counting steps at zero.  Okay.  When things start.  And then every time the player moves, this is the function.  You will just increment it.  Plus one.  Okay.  And then if you remember, there's a method here in game that writes a message with the  you won, you lost.  We'll just copy and paste that and use a comma turtle to write a different message.  We'll use a funky f string.  F strings are so cool.  Don't you like them?  Yeah.  Player steps.  We'll make it slightly smaller.  And this should be it.  Let's see.  Three statements of Python.  We've implemented a score.  Isn't Python cool?  The three steps.  So let's cheat the other way around.  Let's instead remove the cheat and go for a real quick run of the game to get a feel.  And I won't go until the end.  This is one of those games that may never end.  So dangerous for the dinner thing with the kids.  But it seems to work.  It's fun engaging enough.  And I won't play it anymore.  I won't bore you.  Because if you play it, you'll have fun.  But just watching it is boring.  So let's step back for a minute.  What we have here.  So we have 100 lines of Python code.  Created pretty much, you know, make it up as you go along.  Okay.  Yeah, I don't care.  Just create a function.  Oh, that's not cool.  And what I'd like to do now is do a quick review of this code.  I'll highlight a few things.  I don't have time to go over all of it, of course.  Highlighting maybe good ideas, bad ideas.  Would you do this at work?  Yes or no?  Okay.  So let's get here.  So these variables are constants.  These are a very good practice.  The character movements and the grid drawing, they're all based on these constants.  So if we need to change something, let's say, if I go five here, five, can I go five, please?  Five?  Yeah, there you go.  Five.  Then it all still works.  Okay.  So this is clearly something that you would do at work.  It's a good practice.  Okay.  To have common constants or variables.  And same can be said for these.  It's the game difficulty.  Okay.  This is a good thing.  Then I'm going to take a look at these.  This is kind of a mess.  So this loop draws the grid, but it's difficult to read.  I wouldn't want something like this in my serious, sustainable code.  Maybe it's the variable names I selected.  I don't know.  But I don't like this very much.  It's hard to read.  It's lots of John Tree.  I hate it.  But it works.  There you go.  And then there's this line.  This line deserves a mention because it could have been written as fmh of minus 40 blah,  blah, blah equals to dot k of, blah, blah, blah.  These are semantically equivalent.  And I claim that the first one that I used is much better for two reasons.  First reason, readability.  Read that says if image ends with that, so it's clear for you to your brain.  It's dark to your brain.  This string ends with that string.  Whereas in the other one, whether you're a beginner or an experienced professional,  something like this is going on more consciously or subconsciously.  What's that?  Oh, that's the colon thing.  The colon thing is a slice.  It's from there to there.  What's the there on the right?  There's nothing there on the right-hand side.  So that's still the end of the string.  What about minus four?  So that's four from the end.  Does it include the fourth from the end or is it from the fifth or from the month?  It's a mess.  This happens in a split second for advanced developers.  And it takes a long time for beginners.  It's not readable.  And then there's this.  If you change at some point, you want to use JPEG images.  Then this line of code still works.  And the other one doesn't any longer because image of minus four till the end is four characters  long and dot JPEG is five characters long.  So you need to change in two places.  You need to change your code in both sides of the comparison.  So it's clearly a worse solution.  So go with ends with and starts with.  It's simpler.  I don't know.  Just use ends with and starts with.  Keep it simple.  Now this deserves some mention too.  What's going on here?  So we're calling the active function that creates a turtle ready to use.  So we're ready to play with it.  And then we're slapping a dot steps attribute there to counter steps.  It's our solution to tracking the player steps.  And it's effective, simple.  So let's review this.  So in general, everything in Python is an object.  And Python objects have a type and have attributes.  Now again, in general, any piece of code can create, destroy, rebind or reassign values  to any attribute in any object.  There's no protections.  There are some exceptions to this, but this is the fundamental model of the way Python  works.  So in general, this is not really a good idea because we're poking around it, objects that  might behave differently.  So this isn't something you would do at work, but it's possible.  And again, with great power comes great responsibility.  So use these kinds of things wisely.  But I wouldn't want this in any serious, sustainable code.  We would need to find different solutions to that.  Now I'll highlight just one more thing, two more things for the sake of time.  So we can step back furthermore.  And again, this statement could have been written as comma position of zero or bracket  zero.  And again, I say that the one I use is better for two reasons.  First again, readability.  Maybe for some people that funky thing with the comma, comma and the score blah blah  blah is somewhat strange.  But you'll quickly get used to that.  What I claim is that this line has the comma position in parenthesis and brackets and blah.  So it's slightly harder to read.  I'll grant you that might be a personal opinion.  But check this.  When you look at this code, you wonder, well, could I have used 42 instead of zero?  Maybe that comma position is a dictionary-like thing.  Maybe could I have used key there?  You don't know.  The only way to answer these questions is to look at the function documentation.  Or God forbid, look at the source code.  You worried about your update comma function.  You don't want to know about the others.  Whereas here, you know that that comma position thing, I'll short it to right-hand side is  iterable.  That's a funky thing.  And we won't go into that.  Think less like maybe it's a bunch of things.  It's a bunch of things.  If you want to know more, we'll talk in the quarters.  And it's iterable and it has two elements.  It's guaranteed to have that because there are two things here, comma separated.  Otherwise this code wouldn't work.  And by the way, if we're using that underscore, that's a variable like any other.  But it's a way of saying we don't really care about what's here.  So we also know that we care about the first.  So it's clearly, first, no, first, Tiago.  So it's clear other than readability, the line that I used gives you three facts immediately.  And the other line leaves you with a few questions.  So again, I say this is better.  There's a very interesting article by Trey Hunter.  I think.  Trey Hunter, he's a trainer too, I think.  Go read it.  And come to me, I can point you to that.  It's very interesting on this idea.  Let's wrap up our code review to move on to some different thoughts.  Now just go here.  This is the most horrible two lines I've written here in my understanding.  And why?  Because there's repetition.  The up, down, left and right string constants are repeated here.  And you see in this code that sets up the keyword initially.  And that's really a no, no, no, no, no.  So possible solutions would be to define constants with these values, wrap them in a list in  a dictionary, create an enum, something like that.  This is really, you wouldn't do this at work.  I would be angry or disappointed if someone said Tiago just created the best looking code.  Now I think we can improve that.  So let's forget about the code for a minute.  So this is the code.  Now here are a few thoughts.  Well the Python scenario is amazing.  It has a bunch of functionality.  And quite often it does surprise you.  It has its smelling corners, it does.  But if you dig deeper into a given module, you're bound to be surprised and you're bound  to find useful functions, tidbits, examples, okay?  That was the case with the turtle module.  I didn't know you could do this with the turtle module.  Keyboard input, multiple turtles, GIF images.  I can do a bunch, okay?  I can nearly serve a breakfast with the turtle module.  I don't know.  So there have been recent discussions on the standard library and they're very relevant,  I think.  But the fact of the matter is that the standard library is bound to change in the long term,  okay?  But in the near term, it will stay pretty much as it is.  And knowing it and using it is a very valuable skill.  Don't rush into it.  It takes time, but it pays back.  So I learn a lot.  Every time I go into the docs, go docs, Python, or the library reference.  That's it.  You go there, there's a bunch of cool things.  And then, of course, there's this, you know, I'll read my own slides.  Don't do this.  Direct in your face.  Python is effective and fun, and it is.  And maybe the reason why so many of us are here today.  Because one day we said, oh, this is Python.  Maybe if I just, hmm, funny.  Oh, cool.  Oh, I like this.  I want more.  And then 15 years later, here we are.  I don't know if you're relate to this.  This is what happened to me.  And having fun is obviously the best way to learn new things, and the kids did learn a  few things.  While the workshop was back in March, and certainly three months after the fact, or  four, whatever, they probably don't know much Python now.  But there's one thing they learned.  They will never forget.  And that is that they're gaming consoles, they're tablets, they're electronic devices.  They're all programmable.  They have seen the lights in a way.  They know there's a way to make the machine do something they want.  So maybe in 5, 10, 20, 40 years time, they're faced with some kind of software that just  doesn't feel right for some reason.  They know, no, I'll fix it.  And I'll go pick up back on that path.  And this is a very powerful thing to know that you can't really unlearn.  Okay?  And this was my main objective with the kids.  These machines, you are the master.  So you can make them do whatever you want.  Okay?  So if you want, go do that.  Now what if you're a professional seasoned developer, four years experience, you've done  it all.  You've never done it all.  Okay?  That's my opinion.  There's always something else to do.  Now, would you do this at work?  That's something like this.  Exactly this.  This silly game.  Would you do it?  Well, could you learn something from it?  Would say extending it to network-based gameplay.  Would you learn socket programming, IP addressing, IPv6, by the way, at DNS, I don't know, Bluetooth?  Would you learn that there's no way, no technology, no protocol, no whatever that guarantees that  when you send a message out through the network, there's no guarantee that you'll ever get  back a response.  So you need to use timers and timeouts and things.  Would you learn something from it?  Would that compel you to write a low-level event loop managing network traffic, keyboard  input, internal animation, and sound, by the way, why not?  And would that help you understand different models of concurrent programming with coroutines  and learning about the async and await keywords that are so mysterious to many?  Would that be helpful in something else that you do?  Would you learn about race conditions?  This game here has race conditions.  You might say, oh, I don't care about race conditions because I do data analysis.  And you don't need network code to have race conditions.  You don't need to have a web-driven code to have race conditions.  All you need to have is concurrency.  And concurrency is everywhere, more and more.  But tuning your mind into grasping what the race condition is and kind of smelling it  from the distance and knowing how to avoid and improve your code to avoid those because  they are very difficult to diagnose and fix.  But if your mind is kind of tuned into that, you've learned a very valuable skill, OK,  and so on and so forth, OK?  So I clearly say, yes, you should do this at work.  Go ahead and tell your boss, yeah, what are you doing?  I'm doing a silly game.  Are you crazy?  No, I'm not crazy.  I'm learning the best way possible because I'm having a bunch of fun.  But don't do, don't just do this at work, OK?  You balance it out, OK?  Now the part in fun is this.  It came to me as I evolved and parted away from the workshop as that learning and having  fun, hopefully learning while having fun, OK, is probably the best way to grow into better  versions of ourselves.  And I think in the end that's what it's all about.  I mean, I've had a bunch of fun since January, thinking, discussing, working long nights.  It was a lot of work, but a bunch of fun for, why did I do it?  For love, I don't know, for passion, for friendship, for kids.  But I learned a lot too, OK?  I'm still figuring out all that I learned from this experience, and I humbly hope that  all of this, what shall I call it?  This is not to talk, this is some silliness, some fun, that it might motivate you and inspire  you to think, maybe to put away some time, some energy or karma, if you will, and dedicate  it to learning and having fun with whichever silly, however silly, whatever, who are they  to say, oh, this is silly, you do whatever you like.  So to dedicate some time and energy to having fun and learning, and if you need to choose,  if you can't have both, OK, go for fun, OK?  If you can't have learning and fun, go for fun.  So this is it.  Thank you very much.  I hope you go out and have a lot of fun.  Thank you.  Thank you, Tiago, for this very entertaining talk.  Thank you.  We have a few minutes for questions.  Yes, I'm happy to address anything about the code, the kids, the method, and catch me  out there.  I'll be happy to discuss all of this at any time, OK?  Go ahead.  Thank you.  I really love the message that we have about providing kids the ability to think, yeah,  I can tweak this in the future.  I really don't know how it works, but I know that it can be fixed.  So my question is, how would you address it to adults if you had to do something like  this, like 20-something or 30-something?  That's a great question.  I haven't thought about that much, but this is a thought that crossed my mind a lot of  times.  Working with kids is serious business, and you heard me say that, because kids are very  wide open.  So you can pretty much kind of drive them the way you want, OK?  So that's a huge responsibility, OK?  So they're more malleable, so to speak, OK?  That's what I meant, that kids, working with kids is very serious, OK?  Because you can't mold them some way.  I don't know how I would do it adults, because as we grow up, we tend to become stiffer.  But in the end, it's about showing and not telling.  If you show people something that resonates with them, they will resonate with that and  go from there.  So from an educational standpoint, I would say that it's about finding what resonates  with your target audience.  And certainly what resonates with kids is a game like this.  And if I went to this with an adult, this wouldn't probably be interesting.  It wouldn't resonate.  I'd say that that's the key idea.  But I'm happy to discuss this more.  OK.  It works.  Thank you very much.  It was great.  It was very important, I think.  But I have a neat pick.  Go ahead.  This pattern where you use a single underscore for a variable that you don't use, have you  ever had to use getText?  GetText, yes.  Sure.  Yeah, getText is a way, is a module in the standard library that helps you internationalize  or translate your code to different languages, OK?  And it does a hack.  It uses this underscore variable that becomes a function.  So you convert all your strings that you say to the user, say, hello, user.  And then you wrap it up with underscore and parenthesis.  And then in another file, we say, well, hello, user is, hola, oclizador, hola, oswario,  blah, blah, blah, blah, and all the languages.  And then it does that for you.  So thank you, Radhmer.  That's a great point.  That's like a counterpoint, OK, this code that we've seen is much more advanced than  what we did with the kids.  We didn't do any kind of lambdas.  We didn't do loops.  So they went like draw line, draw line, draw line, draw line, draw line, draw line, draw  line.  So we went for the basics.  Thank you.  That's a great nitpick.  And I'd like to know how to solve that.  I don't know.  I would like to.  That's why I'm asking.  I have no idea.  I never thought about it.  I never thought about it.  I go with a double underscore variable, I don't know.  Good idea.  Thanks, Radhmer.  So it's gone red.  Yeah, I'm sorry.  OK, so let's talk out there, OK?  Yeah, you can.  Very short question.  Go.  How long did it take for the kids to reach this level of?  OK, we did eight hours, OK, two hours, two hours, two hours, two hours across two days.  So two hours in the morning, and we went slowly, OK, from I'm happy to share the materials.  I have all the materials, all the step by step lessons, OK?  But when they got here, they were comfortable enough to vary some, change some conditions,  play around, OK?  But this was like a bit too sophisticated for what they were comfortable with.  So it was kind of a balance between having fun, being proud, look what I did, but I don't  completely understand it, OK?  OK.  Thank you.  Thank you again.  Thank you.
Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_0_959.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_960_2615.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_2616_2675.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_2676_3551.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_3552_3647.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_3648_3731.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_3732_3791.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_3792_3935.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_3936_4031.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_4032_4163.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_4164_4487.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_4488_4559.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_4560_4967.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_4968_5063.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5064_5111.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5112_5195.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5196_5363.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5364_5411.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5412_5483.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5484_5567.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5568_5615.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5616_5663.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5664_5831.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5832_5939.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_5940_9311.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_9312_9959.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_9960_10091.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_10092_13583.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_13584_18491.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_18492_36515.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_36516_37475.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_37476_42719.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_42720_45287.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_45288_49847.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_49848_50483.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_50484_54599.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_54600_55547.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_55548_56171.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_56172_56243.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_56244_56387.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_56388_56687.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_56688_56843.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_56844_57563.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_57564_58451.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_58452_59507.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_59508_60575.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_60576_60887.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_60888_65123.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_65124_66983.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_66984_67319.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_67320_67379.png Tiago_Montes_-_Don_t_do_this_at_work_gKu3AyRZ1yA_67380_68267.png