WarLight as a candidate to the Google AI Challenge

There has been some talk of WarLight being a candidate for the next Google AI Challenge. For those not familiar with the Google AI Challenge, the GAIC is a competition where software engineers write a bot to play a game for them. They then upload their bot into the GAIC website which matches their AI against everyone else’s. It’s a lot of fun – they’ve featured other popular games such as Galcon and the Tron game, which is a bit like the old snake games.

To prepare for WarLight as a candidate, I threw together a prototype of a framework that can run a WarLight AI Challenge. This contains everything you need to write and run a WarLight AI on your own computer, completely separate from the WarLight servers.

I appreciate any feedback on this prototype – shoot me an email at fizzer@warlight.net!

Game Settings

WarLight is a very flexible engine that supports many different variations and settings. For this prototype, I selected settings that I think would make for a good AI challenge. I chose these settings both to make the game as fair as possible, as well as making it as easy as possible to write an AI.

Map

I chose the Double Earth map for this prototype, since it’s symmetrical and therefore can be completely fair to both parties. For the initial territory layout, I pick three random territories from the top earth and give these to one AI, and give the same three from the lower world to the other AI. The rest of the territories start out as neutral 2s.

Most strategic WarLight games let players choose where they start. This is entirely plausible for the AI Challenge as well, however I decided that a random (but mirroed) approach was better simply because it makes it easier to write an AI. Having to write code to determine where to start is a fun AI challenge itself, but doing this adds more syntax to the AI language and is just one more thing you need to learn and write before you can have a working AI. If the GAIC sponsors want this turned back on it can be.

Cards

For those unfamiliar, WarLight contains a dozen different types of cards that have a variety of effects on the game. I decided for the AI Challenge that cards should be left out, mostly because they add more syntax to the AI language and, like above, increase the base knowledge you need to learn to write an AI.

Fog

Fog is the WarLight feature that controls whether or not you can see the entire map or just what’s next to you. Whether or not to include fog in an AI challenge is an interesting decision that I thought a lot about. Ultimately I decided to turn it on, since it’s a feature unlike things that the GAIC has done before. If you’d like to try it without fog, you can turn it off in the downloaded source on line 34 that says “useFog: true”

Randomness

WarLight’s rules do contain some randomness, which enhances the game experience for human players. However, for an AI challenge, it may be beneficial to remove the use of the random number generator. There are four places that Warlight uses the RNG: distribution, combat, rounding, and move order. Two of these have already been removed from the prototype, and the other two could also be eliminated if we wanted to get rid of the RNG completely.

– Distribution: As mentioned above, bots don’t get to choose where they start so the normal randomness that affects strategic 1 v 1 games during distribution has already been removed for this AI challenge.

– Combat: WarLight’s main combat rules contain some use of the RNG. WarLight already contains a slider that allows you to control how much you want the RNG to affect your game. For the AI challenge, I have set this slider to 0, which eliminates this use of the RNG. If you want to turn it back on, you can do so in the downloaded source on line 33 that says “luckModifier: 0”

– Rounding: WarLight uses random rounding, where 0.4 has a 40% chance of being rounded up and a 60% chance of being rounded down. This is left turned on in the prototype, however if the GAIC sponsors wish, we could change this to a straight round to eliminate this use of the RNG.

– Move order: WarLight randomizes the order that players move within a turn. Although this does have an effect on the game, it’s typically not the deciding factor. Nevertheless, if the GAIC sponsors wish, we can change this to order based on a predictable heuristic, such as alternating turns or giving first move to the player with fewer armies or something like this.

How to Write an AI

For those unfamiliar with GAIC, this prototype uses standard in/out to communicate with bots. This means you can write your bot in any language that can print to and read from the console. The fastest way to get started is to take a look at the C# starter pack included in the downloadable below as it contains a fully functional (although not incredibly smart) AI.

At Startup: The Map

WarLight maps are obviously a graph. When your AI is started, the first thing it will do is read the map from standard-in. The first line is simply the word “Map” informing you that a map is coming up.

After that, your AI will read a series of lines starting with TerritoryDefinition. For example:

