Trag has asked for the wisdom of the Perl Monks concerning the following question:

I'm attempting to write a text adventure in Perl, but I'm having some trouble.
Specifically, I need to know how to make it recognize when a command is entered, and possibly combine that with an object (like say, examine lantern). I'm trying to load all the data (Descriptions, items and such) from hashes in a seperate file.

Do you have any ideas that could help me along?

Thanks

Trag

Just another Perl Hack

Replies are listed 'Best First'.
Re: Writing a text adventure in Perl
by Roy Johnson (Monsignor) on Jul 29, 2004 at 14:07 UTC
    If your goal is to write a text adventure, you should not be rolling your own tools. It's a big task, and it's been done before. Go to The Interactive Fiction Archive and download a development system (TADS is a good one).

    If your goal is to enhance your Perl programming skills, I recommend you set modest goals, particularly for your command parser. What are you finding difficult about recognizing when a command is entered? It seems like you should have a main loop that looks like this:

    while (<STDIN>) { # Command is in $_ chomp; handle_command($_); }
    Where your handle_command sub is going to split the command and recognize whether it's a direction or verb noun or whatever.

    We're not really tightening our belts, it just feels that way because we're getting fatter.
Re: Writing a text adventure in Perl
by Corion (Patriarch) on Jul 29, 2004 at 14:24 UTC

    In addition to TADS, I recommend you check out the Inform language and the introduction to Inform on that website, which also tells you a lot about how the Infocom adventures were implemented and how the grammar works.

    In most cases, the feature set available through Inform will be total overkill for you, as you want to simply split up an (english) sentence into words and act upon the words. If you want to simplify and assume that all sentences are in the imperative form, then the first word will always be the action and the rest of the sentence (if any) will be objects belonging to that action. A different, also simplicistic approach would be stupid pattern matching where you specify (regular expression) patterns that get applied to the sentence entered to describe what you want:

    my %action = ( qr/^give (.*)(?:\s+(to) (.+)))$/ => \&give_to, qr/^go (.*)$/ => \&go_to, qr/^take (\w+)$/ => \&take_item, ); while (<>) { my $matched; for my $pattern (keys %action) { if (/$pattern/) { $action{$pattern}->(); $matched++; last; }; }; print "I didn't understand what you meant by '$_'.\n"; };

    Of course, that will only get you so far, as the concepts of reference to the last sentence/object (look at banana. eat it.) and error correction (go nwrth. oops north.) won't be caught by this scheme, but for a simple start giving you quick results, this is a viable way.

Re: Writing a text adventure in Perl
by matija (Priest) on Jul 29, 2004 at 14:13 UTC
    For knowing when a command is entered, you could employ the services of Term::ReadLine - that should give you not only notification of a command's entry, but also such wellcome features as command line editing and history.

    As for combining it with an object, you should first define the commands and the grammar you would accept, then perhaps parse the commands with something akin to Parse::RecDescent - or something simpler if your grammar is simple enough.

    Personaly, for an adventure of any sophistication, I don't think hashes are going to be sophisticated enough - to simulate actions on objects you should use, well, objects...

Re: Writing a text adventure in Perl
by atcroft (Abbot) on Jul 29, 2004 at 14:00 UTC

    My suggestion would be to take input, chomp it, then split it on spaces, taking the first as the potential action, then any remaining values as the object, if necessary. Then, you just need to have some structure that has the results of that action, or return a message that says that action could not be performed on the object. Just tossing some code together might look something like this (untested):

    while (($alive) and ($playing)) { $input = <STDIN>; chomp($input); my @part = split(/\s+/, $input, 2); if (defined($actions{$part[0]})) { &handle_action(\@part, \$playing, \$alive); } else { print "Huh?\n"; } }

    The handle_action routine would then have more logic regarding how to handle individual actions.

    Hope that helps, at least give you an idea to start from.

Re: Writing a text adventure in Perl
by dragonchild (Archbishop) on Jul 29, 2004 at 14:24 UTC
    I recently wrote on in C (primarily to play with C which I haven't done in about 10 years). My biggest friend was tok(). I would be very surprised if there wasn't a wrapper around tok() already built. Or, even better, you can probably build your own version of tok() quite easily.

    As for mapping what you parse from the commandline into your data structures, I found it very useful to write callbacks and associate them with commands. So, the "examine" command would have a function associated with it that would be called whenever the "examine" command was entered. This is sometimes known as a dispatch table. Although I worked primarily with the command, there is no reason why you cannot extend that idea to a function that will, given the name of something, return back a list of objects that map to that something. You could even have that function constrain based on various criteria, such as what the player can see, what the player has in inventory, etc.

    I have a node here regarding the testing of this game. The "Adventure" link links to the a PDF written by Donald Knuth dissecting the original Adventure game. It's a C translation of the original game in Fortran, but it has a number of good ideas.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re: Writing a text adventure in Perl
by davidj (Priest) on Jul 29, 2004 at 16:32 UTC
    If you are interested in learning a new technology while you are developing your game (which is always a good thing), in addition to TADS and inform, you might want to take a look at prolog, as it is ideal for developing such applications. Adventure games in prolog can be written in less than an hour (once you know what you are doing). There are a lot of free prolog compilers out there. The consensus is that swi prolog is the best. It has ports for a multitude of operating systems. You might want to check out Amzi!Prolog. It, too, is free and also a tutorial in which they develop an adventure game. Might be right up your alley.

    davidj