Replicator Tuesday Issue #47: Vassal Update for Space Empires

Replicator Tuesdays is an article series appearing on InsideGMT. It features insights into the development of the 2nd expansion for the board wargame Space Empires: 4x by Jim Krohn.  Here the designer, developer and play testers will share their thoughts and experiences on this upcoming expansion. Since there is much crossover between the Space Empires and Talon development teams, both Space Empires and Talon articles will be featured in this series.

Issue #47: Vassal Update for Space Empires

FINALLY FINISHED!

Module updated here

The original Vassal module for Space Empires 4x was made in 2011…almost 9 years ago. It was the product of a lot of work but also of several different people. By the time I was working on it some of the ground work was already in place, but many things had to be revamped. Then when SE: Close Encounters came out I had to tack on a number of new features. This led to a very bogged down Vassal module. The module was not only using a lot of unnecessary resources to load images that were outdated, but there were a lot of counters that didn’t need to exist that also took up memory and processing time for some actions.

Case in point, if you’ve used it, is how long it takes to load up and randomize the map. On top of that, sometimes the map randomizer would goof up and put 2 counters in one hex. Vassal was never really designed to be able to do some of the things I’ve made it do both in that module and the new v3.0 module—things like randomizing the map or automating the production sheets. But I’ve felt these features were both very necessary if you were going to play Space Empires on a computer.

Before Replicators was published, I began working on the revised v3.0 Vassal module. This was a complete rebuild of the module from the ground up. No framework from the original module was to be used. I wanted to start fresh to make sure things ran as optimally as possible. Over 3 years later the module is finally finished. This delay had way more to do with life getting in the way of Vassal development than the module itself, although I’ve still probably put a few hundred hours into it. It was really hard to work on if I couldn’t find 2-3 solid consecutive hours to work. Redesigning the map alone was probably 50% of the work for this. I developed something to manage board randomization that I don’t think any Vassal developer has done before (not to toot my own horn but I’m pretty happy with what I built). What I’d like to do here is first explain some of the new Vassal features for users. Then I’d like to walk through some of the development aspects for other Vassal developers—good resources for Vassal developers are hard to come by so I hope this post can help some folks out.

FEATURES

  • Automated Scenario Loading and Board Randomization
  • Automated Home World Setup
  • Automated Production Sheets
  • Automated Fleet Size calculating
  • Dynamic ship stats
  • Easier to implement Card Effects
  • Check for Cloaking/Decoy
  • Rename Planets and Flagships
  • Automated ship group enumeration
  • Capacity for Epic (double) and Galactic (quadruple) maps
  • Matching Warp Point finder
  • Performance improvements

You’ll find a quick start guide in the module itself that can explain many basic features to get you started. Here I’ll walk through some other changes for reference, but I probably ought to make a formal video/manual at some point.

Space Counters Menu Button

The original module has a pretty poor feature for loading scenarios. Now basic scenarios (not all of them yet) can be loaded from a drop down menu. By basic I mean things like the 2 player normal sized map or the 4 player map. I tried to pick the most common layouts first. The good thing about these maps is many other scenarios can be built from them. For instance, if you want to do a Galactic Capital based scenario, just put that marker in the center of the map after loading the 2 Player map. Same goes for many of the solo and co-op maps. This feature took the longest to build and I’ll discuss this more in the Vassal development section below. The map loader picks the player colors based on what is set in the Setup Options and Space Counters menu (menu button can be seen to the upper right of this paragraph). There you can change what color is loaded. This does mean you have to pick a color when you first create/join a game and also set which player is which here. So, if you are player 1 and want to be Red change player 1 to red here and the Player 1 counters will be loaded on (say) the 2 player map as red. The board loading time is also much better. Larger maps (like the 4 player galactic or 4 board map) takes around 2-3 minutes to load on an older laptop of mine but the regular sized maps all take less than 30 seconds. If you want to remove certain counter types from ever appearing in the mix of Deep Space Counters you can right click a stack, select them and remove them manually. However, most of the time, if say I don’t want to play with Warp Points, I’ll just remove them when I encounter them in the game.

Speaking of Warp points, I’ve worked in an optional feature where you can “blind” jump into a warp point. If you find WP1 and the other WP1 has not yet been revealed, and exists on the map, you can force it to be flipped as your ships jump into the unknown. This is the kind of optional rule that can’t really exist outside of a digital version of the game.

