A simple recursive algorithm that works for most cases
The great thing about using the equations-based analysis is that it removes the risk of being tripped up by the interpretation of the rulebook while constructing an algorithm. The interpretation has to do with the definition of the equations, but any follow up is a matter of mathematics! So we have gained freedom in reasoning, and we can look at different approaches.
First of all we want to know whether an order is already resolved. This means that during adjudication, an order is in one of the following states: SUCCEEDS, FAILS, or UNRESOLVED.
The UNRESOLVED state might not be used in algorithms that are not derived from equations (such as the DPTG), or at least not so explicitly. These algorithms process the orders in a specific sequence; and the sequence guarantees that when an order is processed, any prerequisites are resolved first. They often follow the principle that a move order succeeds until a reason is found for it to fail, and a support order succeeds until it is found to have been cut. This approach requires the construction of a correct sequence. However, in the choice of our algorithm, we don't want to be restricted in this way.
With the UNRESOLVED state, an obvious approach for an algorithm is to make a simple recursive function for resolving an order:
If the state of the order is not UNRESOLVED, then return.
If the order is UNRESOLVED, look if the resolution of the order is dependent on the resolution of other orders.
If so, resolve those orders first, by calling the function in recursion.
When all dependencies are resolved, adjudicate the original order given the equations.
Set the state of the order according to the adjudication result (so it is no longer UNRESOLVED).
The complete algorithm initializes the states of all orders to UNRESOLVED, and then calls the function for every order.
For example, suppose we have the following simple situation:
Initially both orders are assigned the UNRESOLVED state. If we start resolving the Paris order, then we need to know the attack strength of the unit in Paris and the hold strength of the Brest area. For this, we need to know whether the move of the Brest unit is successful. So we try to resolve the Brest order in recursion. Since this order is not dependent on any other orders, it can be adjudicated directly, with a positive result. After this, the adjudication of the Paris order can be completed.
This simple recursive algorithm using the UNRESOLVED state works fine for most situations. However, things get complicated when dealing with a circular movement or convoy paradox. In these cases, the described simple recursive algorithm will enter an endless recursive loop. This means that the algorithm cannot handle all situations.
Actually, the circular movement and convoy paradoxes are not the real problem. If those situations were the only difficulty, then the simple recursive algorithm could easily be adapted, such that it recognizes when it enters an endless loop (that is, when in recursion the recursive function is called for the second time for the same order). In such cases, the orders in the cyclic dependency should be passed to the backup procedure, which determines whether it is a circular dependency or a convoy paradox and adjudicates accordingly.
However, it is not that easy. The really problematic situations are those that have a cyclic dependency, but for which the number of resolutions that respect the equations is nevertheless exactly one. These situations always consist of a circular movement or elements of a convoy paradox, supplemented with additional units and orders. For instance, consider a circular movement with one of the units supported, as shown below:
Normally, a circular movement will have two valid resolutions that respect the equations (if the circular movement rule is not considered). Either all units fail to move, or all units succeed in moving. However, in the situation above, a resolution where all units fail to move is incorrect, because the German fleet in the North Sea should always succeed in its move. (thanks to the support from the fleet in Skagerrak).
Similarly, if the fleet in Skagerrak were to move to the North Sea, all units would bounce. A resolution with all moving fleets advancing would be inconsistent.
In the following example, there would be a convoy paradox if the Russians did not intervene:
Without the Russian orders, there are two resolutions that respect the equations. The first will advance the fleet in Denmark and disrupt the convoy as consequence, while the second is a successful convoy that cuts the support in Sweden. But with the Russian orders this all becomes irrelevant, because the Russian orders disrupt the convoy in any case.
Other ways for Russia to take away the paradoxical aspect of the scene are to support the fleet in Denmark, or to cut the support in Sweden (both can be done with the fleet in Norway). An alternative convoy path could also be ordered, but the geography in this particular example does not allow it.
The feature that all these situations have in common is that the equations contain a cyclic dependency, while the number of resolutions for the equations is still exactly one. And because there is only one resolution, we want to find this resolution. Passing the situation to the backup rule would give the wrong results. These situations jeopardize the simple recursive algorithm.
One possibility for dealing with these cyclic dependencies is to try to recognize the different situations, and adjudicate those special cases separately. This has been done in many older adjudicators, and since the possibilities are limited this is certainly possible.
For a circular movement situation this does not sound very difficult. The only thing that has to be done is to check whether there is unit outside the circle that disrupts the circular movement with enough support. If so, the bouncing unit part of the circular movement fails, and all the other orders are adjudicated normally. If there is no unit that disrupts the circular movement, then all units advance, and units that support a movement within the circle are irrelevant. Although this sounds simple, remember that the additional unit may come by convoy, or that one of the crucial supports may be cut by a convoy.
It is far more complex to recognize the convoys correctly. The DPTG has described this approach in detail, and uses the notion of subverted convoys, with subcategories: futile convoys, indomitable convoys, and confused convoys.
To avoid this complexity, we can look for a generic method of handling cyclic dependencies. A generic method may sound more difficult, but there are only a few requirements for such a generic algorithm:
This doesn't look impossible. In the next chapter we will look at one such approach, and in the last chapter we will look at an approach that is close to the simple recursive algorithm.