Implement nose coupling so run-arounds work, and stop coupling wiping the district

This commit is contained in:
Jesse
2026-08-01 15:15:28 -04:00
parent f52ff0e9ac
commit e23d81eade
12 changed files with 366 additions and 23 deletions
+19 -6
View File
@@ -276,15 +276,28 @@ describe('switching accomplishes something (regression)', () => {
assert.ok(worstRun < 3, `crew oscillated ${worstRun + 1} times without doing any work`);
});
it('does not spend its whole Local Operations budget on motion', () => {
// The absolute ratio is no longer a fair test: with only 9 industries in 115 cards there is
// often nothing to switch, so `work` is legitimately near zero. What still must hold is that
// the crew is not burning all six Moves every Stage — the shuttling bug.
it('does not shuttle aimlessly — Moves have to buy something', () => {
// Counting Moves alone stopped being a fair test once the crew could do real work. Run-arounds
// and sidings are SUPPOSED to cost several Moves each: the crew leaves the main, runs the loop,
// and comes back with a different car droppable. Measured before sidings existed the crew
// coupled ~0.4 cars a game; it now couples ~8 and drops ~11.
//
// So test the thing the old threshold was a proxy for: motion must convert into work. A crew
// that shuttles for its own sake shows a high ratio here, however few or many Moves it makes.
const report = simulate({
games: 40, length: 'standard', mode: 'solitaire', players: ['bot'], policy: developerBot,
});
const moves = report.perGame.reduce((n, g) => n + g.actions.moves, 0) / report.perGame.length;
assert.ok(moves < 60, `${moves.toFixed(0)} Moves per game suggests aimless shuttling`);
const per = (f: (g: (typeof report.perGame)[number]) => number): number =>
report.perGame.reduce((n, g) => n + f(g), 0) / report.perGame.length;
const moves = per((g) => g.actions.moves);
const work = per((g) => g.actions.drops + g.actions.couples);
assert.ok(work > 2, `only ${work.toFixed(1)} productive acts a game — the crew is doing nothing`);
assert.ok(
moves / work < 8,
`${(moves / work).toFixed(1)} Moves per drop or coupling suggests aimless shuttling ` +
`(${moves.toFixed(0)} Moves, ${work.toFixed(1)} productive acts)`,
);
});
});