Yearly Archives: 2009

Magma MUD Codebase: Generally Quite Stable

The Magma MUD test site has been running for over a month now without any administrative intervention.  I have it set to automatically reboot the MUD after it’s been up a week.  That has happened 4 times now.  The fifth reboot was due to a segmentation fault (null reference exception) on June 10.  This means that in a month there has only been one unexpected reboot.

Any number more than zero isn’t particularly good, but it seems to be pretty stable under miniscule load (there isn’t really a playerbase, just people wandering in and out infrequently).

Telnet:  basternae.org port 4001.

The Ring of Winter

I finished reading “The Ring of Winter” by James Lowder yesterday.  It was your standard formula “fantasy in the jungle” novel, complete with dinosaurs, cannibalistic goblins, and mysterious artifacts.  I would rate it as “completely average”, three out of five stars.  If you like sword-and-sorcery fiction you’ll like it.  If not, you won’t.

Almost Working on Mono

There’s apparently a strange quirk to the XmlElementAttribute where you have to specify the data type for any type that isn’t a string (you’d think it would auto-detect an int property!)

So, with this:

///
/// The id number of the race.
///
[XmlElement("_number", typeof(int))]
public int Number
{
get { return _number; }
set { _number = value; }
}

Everything now loads, boots up, and characters can log in. However, when entering the game, there’s a NullReferenceException that happens on Mono (but not on the Windows version):

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object
at BasternaeMud.CharData.ResetStats () [0x00000]
at BasternaeMud.SocketConnection.ProcessMenuSelection (System.String argument) [0x00000]
at BasternaeMud.SocketConnection.ConnectionStateManager (System.String argument) [0x00000]
at BasternaeMud.SocketConnection.ProcessPlayerActions () [0x00000]
at BasternaeMud.SocketConnection.MainGameLoop (System.Net.Sockets.Socket control) [0x00000]
at BasternaeMud.Program.Main (System.String[] args) [0x00000]

So far it seems that this only happens for existing players. Creating a new player doesn’t cause this to happen. Might take quite a bit of effort to track down.

Technorati, Eh?

I finally went and set up a Technorati profile for the first time and claimed the Basternae blog.

I’m still not quite sure what you can really accomplish with Technorati. I guess I’ll find out. In the meantime, you can “favorite” this blog if you use Technorati:

Add to Technorati Favorites

If It Ain’t Broke Don’t Upgrade It

I hate software “upgrades” and updates. They invariably break something that I didn’t want to be broken. I’ve learned the hard way time and time again that switching to a newer version of something is a bad idea if the new version hasn’t added a feature I desperately need.

So the rule here is:
If it ain’t broke don’t upgrade it.

… because something important *will* break.

Website Grader

HubSpot has a website SEO grader at http://website.grader.com. It tells how well a site is optimized for search engines.

I ran half a dozen of my websites, including basternae.org, through the grader. Basternae’s score was 69% (second lowest of the six). That’s only a D+, not so great.

The nice thing is that it pointed out a few tags that I could change to improve the grade, so we’ll see whether the score goes up after the adjustments.

Of course, search engine optimization isn’t particularly relevant for this site — people who are looking for Basternae are going to find it easily.

Not Working on Mono

I tried firing up the current Basternae 3 codebase using Mono on my Ubuntu server. It crashed. So, here are the errors I have to sort out before I can get to the next errors:

