Saturday, April 6, 2013

Let's Code - CPM2DoB Part 4: WHAM!

That, my friends, is the sound of running head-first into the solid brick wall of poor code structure.

I just wanted to let you know that yes, this project is still alive. As Easter loomed, I had a major project due at work that kept me from working on it much, and The Murloc also had a thing happening that required I look after the boys at home. All in all, not much time was to be had for coding.

But I did get it working and playable! (Barely.)

So back to the aforementioned skull-shattering, neck-breaking, spine-telescoping, head-on collision. I was probably about an hour away from a playable build of the game, just putting the finishing touches on the methods that handled pieces movement, damage, captures, transformation, and victory checks, when I discovered a fatal flaw in my code organization. It was caused mainly due to laziness and not thinking ahead, but resulted in a flaming crash.

(The specifics were that I was writing the piece transformation method, y'know to allow a pawn to turn into a queen. Unfortunately, the master list of the different piece types (or "masterPieces" as it's known in the code), was not visible in scope to the transformation algorithm. I could have patched it by awkwardly passing the list as a parameter through the several layers of function calls necessary to get it where it was needed, but that would have been an awkward kludge on what was already a very kludgy mess. The alternative was to move the master piece list to the class where it was needed. But that required one change, which required a restructuring over here, which meant these other methods wouldn't work and would need to be redesigned, which meant this part was now over-complicated and should be streamlined, etc., etc. All in all, what was looking to be an hour or so of coding turned into a week. On the plus side, the code was much better organized once I finished.)

So after struggling fuming, and fussing, I finally got a working build! You can move pieces! And capture! And it will even check for victory conditions! (Yay!)
Rememeber: victory is capture-based, not checkmate-based, since checkmate is impossible to determine for random damage and kings that can fight back after taking a few hits.
NYI: Auras.

Saving and Loading
Imagine Homestar saying it

I've always hated dealing with save files. Saving data is always a pain. You have to decide on a file format, worry about text parsing, data validation, etc, etc. It's always such an annoyance.

This time around (this being an experimental project to teach me new things), I decided to investigate XML file formats. [That company I work for] has switched to XML formats for project files, so I'm becoming a bit more familiar with them. So I decided to read up on XML handling with C#. My reads through the MSDN library mentioned the newest feature, using the Systems.Xml.Linq namespace, as the new best way for XML parsing.

Here's how you write that  a class and its properties with Systems.Xml.Linq:
XElement El = new XElement("Class");
El.Add(new XElement("property1", class.property1));
El.Add(new XElement("property2", class.property2));
...
El.Save(filename);

Here's how you read that same data.
XElement El = XElement.Load(filename);
class.property1 = El.Element("property1");
class.property2 = El.Element("property2");
...
(Well, in reality, you'll need to convert El.Element to the appropriate data type, but that's simple.)

Oh, dear goodness, does this make it easy. It basically does all the text parsing for you. If it can't find something, it just returns a null value, and since in the latest version of C# strings are a nullable type, I don't have to worry about ifs and thens to determine if the data I'm looking for is in the file. This is critical during design, while I'm continually adding new features, which requires more input and output from save files. I don't want to rebuild the pieces and board configurations with each update, so if I read in an older save file, and some data is missing from the save file, it essentially is just assigned the default value. Also, the save file is easily human-readable and can be modified by hand if need be.

All in all, a much easier way to work.

Existential Crisis

A little earlier, before the code-scope crisis, I did run into another sort of fundamental-to-the-nature-of-the-project crisis, while trying to design an alternate piece set. I was giving the standard chess pieces health and armor and damage as I thought might be appropriate, when I stopped to think about what I was doing.

In chess, the whole strategy is about bring pieces to bear on a space, either to attack or defend a piece. The strategy revolves around the fact that when you capture a piece, your piece then become vulnerable, because it moves to the space you just attacked. So the game is about disincentivizing the other player from capturing your pieces by defending that piece. It's MAD. You kill me, I kill you.

But this changes, once you introduce the concept of hit points into the game. Suddenly, there is no cost to attacking. In normal chess, a queen might not capture a pawn because then she'd get taken by a knight. Even if you can take the knight with another piece, it's not worth losing a queen to get a pawn and knight. But in battle chess, the queen can attack the pawn and weaken it without exposing herself and without fear of retaliation. So where's the strategy? If you can just snipe at the enemy without risking yourself, it sorta takes out the fun.

But then, I thought, maybe that is the strategy: put yourself into a position where you can attack the enemies pieces without retaliation. And keep your pieces from being sniped without being able to return the attack. I think the strategy would be in the pieces armor and in if you can risk letting the enemy take a shot at you to get in good position to take a shot at him. In short, in concept it's a lot like regular chess.

I think this will be facilitated by the piece set I have in mind. My idea was that pawns should have very strong front armor, such that very few pieces, probably rooks and kings only, can take them from the front. So your wall of pawns is a mostly-impenetrable line. The weakness is in the flanks. This would make the strategy to outflank the other player's wall of pawns, to sneak around behind them, or find gaps that allow you to attack the pieces behind the pawns.

I haven't completely worked out the details, but I think it might be fun. We'll have to see. And I won't know for sure until I've built in some AI, so I have something to play against.

Speaking of coding nightmares that I'm not looking forward to....

2 comments:

  1. Okay, so, question from the peanut gallery which might be totally asinine, since most of this post was like, "blah blah chess blah blah something strategy" to me, being totally and completely code illiterate. (C#? Isn't that the key in which the Moonlight Sonata was written?) My question regards assigning hit points to pieces: could there be a version of the game in which you don't get to pick the strength of your opponent's pieces, and it's assigned randomly by the program? That way, you wouldn't KNOW exactly how much damage your attack would do. That could add a whole level of interestingness to the game.

    ReplyDelete
  2. There already is the ability for random damage. When defining a piece, you can define a minimum and maximum damage, and when calculating damage, the program randomly picks a value from that range.

    The health is set in stone, though. I suppose it could be random. It would also be interesting if you don't KNOW the health of the opponent pieces. Perhaps a tool-tip off mode, so you can't see the information on each piece's health and damage?

    ReplyDelete