MUD Progress
Posted in MUD Development
First watch, 4 bells (10:21 pm)

I've been making a little progress on the MUD again. I don't work on it much, but it hasn't been building for a while, and I've got a drive to get it fixed so at least I can continue testing it.

I've made a few modifications lately, the biggest being changing the command objects to Singleton objects since that's the way I've been using them anyway. I've also been working on the get command, and as happens when a design gets better, it's shrinking in size. Hopefully I'll be able to wrap it up tomorrow, since Lorien will be working until almost 9:30pm tomorrow night anyway.

I've also been lax about source control. My current system is rolling up a tarball, bz2-compressing it, and dropping it into my gmail account. I really should get something a little more sophisticated. At some point I'm going to have to do something about it. But the goal right now is to get it building again, and to test out the get revision.

Leave a Comment »
Using the yaml-cpp Library
Forenoon watch, 7 bells (11:57 am)

I've been using the yaml-cpp library for a while now, and I have to say that overall I'm greatly pleased by how well it works.

As I was making some adjustments to my I/O last night I ran across a bit of documentation that I never noticed before. Of course, it could be newly added. Anyway, I've found the most convenient way to parse my documents (I have many thousands of them to read and write), is to access them by node-name. For example:

node["location"]["name"] >> mObjectLocation.location;

The information I read last night, however, may convince me to change this behavior.

Apparently, named-node access in yaml-cpp is order-n2 complex over the entire document. Put simply, every time you access a node like this the library loops through all nodes looking for a match. Personally, I think a hashed table lookup would have been much faster, and perhaps they'll add that later.

Overall, I wouldn't normally worry about it because my documents tend to only have a few dozen nodes. But I do have 20,000 documents to parse. And to top that off, as they are used they become more complex. And as more items are added, the node size will grow geometrically. I can easily envision a future where a single document contains hundreds of nodes, and it's starting to scare me.

The solution? Well, I can honestly say I don't have a good one yet. I think perhaps if I enforce the order things are written, which already only happens in one way, I can then read in linearly instead of by node-name. The problem with that is if a file is edited by hand and the order is accidentally changed. So by renaming my current solution to readCompatible() and writing a new linear read() function, I should cut down on a lot of extra unnecessary processing.

But I'm still not sure that's the best solution. Any smart people out there have a better idea?

Leave a Comment »
Boost::Spirit 2 Redux
Last dog watch, 8 bells (8:27 pm)

Well if you stopped by yesterday you may have read my post about Boost::Spirit 2 and the trouble I had converting to the new Spirit 2 library. Fortunately, Hartmut Kaiser, one of the Boost::Spirit authors must have a Google blog notification when Spirit is mentioned in a blog, because he left a comment with a suggestion for me earlier!

Unfortunately, I still can't seem to get qi::phrase_parse to work right. The problem is that I'm trying to match one of a set of increasingly complicated grammar structures (perhaps starting at the most complicated and working backwards would fix this issue…). So, here is my problem in gruesome detail:

I'm implementing a get command for a MUD, an online text-only game system. Since I'm writing it from scratch, I decided to use some of the most up-to-date tools I could find to do so, and Boost has some terrific libraries that make this possible. As far as I can discern, the get command can come in the following forms:

  1. get hammer
  2. get 20 nails
  3. get hammer 2 (the second hammer)
  4. get 20 nails 3 (20 of the 3rd type of nails visible)
  5. get hammer from toolbelt
  6. get 20 nails from bucket
  7. get hammer from toolbox 2 (the hammer from the second toolbox)
  8. get 20 nails from bucket 3 (you get the idea)
  9. get hammer 3 from toolbox 2
  10. get 20 nails 2 from bucket 3

The problem comes when using phrase_parse with an empty space skip-parser. Given the two rules:

bool res = qi::phrase_parse(first, str.end(),
				(
					+qi::alpha
				),
				' ',
				item
);

And

bool res = qi::phrase_parse(first, str.end(),
					(
						+qi::alpha
						>> "from"
						>> +qi::alpha
					),
					' ',
					item,
					container
);

If I check the phrase get hammer from bucket it matches rule one, because after you remove all the spaces from the string it's just one long word! This is an unexpected result, and even if I check rule two before rule one I only match rule one!

And now I'm really lost. I imagine there's a better way to do this, but I can't seem to figure it out. Also, since my allergies are going crazy, I've got to take the night off anyway. Anybody out there know of a solution?

3 Comments »
Boost::Spirit 2
Last dog watch, 1 bell (6:34 pm)

Last year I added Boost::Spirit to my MUD project. A few weeks ago I learned that all of the work I had done was deprecated in the new Spirit 2 library. I could still use "Spirit classic," but it is deprecated and may be removed at some point in the future. So I spent some time today figuring out how to convert my grammar rules.

