mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
feat(draw): generational TOP-OFF — every wave fills from the lowest generation up
Neither extreme was right. Ignoring generations lets a card that has failed five waves
compete with one nobody has ever drafted; filtering to a single generation starved the fleet
to 46 cards. So generation becomes the PRIMARY ORDERING and the existing mass/count criterion
breaks ties, at both levels of the assembly:
* gate groups holding never-drafted cards rank ahead of all-retry groups (before the
--max-bins truncation, so an untouched group is never cut for a fat retry group);
* within a group, untouched cards are taken before retries.
Wave SIZE is untouched — only the order changes — so the fleet stays full while the scarce
never-drafted work always goes out first.
Verified on a live draw: gen0 2 · gen1 2 · gen2 14 · gen3 2 · gen4 3 · gen5+ 340. It took
EVERY card below generation 5 (all 23 available) and filled the remaining 340 slots from the
5+ pile, which is the whole point.
The gen0 count is 2 because wave dw drew the last 51 untouched skeletons an hour ago. That is
the campaign's real state: essentially everything drawable has now been drafted at least
once, and ~635 distinct skeletons have refused. The remaining work is levers, not draws.
This commit is contained in:
@@ -597,6 +597,14 @@ if a.one_per_gid:
|
||||
by_tu = collections.defaultdict(list)
|
||||
for c in cands:
|
||||
by_tu[(c['binary'], c['tu'])].append(c)
|
||||
# GENERATIONAL TOP-OFF (P31 S60, Drew): a wave fills from the LOWEST generation available and
|
||||
# only then moves up, instead of either ignoring generations (retries compete with never-drafted
|
||||
# work) or filtering to one generation (which starved the fleet to 46 cards — see --generational).
|
||||
# Applied at BOTH levels: gate groups holding never-drafted cards rank ahead of all-retry groups,
|
||||
# and within a group the untouched cards are taken first. Generation is the primary key and the
|
||||
# existing mass/count criterion breaks ties, so wave SIZE is untouched — only the ORDER changes.
|
||||
_mingen = {k: min(draw_count.get(c['fn'], 0) for c in v) for k, v in by_tu.items()}
|
||||
|
||||
if a.rank == 'total':
|
||||
# P31 S54: rank by the mass a card actually DELIVERS -- its own instructions plus the same-gid
|
||||
# siblings the post-bank remap banks for free. Measured on the wave-T draw: the 70 selected
|
||||
@@ -606,12 +614,13 @@ if a.rank == 'total':
|
||||
if not a.one_per_gid:
|
||||
sys.exit("--rank total requires --one-per-gid (there are no deferred siblings otherwise)")
|
||||
_sibins = {g: sum(c['nins'] for c in v) for g, v in siblings.items()}
|
||||
ranked = sorted(by_tu, key=lambda k: -sum(c['nins'] + _sibins.get(c['gid'], 0)
|
||||
for c in by_tu[k]))[:a.max_bins]
|
||||
ranked = sorted(by_tu, key=lambda k: (_mingen[k],
|
||||
-sum(c['nins'] + _sibins.get(c['gid'], 0)
|
||||
for c in by_tu[k])))[:a.max_bins]
|
||||
elif a.rank == 'mass':
|
||||
ranked = sorted(by_tu, key=lambda k: -sum(c['nins'] for c in by_tu[k]))[:a.max_bins]
|
||||
ranked = sorted(by_tu, key=lambda k: (_mingen[k], -sum(c['nins'] for c in by_tu[k])))[:a.max_bins]
|
||||
else:
|
||||
ranked = sorted(by_tu, key=lambda k: -len(by_tu[k]))[:a.max_bins]
|
||||
ranked = sorted(by_tu, key=lambda k: (_mingen[k], -len(by_tu[k])))[:a.max_bins]
|
||||
|
||||
# principle 3 (P31 S52): SIZE A WAVE BY INSTRUCTIONS, NOT BY CARDS. The public metric is
|
||||
# instruction-weighted, so a wave is worth what its instructions are worth: the 12-42-ins card
|
||||
@@ -656,7 +665,7 @@ if _jt_pool:
|
||||
f"card(s) (quota; one per binary, each one extra rebuild at gate time)", file=sys.stderr)
|
||||
|
||||
for k in ranked: # principle 2: within a group, mass first
|
||||
for c in sorted(by_tu[k], key=lambda c: -_deliver(c)):
|
||||
for c in sorted(by_tu[k], key=lambda c: (draw_count.get(c['fn'], 0), -_deliver(c))):
|
||||
if _full(): break
|
||||
if id(c) in _in_wave: continue # already seeded by a quota
|
||||
# QUOTA-ONLY LEVERS. A quota is a FLOOR unless it is also a ceiling: with the tell levers in
|
||||
|
||||
Reference in New Issue
Block a user