14:30:34 Trace: Loading spells.
System.InvalidOperationException: Standard output has not been redirected or pro cess has not been started.
at System.Diagnostics.Process.CancelErrorRead () [0x00000]
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:CancelError Read ()
at Mono.CSharp.CSharpCodeCompiler.CompileFromFileBatch (System.CodeDom.Compile r.CompilerParameters options, System.String[] fileNames) [0x00000]
at Mono.CSharp.CSharpCodeCompiler.CompileAssemblyFromFileBatch (System.CodeDom .Compiler.CompilerParameters options, System.String[] fileNames) [0x00000]
at Mono.CSharp.CSharpCodeCompiler.CompileAssemblyFromFile (System.CodeDom.Comp iler.CompilerParameters options, System.String fileName) [0x00000]
at System.Xml.Serialization.XmlSerializer.GenerateSerializers (System.Xml.Seri alization.GenerationBatch batch, System.CodeDom.Compiler.CompilerParameters cp) [0x00000]
at System.Xml.Serialization.XmlSerializer.RunSerializerGeneration (System.Obje ct obj) [0x00000]
14:30:36 Trace: Loaded 421 spells.
14:30:36 Trace: Loading skills.
System.InvalidOperationException: Standard output has not been redirected or pro cess has not been started.
at System.Diagnostics.Process.CancelErrorRead () [0x00000]
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process:CancelError Read ()
at Mono.CSharp.CSharpCodeCompiler.CompileFromFileBatch (System.CodeDom.Compile r.CompilerParameters options, System.String[] fileNames) [0x00000]
at Mono.CSharp.CSharpCodeCompiler.CompileAssemblyFromFileBatch (System.CodeDom .Compiler.CompilerParameters options, System.String[] fileNames) [0x00000]
at Mono.CSharp.CSharpCodeCompiler.CompileAssemblyFromFile (System.CodeDom.Comp iler.CompilerParameters options, System.String fileName) [0x00000]
at System.Xml.Serialization.XmlSerializer.GenerateSerializers (System.Xml.Seri alization.GenerationBatch batch, System.CodeDom.Compiler.CompilerParameters cp) [0x00000]
at System.Xml.Serialization.XmlSerializer.RunSerializerGeneration (System.Obje ct obj) [0x00000]
14:30:36 Trace: Loaded 95 skills.
14:30:36 Trace: Loading races.
Unhandled Exception: System.Exception: Error loading races in Race.LoadRaces(): System.Exception: Error loading race in Race.Load(): ../races/Barbarian.raceSyst em.Exception: Race.Load(): Race number 0 already taken by Human. Can't load Bar barian
at BasternaeMud.Race.Load (System.String filename) [0x00000]
at BasternaeMud.Race.Load (System.String filename) [0x00000]
at BasternaeMud.Race.LoadRaces () [0x00000]
at BasternaeMud.Race.LoadRaces () [0x00000]
at BasternaeMud.Database.LoadDatabase () [0x00000]
at BasternaeMud.Program.Main (System.String[] args) [0x00000]

The first error happens when the engine tries to compile custom code in a spell file.

The last error, “race number 0 already taken” is not correct — the ID for Barbarians is set to 1, so the files are obviously not being read correctly.

Integrating Python?

One of the things I’ve been worrying over is how to write a new scripting and artificial intelligence engine that integrates all the buttery goodness and capabilities of MobProgs and the homebrew probability-based AI system I wrote for Basternae II along with the only-used-once movement scripts I put together. They were all pretty powerful, but the bad things are/were:

1. Too many pieces of code to maintain.
2. Required a programmer’s full attention — far too complex for a zone writer or newbie-level web scripter to use.
3. Always required a recompile if changes were made.
4. Always required a reboot to load new changes. This made it un-tweakable. Want a mob to cast fireball half as often? Change it and reboot the MUD.
5. Extremely zone-dependent. If we unload the plane of fire, we still have all of the plane of fire scripts active, including hard-coded mob names and numbers.

It definitely shouldn’t require a restart of the game just to make a troll kick someone in the head more often. This naturally leads me to Python and/or IronPython, since it’s my current obsession. I have some reading to do, but don’t be surprised if I come up with a scripting engine of pure awesomeness.

22 Hours Uptime

Mind you, only about 5 players have logged into the Magma 3.04 demo site, but it’s been up 22 hours so far.

I remember back when Magma was first being developed. An hour of uptime was considered a good thing.

Funny how things progress. I remember my first MUD in 1999, Illustrium Arcana, running on a Cyrix 6×86-PR200 on a 32MB machine co-located on a friend’s ISP (stax.net, apparently shut down around the end of 2006). Having T1 access was so amazing ten years ago. Now I’d be angry if my cable modem slowed down to 1.5 MBPS.

The original Cyrix machine ran at about 200 BogoMIPS, which was screaming fast. Right now I have what is effectively 1/10 of a Xeon 2.5 GHz processor. That gives me 500 BogoMIPS and 320 MB of RAM. That’s more than enough to run a MUD and a few websites.

Moved To A New Host

Basternae.org has moved to a new host.  We are no longer on Hostmonster and are now on Linode.

Why Move?