TerritoryDefinition 1 SolomonIslandsN 48 8
TerritoryDefinition 2 St.PetersburgN 87 4 11 110 111 104
TerritoryDefinition 3 PeruN 125 96 147 64
TerritoryDefinition 4 PermN 110 92 2 87 70
TerritoryDefinition 5 MyanmarN 26 29 49 119
TerritoryDefinition 6 PanamaN 147 25
TerritoryDefinition 7 ShanghaiN 50 26 151 114

Territory definition arguments:
– Argument 0: The word TerritoryDefinition
– Argument 1: The ID of this territory
– Argument 2: The name of the territory with spaces stripped out. This is not used by your AI, but it assists in debugging as knowing the name of the territory makes it easier to locate on a map.
– Argument 3+: The IDs of the territories that this territory connects to.

After reading territories, your AI will be fed a series of lines starting with BonusDefinition. For example:

BonusDefinition 5 CentralRussiaN 83 45 120 105 75 137 150
BonusDefinition 4 AustraliaN 27 122 14 135 134 12 91 15
BonusDefinition 6 EastRussiaN 136 115 66 18 46 103 65 129 72 149
BonusDefinition 6 EuropeN 54 51 109 34 10 80 11 101 95
BonusDefinition 4 MiddleEastN 138 52 21 53 43 19

Bonus definition arguments:
– Argument 0: The word BonusDefinition
– Argument 1: The number of armies this bonus is worth if you control all of its territories
– Argument 2: The name of the bonus. This is not used by your AI, but it assists in debugging as knowing the name of the bonus makes it easier to locate on a map.
– Argument 3+: The IDs of the territories that make up this bonus.

After the bonuses, your AI will be fed a line that says “EndMap” and nothing else. This notifies you to stop reading the map and to get ready to start the first turn of the game.

Each Turn: The Standing

In your main game loop, first read a line that will say either “GameOver” or “Turn #” where # is the turn number. Upon reading GameOver, you should obviously exit your process.

If you don’t see GameOver, you should start receiving a game “standing.” A standing is the state of the board at one point in time – it tells you who controls each territory and how many armies on are on it.

Territory 198 ownedBy Neutral withArmies 1
Territory 199 ownedBy Neutral withArmies 2
Territory 200 ownedBy You withArmies 5
Territory 209 ownedBy Neutral withArmies 2
Territory 214 ownedBy You withArmies 5

Territory arguments:
– Argument 0: The word “Territory”
– Argument 1: The territory ID
– Argument 2: The word “ownedBy”
– Argument 3: Either “You”, “Neutral” or “Opponent”
– Argument 4: The word “withArmies”
– Argument 5: The number of armies on this territory

Keep reading territories until you read the word “EndStanding” alone on a line.

Each Turn: Send Your Orders

After reading the standing, it’s time to execute your custom AI logic! As we’ve removed cards, the only thing your AI needs to issue are Deploy orders and AttackTransfer orders, which is what can order armies to attack or transfer from one territory to an adjacent one.

You should print out orders to standard out like this:

Deploy 4 on 5
Deploy 1 on 112
AttackTransfer 4 from 5 to 29
AttackTransfer 3 from 5 to 119
AttackTransfer 8 from 26 to 119
end

Deploy arguments:
– Argument 0: The word “Deploy”
– Argument 1: The number of armies you’re deploying
– Argument 2: The word “on”
– Argument 3: The territory ID you’re deploying on

AttackTransfer arguments:
– Argument 0: The word “AttackTransfer”
– Argument 1: The number of armies to attack or transfer
– Argument 2: The word “from”
– Argument 3: The territory ID to attack or transfer from
– Argument 4: The word “to”
– Argument 5: The territory ID to attack or transfer to

Finally, after issuing all of your orders, simply print out “end” to signal that you’re done. That’s all there is to it!

How to run your AI

The downloadable below contains an executable named WarLightAIChallenge.exe. Simply run this with two arguments that point at the bots you wish to execute. For example, to have the included starter pack fight itself on Windows, run: (note: Windows users must have .net 4.0 installed)

WarLightAIChallenge.exe StarterPack.exe StarerPack.exe

On OSX or Linux, run it in Mono 2.8 or higher:

mono WarLightAIChallenge.exe StarterPack.exe StarerPack.exe

