Summarized using AI

Names from a hat

Murray Steele • November 13, 2024 • Chicago, IL • Talk

In his talk "Names from a Hat" at RubyConf 2024, Murray Steele explores creative ways to randomize speaker selections and raffle winners using Ruby programming techniques. As co-organizer of the London Ruby User Group, he highlights the practical needs for randomization in a fun and engaging manner. Here are the key points discussed throughout the talk:

  • Introduction to Randomization in Events: Murray explains the necessity of randomizing names for raffles and agenda ordering at meetups, presenting traditional methods such as drawing from a hat. He quickly notes this isn't satisfying for a Ruby conference, thereby introducing programming solutions.

  • Initial Ruby Approaches: He demonstrates how built-in Ruby methods, such as Array#sample and Array#shuffle, can be used for easy randomization, noting their elegance and efficiency.

  • Over Engineering for Fun: Transitioning into the fun side, Murray discusses his penchant for over-engineering, where he indulges in unnecessary complexity just for enjoyment. He contrasts the approach taken in work environments with explorative programming for educational purposes.

  • Using Fibers: Murray elaborates on Fiber, a Ruby feature for managing concurrency, which he applied for a random speaker order. He explains fiber yield and resume processes, showcasing how he controlled randomization safely while manipulating speaker names without traditional interrupt concerns.

  • Interactive User Interfaces with Shoes: He shares his adventures with _why's Shoes framework, wherein he built a Ruby application that visually displays the randomization process. Murray emphasizes the joy of using one language (Ruby) for both backend and GUI development, describing his progress from text output to animated visual selection of names.

  • Game Development Experience: In a culminating project, Murray details developing a terminal-based dungeon crawler named "L Rogue" that blends human choice and computer randomization, illustrating how string manipulation can create engaging game mechanics.

  • Lessons Learned: He concludes with a discussion on the value of stepping outside standard practices to embrace new technologies and innovation, advocating for playful experimentation as a means of growth and deeper understanding of programming concepts.

Murray’s engaging presentation encapsulates the essence of Ruby programming and its ability to handle randomization in creative and entertaining ways, stimulating both learning and enjoyment with practical applications.

Main Takeaways:

  • Embracing over-engineering can lead to exciting learning experiences.
  • Utilize Ruby’s rich features for unique problem-solving.
  • Explore the intersection of programming and play for deeper understanding.
  • Engaging in creative coding can foster community and collaboration.

Overall, Murray Steele's approach inspires attendees to innovate, experiment, and enjoy the process of coding beyond conventions.

Names from a hat
Murray Steele • November 13, 2024 • Chicago, IL • Talk

As an organiser of a local ruby meetup group I occasionally need to pluck names from a hat to announce winners of raffles or randomise the order of speakers for a particularly packed agenda. We can do that with actual bits of paper from a hat, but being a rubyist I'm much more interested in writing little ruby scripts to do it for me.

We'll start with the obvious technique of using `Array#sample` but as it's not very interesting or satisfying to write we'll go a bit further. We'll look at interactivity using `Fiber`, and several attempts at animation using _why's Shoes framework. Finally, we'll explore my magnum opus of a terminal-based dungeon crawler (like nethack and rogue) written in ruby that introduces a human element of randomisation alongside the computer element.

RubyConf 2024

