Wednesday, November 9, 2011

Finished random name generator in Ruby

I've finished up a working version of my random name generator. Here's a gist of the code:

Random Name Generator

I'm calling it aan (short for adjective, adjective, noun) because the original was just three phrases slapped together. Now I've added functionality that will generate a prefix or a suffix (seemingly) at random. I might spend a bit more time working with this. It's been a fun little project and I'd like to make a Rails project for it so I can put it up on Heroku and show it to non-coders.

Some other things I may look into:

A way to output the full name on a single line. I tried print instead of puts, but it simply outputs the pieces of the array, not the entire string built from the various arrays.

A way to capitalize every word except for words like "of", "the" and so on.

Using this with other data. What about a Full House episode plot generator? What if instead of specifically saying "Uncle Jesse takes Stephanie to the movies, which makes DJ incredibly jealous" I had "DAD takes DAUGHTER1 to the EVENT, which makes DAUGHTER2 incredibly jealous" and I passed in variables, to further randomize output? Maybe this will be my next project. It kind of combines stuff I was doing with the MadLib generator and this random name generator.

One of the things I like most about Ruby is how much you can do with it once you have an idea of what you're doing. I've definitely got a better idea of how reading files and using data found in those files works now. It's also pretty awesome to sit down for a couple of hours and bang out a working program.

I've also found that since I've become less focused on making a career change and more interested in learning how Ruby works, I'm having a lot more fun coding. That's a plus, right?

Monday, November 7, 2011

Random Name Generator with Ruby

I like making stupid things with Ruby. Last week I was working on a MadLibs generator, not because I have an uncontrollable urge to make MadLibs, but because it was a project I could understand and I wanted to build.

My friend Eli showed me how to refactor the code so it was less specific and therefore much more versatile. Whereas the code I wrote was very specific to one MadLib, the one Eli helped me write is far more general, and can make MadLibs out of any text file that's been prepared (substituting all instances of a noun with NOUN, or NOUN1, NOUN2, etc, for repeating nouns)

It's obvious to me how valuable separating logic and data is, but it's going to take some work for me to really wrap my head around this. I've been coding with my logic and data entwined in a big hot nasty mess for a while.

Here's a gist of the finalized, objectified MadLibs generator:

MadLibs Generator

So my next goal is to take what I learned with refactoring the MadLibs generator and make another stupid project. I ran across this site a few nights ago:

Video Game Name Generator

So I've decided to build one using Ruby. I'm calling it aan so far (adjective, adjective, noun) and I've got a version working that will generate random combinations from pre-defined arrays, but I'm working on expanding it so it will read text files and generate lists from those files.

Once I get THAT up and running, I want to work on making it a bit more complex. Adding support for generating names that may or may not include a prefix or a suffix in addition to the standard adjective-adjective-noun, for example.

I think I'm having a lot more fun with coding when I'm working on stupid things like this than when I was working on larger-scale projects (long tutorials, Manticore, Chorenivore) but it's hard for me to objectively say which is more valuable.

Sunday, October 30, 2011

Refactoring Ruby Code

Since I've been working on this MadLibs generator, I've been through a couple of refactorings. Friday night, I got the code hammered out but I ended up with this:

MadLib Generator, first version

It works, sure, but it's ugly. A ton of gets.chomp()'s, and there's obviously a better way to do it. Still, my plan was to hack it out as best I knew how, identify problems with it, and then rework the code.

So here's my second attempt:

MadLib generator, first refactoring

Not bad! I've gotten rid of all the gets.chomp() commands in favor of loops that will collect the correct number of nouns, verbs, adjectives and so forth. I also got rid of the prompt method - it's a hold over from the dungeon games I've been working on and I felt it was unnecessary. I was pretty proud of this, but my friend Eli thought it could be refined further, suggesting I try to Objectify the code. I'm a bit puzzled by this. What does this mean?

At any rate, I took another look and here's what I've got now:

MadLib generator, second refactoring

In this iteration, I cleaned up what's being collected a bit, and took out the definitions for popping words out of the arrays. I realized I could just call the .pop method directly by defining the array as an instance variable. This way, I was able to shorten the code by several lines by adding a character to each variable. Pretty good trade off, if you ask me!

I also redefined each array after calling a .reverse method on it. Since I'm using .pop to pull words out of the array to place in the Mad Lib, this will keep the words in the same order the user entered them.

Things are going pretty well. I feel proud that I'm anticipating problems and finding solutions for them now. Also, I should've been using Gists for a long time now.

Friday, October 28, 2011

