This is part 2 of a series of articles about my upcoming Combat Commander: Adversary game module—a solitaire system that lets one player duke it out with an automated opponent on the storied battlefields of GMT's classic wargame.
I explained in part 1 of this design diary that I started working on Adversary quite a few years ago, slowly chipping away at one problem after another. Most of those problems I expected from the get-go: I knew going in I'd have to design systems for the bot to select units, to order them around, to react to player actions, to act according to secret objectives, and so on.
But there was one problem that did come as a surprise—a shock, even—and which nevertheless made me smile in wonderment, because it unveiled a process we humans all go through without thinking about it when we're playing games like Combat Commander. And that thing's never mentioned in the rulebook, either.
Wargames all run on a variety of metrics: line of sight, range, firepower, cover value, movement allocation, and so on. Most of those concepts have a numerical value, or else a binary state, attached to them. The rulebook can direct you to perform X "if the attack roll is higher than the defense value," or that you can't perform Y "if the unit lacks sufficient movement points to reach its intended destination." Those concepts are quantifiable, and the rules teach you how to handle them.
When I set out to test an early version of, say, the movement system, I had the bot run through a simple algorithm intended to conform to the automated opponent's "intentions" at that point in the game. It wants to send some of its units to better cover? That's easy enough: look at the cover values of neighboring hexes. On a quest for higher elevation? Climb a neighboring hill. But what do you use to break a tie if several hexes qualify? Well, obviously you just send the units to the hex where they'll better be able to see the enemy that's com—
And there it was. What I started out calling "coverage" was that elusive metric, that value we all compute in our heads even though we never speak it aloud and the rulebook doesn't cover it. (It just doesn't need to.) How well can you see around you from that point on the map, so that you can fight off incoming enemy units? It's a very human, very intuitive notion that's blindingly obvious to us meat sacks. But for a bot trying to hold its own in a tactical game, it's a different matter.
No sooner had I made that realization, however, that I put it aside—temporarily. I wanted to finish the ordering system first, always keeping in mind that the bot would eventually make use of that "coverage" thingy.
(Much later, Kai Jensen at GMT would suggest I pick a different label for that value, pointing out that the game already used "cover" as an operational term, which might bring about unwanted confusion. She was right, as usual, and I renamed that concept "Horizon.")
A workable definition of Horizon became a burning need when I set out to design setup rules for the bot. At the start of any given scenario, each faction gets assigned an array of units it must deploy on its side of the map. Humans perform this task without a hitch, using established notions to hedge their bets and spread the risk: "I'll split my forces into two main stacks so that I can pack serious firepower at both ends of that road, and still remain mobile if I need to leave in a hurry." We also wield the idea I'm calling Horizon like we came out of the womb playing games like Combat Commander: "I'll put my guys at the very edge of that hill, so they can see—and shoot at—the entire valley below." (It's something akin to balancing a mathematical equation, except you're using machine-guns in lieu of plus signs.) No need for numbers, man: you just LOOK at the map and you see it, clear as day.
But a bot lacks eyes, and so it very much craves its numbers.
My first definition for Horizon remained open-ended. I knew I had to give the bot a Horizon value for each hex on the map so that it could compute decisions in an effective manner. And it seemed to me like that value should be the number of directions, from each hex, into which units standing there could see "far enough." Just how far was enough remained to be determined.
I decided to start with 6; in other words, Horizon would be, for any given hex, the number of directions into which you could see at least six hexes away. Since I defined direction as "looking through one of the hexsides," it meant the maximum Horizon value for a hex would be, coincidentally, 6.
So far, so good. I now possessed a metric I could access to steer adversary units towards hexes more suited to their nefarious purposes.
Of course, on most maps, a line of sight six hexes long is very hard to achieve, which meant that most Horizons would be listed as 1 or 2; maybe a little more in certain, rare cases. Hardly a usable data point.
| Map #2, also known as "Where LOS Comes to Die" |
For a brief moment I considered including in my calculations the range of that hypothetical unit (i.e. how far it can shoot) standing in the hex. But considering the wide variety of ranges assigned to units in the game—not to mention the weapons they carry!—it became clear that that way lay madness.
So I opted to attack (assault? melee?) the problem from the opposite direction: I made the Horizon requirement a LOS of 1. I knew it wouldn't suffice, but I wanted to build up to the right number. Plus, looking at Horizon values for hexes with such a short LOS (which instantly became 5 or 6 for almost every hex on most maps) helped me rephrase my question: instead of wondering how far is enough for a unit to see around itself, I started asking myself how far the unit needs to see. Or, considered differently, when do human players stop caring, in the heat of the moment? Two hexes (as in "two hexes away") opened things up a bit, but three hexes felt just right to me, and I proceeded to run Horizon evaluations using that metric.
(Much later, out of curiosity, I ended up computing the average range of "common" units across all six nationalities in the game, ignoring those elite dudes who only show up in a handful of scenarios or when they feel like it. It worked out to 3.17 hexes.)
It didn't take me long to realize that my "base 3" Horizon chart worked like a charm: the adversary was making great use of it, shifting its units towards spots that would put my own guys at a disadvantage. Naturally, I took some time to experiment with making the requirement 4 hexes, but there was no joy to be found in that expanded definition. Without doubt, Horizon was a 3-hex-range affair.
End of story? Hardly.
You see, back when I was attempting to read my bot's intentions in hex leaves, I still wasn't in "publication mode." I had yet to reach out to GMT, and I was still building this thing for me. (Take a look at Part 1 in this series of articles for a detailed retelling of those halcyon days.) And as such, I was trying to make do, as much as possible, with whatever shipped in the Combat Commander box. This doctrine meant that players (i.e. just me at that point) were required to figure out the "best Horizon value" at various moments in the game, and to compute that value mentally. I got really good at it—although it still slowed things down—but it was an insane thing to ask of everyone else.
Would you find it thrilling to stop in the middle of a turn to compute LOS in six directions for half a dozen hexes? Yeah, me neither.
Then Jason Carr (that guy again!) reached out across the screen during a video call and virtually slapped me. And I'm glad he did.
(Next time: MOAR about Horizon charts!)
* * *
No comments:
Post a Comment