Visualizer

For this prototype, I have not yet written a visualizer. This means that there’s no provided app that lets you view your game data in a graphical format to easily see what’s going on. If anyone writes one and is willing to share, send me an e-mail and I’ll post it here.

Downloads

Download Here

This package contains:
– StarterPack source code
– StarterPack pre-compiled binary
– AI runner source code (named WarLightAIChallenge)
– AI runner pre-compiled binary (named WarLightAIChallenge.exe)

If you run into any problems or have any comments, please send me an email at fizzer@warlight.net.

Create WarLight Games Programmatically

WarLight now supports the ability to create multi-player games programmatically via an API. This opens up a wealth of new possibilities for application writers, such as creating custom WarLight tournaments or ladders.

Of course, it’s always been possible to create custom tournaments or ladders manually, but this API allows you to write a system that will automate this process. This blog post describes how to write an automated system like this.

Invite Tokens

To invite players to a game via the API, you must get each participating player’s invite token or e-mail address. It’s preferable to use invite tokens over e-mail addresses, since players may be reluctant to share their e-mail addresses. However, inviting by e-mail address is provided as an option for situations where you know everyone’s e-mail, such as setting up a tournament with friends or co-workers.

Players can get their invite token by visiting this url: http://warlight.net/InviteToken.aspx. Incidentally, this is the same number as what’s displayed in the address bar when looking at a player’s profile. So it’s easy to get someone’s invite token from a forum post, if you’re handling adding players to your system manually.

After getting a player’s invite token, you can pass it to the ValidateInviteToken API. This API tells you whether an invite token is valid, which ensures you that you will be able to invite them to a game. Calling VaidateInviteToken is not strictly necessary to invite players to a game, however it’s handy if you want to know up-front whether or not it’s valid rather than waiting for the game creation to fail later.

You can call ValidateInviteToken with a URL like this: http://warlight.net/API/ValidateInviteToken.aspx?Token=[token].

Creating the Games

Once you’ve got all your invite tokens, you can divide them up into games according to whatever logic you’re trying to achieve. To create a game, call the CreateGame API. You can specify the game settings, game name, boot times, and the players you’re inviting.

When calling http://warlight.net/API/CreateGame.aspx, you should POST xml that contains the details about the game you’re creating. Here’s an example:

 <createGame>
	<hostEmail>your@email.com</hostEmail>
	<hostPassword>yourPassword</hostPassword>
	<templateID>1234</templateID>
	<gameName>Game name here (max 50 chars)</gameName>
	<personalMessage>Description to include with the game.
                   (Max 1024 characters)</personalMessage>
	<realTime>false</realTime>
	<voteBootTimeInMinutes>Never</voteBootTimeInMinutes>
	<directBootTimeInMinutes>2880</directBootTimeInMinutes>
	<autoBootTimeInMinutes>4320</autoBootTimeInMinutes>
	<practiceGame>false</practiceGame>
	
	<invite>
		<player token="player1@email.com" team="None" />
		<player token="player2@email.com" team="None" />
		<player token="123456789" team="None" />
		<player token="player4@email.com" team="None" />
	</invite>
 </createGame>
 
  • hostEmail / hostPassword: These elements identify you. The game will be recorded as created by you.
  • templateID: Specifies the ID of a template that you create through the normal game GUI. You can either use a built-in template or you can create your own. It does not matter if you create it as a single-player or multi-player template.
  • gameName: This will show up as the name of the game. Maximum 50 characters.
  • personalMessage: This will show up in the Lobby as well as the Settings. Maximum 1024 characters.
  • realTime: True for real-time game, false for a multi-day game. This is typically false.
  • voteBootTimeInMinutes / directBootTimeInMinutes / autoBootTimeInMinutes: These define the boot times for the game. 2880 is 2 days, 4320 is 3 days.
  • practiceGame: True for a practice game, false for a ranked game.
  • invite: This node defines the players that will be invited. It consists of ‘player’ elements, each of which contains a ‘token’ attribute and a ‘team’ attribute:
    • player team: This can be the string ‘None’ if you’re not creating a team game. If you are creating a team game, then supply a number for each player identifying the team that they’re on. 0 is team A, 1 is team B, 2 is team C, etc.
    • player token: The token covered in the previous section.
    • slot: If you’re making a game that uses a custom scenario, you must provide a “slot” attribute on each player that let’s WarLight know what scenario to give this player. This should be an integer, where 0 is slot A, 1 is slot B, 2 is slot C, etc.