For example, in Spirit classic, I had this rule to handle the most complex rule for my get command. In this case, it handles a command like get 20 items 2 from container 3:

rule6 = int_p[assign_a(mNumberToGet)] >> ' ' >>
			(+alpha_p)[assign_a(mItemToFind)] >> ' ' >>
			int_p[assign_a(mItemNumber)] >> ' ' >>
			str_p("from") >> ' ' >>
			(+alpha_p)[assign_a(mContainerToLookIn)] >> ' ' >>
			int_p[assign_a(mContainerNumber)];

which could be tested by the following code: if(parse(str.c_str(), rule6).full)

Here is the equivalent code in Spirit 2

	std::string::iterator first = str.begin();

	bool r = qi::parse(first, str.end(),
					(
						qi::int_ >> ' '
						>> +(~qi::char_(' ')) >> ' '
						>> qi::int_ 	>> ' '
						>> qi::lit("from") >> ' '
						>> +(~qi::char_(' ')) >> ' '
						>> qi::int_
					),
					mNumberToGet,
					mItemToFind,
					mItemNumber,
					mContainerToLookIn,
					mContainerNumber
	);

	if(r && first == command.end()) {
		return true;
	}

In many ways, the new Spirit 2 library is better, and purports to be much faster as well. The parse function has certainly been made somewhat more convenient. Overall, I'd rather not have had to spend time on this, but the only other option is to lock in with an old version of Boost that may hamper me in the future.

5 Comments »
Tons of Progress
Posted in MUD Development
Morning watch, 8 bells (8:06 am)

I've had a lot of time here in Portland, especially in the mornings when nobody else is up, to work on my MUD project. I converted it to use YAML to load and save everything, and the issue that caused me to have to choose a structured language, the inability to show relationships between deeply nested containers is now fixed. I also rewrote the login process to use dynamic handlers depending on the login state you're in (thanks Jeff!).

I know I'm on the right track, because in nearly every case, the code changes were smaller than the original code. So far, that's always been a good sign for me.

The best part is now I have loadable and saveable objects all working, and I can continue to build the rest of the functionality to complete the MUD and make it playable. Thank goodness for lazy vacations!

Leave a Comment »
Getting Ready
Posted in General
Afternoon watch, 6 bells (3:04 pm)

Today I'm doing a bunch of things around the house so we can leave for Portland on Monday. We'll be staying for a whole week! My cousin is getting married next Saturday in Coburg. We'll also take an afternoon to visit my grandparents near Eugene. Maybe even take a trip to the coast!

I should also have some time to continue working on my MUD project. I haven't had much time this week. Now that most of the issues I've had with the yaml-cpp library have been worked out I'm able to begin working on conversion to the YAML format.

Leave a Comment »
MUD Update
Posted in MUD Development
First watch, 7 bells (11:44 pm)

I got some more bits together for the MUD today, but not very much. I was hoping to have all the zone exits working properly, but there have been a few issues and I'm too tired to solve them right now. I'm very close to having custom, printable maps displaying for each client. Screenshots will be taken when the feature is working.

Leave a Comment »
Tracking the MUD
Posted in Hobbies
First watch, 4 bells (10:09 pm)

Well my MUD project is back up and working after a big reorganization of globally-scoped data. Yes, it is evil. No, there isn't much of a way around it. It's not a lot, but it needed to be wrapped up in a single class to simplify referencing to in other objects.

Things are running smooth again, but now I have to go back and take out some place holder room code and move its functionality to the new zone system. I changed a helper class over to be a namespace while I had things taken apart, since it never had any data associated with it, just functions. I'm using online GDCU course offered by Ian Schreiber (it's about game design in general), and it's been real interesting so far.

Leave a Comment »
Telnet Issues
Posted in MUD Development
First watch, 1 bell (8:33 pm)

My MUD server (yes, the one I've been writing forever) seems to have some issues with certain telnet clients. I think it's because they're sending weird telnet option requests and I just ignore them. I really should fix that. Here's a nice site that talks about the telnet protocol and its large group of obscure options.

What I really need to do is read up some more about boost::asio and enter the modern age of network coding. Maybe.

Oh yeah, and boost::format, too! So many tools, so little room in the toolbox…

Leave a Comment »
Happy Birthday, MUD! And Mom!
Posted in Warm and Fuzzy
Forenoon watch, 4 bells (10:28 am)

According to Richard Bartle, today is MUD's 30th birthday! Today is also my mom's birthday!

I started playing different MUDs years ago, and they took up way too much of my time. But I really did love playing, and my time on various servers inspired me to start writing my own. And someday I'll finish that project, but for now I pay homage to the ancestor of online, virtual worlds that has inspired so many other projects as well as my own. You should read the whole post about MUD's birthday, it has interesting history and lots of Richard's own observations about why such a thing isn't really celebrated, or really even talked about very much.

Leave a Comment »