Hostmonster is a great host and you get a *LOT* for the money considering that it’s less than $10 per month if you prepay. I’ve just simply outgrown it. I how have ~30 domains, ~30 databases, 6GB of data, and run all manner of things — WordPress, Drupal, Django, and custom Python and PHP scripts.

Hostmonster can almost support all of that. If I had 20 domains or less I *almost* wouldn’t have any trouble. However, here are the limitations that I’ve outgrown:

1. 32MB PHP memory limit. This is a wall that larger Drupal sites will hit regularly.
2. If you’re doing something they don’t like, your account can be suspended instantly. This happened to me once when some Chinese bot was spamming a database script and was performing what they called “long-running queries”. A call to tech support straightened it out (I had to delete a few files, but wasn’t using them anyway).
3. Support for Python and Django is pretty sparse. Since I’ve consumed the Python kool-aid, this has suddenly become important.
4. Lack of customization ability. Since it’s shared hosting, they don’t want me possibly screwing it up for other people.
5. No support for long-running processes. I couldn’t run a MUD on it.

These are things that most mere mortals wouldn’t run into, and if you’re just starting off with web design/development, I do recommend starting with Hostmonster. Everyone eventually outgrows shared hosting. It took me three years.

The New Host

Why would I choose Linode? I’ve mentioned in previous posts that I like Slicehost, and Linode is almost exactly the same thing — Linux-based Xen VPS (Virtual Private Server) hosting.

What pushed me over the top is that for the basic $20 per month plan I get 320MB of RAM at Linode instead of 256MB I would get at Slicehost *and* Linode allows you to run a 32-bit OS, while Slicehost is 64-bit only. That’s not just 64MB more memory, it’s more like 128MB more according to statistics I’ve seen on memory use for 64-bit Ubuntu.

I am extremely RAM-hungry. I eat it like candy.

Setting Up The New Server

Friday evening I signed up for Linode. I had an Ubuntu 9.04 VPS up and running in 10 minutes. There was nothing to do for basic configuration — network, DNS, ssh, it was all good out of the box. It was a naked server with pretty much nothing on it (not even a web server), but that was exactly what I wanted since I was going to configure the machine from scratch.

Knowing what a memory hog the Apache web server is, I went something faster and more lightweight — nginx (“Engine X”). Nginx isn’t very well-documented if you don’t speak Russian, so I had to spend some time trolling blogs and forums to get the info needed to set up PHP and FastCGI and a few dozen virtual hosts.

This is also the first time I’ve tried using Drupal multi-site. It’s been such a hassle updating Drupal modules on every site each time there’s an update or security fix, so I wanted to use one core codebase. It was far easier to set up than I had ever imagined (just add a separate directory in your sites folder for each domain).

I had to install a boatload of modules, move a ton of content, set up scads of virtual host files, edit piles of configuration files, configure and export/import dozens of databases, and all of that other craziness involved with setting up a web server from scratch. This took part of Friday, all of Saturday, and half of Sunday.

In the process I also upgraded a few Drupal installs from v5 to v6. It’s not a very pretty process if you have complex custom views.

The most annoying part of the update was getting the nginx rewrite rule for WordPress set up so that the CSS file would actually load. For a few hours this site was just plain text on a white background.

I still have a few sites to move (the *big* ones) and a few kinks to work out, but I’m already pretty happy with the server — it is much more snappy and responsive, and I can edit sites faster thanks to quicker page loads.

If you’ve outgrown shared hosting and know Linux well, I recommend moving to Linode.

Skip “The Night Parade”

I just finished “The Night Parade” by Scott Ciencin. It’s book #4 in The Harpers series. I liked the first three quite a bit, but this one just wasn’t all that great — characters were too one-dimensional, plot devices too ham-handed, and all in all it just wasn’t very good. It also had too much of a “dingos ate my baby” feel to it.

Accepted Into Microsoft BizSpark

Microsoft has this neat little program, BizSpark, that gives a company free access to pretty much all of their products for three years for a total of $100.  The idea is that if they can get startups hooked on Microsoft operating systems, databases, and development tools, then if the companies are still alive after three years they’ll become thriving, paying customers.

Seems like a smart idea to me.  After all, startups generally have to be run “on the cheap”, so most of them turn to Linux and open source solutions.  BizSpark is keeping Microsoft competitive, helping out startups, and is an all-around good thing.