Check for Finished Games

If your call to CreateGame is successful, it will return you a game ID. Store this number for future reference, along with a flag indicating that the game is not finished.

Periodically, (say, every few hours), you should scan all unfinished games and query http://warlight.net/API/GameFeed.aspx for each one. If the game is still in-progress, this API will tell you so. If the game is finished, you can parse the results of this API to determine who won and update your own database accordingly and create new games if necessary.

Member Requirement

All of these APIs are only callable by members, and the CreateGame API can only invite members to games. I realize the latter requirement is a bit restrictive, but since the ladder is one of the biggest draws of becoming a WarLight member, there needs to be a restriction that prevents a third-party ladder from offering this benefit to non-members. This restriction may loosen up over time – it’s much easier to loosen up on these kinds of things than it is to tighten them. Tightening them breaks existing code, whereas loosening them just pleases people.

Reference

For a full reference that contains a few more details on how to use these APIs, please see the API Reference page. If you have any questions, feel free to e-mail me!

Game Data Feed

WarLight can now provide an xml feed of data about a specific game. This allows for the more technical users to write a program that can analyze information about games.

This initial release of the feed should be considered an “alpha” experimental project. If this proves useful, it can be expanded to include more information. Currently, the feed is only available for finished ladder and tournament games and is only available for WarLight members.

Being able to consume this data via an API allows for broader analysis of many games at once, which can answer questions such as:

– How often does a player know one or more of an opponent’s picks?
– How often does the person who definitively knows his opponents starting spots win?
– Does early 3v2 luck affect winning percentage?
– Does getting first pick affect winning percentage?
– Does first move affect winning percentage?

There’s nothing the feed can see that isn’t already available through the game’s normal interface. This is just a way to write custom analyzers which allows for a broader analysis across games.

To access the data, use a URL like this:
http://warlight.net/GameFeed.aspx?GameID=1212978

This will present you with a large XML blob describing everything about the game. To help understand the data, let’s first define some terminology:

– A “standing” is the state of the board at any given point in time. This contains one entry per territory that contains the number of armies on that territory, who controls it, and the fog level.
– A “turn” is just a collection of orders. This includes all the orders each player submitted, mixed together in the sequence they played out.
– An “order” is obviously one order that a player submitted. But it can also include other things, such notifications when a player gets eliminated, or when cards are received, etc. Essentially, this represents what you see in the “Orders” panel on the right side of a game when viewing history.

In the xml blob, you’ll find:

– The players in the game (their names, color, their state, etc.)
– All of the details of the map (it’s name, all of its territories and what they connect to, all of its bonuses and what territories are in each bonus)
– The “distribution standing”: This is what the map looked like when it was time to pick the territories you started with. This is only present for manual distribution games.
– The picks: This tells you which territories each player picked, and in what order. Like the distribution standing, this is only present for manual distribution games.
– Standing 0: This tells you what the map looked like at the beginning of the game.
– Turn 0: This is all of the orders that played out on the first turn of the game.
– Standing x/turn x: Standings and turns then alternate for each turn of the game, all the way until the final standing.

If there is something you’d like to see included that isn’t currently included, I’d like to hear about it.

Why WarLight switched from Silverlight to Flash

The old-timers all remember back when WarLight was a pure Silverlight site. The original post explaining why the change was made is buried in an old forum post, so I figured I would document the switch here.

History

I first started writing WarLight with the Silverlight 1.1 Alpha. At the time I was just playing around with Silverlight to see what it was; I had no idea WarLight would balloon into something as big as it has. I liked what I saw in Silverlight, as it was quick, efficient and allowed me to easily share C# code between the client and server. This allowed me to get a prototype up and running quickly.

WarLight launched using the Silverlight 2.0 beta, and migrated to 2.0 RTM on launch day and then to 3.0 RTM shortly after it launched. Sadly, this is the last version of Silverlight that WarLight would ever see.

