Monday, March 30, 2009

WinWar II 5.0 Diplomacy

I've completed the Diplomacy system for WinWar II 5.0. Each Nation in the game has a Stance against each other Nation in the game, even Minor Powers to Minor Powers. Actions that occur in the game can impact the Stances of Nations toward one another. Stances can more directly be affected by executing a Diplomatic Action.

Each Major Power can take a Diplomatic Action when it's available. After an Action is taken, another Action isn't possible until an internal counter counts back down to zero. The length of time between Actions is determined by the last Action taken (some are more costly than others), the Political Strength of the Nation's Head of State, and a randomizer.

Below are the Diploamtic Actions available in WinWar II 5.0:

Conduct Summit - If successful the Stance of the target Nation is improved. There is a small chance that the Summit will backfire, reducing Stance. This chance is based roughly on the current Stance between the two Nations, the lower the Stance the greater that chance that the Summit will backfire. Note - if you raise the Stance of a Minor Power to 100, that Nation comes under your control!

Denounce - Available only to Nations that are not flagged as "Imperial". This reduces the Stance between your Nation and the target Nation, and also impact the Stances of other Nations friendly to you toward the Target. A non-Imperial Major Power can only attack another Nation when they are At War (Stance = -100) so Denounce will be an important the Allied Powers.

Declare War - Imperial Powers will have a Declare War Diplomatic Action instead of Denounce. An Imperial Power could Declare War automatically by just invading a Nation, but they might want to issue this Action if they want to attack an enemy navy without having to invade a Land Zone.

Exert Pressure - If the target Nation succumbs to the pressure, it comes under your control immediately. If not, the Stance between the two Nations suffers. The Action has a greater chance of success if forces are massed along the target's border.

Incite Coup - If successful, a new Government is formed in the target Nation, having a set of roughly opposing stances, with some randomization involved here.

Another nuance of the Diplomatic System: taking hostile Diplomatic Actions has the effect of making the target Nation's neighbors nervous, and reducing your Stance with them. Also, Diplomatic Stances are dynamic, and can shift during the game spontaneously, sometimes with interesting results. For example, in one game, early on, Spain spontaneously allied with the UK. That would surely shake up the strategies in the early phases of play!

A scolling ticker informs you of various events on the bottom of the screen, allowing you to keep up to date without providing too much of a distraction. Game event history is also available in a dedicated window if desired.

Friday, March 20, 2009

PrismServer Update

PrismServer is the TCP/IP server I developed to handle communication between players in my MultiPlayer games. The newest version is written in C# and offered as open-source. It features a set of components that abstract the client/server communication protocol and exposes it through simple properties, events and methods.

When I first switched from the Delphi programming language to C#, PrismServer was the first serious development effort I undertook. I always like to have a concrete project to work through when I learn a new language.

Looking back at my original effort, I discovered some flaws in my work that experience with C# helped me recognize now. These flaws manifested themselves as sporadic crashes in the server piece of the PrismServer package.

I have spent some time over the past few weeks nailing down and correcting these problems. The problems revolved mostly around multi-threading issues. I was not properly locking variables that could be access from different thread. The problems most frequently occurred when using a foreach loop, and then having the List<> that the loop was enumerating change by a call from another thread.

For example, when PrismServer is trying to send information to all of the players in a specific room, it uses a foreach to enumerate the players in the room. If a player entered or exited a room during this loop, PrismServer.exe would crash hard.

After identifying all of the appropriate places to put lock statements, another problem manifested. When a player would drop from the game, there would be noticable lag of about 30 seconds that stalled all traffic in the server. This sounded like a locking issue; i.e. one method waiting for a lock to be released that was set in another method.

Sure enough, I discovered that the method that writes information to the players' sockets was locking the list of connected Guests in that subject. When one of the players dropped, this caused a delay as the socket timed out, and the lock was still set until the socket timeout completed. This caused a bad cascade that eventually brought the whole server to its knees until the socket timeout completed.

I corrected this by creating a new thread to handle outgoing communication. When PrismServer wants to send something out on a socket, it now adds the string to a Queue. The outgoing thread examines this Queue and sends the strings it finds there out the client socket. The Queue is locked only long enough to get the next piece of information to be sent. This design allows the server to run smoothly even when clients are timing out.

After stress testing, I'm happy with the performance and stability of PrismServer, and look forward to seeing how long the new build can run before it needs to be restarted.

Below is the relevant section of code that resulted in the most bang for the buck improvement (from PrismNetworkStream.cs)

//This thread keeps executing and writing information to the client
private void WriteThreadExecute()
while (!_closed)
bool written = true;
while (written)
written = false;
string s = null;
lock (_outgoing)
if (_outgoing.Count > 0)
s = _outgoing.Dequeue();
if (s != null)
written = true;

Sunday, March 15, 2009

Solar Vengeance 5.1

This is the first entry in my new SCG Development Blog. I decided to finally switch to a standard blog to document my efforts in developing Silicon Commander Games. If you want to read the previous blog entries they can be found here ...

Today I released the beta version of Solar Vengeance 5.1. It includes some interesting new features that have never been seen in the SV line before:

DynamicEvents Programming Model

I re-organized how Dynamic Scenarios can be programmed for SV by creating an interface called IDynamicEvents. This interface contains a number of methods that you can call in a Scenario to cause dynamic behavior in the Scenario's ProcessImpulse method. The interface is exposed in the Scenario class via the DynamicEvents property.

This change is largely cosmetic from the previous "DS_Method" model of SV5, but I like the fact that the dynamic methods are now cleanly separated into their own interface.

UDOs - User-Defined Objects

Scenarios can now include UDOs that can represent anything you want in the game. You can assign a static or animated image to a UDO of any size, and you can control how they move via UDO related DynamicEvents methods. UDOs can also be "picked up" and carried by StarShips, making "capture the flag" style Scenarios easy to create.

SV5.1 includes a new Scenario, CollectTheScientists, that relies on UDOs. You have to find the Scientists that are scattered in the middle of a supernova remnant and bring them back to a safe zone next to your Capital.


Scenarios can now render directly to the game map during the animation cycle. The PaintHook methods pass you the .NET Graphics object that represents the map, and you are free to render to it to your heart's content.

Transport Order Overhauled

After much demand, the Transport order can now pick up Resources from any number of friendly StarSystems or BattleStations, and deposit them to any friendly StarSystem or BattleStation.

Download SV5.1 beta now and help me put these new features through their paces!