 I'm gonna talk about twisty little passages and rediscovering the joy in programming. How many of you have had fun programming in the last week? Awesome, I love it. Like, even maybe yesterday. How many of you had fun yesterday writing code? A few more hands? Not everyone, okay. That's okay, you can't enjoy it all the time, right? Well, for me, actually, you know what? Before I go any further on this, I need to do a shameless plug. As Mike mentioned, I am writing a book. It's called Maze's for Programmers. And I have a free copy to give away, electronic only, so it's not gonna like grace your bookshelves or anything. But if you're interested in this book, and you all should be, because it's awesome. So to introduce this slide, it was probably about the last year or two, I really started feeling burned out on writing code. How many of you have ever felt burned out on writing code? Yeah, it's not a good place to be. It's really kind of scary, especially if coding is your livelihood, right? It's not a fun place to be. So I really struggled for a long time. So what I discovered is in order to conquer that burnout, one of the things, there's a lot of different things I had to do and try, one of the things was to rediscover what made programming fun and enjoyable for me. And that's kind of been a journey for the last year, as I thought about this. And so what makes coding fun for you? I don't know what's gonna be fun for you, but for me, these are some of the things that I particularly enjoy that make coding fun. For one, it has to be intellectually challenging but not intimidating. Like ray tracing, I went a period about 10 years ago where I wrote a ray tracer. How many of you have ever used a ray tracer? Does anyone know what I'm talking about? Okay, good. How many of you have ever written a ray tracer? A few hands. So you'll know what I mean when I say that it is definitely intellectually challenging, but it's also a little bit intimidating, especially when you start moving beyond spheres and you start wanting to do things like parametric surfaces and things like that. It definitely starts to move into the intimidating realm. So that meant part of it for me, but it's something new. Like after a while, after you've ray traced a dozen spheres, the joy starts to wear a little thin. Also, I mean, fractals. How many of you have ever played with fractals? Like iterated function systems or different things? Those are always new. Like you can do so many, it's new every time you do it, it's great. Rapid feedback cycle is something else that's important. Like you can't spend days getting to where you have something to show. You need something quick. That's another big win. Easy to experiment with. I need something where I can go in and change one line and get something totally different. Fractals were great for that. Like the iterated function systems, you change one little thing and you get a totally different fractal. Like that is a lot of fun to experiment with. For a bonus, if it's visually interesting, that helps a lot too. Like if it's something exciting to look at, that plays a lot towards what makes things fun for me. And if it's shareable, that counts a lot. Can I share it with my coworkers? Can I share it with my wife and kids? Like ray tracing. For me, it's great. You get that sphere up there and it's reflecting the checkered plane and it's great and you're excited about it and you show your wife, show your kids and you're like, dad, it's a ball. And you're like, I know it's a ball, but the light went over here and they just don't get it. So I appreciate it, but it's not as shareable as fractals or like, ooh, pretty colors. So there's a lot of different projects that I've played with, like ray tracers and fractals and generators and Celtic knots and making my own programming language and playing with grammars and genealogical databases. I've done a lot of things for fun, but some of them are more fun by the previous slide than others. And today I'm gonna focus on mazes because it nails every single one of those points for me. Challenging but not intimidating. These algorithms are so easy, you can fit them on, like some of them, two lines of code, some of them, a page of code. They're not hard to understand. Every time you run the maze, you get a different maze and there's so many different ways to experiment with it. You get the rapid feedback, you change something, you generate the maze, you get a totally different thing. They're visually interesting, they're really shareable. Like my kids love these random mazes. I made a maze on a Mobius strip the other day and my seven-year-old, seriously, he spent hours just tracing the maze around that strip over and over. So there's a lot going for this. I'm gonna show you what I mean by this. This is where it's gonna get tricky because I need to do some code while I'm holding this mic. Thank you. I won't need, we'll say I just need to type something here. All right. You sure? All right. There's a reason he's called Mike. Wow. So what we have here is a binary tree algorithm. The way it works is I create a 10 by 10 grid of cells. Then for each grid, each cell in that grid, I'm going to say, okay, take the neighbor to the north and the neighbor to the east, choose one of them at random and then link those two together. And what you get when you run that is a maze. Like it's a real bona fide maze and it's so straightforward to do. Now this next bit, this is what I'm talking about where I talk about how easy it is to experiment. One of the easiest things to do with these is to change the dimensions of the maze. So here we went from a 10 by 10 to 40 rows by 80 columns. We run that and once again, we get this maze. It's so straightforward and easy to play with, easy to experiment with. Another really easy thing to experiment with this, instead of choosing north and east, we're gonna choose south and east. And you look at that, you say it's about the same thing, but one of the big differences is instead of there being a big long row along the top, now it's on the bottom. You see over here, there's one on the east, that column there. If we switch and say, let's do south and west, now when we run it, oops. Now when we run it, that thing switched over here. So just by changing one thing, we get different textures of the maze, different features, different aspects of it. Another thing to play with, maybe. There we go. What if we prefer one of the directions over the other? So this time we're gonna say, let's take the south and the west still, but we're gonna put the south in this array five times and then choose one at random. So obviously that south is weighted a lot more. So what happens when we do that? When you choose south more often, well, you get a very different texture. Suddenly everything wants to go north to south all over the place. You could do the same with the east and west and get the same thing just horizontally biased. But now here's a cool thing. What if going from the left, where let's say on the left side of this, we're gonna prefer east to west and on the right side of it, we're gonna prefer north to south and in between we're going to gradually shift from one bias to the other. So for the south, we're gonna choose south based whatever column we're looking at and west is just gonna be however many columns in the grid minus that column. We set that up and we choose one of them and we get this. So from one side, it gradually shifts to the other. This is a game of what if. Like you sit there and you look at this algorithm and this implementation, you start saying, what if I change this? What if I change that line? What if we make this do this? I wonder how I could make the maze behave differently. Really easy to play with. There's other ways to vary this. Instead of changing the algorithm, you can change the way things are displayed. The ones I've shown you before, the walls of the maze are just single lines, but you can change that. What if we render the walls as blocks? You get a very different look to the way it's displayed. You can change the colors, you can change all kinds of things like that. Another way to change it is you make insets. So instead of having the walls but right up against each other, you say we're gonna separate the walls, we're gonna inset them a little bit so that there's some separation there and you get something like that, which is similar to the blocks, but now the walls can be a different thickness from the size of the cell itself. Another way, instead of drawing the individual walls and the passages, you can pre-render a bunch of tiles and then draw each cell based on the corresponding tile and you get something like this. This is really simple. You could get really elaborate with, you could theoretically say for a given intersection, five different ways, five different types of tiles and randomly choose them. Lots of different ways to experiment with this. Let's move on. Here's another algorithm. This one's called the growing tree. This one works by basically setting up a list of seeds and starting with one. We're just gonna choose with a random cell in the grid. We're gonna put it in there and while there are any seeds in this array, we choose one at random. We look for all of the unvisited neighbors of that and if there are any, we link the seed that we chose to that, add that new one to that basket of seeds and go around again. If there aren't any neighbors, then we remove that seed from the list and go around again and that way eventually we'll run out of seeds. When we run that, you get another maze. Surprise, right? I'm sure you're totally boggled by that. But now there's lots of ways to vary this one. For instance, in this case, we chose one at random from that but what if instead of choosing at random, what if we take the last seed that we put in and always choose the last one? Well, we get another maze, obviously. Now, if you paid attention, you might have noticed there's some differences there but it's hard to see. So what we can do, actually before we get there, you can also randomly switch between them. So half the time we're gonna choose the last seed and half the time we're gonna choose a random seed and surprise, we get another maze. But as I was saying, there's a difference there but it's hard to see. So what happens if we render these side by side? Here's another what if. What if we take it and we render two mazes with these different methods? One we're gonna choose randomly from that list. One we're gonna choose last. Let me just stop selecting text. Okay. Well, there we have the one on the left here is chosen, the seed is chosen randomly and the one on the right, the seed is, I always choose the last. How many of you see a difference between those two? It's a little subtle, isn't it? Some of you maybe you're like, no duh, it's really obvious but others, I mean, if you don't know what you're looking for, it's a little hard to see. So what we can do, we can make that easier. We can use Dijkstra's algorithm to actually color the cells based on distance. So what we do is we choose a single cell inside this maze, measure the distance of every other cell from that one and then color the cells based on that distance. How many of you have ever used Dijkstra's algorithm, what I'm talking about? It's a really cool algorithm. It's like the Swiss army knife of pathfinding algorithms. I don't have time to go over into it now but it's worth learning. So if we run this now, now the one on the left is the seed is chosen at random. The one on the right is we always choose the last seed. Now it's a little more obvious that there's a difference there but we can make it more obvious. Let's go by a 40 by 40 grid instead of 20 by 20 and now the texture kind of pops out a little better. There's a lot more movement over here on the right versus here is over here. It's basically just a radial gradient moving outward. That's kind of what you get when you choose at random versus always choosing the last cell. We can make this even more obvious. Let's do an 80 by 80 grid and we're not gonna draw the walls. We're just gonna draw the colors and you start to get some really cool artwork. Like this is stuff I wouldn't mind hanging on my wall but that's cause I'm weird. You can animate this. This is another cool thing. You've seen the results now of these algorithms. What happens when you actually animate it and you show step by step how these things come together? Well, let's look at a binary tree. Let's animate how it comes together. This is the binary tree being constructed cell by cell in sequence but the cool thing about binary trees you can actually do is visit the cells in random order and get the exact same result. So it doesn't matter what order you do it. It still gives you a maze. Bam. Let's try a growing tree. What happens when we choose at random with the growing tree? Every time we add we're gonna highlight that seed and every time we remove it we're gonna basically return it to its previous color. So the cells that are currently in that big seed bucket we're gonna see those in yellow. This is what happens. There's a reason it's called the growing tree. You can see how it kind of organically moves outward from that starting cell and at the end of it and you can also see this is why you get that radial texture like the flooding outward. So what happens is when we switch that to last we get a totally different behavior. It becomes very snake like. We're always choosing the last one and it chooses a random neighbor and it just goes around like a snake. In fact, this algorithm is also called depth first search or recursive backtracker. We'll try it. Does that work? All right. So now, yes, thank you, Mike. So now what if we take this growing tree and we actually show dikstra's animated on it to show how dikstra's algorithm works. It works by flooding outward from a cell that you choose but we can really see how that works by animating it, showing each individual step as a frame. Let's make that a 40 by 40 grid and we'll take the walls out so you can really see how things flood outward and there it goes. See it's following the different pathways all the way to the end and the darker it is the further it is from that starting point. It's really kind of hypnotic. I love this aspect of it. All right, now there's nothing sacred about these rectangular square cells. We can do all kinds of different shapes of cells. We can do hexagons. We can do octagons and squares tied together. We can do triangles. We can do polar grids. A polar grid is just a circle with like nested circles with spokes radiating outward. This is a polar grid but it's a grid. We've got cells that are adjacent to each other so theoretically we could run any of these algorithms on it and get amazed and sure enough if we run growing tree on it we get a circle maze just like that. And you bet there's a ton of stuff we can do to experiment with this. We can change the size. Instead of a radius of 12, we're gonna make 24. So there's 24 nested circles inside of it. That's the kind of thing that would give you a headache. But now we can compare those two. We can do diastres on these and compare them side by side again. And again you can see on the left and see what was it. I switched it around this time. Okay on the left we have the choosing the last cell and on the right we have choosing the random cell. But we can increase the resolution again. Go 24 and you start seeing more of these patterns. We can go even larger. Let's go 48 and we're gonna take the walls off again. This time you can really see the difference. The how the choosing last gives you more of the winding and the paths that, man, I'm losing my English today. Whereas on the right, what I'm trying to say, on the right you get more of the smooth gradient. That's what I'm trying to say. Now the cool thing is once you have a polar grid you're almost to a sphere because if you take a flat polar grid and you poke it up in the middle you get a hemisphere. And if you take that hemisphere and you join it with another one you got a sphere. So we're basically to the point where we can do a sphere. What does that mean to render a sphere maze? This is kind of one way to think about it. This is a cylindrical projection of a sphere grid. You can see the distortion at the tops and the bottoms. It's just like looking at a map of the earth. Iceland and Greenland look enormous compared to their actual sizes. And that's because of the distortion near the poles. Well, this isn't quite as exciting. Like you say you wanna see a sphere maze and people are like sure and you show them this and you're like that's not what I was expecting. So let's map that onto a sphere. Well there we have it. We've taken that grid and mapped it onto a sphere. And like I said, once you have a grid you can make a maze. So let's apply a growing tree on that. And there you have a maze on the surface of the sphere. And we can start doing a lot of the same experiments that we did with the flat rectangular or the polar mazes. We can color them using Dijkstra's algorithm. And we get that winding pattern in color on the surface of our sphere. And of course, the very next thing we wanna try is what happens when we make it bigger? 50, right? Pretty, okay. And red of course because Ruby Conference. Well, that's one thing but what we would love, we're seeing this in 3D now. Let's actually see if we can rotate it. Ooh. If you're fast you could probably solve the maze while it's rotating. I can't. Okay, so now, obviously that was a ray traced sphere. And I didn't write the ray tracers using Pavaret. But ray tracing kind of falls down when you want things in real time. What I would like now is to say, okay, we've got this sphere. What if we could render the actual geometry of the walls and actually watch that thing turn around in real time? Well, OpenGL kind of excels at that. So what we've got here is now a grid where we're gonna build the geometry of the walls and then fly. It's actually kind of a dumb flying right now. We're just gonna sit and stare at it from some distance above the sphere. But those are the real walls. Well, okay. What if we increase the resolution on the end? Let's do 40 instead of 20. Ooh, wow, yeah, we're exciting. Okay, but we can do better. We can play with how high the walls are because this is real geometry now. We're not just painting a texture on a 3D sphere. We've actually got triangles and quads that we're playing with here. So we can change the wall height. You can go way nuts with that. In fact, let's do it. What if we change that to like 0.5? This number is relative to the radius of a unit sphere. So a unit sphere would have a height of one. So we're making these walls half the radius of that sphere. Whoa. And you can take it way down. But this is what I'm talking about. It's that immediate feedback. You can change the wall thickness. Make them thicker, oh, that kind of was wimpy. We can do better. There you can hardly even see the passages now. But you can combine them. It's a wall height. And it's just, I love the immediacy of this. This is what makes it fun for me. I'm like, what happens if, and you change something, you can immediately see what happens there. So now that we've got this, we can actually start doing some real animation in real time with this. We can rotate it like that, you know? Yeah, we're getting somewhere. We can rotate it around y and x simultaneously. This is cool because you can actually see what it looks like at the poles. And I'll admit, my OpenGL, I had to learn OpenGL just for this presentation. So I'm obviously doing something wrong with the lighting. If you're an OpenGL guru, I'd love to sit down with you and have you teach me how to do this right. But now the black background is kind of dull. It'd be nice to have a little skybox in there. Give us a background to see it on. Serene, just make you wanna like relax. I need some like elevator music. But now here's where we can really have fun. We've got this. We can compute paths through this grid, just like any other grid, thanks to Dijkstra's. How about we actually move our camera right down inside that maze and actually walk it. Now this is where I need to warn those of you prone to motion sickness. You might want to avert your eyes because it gets a little, yeah, you'll see. We're gonna walk from the north pole to the south pole. And I actually won't do the whole walk, but we'll get started on it. There we are, walking the surface of a sphere, a maze on the surface of a sphere. Yeah, I can pause it here, let you catch your breath, find your doggie bags. Yeah, so again, we can play with this. We could change the resolution on this and do it again. The walls are a little closer together now. We could fix that by changing the wall height to make them feel like they're not so close together. Anyway, you just immediately play with that, but we can do really cool things now. Because one of the first things when I got this working, one of the first things I wanted to see was, well, I want to see, I want to fly in from outside and land inside the sphere and start walking it. So, of course, I had to implement swoop, which we'll do that. It's gonna swoop us in, land us on the north pole of our sphere and start walking that. We plop, and there we go. Let's do it again, because it's fun. And one more time. Every good special effect deserves to be shown at least three times. But now the problem is we're always landing on the north pole. It'd be nice if we could just choose a path that starts at some random cell and goes to some other cell. So what we've got, let's just find the longest path through our grid and walk that one. It's gonna land us at a random location, and so here we go. I am. See, I mean, that never gets old until you get motion sick. Let's try it from a different location. There we go. So that's what I'm talking about. I went from a simple binary tree algorithm step by step, what if, what if, what if, following the chain, and it got me all the way to an OpenGL animation where I'm walking around on the surface of a sphere. That's not where I expected to be when I started out, but that's where I wound up. And I'll admit, implementing the whole OpenGL thing was not the rapid feedback I usually desire, but by the time I got to that point, I'm gonna walk around a little bit, by the time I got to that point, I was willing to invest a little more time because I'd seen how things had progressed so far. The rapid feedback to that point had encouraged me to try bigger and bigger steps. Now, will this type of thing cure everyone's burnout? Not by itself, no, but it's one thing to try. Find something that's interesting and exciting and fun and play with it. How many of you came to programming because it was fun initially? I love all the hands there. That's how I found it. My mom had an ancient Tandy computer with GWBasic on it, and I was like, okay, let's see what we can do. And so I made a Choose Your Own Adventure game. I made, I implemented the card game War. I did all kinds of simple little things, but it was fun. And playing with these mazes helped me rediscover a lot of that fun. But what else would you try? I'm sure as you've sat there and watched me play with some of this, you might have been thinking, oh, I wonder what if? What if you were to change this? What if you were to alter that? It really is as easy as changing one line to get something totally new. It's exciting, it's playful, it's interesting, it's challenging, but it's not intimidating. If I can do it, seriously, it's not that hard. Rediscover or discover the joy of programming because that's what's gonna take you to tomorrow, like the next day. It's gonna carry you through the doldrums of your daily programming jobs. Because let's be honest, you may love your job, but it's not always this thrilling adventure, right? But find the joy, look for it. So don't forget to tweet, Mountain West Ruby Conference mazes, MWRC mazes, and I will announce the winner just before.