The Switch

Fast forward to September 2009. I had just finished adding the Single-Player mode to WarLight, and had decided that I enjoyed working on WarLight and wanted to continue with it. Silverlight was, unfortunately, the biggest thing holding WarLight back. Silverlight’s marketshare was less than 50% according to riastats.com, meaning that most players coming to WarLight were faced with an install prompt. Admittedly, Silverlight’s install rate rose very quickly – much more quickly than I expected. Getting to almost 50% in such a short time is unprecedented in terms of browser plug-ins.

Asking users to install a plug-in to use a website is a huge barrier to entry, and is unacceptable to me. Many users want to play from work/university/library computers where they don’t have Administrator access and can’t install anything. Many users also just don’t want to install things, which is understandable – my standard procedure is to immediately close the tab when a site wants me to install QuickTime, Java or Unity. (I have nothing against Unity, it just always crashes during install on my main PC for some reason.) And yes, I know Flash is a plug-in too. However, Flash’s 98% marketshare means that for the vast majority of users, no install is required.

The bottom line is that Flash is the de-facto standard for web-based games. Silverlight has definite potential as it’s more developer friendly and, in my experience, performs better. But Silverlight is new and I’m not willing to wait for its marketshare to be comparable to Flash’s.

I often get asked why I didn’t port it to a HTML/Javascript solution using HTML5’s canvas. That’s easy – canvas’s marketshare was far less than Silverlight’s (probably less than 10%), which is a big step in the wrong direction. At some point in the future I’d love to do this, but 2009 was certainly not the time.

Comparison of Flash and Silverlight

Both Flash and Silverlight have their advantages and disadvantages. Writing the same application in both has given me a good appreciation of the differences between them, at least as it compares to WarLight’s specific requirements.