Your home world can be set up automatically by right clicking it after the map loads. This automatically brings in the proper number of SCs, SY and colony ships for most games. You can also toggle 20/30 cp mode for the HWs.

Facilities Button

Facilities can be toggled on/off through the top menu bar by clicking (button pictured to the left of this paragraph). This changes the Production Sheets to account for Facilities with RP for tech.

The production sheets are very different now. They are only one tab now with the Facility related stuff being hidden if not toggled on as above. Instead of clicking every cell in a given column to refresh and recalculate, the entire column is refreshed automatically by hitting the Refresh button at the top. This will only refresh the highlighted column. This means you must use the Turn Tracker to track Econ Phases. So if it is Econ 2, make sure to set the Turn Tracker to Econ 2 so the Production Sheet will refresh the correct column. Refreshing can take a moment (around 20 seconds on my laptop) and it is best to just wait until the button is no longer grayed out before doing anything else. The refresh logic is a lot better overall and won’t mess up Minerals like it did before. Maintenance calculations are smarter too and ships that pay half or no maintenance because of card effects or experience are calculated appropriately as long as you have set this up on the ship itself. Many ship counter stats are dynamic and can be adjusted on the counter itself. Pretty much every number on a ship counter is being handled in game now rather than being part of a separate art file. This is less burdensome on the computer in terms of loading all the images but also gives you more freedom as to automation and displaying stats on the counter.

Also on the production menu is the ability to automatically promote Green ships you own as well as grow colonies. Be sure to have your Colony Ships colonizes AFTER you hit the grow colony button or else they will accidentally become 3 CP colonies too soon. The Commit button logs your ship/tech purchases and locks in your techs. They are recorded in a separate log window. The Ship Buy window is a bit smaller and less unwieldy. Likewise the UN builder is revamped and doesn’t cause math problems that occurred in the previous version. MS Pipeline income can be automated by activating a flag on the MS pipeline ships if they are connected and should contribute CP. Tech Costs in the Production Sheet can actually be changed and can be selected for free (if by a Ship Wreck roll) by shift+clicking the tech level.

The previous version had a Ship Counter tray. This is gone. Now all units are placed through the Counters menu. When you drag a unit onto the Map it will automatically be assigned the correct Group Number. If you bring out too many of a given unit (say a 7th BC) it will throw an error letting you know this may be too many ships given the number of counters in the tabletop game. It will let you keep playing, however, as some of these restrictions may need to be lifted in very large games. Most ships actually can’t be deleted and are sent to your hand when destroyed. You can make changes to ship counters in your hand and redeploy the counter later.

Your hand window also includes buttons to easily draw cards.

The Fleet Menu is bigger and better with the ability to automatically send back/forth ships assigned to a given fleet. The Battle Board can automatically calculate ship counts for Fleet Size Bonus. The Bid Reveal button is on the main toolbar now and works better.

I know there are more things but these are the big changes.

Vassal Development

The Vassal community is great especially considering the breadth of games covered by this engine. The engine itself can leave you wanting sometimes, I mean its free so you can only complain so much, but automation is limited. Resources on how to get things to work right can also be somewhat limited. Sometimes, you may build something one way only to learn you’ve been taking advantage of a bug that eventually gets corrected.  I mostly want to discuss stuff I did here so that it can serve as a reference to other Vassal developers.

One problem I ran into was with the map. You’ll notice it looks much different. There were two reasons for this. One was I needed the map to tile better so that you could play with up to 4 adjacent boards (the tabletop map cannot do this without some kind of connecting piece). The other reason is I had to horizontally flip the map and all scenarios. For some reason the hex numbering scheme used by the tabletop map does not work in Vassal anymore (it did in the original module). So now row A is the top most row. This doesn’t impact play but made things trickier as I went.

The biggest change in the module is the way the board randomization works. Before I used dummy counters and had a system to swap actual randomized space counters from a deck object in Vassal to generate the map. This failed for a number of reasons. It was slow for one, but it also was prone to weird errors. The last and major problem was that I had to generate the scenarios as a separate file.

The way Vassal works, to maintain compatibility, is that all object properties are also saved to a file when you save a game or a pre-generated scenario (which is basically the same thing). This means if say I update something in the way SC counters work, only a new game made after the update will have that change. If you load an old game, even in the new version of the module, it will still show the older version of the SCs. This made it very difficult to push out module updates. In order to push out an update I had to re-make ALL of the pre-generated scenarios by hand.

