As a first whack at the combat pathfinding heuristics, I built a heuristic function that assigns a cost of Distance for an open tile, Distance-1 for a resource node, Distance+10 for a tile with a different-faction destructible, and Distance+20 for a tile with a same-faction destructible. And it works pretty dang well. When presented with a choice of turnings, with either turning being the same cost distance-wise, if one turning has a resource node and the other does not then the resource node turning will be picked. Enemies don't exactly go out of their way to loot things, but they will loot if the lootable is convenient or in the way. They will favor looting a lootable over destroying a barricade, given a choice, but if the only choice is to destroy a barricade or a Tiny Bombard, then they'll do it. If the last resort is to find a path that is blocked by a same-faction ally, then they will follow that path for as far as they can. This ensures that even if GC is completely encircled by the foe, other foes will continue to path toward the fight and pile up around GC in a wonderfully overwhelming manner.
And it all works. However, it is a tad bit slow since I implemented the new AI pathfind in Lua. I might need to move it into C++ and do some optimizations to make it faster, since as of now there is a tiny but noticeable hitch right as an enemy unit starts its turn, while it paths and weighs its options. I have thought, too, about making the pathfinder incremental; letting it run for a few fractions of a second at a time then exiting. This would be simple enough to do if I restructured the pathfind slightly as a Lua coroutine, so that might be the first option I try. That way, the pathfinder would be running behind-the-scenes so to speak. It would be granted a few cycles every Update, and that would prevent any visible framerate hangs or hitches.
This current heuristic would be trivial for the player to game, given the right mix of skills and enemies. But with the test sets, it works wonderfully. And in the process, I even fixed a previously-unnoticed hang-bug I found in some movement queueing code, a bug that wasn't being triggered by the previous path assignment functionality.