00:00:15.360 okay um hi I'm Murray thanks for coming to my talk as my intro mentioned one of the
00:00:22.880 things I do is co-organize the London Ruby User Group L rug for short and if you really stress the L you can
00:00:29.119 pronounce it as L rug hence the logo we meet monthly on the second Monday of the
00:00:34.160 month every month if you're coming to London you should arrange your holiday to coincide with one of our meetings so
00:00:40.360 that you can come chat to us about ruby and learn that the ocean divides that divides us can be easily bridged by a
00:00:46.920 love of open classes blocks and duct typing a thing I have to do as part of
00:00:52.199 organizing that Meetup is randomize the names of people very often I've needed
00:00:57.320 to choose the winners of a raffle or a giveaway once we ran a battleships tournament as a practical exercise and I
00:01:04.040 had to pair up the participants to create the playoffs for a particularly packed meeting rather than curating a
00:01:11.240 perfect agenda as Sarah and Jenny have done for the weird Ruby track at this conference I'll just randomize the order
00:01:17.759 of the talks it happens more than you might think so I like to have a system now the obvious way to do this is to
00:01:24.439 write everyone's name on a bit of paper and put the Bits of Paper in a hat and draw the names one by by one to select a
00:01:30.840 winner and generate the order and that's fine but it's not very Ruby and this is
00:01:37.360 Ruby com not paper and hats comp so how can we do that with Ruby well I'm delighted to tell you that
00:01:44.719 Ruby is the perfect tool for the job array Shuffle will return your array in a New randomized Order Perfect for
00:01:52.040 tournaments and running orders an array sample will pick a random element from the array which is perfect for Prize
00:01:58.240 winners so everything we need is right here they talk about python as being batteries included but I think Ruby is
00:02:05.039 doing really great here in practice if I was Sarah or Jenny I might have done something like this we put the list of
00:02:12.319 names into our hat on array and then we pick the names from it calling Shuffle
00:02:17.480 or sample depending on our need and then we announce that result by calling put if we run the snippet we'll get a
00:02:24.360 running order for the weird Ruby track in an instant and we can go and catch up on some Prestige TV with the time weave
00:02:29.959 saved and the code is so elegant it's it's beautiful so that was names from a hat
00:02:37.080 we got right into it and uh we found out that Ruby does exactly what we want but
00:02:42.200 I have 28 more minutes to fill luckily an alternative title for this talk is
00:02:48.040 over engineering for fun not profit now I'm an engineering manager at a company
00:02:53.640 called Cleo we're a fintech building an AI assistant that turns the complexity of personal finances into a conversation
00:03:00.840 the same kind you'd have with a friend and it supports people throughout their financial lives at work what's important
00:03:08.239 is shipping the smallest possible thing that lets us deliver value to our users or the business ideally both and we do
00:03:16.640 this by building on top of existing features gems third party service providers so on this lets us move
00:03:23.360 quickly to build the simplest thing that will meet the requirements and we're not afraid to shrink those requirements to
00:03:28.760 help us get something out sooner so we can learn why build an all singing all dancing product feature when a landing
00:03:35.720 page test might tell us just as much and sooner what I'm saying is over engineering is bad at work but this is
00:03:44.840 weird Ruby not best practices thought leader Ruby so let's quiet that em at a
00:03:50.480 startup voice down a bit I'm here to sing the Praises of over engineering for fun we're going to do that by exploring
00:03:57.319 some of the ways I've personally over engineered calling array sample or array Shuffle while wearing my L Rog organizer
00:04:04.319 hat along the way because we should embrace all parts of ourselves that em at a startup voice might pop up with a
00:04:11.200 few occasional thoughts on recreational over engineering being good
00:04:16.840 actually so the first thing we're going to look at is that I wanted to learn about a new feature of Ruby as part of
00:04:23.520 the lightning talks evening at El rug I decided to give a talk about the at the time new feature in Ruby called fiber
00:04:30.240 these days you might want to talk about rators I didn't know anything about them
00:04:35.320 so I had to go and research how they worked and what they were so that I could give the talk about them I learn a
00:04:42.479 lot by researching and reading about a topic but I learn even more if I hold the technology in my hands and make
00:04:48.320 something with it so I had a problem I know how to solve randomizing a list of
00:04:53.800 speakers on a technology I wanted to explore Ruby fibers this is the best combination for
00:05:00.400 learning I reckon and it was the final thought of my Talk reinterpreting data last year so I won't belabor the point
00:05:06.479 I'll just suggest that you go find that talk and bask in actually don't watch my talk from last year instead go to this
00:05:13.520 URL and watch pursuing pointlessness by Chris howlet from this year's bright and Ruby conference it's a five minute
00:05:19.960 lightning talk that covers the exact same themes of exploring fun things as my talk but it takes like 10% of the
00:05:27.400 runtime it's so good I'm not even mad about it so back to fibers I'm not here to
00:05:35.120 explain fibers at least not in detail but the extremely highlevel version is
00:05:40.160 that they are a concurrency model that allows for explicit control flow between different running parts of your code you
00:05:46.840 can imagine that this line represents all the code in your Ruby program and
00:05:51.880 this Ruby represents CPU time in the program in a single threaded program
00:05:56.960 your CPU is doing one thing at a time and it just runs through the program program until it gets to the end with multiple threads we get the
00:06:03.960 illusion of multiple things happening at once as represented by two lines of
00:06:09.120 code but it achieves this by giving each thread a tiny bit of CPU time before moving on random interrupts tell each
00:06:16.599 thread stop it's someone else's turn now and you're not in control of when that happens so you have to code really
00:06:24.120 defensively around it to avoid Deadlocks and access to Shared objects
00:06:30.039 in fibers there's still only one thing running at any one time but you are in
00:06:35.280 control as you explicitly tell the CPU when to run code in one fiber and when it should stop and that's what these
00:06:41.440 fiber yield and fiber resume calls are doing we're passing control back and forth between two fibers
00:06:48.360 programmatically anyway this is how I over engineered the problem of randomizing speakers using
00:06:54.440 fibers we can see the fiber yield and fiber resume calls here I've got multiples of both so I'm passing control
00:07:00.560 around a fair bit here we give the random Choice fiber a list of names for it to work with and entirely avoid
00:07:07.639 issues of shared memory access because we're in control of when CPU time has passed around safe between the fiber
00:07:13.879 yield calls in the loop the fiber can do whatever it wants to that array safe in the knowledge that those manipulations
00:07:19.400 won't get interrupted by someone else what it does is randomly pick a name and delete it from the the list before
00:07:25.759 passing that name out in the fiber yield call the uh keywords that you can use to
00:07:31.280 Google later for this are co- routines or cooperative multitasking or like go
00:07:36.960 to the session being run by Jamis and adviti later about flattening recursion with
00:07:42.879 fibers now obviously you don't need fibers to do this I have over engineered
00:07:48.319 this for sure I mean I'm even using the wrong array method I should be using Shuffle but I'm using sample to get
00:07:55.000 individual elements not going to lie though I did enjoy the fra of danger that I got from writing an infinite Loop
00:08:01.560 that's not something you get to do often in production code is it that's one I think of the fun things
00:08:08.120 about fibers you can kind of almost throw away your ideas about termination
00:08:13.520 and Loops anyway I I wouldn't say I've used fibers in production I know that deep in
00:08:19.759 the stack of my rails apps there are fibers being used somewhere but I didn't write that code having explored fibers a
00:08:26.879 bit though I do have some residual knowledge lurking in my M ready to LEAP out and be useful at some point for for
00:08:34.240 example if I have to spelunk deep into the libraries we use on encounter fiber code or if I have to debate the merits
00:08:40.519 of the Puma appserver which is thread-based versus the fulcon appserver which is fiber based so my plea to you
00:08:47.560 go explore some technology you're not using and have no real need to use yet
00:08:53.080 use it to solve some problem it's wildly inappropriate for you'll get exposure to it and be that more familiar when you
00:08:59.880 encounter a problem it is appropriate for you don't want shipping to production a new Mission critical
00:09:05.279 feature of your app to be the first time you've ever used that new
00:09:10.519 technology the next way I over engineered randomizing names was to build a UI on top of the process I
00:09:17.120 wanted a more visual element to the problem because we would randomize the speakers on the night so I wanted there
00:09:22.839 to be something more interesting to view than like strings in a terminal and I wanted to do it end to
00:09:29.160 end in Ruby at the time the tool for doing that was to use shoes which was
00:09:34.640 one of why lucky stiffs projects it's a version of Ruby that can be used to build desktop applications the UI
00:09:41.519 elements are very similar to what you're used to with HTML and positioning is also very similar to what you do with
00:09:48.200 CSS so it's very familiar if you're doing web stuff for the day job so this is what I came up with and
00:09:54.920 before I kick play on the video there is some flickering so if that might hurt you like avert your eyes and I'll tell
00:10:01.360 you when you can look back so this app shows a list of potential speaker names when you press the button it Cycles
00:10:07.600 through the names to highlight the one that might be chosen when you press the button again it picks one and shows it
00:10:13.360 big then you repeat this process until all the names have been chosen and your final button press shows a list of all
00:10:18.880 the names in the order you chose them quite the Step Up from strings and the terminal
00:10:24.360 success now obviously you could do this kind of UI in the web the difference is is that we have to think in two
00:10:30.480 languages to do it Ruby for the back end on the server and JavaScript on the client with shoes it's all ruby and
00:10:38.200 that's what's fun about this version for me the whole app code isn't huge but more than I can squeeze on a single
00:10:43.639 slide so I'll show you some of the interesting Parts um the flickering is done now if
00:10:49.040 you were bothered by it this is the bare bones of the app like fibers I'm not going to go into
00:10:54.920 lots of detail on how shoes works but you can probably see that it's a DSL for writing guies lots of do end blocks and
00:11:02.680 new UI phrases you start everything with a shoes. apppp method and this unlocks the
00:11:08.680 shoes DSL for use in the block and it also renders the shoes UI window onto your
00:11:14.480 desktop there's no initialize method so if you need some internal State you just set that up in the block here I'm using
00:11:21.480 ask open file to get the user to give us a file name that we read the list of names from and then I'm setting some
00:11:27.200 other variables for use later next we have the background method to set the background color of the app all
00:11:34.680 the fun named colors from HTML are there so you don't need to break out RGB triples if you don't want
00:11:41.240 to now we get into something more shoy stack defines a UI element container
00:11:46.959 that Stacks the elements you put into it vertically one on top of the other which is in contrast to the other major
00:11:53.120 building block of shoes which is the flow element which flows the elements horizontally now yes these are are very
00:12:00.079 similar to The Block Level and inline level elements you get in HTML they are
00:12:05.200 simple but give you lots of scope for flexibility in layout the methods in the stack there
00:12:11.839 are some of my other implementation details that actually render the button and list of names that you saw in the
00:12:18.160 video finally we have the animate method and block I'm asking it to run this
00:12:23.240 block of code 24 times a second just like a film seemed like a good choice if
00:12:28.560 our states supports it will pick a winner to display these are the basic building
00:12:34.279 blocks there's lots more to explore but this is enough for now I think it's the Ruby you know and love driving a simple
00:12:41.760 but powerful UI kit and it's well worth exploring if you want to find out more later just search for shoes RB you can't
00:12:49.199 really search for shoes or Ruby shoes CU you are just going to get actual shoe on
00:12:54.639 your foot content I do want to show you how to add
00:13:00.440 interactivity though so here's the code for the button we provide the button text and some styling attributes and a
00:13:06.120 block for the behavior that will be run when you press it and this is where I think I've gone off the rails or should
00:13:12.279 I say shoes anyway triggering the button should just toggle some state that other
00:13:17.560 code reacts to highlighted here where I'm setting the randomizing flag but I've also mixed in updating some
00:13:24.680 internal data some UI code
00:13:30.800 and what's most frustrating is that this the luckiest variable where has that come from well it's part of the pick a
00:13:38.480 winner method called in the animate Loop in this method we have our old friend array sample to pick a name from the
00:13:44.600 list of volunteers and that stores it in the luckiest variable but it also updates the names
00:13:51.759 to style them differently if they're the current chosen one or not all the things I want to happen are
00:13:57.759 happening but it's not really done in the way you'd want it to for sustainable future development that's fine this is a
00:14:04.079 one-off program for a Meetup and I doubt anyone had seen this code until I showed it to you just now there's a lot of code to wrap around
00:14:11.399 that little array sample call so definitely over engineered but why I think this was useful is that it exposed
00:14:17.320 me to guey programming and helped me to understand writing code and a different Paradigm mixing State and behavior is
00:14:23.839 the problem with the code I showed you and while that's not unique to UI code I do think it's a lot easier iier a
00:14:29.440 mistake to make with UI code getting into it in Ruby made it really easy to make those mistakes and I think in part
00:14:36.240 because most of the Ruby code I write is fairly sequential we might Dress It Up in patterns like active record or active
00:14:43.199 job and even use callbacks and pubsub but the fundamental pattern is a web
00:14:48.519 request comes in with some perams we react in the moment to run some action and return a result maybe it kicks off
00:14:55.639 some background processing out of band but there's still a fairly straight line line crucially you don't need to worry
00:15:01.320 about maintaining an updating State on Long lived objects because the web request or background job finishes
00:15:06.880 quickly with guey programming things are explicitly more event driven real time and long lived so to avoid getting into
00:15:13.959 a big ball of mud you need to think about separating behavior and state better front-end patterns like MVC the
00:15:21.399 original UI one not the web one popularized by rails or reactive programming as as popularized by react
00:15:30.040 do this really well and if you want to understand what your front end colleagues are up to it's really useful
00:15:35.560 to have tried your hand at it in Ruby get into a mess like I have and you will
00:15:40.880 really understand why you might want to introduce patterns and structure the next way I over-engineered
00:15:47.360 the problem was another shoes application but this time I wanted some more Pizzaz on the screen this time I
00:15:54.160 needed to pick the winners for a bunch of prize draws we were doing for some books so I wanted to drum up some anticipation of the draw which we'd be
00:16:01.160 doing live on the night of the meeting in the one we just saw the flickering names brought an element of tension oo
00:16:07.199 it's highlighted my name will it be me but this time I really wanted to be true
00:16:12.480 to the original idea drawing names from a hat there's some mild flickering in
00:16:17.600 this video too so here's a simple scene in which I've drawn a classic magic top hat and at the top we have rendered the
00:16:24.399 name of the book we're giving away as a prize when you press the button all the names from our list get animated and
00:16:31.120 they go into the Hat once they're all in the Hat it starts fizzing with magic
00:16:36.160 energy and when you you get a new button with magic words on it pressing that releases some magic energy by picking a
00:16:42.480 name and replacing the book name with the Winner's name you can continue pressing the button until all the names
00:16:47.560 have been chosen I wrote it this way because we were doing the draw in person on the night and if the person wasn't in
00:16:53.839 the room we just did it again I had carried a load of books to the meeting and I was not going to carry a load of
00:16:59.319 books home from the meeting it's still a shoes app but I've leaned less into text and buttons and
00:17:05.880 more into art and animation so there's some neat things to show a case there about how we do that the video was done
00:17:13.480 for now if you were avoiding your eyes so first here's the code for drawing the
00:17:19.640 Hat mostly these methods are picking a color then drawing a simple shape and then we lather rinse repeat in order to
00:17:26.400 build up the overall hat image the last call is to a handy star method
00:17:32.400 so you don't have need to draw a bunch of triangles to approximate a star yourself there was no hat method for the
00:17:38.640 whole thing though missing a trick I reckon and there's not much to say here other than to point out that like all of
00:17:44.559 your designer colleagues I had to painstakingly handcraft all of these left top width and height attributes to
00:17:51.360 position and size the hat in a way that looked good and fitted on the screen if you've done any um programming
00:17:58.520 with processing or nodebox or HTML canvas or even SVG this might be familiar to you so you can learn about
00:18:04.400 this style of programming by searching for those things it really is quite fun and I'd encourage you to explore how to
00:18:10.240 create interactive art using these techniques the next bit I want to highlight is the animation we saw some
00:18:17.159 animation in the last example so you remember we have an animate method that will call the given block each frame
00:18:22.880 I've learned from the last example so the animate block here calls a method instead of having a big inline mess of
00:18:29.360 course the method is a bit of a mess but I have hidden some of it so we can just look at how to make the magic star
00:18:35.480 Jitter about if we don't have a winner we need to do some magic to pick one if
00:18:41.120 we do have a winner we need to stop doing magic and show it doing magic is a case of randomly moving the star within
00:18:47.799 a painstakingly crafted bounding box stopping doing magic is a case of moving
00:18:52.880 it back to the painstakingly crafted midpoint what's interesting here is that
00:18:58.039 for this animation I only needed to think about what needs to happen during a single frame shoes
00:19:05.120 animate method just repeatedly calls that and the animation effect is created the other bit of Animation is
00:19:12.400 dropping the names into the Hat it follows similar principles the animate block calls main loop again I've removed
00:19:19.919 the code for other states relevant to us is that if we don't have a current name we pick one
00:19:26.080 and draw it on the scene if we do do have a current name we then move it towards the hat and if the result of
00:19:33.799 that is that the name is in the Hat we clear out the current name next frame we'll ask the same
00:19:40.280 questions and either draw a new name to move into the hat or move the existing one closer to the
00:19:46.320 hat so how do we move things into the Hat well we work out how much we need to
00:19:52.200 move the Hat each frame in x y and size then we ask if we did move it
00:19:59.159 would it be in the hole at the top of the hat if so we put the name into the hat
00:20:06.559 and then return true to say this name is in the Hat if not we resize and move the
00:20:12.960 element and return false to say this name is not in the Hat the calculations are for movement
00:20:19.679 are interesting because we can change that one number to scale to speed up or slow down the animation right now it's
00:20:26.520 set to 24 which means roughly it should take a second to move each name into the Hat based on the frame rate if I change
00:20:34.120 that to 48 it'll take 2 seconds if I change it to 12 it'll take half a second
00:20:40.840 these calculations are sort of annoying and fiddly ask me later how many times I mixed up X Y top and left but you do
00:20:49.200 just need to run it and Eyeball it to see if it looks nice or not which can be frustrating but it is a real Joy when
00:20:56.280 you get something that looks good an anim at smoothly again I only had to focus on
00:21:02.799 what I needed to do for a single frame and yes it's much more complex than moving this making the star Jitter about
00:21:10.080 but not by much and it's endlessly tweakable and just fun to like
00:21:17.480 watch the thing to take away from this other than honestly just how much fun it is working on animation is about how to
00:21:24.039 break a problem down with animation because the block is called 24 times a second
00:21:29.240 I don't need to think too much about how to animate things completely just about what it should do on each frame break
00:21:36.799 the problem down into tiny slices and you can achieve pretty neat results this is fairly standard programming advice at
00:21:43.440 the macro scale agile anyone anyone so it's nice to have it apply at the micro
00:21:49.480 scale too a good practical reminder of simple things adding up to complex
00:21:55.880 results so I like the spec iacle of the hat but I felt that up to now everything
00:22:01.880 was just a fancy version of the initial array implementation put a list of names
00:22:07.000 in and call a ray sample or a ray Shuffle to get a list of names out I really wanted to make something truly
00:22:14.360 interactive and where it felt like I was more a part of the randomization process
00:22:19.480 at best in the previous versions I was controlling a timing element of when to call array sample to get a random name
00:22:26.360 out the hat with its main Loop and button pressing State changes reminded me of what little I knew about game
00:22:33.480 programming you create a world you take some input you update the state of the world you render it and then you
00:22:40.320 Loop so I created a game called L Rogue and the speakers of lightning Let's uh
00:22:46.400 watch it in action while I talk I didn't think I could whip up a
00:22:51.440 decent game in shoes or anything else remotely graphically complex but I did think I could do something in the
00:22:57.080 terminal Ruby is great at string manipulation and with a big enough terminal window you get plenty of screen
00:23:03.240 real estate to render a world in there's a terminal game called Rogue where you play as a little at symbol traversing a
00:23:10.000 dungeon as delimited by hyphens pipes underscores Etc to make the walls you
00:23:16.320 find other characters as monsters to fight or treasure to collect and Randomness is comes in that the whole
00:23:22.640 dungeon is randomly generated each time you play as is the positioning of the monsters and the treasure
00:23:29.000 finally the player themselves wanders the dungeon on their own desire choosing which monsters to fight and in which
00:23:35.640 order this sounded like the perfect combination of computer and human randomization I didn't know how to do it
00:23:42.919 but it's just string manipulation and emboldened by My Success with conquering animation with the hat version I figured
00:23:49.320 how hard can it be well let's see we'll use that perfect measure lines of code
00:23:55.919 V1 on array eight lines of code and that includes the six lines of codes needed for the names of the
00:24:02.240 speakers fibers 27 lines of code which also includes the lines for the names of the
00:24:07.760 speakers version three a simple grid of text with some mild animation 119
00:24:14.039 lines version four an animated hat with multiple states of Animation 244
00:24:20.679 lines version five a fully-fledged terminal game 1,259 lines of code so obviously I can't
00:24:27.919 show you all of this but there are two things I do want to talk about the first thing I want to show is how we render
00:24:34.080 the graphics for the game as I said it's a terminal game so we're talking puts and strings but don't worry I have over
00:24:41.000 engineered that first up to draw the world I have a tile set
00:24:46.240 object which has a render bang method now this doesn't cause mutation or potentially raise exceptions it's just
00:24:53.440 exciting so I gave it a bang method name sorry rubocop
00:24:59.600 the tile set contains an X by y grid of tile objects where each tile represents a single spot in the world and another
00:25:05.880 part of the system tells each tile what they contain floor wall Corridor
00:25:11.600 occasionally a wizard or L Rogue itself as it wanders the dungeon rendering is
00:25:16.679 just joining the array and asking each tile in the row to tws itself and then
00:25:21.799 adding a new line between each row simple 2 sing the tile is also simple if
00:25:28.320 if El Rogue is here render the character for that if a wizard is here render the character for that otherwise render the
00:25:35.480 content which is you know the character for floor wall empty space whatever the tile was told
00:25:42.559 previously El Rogue moves around so we're constantly having to tell the tiles where it is we do that in a method
00:25:48.640 on TI set that tells all the tiles that El Rogue is not here and then tells the one that represents El rogue's current
00:25:54.720 XY coordinates the El Rogue is here it's not very efficient but Ruby is fast
00:26:01.440 enough to process all of this in between key presses for a terminal game so far so simple what I realized is that with
00:26:09.080 this in place it was fairly trivial to add the circular reveal the map as you walk effect with a different tile set
00:26:15.520 and implementation in my foggy tile set render bang doesn't change we still want
00:26:22.679 to just ask each tile to 2s itself in my foggy tile 2s relies on the
00:26:28.559 knowing if it's visible or not if it is call Super for the original implementation but if it isn't visible
00:26:34.600 we render the empty tile how do we know if it's visible well we change the draw L Rogue method on the
00:26:41.360 tile set to act as before tell the tile that represents L rogue's XY coordinates the L Rogue is here but also tell the
00:26:49.200 tiles surrounding L Rogue that they are visible finding the surrounding tiles is
00:26:54.679 iterating over every tile and using some Pythagoras you will have learned this in high school probably the first time I've
00:27:01.200 ever used it in production on their coordinates to find those that are within the radius of the circle created
00:27:07.000 by the strength of el rogue's eyes not very efficient to do every tile every time but Ruby's fast
00:27:14.799 enough the next thing I want to talk about is how we generate the dungeons the code is fairly complex and spread
00:27:21.039 across multiple files but luckily I could easily tweak the engine to render the world and each step in the dungeon
00:27:27.000 generation process to illustrate it because of how excellent my design was for rendering via tile sets so we take
00:27:34.200 our world here delimited in green the full screen size of our terminal window minus a single Row for
00:27:40.120 instructions then we randomly split it random choice of horizontal versus vertical and random choice of position
00:27:47.200 favoring the middle over the edges this gives us two child worlds inside the original World we then keep doing this
00:27:53.960 with each nested World we've created until we have at least our desired number of leaf worlds there's also a
00:27:59.880 random chance that if we ask a world to split it won't then we ask each world to place a room somewhere in the space
00:28:06.360 randomizing position and width and height and then we link the rooms by drawing corridors to connect them
00:28:11.640 walking up from the leaf nodes to their siblings and then their parents and that is one way to randomly
00:28:17.960 generate a dungeon did I know how to do this absolutely not did I invent this
00:28:25.039 again absolutely not the there are great resources out there for learning these techniques
00:28:30.880 there's a whole Wiki dedicated to Rogue building I just picked the first technique I could get my head around the one with the pictures to make it
00:28:37.919 simple and when I first built it and got it working I spent ages just running it over and over and watching it to see
00:28:43.720 what it would do it was so much fun I could spend forever doing that there are
00:28:49.320 so many more techniques for creating Dungeons and even different types of dungeons I've chosen a rooms and corridors dungeon using a random
00:28:55.720 subdivision model you could use a uniform Grid or a random Walkin Place algorithm you could create more cave
00:29:02.600 likee dungeons that you hollow out of the terminal window using cellular automa or maze generation algorithms or
00:29:09.200 you can combine different techniques what I learned is that just like there are just like there are 1 million blog
00:29:15.760 posts on how to structure your rails business logic there are one million articles out there giving you advice on
00:29:21.559 game programming techniques our community isn't unique in how much it shares as another little aside turns out
00:29:29.320 although there's plenty of non- Ruby terminal rogu likee content out there I'm not the only person to fill around with Ruby for this sort of thing a
00:29:36.320 couple of months ago Dimitri seev published this lovely blog post talking you through the steps to build your own Ruby based Dungeon Crawler it has
00:29:43.320 monsters and his way more game likee you should definitely read this if you're thinking of doing it yourself so the other versions I shared
00:29:51.000 were pretty much single file script just enough Ruby to get the idea out of my head and into an RB file this thing this
00:29:57.760 game I just couldn't do it in one script I had to think about the problem and properly model all the pieces the domain
00:30:03.919 objects like worlds and rooms and creatures and the infrastructure objects like tiles and tile sets and game
00:30:09.519 engines I had to think about patterns for how things would interact I got to use the visitor design
00:30:15.360 pattern it's a small enough problem to keep in my head but it's not a but it's a big enough problem not to just YOLO it
00:30:23.200 it's a good exercise to work on something of reasonable scope and to get to apply this kind of thinking so I could understand how to apply these
00:30:29.240 ideas in a more professional setting shipping a new feature to production shouldn't be when you decide to
00:30:34.399 experiment with a radical new way of modeling your business logic so let's recap all the ways that
00:30:40.679 over engineering can be good actually or let's not just go and have fun pick up
00:30:47.000 something and really push it learn something new or don't make toys thanks
00:30:52.480 for listening bye
Explore all talks recorded at RubyConf 2024
+64