To overcome this, I would have to make a system that randomizes the map in a programmatic fashion. In other words, I needed a way to program into Vassal instructions on how to build a map rather than building the map and saving it as a progenerated scenario file. This is actually very similar to what Stefano did for the Talon module. Space Empires just has WAY more counters.

To save instructions for a given map I was going to need a way to allocate information that could be iterated through. In most actual programming languages this would be through things like arrays or databases. That’s not so easy to do in Vassal. Like with the production sheets I had to find a way to trick it into automating something it shouldn’t normally do. To accomplish this, I used a feature in Vassal that could approximate FOR loops (to iterate) and TONS of global properties with a specialized naming scheme and zoning that could approximate arrays. Not to pat myself on the back but getting this to work was pretty major and I don’t think anybody else has done anything like this in Vassal.

This involved building several loops within an invisible counter that would oversee the whole thing, I called it GalaxyBuilder.

After resetting a few properties the meat of the script occurs in the loadScenRow Trigger property.

This script iterates through a set of Global Properties based on the scenario you picked. The properties tell it key information in what I called a scenario row—basically a row of consecutive counters of the same color. For example, it would tell the script to put Blue counters, randomly from the blue counter deck, on hexes A1-4. This worked because I used a ton of Global Properties, organized into Zones, to approximate typical programming arrays.

Here “s2P” means small 2 player map. Every 4 global properties is essentially 1 array. So gps2P00 tells you which player this is (i.e. player 1 and then the system looks to see what color it should be). gps2P01 tells you which row letter (i.e. A), gps2P02 tells you what is the starting column (i.e. 1) and gps2P03 tells you the ending column number. If you repeat this for every row of consecutive same colored counters, you can effectively program instructions for building the map into Vassal. Pretty neat?

This was still time consuming—more to get right than to set up and overall, but still LESS time that remaking ALL scenarios every time I made an update to the module. Now the module can be updated with relative ease which will be useful for not only fixing bugs but for future expansions.

A couple other things that were frustrating during Vassal development that took a lot of trial and error to fix was interacting with some of the global key commands in a way that could use Expressions (like finding counters that were of type “SC” for example).

I found that if you want a GKC to be triggered on a specific type/types of counters you had to use a different syntax if you were using one counter property to perform the match versus many properties:

Example:

send GKC to counter matching 1 property:

$$ vars work if it is the only prop to match.

To match multiple properties you can only use GLOBAL properties to perform the match:

Above I’m looking for counters that match a given PlayerSide (team color) which is a global property but if I wanted to match counters by using a property on a given counter it’d have to first pass that to a global property. For example if I wanted to do something on all Blue SCs I could build a GKC as above that targeted SC class ships that belonged to Blue. However, if I wanted to do this more dynamically (i.e. not hard code “BLUE SC” into the GKC) and instead of the counter you were clicking on pick the team based on what team it was, I would have to pass that counter’s team to a global property. So if you wanted, for whatever reason, your blue flagship to be able to send a command to all the SCs on your team, you’d have to first pass the Flagship’s team to a global property and then reference that in the GKC. It was this way that wound up saving me time programming wise because I didn’t have to hard code as much into each team. The original version’s production sheets had a LOT of hard coding where I had to manually type in “yellow” for every cell that was doing production in each player’s sheet. This time around I was, hopefully, smarter and now the production sheets are dynamically aware of which team they belong to. 

Also the target of the GKC must be BELOW MASK properties otherwise is inactive and won’t be read.

Some cool tricks I picked up also were that you can concatenate property names as part of a GetProperty lookup. This was extremely useful for the GalaxyBuilder.

So the above is how the pseudo-arrays were able to find the correct deck based on the selected player color and information in the array.

For the Send to Location function the destination had to be given in $$ format and not with {} or GetProperty.

You can reference zones and coordinates manually by typing them in like “A11” but if you want to use variabels you have to use the $$ method and many times you’ll need to use Global Properties. So again I made scripts that passed information to a global first.

I hope other Vassal developers find some of this information or my module useful.


Previous Article in the Series: Talon Tuesday Issue #46: Vassal Update for Talon

Bob Seifert
Author: Bob Seifert

Please note: I reserve the right to delete comments that are offensive or off-topic.

We'd love to hear from you! Please take a minute to share your comments.