The illegal/invalid line (6.A.5, 6.D.8). The document separates an order
that is impossible in this position from one this position allows that
merely did not come off. The first is ignored and its unit is holding like
any other; the second means the unit tried to leave and cannot be propped up
where it stands. An army sent across water with a fleet on the route and no
convoy ordered is the second; the identical order with nobody in the sea at
all is the first. Guessing at this once cost four passing cases to buy one.
Reading the document cost nothing -- it says so outright, in the note under
6.D.8 and again under 6.D.32.
A support that only looked like a hold (6.A.5). "Supports A Yorkshire" and
"Supports A Yorkshire - Yorkshire" are the same shape once parsed, and the
case turns on the difference: the first holds a unit down, the second
supports a move nobody can legally make. The extractor was throwing that
away; it now keeps it, and the fixture is regenerated.
The head of a cycle (6.F.22). Kruijswijk's resolver guesses that an order
fails, sees what follows, then guesses the other way. Only the outermost
order in a cycle may do that, because its answer is the one everything else
was computed against. This engine let any order that reached the dependency
list first declare the cycle its own -- and an inner one takes both guesses
with its callers' provisional answers held fixed, gets the same result twice
for that reason, and writes it down as settled. The cycle then becomes
invisible: the backup rule never runs and Szykman's rule never fires, and
the position resolves to whichever of its two consistent readings the search
happened to walk into first. It had been doing this on every paradox and
getting away with it, because on a first-order paradox both readings agree.
Also carried across from the reference algorithm: an order that resolved
itself while a nested call was away must not have the guess written over it.
Three remain. 6.F.28 and 6.F.29 are sixth-order paradoxes -- the same
twenty-six orders with one support between them, and the point of the pair
is that the answer swings on it, where this resolver gives both the same
answer. 6.G.19 the document itself gives three answers to, calls a little
bit pedantic, and advises adjudicators not to offer at all.
All 176 published cases now parse and run. Retreating passes 18 of 18,
building 7 of 7, civil disorder 13 of 13; movement is unchanged at 133 of
139.
The retreat and winter engine code was written before these cases and mostly
held up, but civil disorder was wrong in a way playing would never have shown.
It measured distance to a power's *home* centres. The rule is distance to the
centres it owns -- a Russia driven out of Moscow and holding Sweden measures
from Sweden -- so every power that had lost a home centre was disbanding the
wrong unit.
And it measured over the graph each unit moves on, which is wrong in both
directions. An army counts sea provinces it would have to be convoyed across,
so Albania is two steps from Naples rather than unreachable. A fleet counts
inland provinces it could never enter, so the Baltic is two from Warsaw. That
reads as nonsense until you notice what is being measured: not how the unit
would get home, but how far out of the way it is. A fleet in the Baltic is
still in the middle of Russia's business; one in the North Atlantic is not.
Civil disorder also only applies to the shortfall. A power that disbanded one
of the two it owed has half answered, and the automatic rule picks from what
is left rather than from what it started with.
tools/datc.py turns the Diplomacy Adjudicator Test Cases into a fixture: the
orders and their annotated outcomes, not the document's prose. 139 movement
cases run; 107 pass.
Three real faults so far, none of which the hand-written cases had caught:
Orders were never validated. An illegal order has to be refused and the unit
left holding -- still standing there, still in everybody's way -- and a fleet
told to go to Spain has to be told which coast when both are reachable.
There is now a validation pass, and ordering another country's unit is
refused without disturbing the order its owner actually gave.
The paradox rule did not terminate. Settling only what was already in the
dependency cycle resolves nothing in a real paradox, so the resolver asked
the same question forever -- Pandin's Paradox was a stack overflow rather
than an answer. It now restarts the whole resolution with the convoyed army
held still, which is inelegant and provably finite: each restart forces one
more army to stand, and there are only so many armies.
A held army kept its path. Szykman's rule stops the army; it has to stop the
army's weight too, or the paradox re-forms on the next pass and the restart
never converges.