This section specifically compares Silverlight 3.0 with Adobe Flex 4.0 running in Flash 10. Flex is required for an adequate comparison, as Silverlight has things like buttons, checkboxes, sliders, and a layout system built in. To get these things in the Flash world, Adobe provides Flex which is a layer on top of Flash.

  • Layout: Comparing the flexibility of the layout systems, I prefer Silverlight’s. Silverlight’s objects fill to their parent by default, whereas Flex requires you to put width/height=100% all over the place. Although, being able to say width=50% in Flex is nice, which takes more typing to do in Silverlight. Flex’s VGroup/HGroup only let you set an alignment for the entire container, whereas Silverlight’s StackPanel lets you set the align for each object in the container.
    Winner: Silverlight.

  • Mxml vs Xaml: Silverlight uses Xaml to design its UI whereas Flex uses Mxml.
    Mxml is nice since you can put event handling code right into the mxml file, but Xaml’s attached properties are a thing of beauty, since they avoid Flex’s problem of having a ton of unusable properties on every object.
    Mxml has hacks like a “width” attribute that sets either the “width” or “percentWidth” properties depending on whether or not you include a %. This is lame, as it’s unintuitive as soon as you try to set it via code.
    Some of the Mxml properties are considered “styles” which mean you can’t set them via a normal property assignment. You need to use the setStyle() method, which is unintuitive since they look just like properties. Silverlight has a similar issue with attached properties, requiring you to use SetValue(), but at least you can easily see in the Xaml which properties require this.
    Visual Studio was always slow to open Xaml files for me, sometimes over 10 seconds. I don’t use the designer, I had them always set to open as text, but I suspect some designer-related components were loading anyway that I couldn’t figure out how to turn off. Endless frustration!
    Xaml is just serialized .net objects, which makes everything intuitive and easy. You can import/export Xaml yourself very easily with XamlReader and XamlWriter, and you can even load Xaml at runtime. Mxml is statically compiled, and can’t be loaded at runtime.
    Winner: Silverlight. Xaml is just a well-designed markup language.

  • Language: Flash uses ActionScript, Silverlight allows (almsot) any .net language but most people use C#. This is one of Flash’s weak areas, as ActionScript has decades of baggage that make it a frustrating coding experience. Although it’s clear that Adobe is trying, as they do support closures, first-class functions and garbage collection. However, the inability to share code between the client and other languages give this one to Silverlight easily.
    Winner: Silverlight by a landslide.

  • Component Customization: Silverlight allows any object to contain any object. For example, you can easily put a list box inside of a button (not that you’d want to…). Flex is a more traditional UI layout system, which tries to cover the most common scenarios but ultimately leaves holes. You can still do more powerful things using skinning, but it’s a lot more cumbersome. I recall having to copy+paste over 100 lines of mxml just to have a button with two lines of text. Sad!
    Winner: Silverlight.

  • Automated Testing: Both Flex and Silverlight have poor automated testing tools. I used the Silverlight Unit Test framework and was able to get it working successfully, but for testing an asynchronous app like WarLight, you have to do all sorts of crazy lambdas and callbacks just for basic operations. This makes maintaining state and looping within a test difficult, and also requires that you run your test code on the UI thread.
    With Flex, I used Selenium with a Flex plugin and it avoids the problem above, but required I write a bunch of plumbing code to give myself strong binding between my app’s UI and the test code.
    Winner: Only losers here.

  • Error Reporting: Silverlight has a global error handler that gives you the exception object which includes details of the error, and a stack trace, even in retail builds of Silverlight.
    The retail version of Flash eats all errors. This is a problem for me, as being able to fix errors quickly is important to me. Flash required me to do a bunch of extra work in this area. Every entry point must do a try/catch in order to handle and report errors gracefully. What a pain!
    Even then, you have no stack traces in retail builds. Without stack traces, you often get back an error where the extent of the message is “1009.” 1009 is the Flash code for a null reference exception, but just knowing you have a null reference exception somewhere in your app is not enough to fix the problem. You can put an identifier on each error handler so you at least know the entry point, but that wasn’t enough for me.
    So I wrote a routine that would track stack traces myself. I wrote some rudimentary ActionScript parsing code that injects a PushStackTrace() call to the start of every function, and a PopStackTrace() at the end. Using this, I can track the stack trace all of the time, and when an error occurs I include it in the error report. This has been wonderfully useful, but it took a lot of work just to get back to what Silverlight does for free.
    Flex 10.1 added a global error handler, but you still don’t get stack traces even in 10.1, so it doesn’t solve the issue.
    Winner: Silverlight by a landslide.

  • Performance: Although I haven’t taken measurements, there was clearly a noticeable and significant drop in performance after migrating to Flex. I believe this is specifically attributed to Flex, not Flash. The speed of constructing bunch of Flex objects (order details) and placing them into a scrollable panel (the orders list) made scrolling through the history of a WarLight game much slower than it was in Silverlight.
    Winner: Silverlight.

  • Adoption: Covered above.
    Winner: Flash by a landslide.

  • Bugs: I ran into bugs on both platforms. I’ve reported a few back to Microsoft and Adobe, but overall I wouldn’t say that either platform is more or less buggy than the other.
    Winner: Wash.

  • Overall Winner: Flash! Flash is of course the winner, as WarLight uses Flash today. I’m not particularly tied to the Flash platform, and I’d be happy to move to something new in the future if the move makes sense.

Current Game/Tournament Tabs

Beta Phase 21 is still a ways away, so don’t get your hopes up. But I wanted to share one change I made tonight since it’s on the top of my mind now.

Under the multi-player tab, there are these two pesky tabs named “Current Game” and “Current Tournament”. I’ve never been happy with them.

Current Tabs

There are several things I don’t like about them:

1. They don’t show up until you first visit a game or tournament. Typically tabs don’t dynamically appear, so this is probably a bit jarring when it’s noticed. (Although I bet most people don’t notice.)

2. Their names are not descriptive. Sure, Current Game makes sense when you’re looking at a game and you see the tab is highlighted. But when you’re on a different tab, seeing a tab named Current Game doesn’t make any sense. Long-time players will remember that this tab used to be called “Last Game”. This has the opposite problem – it makes sense to go to the last game you played, but if you’re looking at a game, why is Last Game highlighted? At one point I considered dynamically renaming it, but I decided against it in fear it would be even more jarring.