Require - No Such File to Load Ruby

The exercise I'm working through in Learn Ruby the Hard Way has me spending a week creating my own game. I've been building various text-based adventure games, but was stuck on what to do next. This morning on the way to work I got the idea of building a MadLib generator.

The way I picture it working is like this: the generator will ask the user to select a Mad Lib from a list, then ask for the requisite input (nouns, adjectives, verbs) depending on the Mad Lib selected and finally spit out the finished product. Simple, right?

So my thinking is this project would be split into two parts: the main program that asks for which Mad Lib the user wants to do, and the Mad Lib that is loaded upon selection. To get this up and running, I decided just to make one Mad Lib work at first, then add support for multiple Mad Libs and the ability to choose between them.

This is just a simple matter of requiring the Mad Lib file from the Main file, but I ran into a small problem.

Using the require 'mermaid' command threw this error:

<internal:lib/rubygems/custom_require&rt;:29:in `require': no such file to load -- mermaid (LoadError)

I wasn't sure why this wasn't working, since I've used require to load separate .rb files before. After a bit of digging around, all I had to to do fix this problem is change require 'mermaid' to require_relative 'mermaid'. This makes sense - both files are in the same directory, so this command is simply saying to require this file located in the same directory as the main file.

On a side note, I'm glad to have fixed the problem, but I'm getting to the point that I think it's better to understand WHY things don't work, rather than finding the solution and moving on. Can anyone tell me why 'require' wasn't working, but 'require_relative' does? Is it an older style of Ruby code that's outdated? Do I need to change some configurations? Is require_relative a workaround? Where does require look for files, if not in the same directory the file that's making that call is located?

Anyway, it felt good to make some progress on this tonight. It's pretty awesome that I can come up with an idea on the way to work, come home and put it together in an hour and a half or so. I think this will be a fun little project. I plan to work on it more this weekend, expanding it, polishing it up and so on. Here's a link to the gist I made of it:

MadLib Generator

Wednesday, October 26, 2011

Initializing Classes in Ruby

I definitely tend to jump around a bit when it comes to learning to code. I was working on Manticore quite a bit, then jumped into Learn Ruby the Hard Way, and now I've hit a bit of a snag so I checked out Code School and the introductory Ruby lesson. (This lesson is based on Why's old lesson, by the way, and is awesome so far) I'm a big fan of Code School so far, because hands-on, practical tutorials have always been one of the best ways for me to learn.

Much like Learn Ruby the Hard Way, it's a lot of review, but I've been interested in seeing what Code School has to offer for a while. Not to mention, switching gears slightly seemed like a better use of my time than sitting around frustrated because I wasn't understanding defining Classes and initializing them properly. I also think the more time I can spend having fun with Ruby, the better. I end up coding longer and enjoying it more, which leads to me learning more and it all kind of snowballs from there until I can build a sort of half-ass snowman with string literals for arms and instance variables for eyes.

Still, Ruby isn't all string methods and arrays, so I'll get back to my problem with Learn Ruby the Hard Way pretty soon. Probably tomorrow!

Here's the basic problem: I have one Class, Game, and the extra credit for this particular exercise is to break the Game into two Classes: Engine and Map.

Here's a link to a gist of what I've got:

Gothons Attack!!

What I'm assuming I need to do is break the rooms a player goes through (methods such as :central_corridor, :bridge_access, etc) into the Map method, and put the code that drives the game into the Engine method. So now I need to learn what initializing a class does, how to do it, how to call a method in one class from another class, and how to make two classes work in concert. For example, Engine will be starting the game (I assume) and moving the player through the rooms that are defined in Map (I also assume) Any input on this problem is, as always, HIGHLY appreciated!

I used to think of learning Ruby as unearthing this huge artifact, but now I think of it as being inside of a mostly darkened room, where I'm stumbling around and looking for switches. Once in a while, I flip a switch and it might illuminate a far off corner, or a whole corridor, or just a tiny little piece of the room. Does that make sense? Or in other words, learning how to do new things is really frustrating right up until it's not, and then it's awesome.

Sunday, October 23, 2011

Here documents in Ruby

I'm still working through Learn Ruby the Hard Way, and the last few exercises have been about building simple text based dungeons. You may recall I spent about a week working on one of my own. This latest exercise introduced me to here documents.

A here document is an easy way to display a long, multiline string. This would have been PERFECT for use in my dungeon adventure. Here's how it works.

This is the original description from the first room in the dungeon game I built:

  puts "This room is dimly lit by two sputtering torches."
  puts "There are three doors leading out of here."
  puts "What do you do?"

You may notice a few "puts" methods. It's not terrible in this case, since I'm putting several small statements, but it's tedious to type and unnecessary to use so many methods when you could do it with one here document. So forget what I said. There's a better, simpler way to do it, so it IS terrible!

So this example can be re-written like this:

  puts <<−TORCH_DESCRIPTION
  This room is dimly lit by two sputtering torches.
  There are three doors leading out of here.
  What do you do?
  TORCH_DESCRIPTION

You begin the here document with <<−TORCH_DESCRIPTION and end it with TORCH_DESCRIPTION. Ruby interprets everything in between as one string. Cleaner, right? Easier to read? Who wouldn't love it!

On a side note, you CAN write this as <<TORCH_DESCRIPTION instead, but by adding the minus sign, you can indent the code as usual. Without the minus sign, the terminator can't be indented, or else Ruby will start complaining about "can't find string TORCH_DESCRIPTION anywhere before EOF".

So I recommend using the minus sign. One more character makes your code a lot easier to read. I also ran into another little problem. Since a here document is a string literal, any variables won't be interpreted correctly. This is where interpolation comes into play. Here's an example from the current exercise I'm working through.

guess = gets.chomp()

if guess != good_pod
  puts "You jump into pod %s and hit the eject button." % guess
  puts "The pod escapes out into the void of space, then"
  puts "implodes as the hull ruptures, crushing your body"
  puts "into jam jelly."
return :death

This bit of code describes an escape pod room, where the user has to pick an escape pod to use. So we set the user's choice as "guess" and then call it in the method below. This is what happens when a user chooses poorly. However, if I were to rewrite the code using a here document, this is what I'd have:

  puts <<-BAD_POD
  "You jump into escape pod %s  and hit the eject button. %guess
  The pod escapes out into the void of space, then
  implodes as the hull ruptures, crushing your body
  into a jelly."
  BAD_POD
return :death

Now the %s and %guess won't be interpreted as variables, since they're inside of a string literal. Luckily, there's an easy solution: interpolation. Just swap out the %s for this little guy:

#{guess}

Ruby will look at this, understand that means you want to use a variable inside of a string literal, and then pull the information it collected when it asked the user which pod he wanted to jump into.

I'm hoping this post will be helpful for others who are grappling with here documents. It took me a bit of digging to figure out how to get the code to index properly (since it looked awful in Textmate, and my solution was to put the string in quotes, which was unnecessary) and I needed to figure out how to call a variable from inside the here document.

Sunday, October 16, 2011

Finished text-based adventure in Ruby

I'm now more or less done with the text dungeon I was building last week. I finished it up last night and fixed some bugs, refactored a bit and made the game more playable today. I also ran the code with -w, which shows a list of warnings. I'm not entirely clear how warnings differ from errors (other than errors stop the code, whereas warnings allow it to continue) but running the code this way allowed me to clean up bad indentation (plenty of it) as well as cleaning up a few other things. I also found out you can indent or unindent (is this a word?) a block of text in TextMate using keyboard shortcuts. Of course, I only found this out after getting frustrated at how long it took to manually indent or unindent a block of code. What's the lesson here? Sometimes it's not about learning new tools, but learning to be more efficient with the tools you already know. 

I've learned a lot with this little project: defining instance variables such as @brass_key, using instance variables to do things within other methods, such as opening doors, creating an inventory for the player that adds or subtracts items as they're found or used, logic to change events if certain instance variables were true and so on and so forth.


Tomorrow I plan to get back to work on Learn Ruby the Hard Way, but this week has definitely been well spent. I may revisit this project in the future and rewrite it to use case / while instead of if / elsif, but I'm ready to work on something new. I spend a lot less time flailing around and feeling stupid now and a lot more time coding or looking for ways to do what I want to do. 


My vocabulary is getting better, too, so it's easier to find information now. And all of this work makes me think about Manticore (don't worry, baby, I haven't forgotten about you!) and how much easier it'll be to redo now. The code I had before I sat down with Eli a few weeks ago took me a couple of months to write, and I'm pretty confident I can get the same functionality with less code in about a week now. But first I need to finish up Learn Ruby the Hard Way. 


And I've been thinking about using what I've learned to write tutorials. I'm sure other new Rubyists will be confused about local and instance variables, or how to write and call methods, and I'd like to try and write something up that will explain these basic ideas in the context of a text-based dungeon crawler. I haven't thought too much about it yet, but it's something I'd like to do in the future.


Here's a link to a gist of the game:

Dungeon of Unfathomable Horror