Reserve, global wildcards

Posted by Zeno on Tue 22 Feb 2005 12:59 AM — 5 posts, 18,179 views.

USA #0
Does anyone have a reserve function (the Smaug command) where it instead of just preceding with a wildcard, it also allows after the name usage. For example stock will handle:
*zeno
But not:
zeno*

Ran into problems with certain users making bad names, yet zeno* was already reserved.
#1
I only have a few minutes, so I'll try to explain how to do it instead of writing code atm:

Find the is_reserved_name in comm.c. What you need to do is add a test that when the last character is a '*', that you should take the str_prefix() of the name and compare it to the input. You are going to need to copy the string into a buffer in order to use the str_prefix() function though (since you need to eliminate the '*' character from the string you wish to test).

Test some code and post it and I can try to help a bit more tomorrow.
USA #2
Or, use a wildcard matching function. If you're using C++ this will be helpful:

bool Matches(const std::string & pattern, const std::string  & str)
{
	bool result;

	// base case: if the pattern is the string, then we've succeeded.
	if (pattern == str)
	{
		return true;
	}
	// If the pattern is empty, then it can't match a string, hmm?
	if (pattern == "")
	{
		return false;
	}

	// * : 0 or more characters
	if (pattern[0] == '*')
	{
		// First try 0 characters... remove the star from the pattern, and use same string
		result = Matches(pattern.substr(1),  str);
		if (str !=  "" && !result)
		{
			// ok, that didn't work... so now eat one character and continue with the star in the pattern.
			result = Matches(pattern,  str.substr(1));
		}
		return result;
	}
	// ? : 0 or 1 characters
	else if (pattern[0] == '?')
	{
		// First try 0 characters... remove ?, and use same string.
		result = Matches(pattern.substr(1),  str);
		if (str !=  "" && !result)
		{
			// ok, that didn't work... so eat the ?, eat one character, and try again.
			result = Matches(pattern.substr(1), str.substr(1));
		}
		return result;
	}
	// no wildcard: just check the two characters for equality.
	else if (str != "" && pattern[0] == str[0])
	{
		// munch a character on each and try again.
		return Matches(pattern.substr(1),  str.substr(1));
	}
	return false;
}
I haven't tested this or even looked at it for a while, so I don't 100% guarantee it, but it should do the trick. Changing it to case-insensitive is a rather easy manner.

Not to be immodest but this kind of method is much better than the somewhat hackish approach that SMAUG has. The algorithm is not the most efficient; it could be improved e.g. by using indices for the strings, to avoid having to continuously copy them. That's fairly simple though, so I'll leave it as an exercise to the reader. :P The recursion makes it easy(ier) to read, so I leave it at that to make it as clear as possible.
USA #3
I know the basic concept how to do it, I'm just not positive on how to handle the last character and so on.

Well I'm not using C++ yet, but as I mentioned I plan to.

Basically was wondering if SWR/etc had something like this done already, so I could easily put it in, else I wouldn't put it in for a while with what I've got planned to do.

Call me lazy if you wish. ;)
Amended on Wed 23 Feb 2005 03:00 AM by Zeno
USA #4
The algorithm I gave could be edited to straight C fairly easily. Instead of substr'ing the string to advance it, you'd just give ptr+1. And of course instead of comparing to "" you'd do strlen() == 0 or something.