3. All of these tabs take up extra horizontal space. With both Current tabs, the Sound link, and the Design Maps tab (which only shows up if you’re a WarLight map creator), you need a browser 1144 pixels wide to see everything! This provides a poor experience for those in low resolutions. It’s important to remember that 1024×768 is still a very popular resolution. But it’s not really as bleak as it sounds, since most players won’t have the Design Maps tab or be in tournaments.

The horizontal space issue is fine as long as I don’t need to add a new tab here. But a feature I’m working on for Phase 21 calls for a new tab. Uh oh. Adding more would make it far too wide. Something’s got to go.

I thought a lot about how I could save space here. I could move Create Game to be a button instead of a tab (that would make it more in-line with tournaments, which is a plus). I could move Design Maps somewhere else (it doesn’t really make sense to be under multi-player anyway). I could abbreviate “Tournaments” (why must that word be so long?). I could squish everything together. All of these solutions have their own unique problems.

But ultimately I just kept coming back to the “Current” tabs – they’re taking up almost 40% of the space on that tab bar, and I’ve never been happy with them for the reasons cited above.

I thought about getting rid of them completely since they’re not strictly necessary to play. However, they are useful in a few situations. The time I use them the most often is when checking out a bunch of games in a tournament. The “Current Tournament” makes it easy to switch back and forth.

So maybe keep “Current Tournament” but ditch “Current Game”? It’s not as needed, but I still fear is that people have grown accustomed to using Current Game. I know I have. As a species, we suck at changing our habits, so I’d like to keep both if possible.

In the end I decided to move these out and make them buttons instead of tabs:

Making them buttons instead of tabs may not seem like a profound change, but it actually has subtle advantages. These buttons can be hidden when their click would not make sense – both before you visit a game/tournament, or when you’re already looking at a game/tournament. Hiding tabs wouldn’t really work out since shifting all of the tabs around would be too jarring.

Further, since they can be hidden instead of “activating” when visiting a game/tournament, their text doesn’t suffer from issue #2 described above. This will make it clearer to new players exactly what this does, and how to use it.

Best of all, it frees up valuable space under the multi-player tab. Yes, this does create an even worse horizontal space issue on the top tab bar. However, that’s not nearly as bad in this case, since neither of these buttons are strictly needed to play the game. If we have to push something off, it’s much better to push off “Recall Last Tournament” than “Create Game” since the latter gets used far more often. Even in 1024×768, you can still see the “Recall Last Tournament” button enough to click on it. You may not be able to read the words, but it’s still functional and you can still tell what it does by reading the tooltip text.

While it’s not perfect, I’m happy with the change.

Technology behind WarLight

I often get asked what kind of technology was used to build WarLight. WarLight’s server components are written in C#, and the Flash client is written in haXe utilizing Adobe’s Flex 4 layer for layout / buttons / sliders / checkboxes / etc. All backend data is stored in a Postgresql database running on Ubuntu Linux, while the website is served from IIS 7.5 running on Windows Server 2008 R2, both hosted on virtual Rackspace Cloud Servers.

WarLight’s maps are originally uploaded in SVG format (as every map designer knows), but they’re immediately converted by the server into a custom map format built for WarLight. This format is optimized to be quickly loadable by Flash, which makes loading games much faster than if they tried to render out the SVG directly.

WarLight’s communication protocol is custom written, as well as its object serialization protocol. After all, WarLight was started as a for-fun hobby project, and re-inventing the wheel is fun!

I’m a big believer in automated testing, and I’ve worked to have thorough coverage for WarLight from the very beginning. Before every release, WarLight goes through an extensive automated test pass that takes several hours. The idea is that the tests cover as many possible use-cases as possible. Any time a new bug is found in WarLight, I add a new test to cover it and this ensures the issue never comes up again.

Some of these tests use the Selenium web-testing framework to actually automate the browser and the Flash client. Here’s a short sample of what some of these tests look like when they’re running:

Having the WarLight testing being automated is essential. Due to the vast number of settings (and permutations of those settings) that WarLight games can have, it would be nearly impossible for me to do big changes or to refactor code and still be able to release WarLight with confidence that the game will still work. However, with the tests I can simply run them all and get a level of confidence that all of the features work. The tradeoff is that this makes each feature more time-consuming to add, since I not only have to write the feature but I also have to think up and write all of the tests that ensure the feature works.