Using Commands in a Text Based RPG

Started by
7 comments, last by Kylotan 15 years, 5 months ago
Greetings everyone, I've been working on a text based RPG for a few weeks now, laying out some fundamental classes (written in Java) for things like 'Player' 'Inventory' 'Room' etc... The project is going fairly well and I'm learning a lot about good object oriented programming techniques, but something I know that I'm going to have to face in the near future is how to take and process commands typed in by the user. For example if a user logs in and is in a room and types 'look', the room description will display. I'm sort of in the dark as to how to go about this. Would I need a generic 'Command' class of some kind? Would I just make the game loop function such that it checks user input against a table of commands and then somehow, knows which method to call from which class based on the command type? Anyway, any suggestions you all have would be great, because I know this is something I'm going to have to face.
Advertisement
You will need to parse your command string.

Start by looking up the terms 'parser' and 'tokeniser' in Google.

At the simplest level, you will want to break your command down into a verb-noun structure, such as "get sword". You can then relate each of these items to an object or method in your code and perform an action based on those.
Thanks for the reply. I guess my question really boils down to: How do I actually relate each of the commands to an object or method in code? Should I have a list of acceptable commands in each class that I've made? For example, in my sword class, I would have an array of acceptable commands like 'slash' or 'jab' with different damages being dealt according to which one was used.

With exception to this little issue that I know I'm going to face, the project is going quite well. I'm not quite ready to implement the command system yet, but once I do, it'll be great to have some direction on where to go.
There's no obviously right or wrong way: you can choose.

You could just have a long list of if statements (eg. if (cmd=="kick") do_kick(); if (cmd=="north") do_north();)

You could translate the command to a const or enum and do the same thing with a switch/case statement.

You could make a command interface, with name and execute methods to override. Each command would implement this interface. Put all your commands in a list, then search for the one with the correct name. Call the 'execute' method on it, passing in the person who is performing the command.

You could probably even use reflection to look up a method by name, providing you write methods whose names match the commands.

90% of C++ text based games probably just have a table mapping command names to function pointers, but in Java that sort of structure is awkward due to a lack of function pointers, I gather.

You would handle commands via the people that perform them. Not the objects they perform them on. Why would a sword have the notion of commands? Swords don't do things; people do things. It's the player that performs the slash or jab command; the sword just happens to be the tool employed in the action. So the command is executed by or on the player, and it looks up which object (eg. sword, knife, pointy stick) is relevant for the command, and queries/modifies it as needed.
Sorry for intruding but I too am making a text rpg. I use c++ however.


'90% of C++ text based games probably just have a table mapping command names to function pointers, but in Java that sort of structure is awkward due to a lack of function pointers, I gather.'

How is that done?
Rather ugly C/C++ style pseudocode:
struct command{    char* name;    void (*command)(player, argument_list);};void do_north(Player p, ArgList lst){    player.move_north();    player.look();}// ...etc... command command_table[] ={    { "north", &do_north },    { "south", &do_south },    { "quit", &do_quit },    ...    { "", 0 }};// Get the command and the arguments to that commandinput_command = player.get_input();verb = first_word(input_command);argument_list = everything_but_first_word(input_command);// Find it in the tablesize_t ii=0;do{    if (command_table[ii].name == verb)    {        // execute the command then exit        command_table[ii].command(player, argument_list);        return;    }    ++ii;} while (command_table[ii].command);// if we got here, we didn't find that verb, so emit an error for the userprint "Command " + verb + " not found."


Not great style, just a quick example knocked up in 5 minutes.
If you're actually doing this is C++, it's a lot easier than that(I also think Java has similarish containers)!

typedef boost::function<void (player, argument_list)> command;typedef std::map<std::string, command>::iterator commandIter;std::map<std::string, command> commandTable;boost::assign::insert(commandTable)        ("north", &do_south)        ("south", &do_south )        ("quit", &do_quit );input_command = player.get_input();verb = first_word(input_command);argument_list = everything_but_first_word(input_command);commandIter iCommand = commandTable.find(input_command);if(iCommand != commandTable.end()){    iCommand->second(player, argument_list);}else{    std::cout << "Command " << verb << " not found." << std::endl;}
Thanks for this explanation. It helps immensely!

Quote:Original post by Kylotan
You would handle commands via the people that perform them. Not the objects they perform them on. Why would a sword have the notion of commands? Swords don't do things; people do things. It's the player that performs the slash or jab command; the sword just happens to be the tool employed in the action. So the command is executed by or on the player, and it looks up which object (eg. sword, knife, pointy stick) is relevant for the command, and queries/modifies it as needed.


Quote:Original post by BigJim
If you're actually doing this is C++, it's a lot easier than that(I also think Java has similarish containers)!

*** Source Snippet Removed ***

Yeah. However, there are 2 things to bear in mind:

1) Usually you end up needing to store extra data with the command, such as logging status, access permissions, etc. So you often need more than just a function pointer.

2) Java doesn't have function pointers so you'd probably need to wrap it in a class anyway. There's some rather convoluted examples online of simulating function pointers with the Command Pattern, but personally I'm just glad I don't use Java. ;)

This topic is closed to new replies.

Advertisement