Strategic Primer: Assistive programs progress

In the last couple of months since I last described my progress on my suite of assistive programs for players and Judges of campaigns of Strategic Primer, I’ve made some significant changes to the map viewer—whether they’re improvements may be debatable.

Recent Changes

First, I fixed a long-standing but minor bug: file-choosing dialogs opened by default in the user’s home directory, which is highly obscure on Windows and not ideal for my workflow either.

Second, I implemented the keyboard-navigation feature, as I had hoped.

Third, I got rid of nearly every code path where some object might be null, replacing them with objects to represent the same cases, and then dropped the special-case logic for handling null.

As an offshoot of that, I implemented, or perhaps reimplemented as I claimed to have done it last time but my commit messages suggest otherwise, the feature that shows the code-name of the owner of a fortress or unit if that information is included in the map file.

Fourth, I reimplemented the map-reading code nearly from scratch. Yes, again. The technical details: This time, I convert the XML to a tree of Nodes, which then check themselves for nonsense data and convert themselves to the new map. This is far more extensible than either previous implementation. Once that implementation was feature-complete—which entailed fixing a number of bugs in deep-comparison functions—I deprecated the previous reader and dropped its predecessor entirely. This new version feels faster to me, though it made some model API changes necessary that then caused some GUI performance regressions. Other than those API changes, though, this new version is a drop-in replacement; its API is identical to that of the previous version.

(As an aside: one of the first things I did in implementing the new reader was to finally come up with an alternative to this monstrosity:

while (events.hasNext()) {
    final Event event =;

Static analysis plugins kept telling me that I could replace that with a for-each loop, but it’s not that simple. In Java a for-each loop only works on an Iterable, and events is an Iterator. What I finally came up with was a wrapper class that is an Iterable and, given an Iterator, returns that as the Iterator the for-each loop asks for. I now use this throughout, even in the previous map-reader implementation. If this trick was mentioned in my CS108 textbook, I’ll feel somewhat foolish—I did read it—but I wish someone had pointed me to this long ago.)

Fifth, I dropped my hand-crafted panel management code, which had controlled widget sizes to a percentage of their parents’ size, entirely, replacing it with reasonable fixed maximum and minimum sizes in pixels for controls on the detail panel. I also moved the detail panel from to the right of the map to below it, which I think improved the proportions. (I also have plans for the right-hand side … but see below.)

I fixed a lot of bugs, warnings, and potential bugs. One problem throughout that is now, at last, fixed was my placement of stream-closing methods. Somehow I’d never learned that a finally block always runs; I had thought that it ran only if another exception was thrown in the catch block, so I never used finally blocks. Now I do; as best I can tell, my stream management code is now correct.

Lastly, I added a way to warn the user (or, really, a developer—these warnings go wherever log messages go, which is who-knows-where if you’re not running the application from the command line!) about deprecated or otherwise not-quite-right map format (or other) issues that aren’t worth aborting over. Then I also added a set of XML tags I expect to use in the near future but don’t now, which the viewer will warn you about if it encounter one—but it won’t fail, which is what it does on a totally unexpected tag.


In my last report I suggested changing the resolution of the map; I’m now planning on that, as soon as I finish running the current turn. (Since the conversion will require largely-by-hand expansion of tile contents, at the very least.) This will require changes to the model, the view, and the parsing code in the controller—though that last won’t be nearly as painful now that I have the new Node-based map reader. I may even be able to continue to support the current map format for a while.

Once that goes through, there are several new features I want to add to the viewer. First is changesets: the idea that a map may contain its original state, but then later on contain changes to that state. This will allow me to keep track of which explorer went over what area, and should eventually help in turning the viewer into a strategy-composition application.

The other thing I want to do pretty much as soon as we change the resolution of the map is to implement more realistic encounters. I’ve described this elsewhere—near the end of this blog post, for example—so I won’t go into much detail here.

After—or perhaps, rather, as part of—that, I hope to add unit vision range and movement. Implementing these properly may require finally adding support for loading some kinds of data (including custom map tags!) at runtime from file, which is one of the reasons I began the most recent map-reader overhaul.

In my last report I expressed hope for significant progress soon on the character (worker) management program; I have made no progress whatsoever on it. However, if my plans for the map viewer advance at any reasonable pace, simple worker and structure management functions should be part of the viewer by the end of the year, God willing. Again, we’ll see.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s