From d8d41da0208a48a5c5cf1328d0d1bcf482192cc8 Mon Sep 17 00:00:00 2001 From: "@permadeath.com" Date: Wed, 19 Aug 2026 23:20:25 -0400 Subject: [PATCH] test(unit-rules): sample the library for damaged states `DumpDamaged.java out.jsonl every:40` asks fourteen states of every fortieth Mek rather than of nine named ones, which is how the shapes and construction a hand-picked list never covers get asked about. Meks only: getAllMeks is named for the file format and hands back tanks too, whose locations are not a Mek's. --- bridge/DumpDamaged.java | 49 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/bridge/DumpDamaged.java b/bridge/DumpDamaged.java index 6d2261f..44b61f1 100644 --- a/bridge/DumpDamaged.java +++ b/bridge/DumpDamaged.java @@ -51,16 +51,34 @@ public final class DumpDamaged { "Griffin GRF-1N", "Hatchetman HCT-3F", "Celerity CLR-03-O", + // A weapon that did not fit one location: the autocannon fills nine + // slots of an arm and one of the torso beside it, so blowing the arm + // off has to take the whole gun. + "Victor VTR-9Ka", + // An engine that does not run hot when it is hit, because it burns + // fuel rather than fusing anything. + "Pacifier CCU-36 SecurityMech", }; public static void main(String[] args) throws Exception { if (args.length < 1) { - System.err.println("usage: DumpDamaged [design ...]"); + System.err.println("usage: DumpDamaged [every:N | design ...]"); System.exit(2); } - String[] wanted = args.length > 1 - ? java.util.Arrays.copyOfRange(args, 1, args.length) - : DEFAULT_DESIGNS; + // `every:N` samples the library rather than naming designs: every Nth + // Mek by name, plus the hand-picked ones. The hand-picked list covers + // the systems whose loss changes a figure; a sample covers the shapes + // and construction the list does not - quads, tripods, superheavies, + // Clan engines that reach into the side torsos, patchwork armour. + int every = 0; + String[] named = DEFAULT_DESIGNS; + if (args.length > 1) { + if (args[1].startsWith("every:")) { + every = Integer.parseInt(args[1].substring("every:".length())); + } else { + named = java.util.Arrays.copyOfRange(args, 1, args.length); + } + } MekSummaryCache cache = MekSummaryCache.getInstance(); long deadline = System.currentTimeMillis() + 600_000L; @@ -77,6 +95,29 @@ public final class DumpDamaged { byName.putIfAbsent(ms.getName(), ms); } + java.util.List wanted = new java.util.ArrayList<>(java.util.Arrays.asList(named)); + if (every > 0) { + // Sorted so that the sample is the same one every time: the cache + // iterates in whatever order it loaded, and an oracle that changes + // under the test is the thing `logs/` already taught us to avoid. + // Meks only. `getAllMeks` is named for the file format rather than + // the unit type and hands back tanks and infantry too, whose + // locations are not a Mek's - shooting a centre torso off one is + // an index out of bounds rather than a scenario. + java.util.List all = new java.util.ArrayList<>(); + for (Map.Entry e : byName.entrySet()) { + if ("Mek".equalsIgnoreCase(e.getValue().getUnitType())) { + all.add(e.getKey()); + } + } + java.util.Collections.sort(all); + for (int i = 0; i < all.size(); i += every) { + if (!wanted.contains(all.get(i))) { + wanted.add(all.get(i)); + } + } + } + int written = 0; try (PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(new FileOutputStream(args[0]), StandardCharsets.UTF_8)))) { -- 2.51.2