Jump to content
  • Advertisement
Sign in to follow this  
GamerCon

MUD commands

This topic is 5036 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I dont know how to explain it so ill just do my best in commenting.
#include <iostream>

#define NUM_COMMANDS 2

void (*function)(char*); // This holds a pointer of the function to be called. It's global because I dont know how to get a function to return a pointer to a function (if it is possible, can someone explain how?)

struct CMD // The magic structure
{
    char *cmd; // this will hold the actual command to be compaired with a players input
    void (*fun)(char*); // If players input and cmd are equal this is the function  address that will be set into (*function)(char*)
};

//The below functions are called when the proper command was input
void say(char *str)
{
    //just so i know this function was called successfully
    std::cout << "This is the \"say\" function accesed by " << str << std::endl;
}

void get(char *str)
{
    //just so i know this function was called successfull
    std::cout << "This is the \"get\" function accesed by " << str << std::endl;
}

//Now that there are a couple command functions, create the CMD structure array
CMD commands[NUM_COMMANDS] = //an array NUM_COMMANDS wide
{
    {"say ",say},  //first part is the command that must be input, second part is the pointer the the function
    {"get ",get}
};

// this next function compares player input to the current command being looked at by "i"
bool compare_command(char *str,int i) //str is the player input, "i" is the element of the command array to look at
{
    if(strncmp(str,commands.cmd,strlen(commands.cmd))==0) // If the players input matches the current, looked at, command
    {
        function = command.fun // function is the global void (*function)(char*) variable
                                 // command.fun is address of the command function
        return true; // so we know to call function(char *str)
    }
    return false; //meanse that player input didnt match the looked at command
}

int main() // where it all happens
{
    char *input = "say ";  // this is the player input, since im not wrapping any socket programming around this source, it'l have to do

    for(int i=0; i < NUM_COMMANDS; i++) //loop through all the commands comparing them to the player input
    {
        if(compare_command(input,i)) //if this function returns true
        {
            function(input); // call function() which holds the address say() so it technically calls say()
        }
    }
    system("pause"); //I need to see the output before the console closes
    return 0; //all went well
}




Am I doing this correctly? does this method make any sense to anyone? Know any better methods to accomplish the same thing? Thanks -GamerCon

Share this post


Link to post
Share on other sites
Advertisement
Seems like it would work. I personally would use a std::map mapping strings to function pointers or better yet functors.

I haven't checked this so it may (and will) contain small errors, but you get the general gist of it. As for a good resource on function pointers - you should check out http://www.function-pointer.org/




#include <string>
#include <map>
#include <iostream>
#include <pair>

using namespace std;
typedef void (*fnPtr)(string);
map<string,fnPtr> gFunctionMap;

void say(string params)
{
cout << "You say: \"" << params << "\"\n";
}

int main()
{
gFunctionMap.insert(pair<"say",say);

string command = "say";
string params = "I am awesome!";
fnPtr f = gFunctionMap(command);
f(params);
}


Share this post


Link to post
Share on other sites
The illustrated typedef is a good idea, it will keep things clearer since the syntax for function-pointer types is pretty messy.

The map is a good idea too; the map lookup will automatically use a good algorithm for managing your list of command names and looking them up (it will basically do a binary search, except you can change the list without major problems, and it will do all the management for you - take an algorithms class, or [google] "red-black tree" to see how this is done).

Using functors is a really good idea; it will let you change the behaviour of commands over time (by associating state with them - since they are objects), and avoid those messy typedefs. Basically in C++, all you need is an object that implements the operator():


#include <string>
#include <map>
#include <iostream>
#include <pair>
#include <algorithm>

using namespace std;

class Functor {
// This is my weird Java-influenced organization of things at work...
// You might prefer to put the function map in a namespace, or leave it global.
public:
static map<string, Functor> commands; // note "static".
virtual void operator()(vector<string> words) = 0;
// Assumes you will tokenize your input later...

static void insert(string& name, Functor& cmd) {
// Just for convenience.
commands.insert(std::pair<string, Functor>(name, cmd));
}
protected:
static void output_word(string& word) {
cout << word;
} // definitely note "static" here. Otherwise we're looking at a
// "member function pointer" and things get a lot harder.
}

class Say: public Functor {
public:
void operator()(vector<string>& words) {
cout << "You say: \"";
std::for_each(words.begin(), words.end(), output_word);
cout << "\"" << endl;
}
}

// Similarly for other commands... notice you can do anything with them you
// could with a normal object

int main() {
// initialization
Functor.insert("say",say);

// Get a command and arguments from user input
string command = "say";
vector<string> params = // get the words of input here

// Respond to user input
Functor.commands[command](params);
}

Share this post


Link to post
Share on other sites
In C, rather than having a constant to indicate the number of commands in the array, it is much, much simpler to have a sentry in the array itself, like a NULL pointer for your command string.


#include <string.h>

typedef void command_func(char*);

struct command_table_entry
{
char *command;
command_func* function;
};

command_table_entry command_table[] = // No need to specify the array size
{
"say", say,
"get", get,
NULL, NULL, // Handy for cut/paste: a trailing comma is not an error
};

void execute(char* command, char* args)
{
int cmd_len = strlen(command);

command_table_entry* ptr;
for(ptr = command_table; ptr->command != NULL; ++ptr)
if( !strncmp(command, ptr->command, cmd_len) )
break;

if(ptr->command == NULL || ptr->function == NULL)
{
// Error - no matching command
}
else
{
ptr->function(args);
}
}





Variations are of course possible, including, in C++, std::map.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!