So, my company, Zeta Centauri, Inc., was just accepted into the BizSpark program and I now have access to all these neat development tools, including Visual Studio 2008 Team Suite (which is $10k retail).  It’s still downloading, but I’m sure I’ll have to post about some of the bells and whistles that come with it.  I’ve never worked with anything above Visual Studio Professional.   With any luck these new and shiny tools will help me build something awesome.

A New Laptop

I’ve been meaning to get a laptop for a while.  One might say that I don’t need another laptop.  After all, I do have five already.

Of course, all five of these have bad hard drives.  The newest one is seven years old.  One has a blown motherboard.  One lacks a power supply.  One has a dead keyboard.

So maybe it’s time for a new one.

Newegg.com had a sale on one I couldn’t resist — a Gateway T-6345U Pentium T3400 2.16GHz dual core system with 2GB of RAM and 250 GB hard drive for $399 (normally $549).  Since it’s pretty much the same spec as an $800 machine I was considering, it was a no-brainer.  I’ve always thought you had to have no brains to buy Gateway, so in this case it was a done deal.

Believe it or not, the hardware doesn’t actually suck.  You get a lot for 400 bucks.

It shipped with Vista Home Premium.  Resizing the partition to make room for Ubuntu Linux was a bit of a pain — I couldn’t squeeze more than 110GB out of the Vista partiton in the resize, and that was with page files and snapshots turned off and a good solid defrag.  And, of course, after all that ridiculous junk that gets bundled with a new PC was removed.  Why do they even try to sell people Earthlink dialup?

After trying to install Ubuntu 8.04 and totally botching the partition job (it boots, but can’t login because home directories can’t exist — Whoops!), I’ve thrown in the towel on 8.04 and will be installing 9.04 after it finishes downloading (at a blazing 25kb a second — why do I have this 4 meg high-speed connection again?)

Eventually I’ll have the sucker set up for dual booting Vista and Ubuntu and not long after that, set up for developing Basternae 3 and all of the other web miscellany that I’ve been working on (Django, ASP.NET MVC, etc.)

Studying For The 70-503 Exam

On to the next one… this time it’s the .NET Framework 3.5 Windows Communication Foundation exam. The study guide for this one seems pretty dry and repetitive so far.

It might just be that I have less experience with WCF than I did with the other exam subjects, but so far this one is requiring a serious act of willpower to stay focused on reading.

I doubt I’ll be able to continue my one-exam-every-two-weeks pace, but we’ll see…

Passed The 70-561

I took and passed the Microsoft 70-561 exam today and how have the “MCTS: .NET Framework 3.5 ADO.NET Applications” certification.

This exam was incredibly hard, and I didn’t obliterate like I did to the previous two.  A score of 700 was required to pass and I picked up a 768.

The study book for the ADO exam wasn’t really all that good — it was far too sparse and left out too much information.  It was only about 450 pages or so and should have been around 700 to really cover the material.

The Harpers

Believe it or not, before this year I had never read any of the novels in the Forgotten Realms series. I had always been more of a fan of Dragonlance.

Lately I’ve started reading The Harpers series. I started because I read and enjoyed the Dark Sun novels by Troy Denning. Since he wrote the first book in the Harpers series, I decided to give them a try. So far I’m up to the third book, Red Magic, and I’m pretty sure I’m going to eventually end up finishing the whole series.

Of course, I know it’s a gateway drug. Before long I’ll be reading all of RA Salvatore.

Random Character Name Generator

I wrote a random character name generator in Python today. It’s HERE at Xangis.com.

The system used is:
1. Roll a d6. 1-3 = consonant (1d20). 4-5 = vowel (1d6 with ‘y’ counting as a vowel), 6 = end name.
2. Names must be at least 3 characters long, ignore a roll of 6 if the name is too short.
3. If you get three consonants in a row, end the name.

I used to use that method to generate horrible character names for AD&D a decade and a half ago.

Zone Data Encapsulation Complete

Zone data encapsulation is complete now.  It was a long, tedious process, but it’s all for the greater good.

Last time the code was Fx-Copped, It ran 778,249 checks and found 10,850 issues.  This time, it ran 865,441 checks and found 10,370 issues.  It’s an improvement, but not a huge one.

We now have the power to enforce sanity.  For instance, when an object’s condition is set, we cap it at a max of 100% (perfect) and a minimum of 0% (destroyed).