Epic: #64 (AffinityEngine)
Depends on: #65 (crate scaffold), #66 (InteractionGraph), #68 (AffinityConfig)
What
Implement score_entity() in crates/arcane-affinity/src/scorer.rs:
score(E, C) = interaction_score(E, C) + spatial_score(E, C)
interaction_score = sum of interaction_weight(E, F) for all F in cluster C
spatial_score = spatial_weight * (1.0 / (1.0 + distance(E_pos, C_centroid)))
Plus capacity soft penalty when cluster approaches max size.
Key details
- Positions are
Vec2 (x, y) — no distance_squared() method, compute manually
cluster_centroids computed ONCE per tick (caller responsibility), not per-entity
- Capacity penalty:
score *= max(0.1, 1.0 - (overfill_fraction)) — never fully zero
- Returns
ScoringResult { best_cluster, best_score, current_score }
Acceptance criteria
score_entity() function implemented
- Unit tests for: interaction-dominated scoring, spatial fallback (zero interactions), capacity penalty, spatial_weight=0 vs 1.0
Spec
See arcane-engine repo: in_08_02_cluster_scorer.md
Epic: #64 (AffinityEngine)
Depends on: #65 (crate scaffold), #66 (InteractionGraph), #68 (AffinityConfig)
What
Implement
score_entity()incrates/arcane-affinity/src/scorer.rs:Plus capacity soft penalty when cluster approaches max size.
Key details
Vec2(x, y) — nodistance_squared()method, compute manuallycluster_centroidscomputed ONCE per tick (caller responsibility), not per-entityscore *= max(0.1, 1.0 - (overfill_fraction))— never fully zeroScoringResult { best_cluster, best_score, current_score }Acceptance criteria
score_entity()function implementedSpec
See
arcane-enginerepo:in_08_02_cluster_scorer.md