UEFI News and Commentary

Thursday, July 26, 2012

Creating an Interactive Fiction Game with UEFI (Part 2)

In the last blog post, I wrote about the basic structs needed to create an interactive fiction game in UEFI.  This time, I'll talk about the actual game loop and the function that interprets user input.
When writing a game, unless there are only a set number of turns, the game will continue until a player either wins or loses.  In interactive fiction games, there is only one player, so it is fairly simple to keep track of that one player's win or loss status.  The game will continue to loop so long as the player has not lost or won the game.
Now, in my game, there is no way to lose.  You simply continue playing until you quit, or you have figured out how to win.  Therefore, my loop only has one condition: the winning condition.  Because the goal of my game is to escape from a building, I simply made it so that once the player has done so, the room they enter is simply NULL.  That way, the loop will continue so long as the character has not entered that room yet.
Once inside the loop, we have a string (creatively named string) that will store the user input.  At the beginning of the loop, we set it to NULL just to make sure no garbage gets mixed in.  Then we print a little prompt for user input, a simple ">", and then wait for the player to enter a command.  As soon as they enter a carriage return, I use strtok() to get the first word, and store it as the verb.  The user input string will be divided, eventually, into two parts: the verb and the noun.  For now, though, all I need is the verb, to make sure that the user didn't enter an empty string or a set of spaces.  So I check to see if the verb is NULL.  If so, it skips the rest of the loop, and will continue to prompt the player for input until they actually type something.
After something is entered, I then use strtok() again to concatenate the rest of the user input string together and store it into noun.  Once the rest of the input has been properly stored away, I call takeAction(), which uses the user input to determine which functions to call to carry out the appropriate action.  Now, I put it inside an if statement because takeAction() returns a value.  For most commands, or even nonsense, it will simply return 0.  However, if the user enters "quit" or "exit", it will return 1.  After confirming the user's command, the loop will exit.
Now, I will spend a little time on takeAction(), though it is truly a very simple function.  All it does is take the user input and determine which functions to call so the desired action is carried out.  In essence, all it contains is several if statements, comparing the user input to several anticipated strings.  I used strcasecmp() to compare the strings so there is no problem whether or not the player has odd capitalization habits.

The most basic function is move(), and it has the most possible inputs.  This could also be handled by checking to see if the user entered "go," "move," or "walk" and then specified a direction, and pass the direction into move() as well.  Many people who play interactive fiction, however, tend to get lazy and will just type the shortest command possible.  

The rest of the commands are ones that I have found very common and useful in most interactive fiction games.  Some of them, like take and drop are player actions that cause a change in the game state.  Others, like inventory or help, are helper functions to lend a hand to the user.  And then are the "just for fun" commands, like yell, that don't do anything significant, but the game accounts for them.  If the player wants to quit, this function will return 1 instead of 0, and the game loop will account for that.  Finally, if the player enters gibberish or a command that wasn't accounted for, this function will print out a statement, and the game loop will continue.  

Finally, I'll talk a bit about move(), just to show a little real action.  This function takes the character and a string as parameters.  Now, all of these separate functions will take the Character as a parameter because the Character functions as a sort of game state, keeping track of location and objects held.

The first step in this function is to interpret exactly which direction the user wants to go.  So we get the room the character is currently in, determine which direction the player wanted, and then get the corresponding exit.

Now, next is determining whether or not you can go that way. It's simple enough.  Either there is no Room in that direction (exit.room == NULL) or the door is locked (exit.locked).  If you can't go, you print out the exit's pre-defined statement on why you can't go that way and exit the method.  Now, I put a little something in there so that if the door is locked and you have the key in your possession, it prompts you to unlock the door.  I may change it later so that it automatically unlocks the door if you have the key, but for now, it simply prompts the player.

And finally, if there is a way out in the specified direction and it's not locked, it sets the character's current room to the one designated by the exit, prints out the new room name and has the character "look" at the room.

Of course, the basics of a game are pretty straightforward.  The actual hard work is finding an engineer who can write decent interactive fiction.  Next time, I'll focus on a different category of game.

Also, if anyone is interested in the code, I will zip it up and send it to you if you send me a note.


Kevin said...

What a great set of posts. I sense a trip to the next UEFI plugfest to give a presentation about your game!

pdplaza said...

Hi Tim,

Could you please send me this code to my mail padmarao.i@gmail.com , i am very much interested to run this game in my EDK2 environment.

Tim Lewis said...

Sure. Give me a few days because Shannon is away from her home.

lrwr said...

Hi you two.

First of all thanks for this blog, it helped me a lot so far.
I'm currently an engineering student and am working together with a conpany to develop the UEFIs for their boards in the future.
By now I've got the task to work with the UEFI shell, "get used to it" and write some test applications.

Before starting here I worked a lot with java, so I'm very used to object orientated programming and hope your program could give me some inspiration to worke with structs. I'd be really happy if I can get your source code.

If you have some additional examples, like accessing boot- or runtime-services I'd really like to get code snippets :)

I set up the edk2 environment for visual studio as you described in your guide, but when testing arround with examples from "Harnessing the UEFI Shell" Visual won't find the include files. When adding the necessary paths to the additional include directorys it's complaining about redefinitions.

Sorry to bother you with my noob questions, but it looks like I need some help to get my development started. As soon as I have a productive development environment and got some examples I should manage on my own.

email: lrwr {at} hotmail {dot} com

(sorry for my bad english, im not a native speaker)

Tim Lewis said...

@lrwr, thanks. You'll be seeing more examples in the coming days. The Harnessing examples are tough, because they were originally created in a pre-production UEFI shell environment.

vj said...

Hi, I'm interested in UEFI development...
Could you send me this code? ammai7 {at} gmail {dot} com

Ed Edson said...

Could you send me the sourcecode as well?

email: edk2 [at] gmx [dot] net