[MUD-Dev] Re: Question on c++ switch optimization, and parsers in general.

Adam Wiggins adam at angel.com
Mon Feb 8 11:47:31 New Zealand Daylight Time 1999


On Sun, 7 Feb 1999, Ben Greear wrote:
> Basically, I'll have a bunch of classes hashed into an array
> that will contain the keywords mapped to an enum.
> Now, I get the enum, and then I need to call the various commands
> that the enum maps to.
> Currently, I'm using a huge (~400 cases) switch statement.

I've always been fond of the simplicity of the "big array with everything
you need to know about a given command" method.  Apparently some folks in
the diku world are as well: I know that stock CircleMUD handles commands
this way.

Basically, you make something like:

typedef void (*CommandMethod)(Character *, char *);

struct CommandInfo
{
   char *Name;
   int MinimumLevel;
   int SkillNeeded;
   int LimbsNeeded;
   CommandMethod Method;
};

Then you just fill out your array as you like:

CommandMethod Smile, Track, Purge /* ... */;

CommandInfo CommandList[] = 
{
  { "smile", LEVEL_MIN, SKILL_NOTHING, SPEACH, Smile },
  { "track", LEVEL_MIN, SKILL_TRACK,   EYES,   Track },
  { "purge", LEVEL_GOD, SKILL_NOTHING, 0,      Purge },

  { NULL, 0, 0, 0, NULL }
};


And your command parsing code looks like:

bool ParseCommand(Character *c, char *arg)
{
  int i;
  for (i = 0; CommandList[i].Name != NULL; i++)
    if (strcasecmp(CommandList[i].Name, arg) == 0 &&
        c->Level >= CommandList[i].MinimumLevel &&
        c->Skill[CommandList[i].SkillNeeded] > 0)
      break;

  if (CommandList[i].Name == NULL)
  {
    InformCharacter(c, "No such command.");
    return false;
  }

  if (CommandList[i].LimbsNeeded)
  {
    if (CommandList[i].LimbsNeeded & SPEACH && !CanSpeak(c))
    {
      InformCharacter(c, "You can't speak!");
      return false;
    }
    if (CommandList[i].LimbsNeeded & EYES && !CanSee(c))
    {
      InformCharacter(c, "You can't see a thing!");
      return false;
    }
    if (CommandList[i].LimbsNeeded & HAND && NumHands(c) < 1)
    {
      InformCharacter(c, "You don't have any hands!");
      return false;
    }
    /* ... */
  }

  CommandList[i].Method(c, arg);
  return true;
} 

Finally, you need to define the methods Smile, Track, Purge, and
whatever else commands you want in whatever module you want.

This was just off the top of my head, btw, so code errors are quite
possible.  Check out the circle mud sources for a working version
of this sort of thing.

Adam W.






More information about the MUD-Dev mailing list