bayes for days
sds plan scoring.md
7.1 kB
Markdown
at main


id: scoring title: One basis, not two status: open dependsOn: [features] exitCriterion: > Every score the bot computes comes from the named feature basis. Intent, Stance, Appraisal and the six-axis asks table are deleted, and no weight the bot uses was written by hand. #

scoring #

The bot has two scoring systems and only one of them is trained.

The first is the named feature basis: normalised, documented in FEATURES.md, fitted from recorded play. It scores candidate stands and volleys.

The second is a parallel arithmetic nobody fitted. unit.rs scores seven intents from hand-written expressions over projected_damage; surface.rs maps each intent to a damage weight and six bespoke axes - take, flank, blind, range, band, heat - and those rank the candidates. The named features are not consulted.

This epic deletes the second one.

What the hand-written arithmetic gets wrong #

Each of these is measured, and each was found from a different direction:

  • Defence is discounted by a hard-coded half. Intent::Hold scores dealt_now - projected_damage(enemy) * 0.5, and asks(Close) prices the incoming-fire axis at -0.10 with the comment "the incoming barely priced". The fitted weights independently land at 1.69:1 favouring closing, and the bot takes a quarter of its shots at one hex.
  • Intents are denominated inconsistently. Five are in damage points and read in the tens; Screen is +/-1 and Withdraw is +/-2 to +/-4. Each wins 0.2% of decisions - not rarely chosen, arithmetically unable to win.
  • Units vote in proportion to their firepower. combine sums raw appraisals, so a unit projecting 40 points outvotes one projecting 1 by forty to one.
  • Two quantities answer one question. projected_damage and expected_damage both mean "what we would land", computed differently, used by the two systems respectively.

The work #

  • So it is one feature rather than two holes: a bounded distance from this
    hex to a coordinate supplied with the decision, which `Reposition` points
    at its destination and `Screen` points at the interposing hex between the
    friend it covers and the enemy nearest that friend. It unblocks `Seize` and
    `Deny` in `plan/objectives.md` at the same time, since a map objective is
    exactly a caller-named hex, and it is the smallest thing that closes four
    gaps.
    
    **The parameter travels in the observation.** `Posture` carries an
    `objective: Option<Coord>`, so every feature is still a function of the
    observation alone and a recorded decision holds the hex it was judged
    against - re-scoring it later cannot reach for a coordinate nobody wrote
    down, which is the replay property `sds tactics` depends on.
    
    The absent case is a **missing column, not a zero one**. `measure` takes a
    `positional::Objective`, which cannot be built without a hex, so the
    feature is simply not measured when no order named one. A candidate that
    was never asked about an objective has not answered badly about one, and
    the fit sees no row rather than a row of zeroes.
    
    **Nothing sets it yet**, so it is inert in this build and a corpus
    recorded today carries no column for it. It is the scoring half of four
    gaps; the ordering half belongs to `plan/tactics.md` and
    `plan/objectives.md`
    

Orphaned feature clusters #

Clustering all 51 against the ten tactics leaves four families that no tactic is about, and they are all resource and method rather than geometry:

cluster features note
heat 5 a set point implied by a tactic, not a tactic. Break cools, Entrench tolerates
ammunition 1 same shape as heat
damage kind p_kill, p_mission_kill, p_psr_threshold, p_breach legging a fast unit and killing a slow one are the same points to opposite purpose
target choice the target_* family finish the wounded, kill the dangerous, kill the cheap

The covered clusters are all geometry - range, arc, cover, visibility, cohesion, position. That the bias runs this way probably reflects how the basis grew rather than what matters, and it is the same finding as "offence is priced exactly and defence is not priced at all" seen from the feature side.