worldbox-observer-mod/IdleSpectator/scoring-model.json
DazedAnon 394968a956 Introduce variety arc scoring penalties and enhance interest handling.
- Implement scoring penalties for consecutive same variety arc shows
- Update InterestVariety and InterestScoring to track arc streaks
- Add new commands for noting interest variety in AgentHarness
- Expand HarnessScenarios to test new variety arc mechanics
- Increment version to 0.28.34 in mod.json and scoring-model.json
2026-07-17 19:07:47 -05:00

210 lines
6.8 KiB
JSON

{
"modVersion": "0.28.34",
"title": "IdleSpectator interest scoring model",
"updated": "2026-07-17",
"note": "Edit weights below - InterestScoringConfig loads this file at mod start. Docs sections are human-facing only (ignored by Unity JsonUtility).",
"weights": {
"charWeightEventLed": 0.18,
"charWeightCharacterLed": 0.55,
"visualMultiplier": 12,
"noveltyMultiplier": 4,
"cutInMargin": 35,
"stickyCutInMargin": 50,
"stickyVarietyValveAfterSeconds": 16,
"stickyVarietyValveAfterSecondsPair": 8,
"stickyVarietyValveMaxWatchFrac": 0.4,
"stickyVarietyValveMargin": 20,
"fightBalanceLopsidedFloor": 0.28,
"fightBalanceFullAt": 0.55,
"warFrontBalanceBonus": 12,
"rotateSlack": 12,
"fillScoreMax": 55,
"noticeScoreMin": 70,
"hotScoreMin": 110,
"dwellFill": 8,
"dwellNormal": 15,
"dwellHot": 15,
"fillRotateSeconds": 8,
"minCameraDwell": 15,
"maxWatchMoment": 15,
"maxWatchStatus": 30,
"maxWatchGrief": 45,
"maxWatchCombat": 60,
"maxWatchDuel": 24,
"maxWatchEpic": 50,
"massFighterThreshold": 4,
"massBaseBonus": 28,
"massPerExtraFighter": 4,
"massExtraCap": 24,
"massCrowdThreshold": 8,
"duelMaxFighters": 2,
"duelNotablePairBonus": 55,
"duelSingleNotableBonus": 15,
"duelAnonymousPenalty": -24,
"skirmishMinFighters": 3,
"notableSkirmishPer": 12,
"notableSkirmishCap": 35,
"clusterDeathWeight": 10,
"clusterFighterWeight": 14,
"clusterNotableWeight": 22,
"clusterMassBonus": 28,
"clusterDuelPenalty": -8,
"clusterNotableDuelBonus": 45,
"clusterSingleNotableBonus": 12,
"preferNotableDuelMargin": 15,
"battleCharPerNotable": 18,
"metaFavorite": 22,
"metaKing": 18,
"metaLeader": 14,
"metaRenownDivisor": 120,
"metaRenownCap": 8,
"metaKillsFactor": 0.35,
"metaKillsCap": 12,
"metaLevelFactor": 0.4,
"metaLevelCap": 10,
"speciesSingletonBonus": 14,
"speciesRareBonus": 8,
"speciesRareMaxPop": 5,
"notableKills": 40,
"notableRenown": 200,
"extremeNotableKills": 80,
"extremeNotableRenown": 400,
"scannerAttackBonus": 40,
"scannerHotBonus": 18,
"scannerWarmBonus": 8,
"scannerSpectacleBonus": 12,
"scannerActionKillsFactor": 0.2,
"scannerActionKillsCap": 10,
"scannerWarriorBonus": 6,
"scannerSingletonBonus": 8,
"scannerCharKillsFactor": 0.15,
"scannerCharKillsCap": 8,
"scannerCharRenownDivisor": 120,
"scannerCharRenownCap": 8,
"scannerColdActionMul": 0.25,
"scannerColdCharMul": 0.35,
"scannerRankCharWeight": 0.18,
"characterLedEventMul": 0.35,
"eventLedTarget": 0.7,
"mixWindow": 20,
"hardCooldownSeconds": 12,
"fixedDwellBeatCooldownSeconds": 45,
"repeatArcPenaltyPer": 24,
"repeatArcPenaltyCap": 72,
"enrichTopK": 8,
"metaCacheTtl": 2
},
"sources": [
"IdleSpectator/scoring-model.json",
"IdleSpectator/InterestScoringConfig.cs",
"IdleSpectator/InterestScoring.cs",
"IdleSpectator/WorldActivityScanner.cs",
"IdleSpectator/InterestDirector.cs",
"IdleSpectator/InterestVariety.cs",
"IdleSpectator/Events/Feeds/InterestFeeds.cs"
],
"designIntent": [
"Actions matter much more than characters.",
"Same action intensity → more important character wins (tie-break).",
"Multi-person fights outrank anonymous 1v1s.",
"Anonymous / single-notable Duels are soft sticky (short MaxWatch, early variety valve).",
"Hard sticky combat is reserved for Skirmish+ or notable-pair Duels.",
"Extremely notable 1v1s (kings/favorites) can beat nameless melees.",
"Founding tips fire on meta outcomes (new_city / new_kingdom), not decision intent.",
"Consecutive same variety-arc shows stack a score penalty until a different arc is shown.",
"TotalScore is the sole ranking signal; typed rules (combat vs vignette) gate interrupts."
],
"pipeline": [
{
"id": "feeds",
"name": "Feeds → candidates",
"detail": "WorldLog, happiness, scanner, battle clusters, harness injects upsert InterestCandidate with EventStrength, CharacterSignificance, ParticipantCount, NotableParticipantCount (no Urgency tier)."
},
{
"id": "variety",
"name": "Variety pick",
"detail": "InterestVariety.Pick soft-splits EventLed vs CharacterLed (~70/30), applies novelty penalties, RecalcTotal, EnrichTopK, then probabilistic top-3 by TotalScore."
},
{
"id": "director",
"name": "Director switch",
"detail": "InterestDirector.CanSwitchTo gates camera changes via score margins (cutInMargin/rotateSlack), settle grace, and typed combat-vs-vignette cut-ins."
},
{
"id": "camera",
"name": "Camera + UI",
"detail": "CameraDirector.Watch + dossier story beats from action verbs (Fighting/War/Grief). Fill/ambient with no sharper beat leaves the reason row empty."
}
],
"totalScore": {
"file": "InterestScoring.RecalcTotal",
"formula": "EventStrength + scaleBonus + CharacterSignificance * charWeight + VisualConfidence * visualMultiplier + Novelty * noveltyMultiplier",
"charWeight": {
"EventLed": "weights.charWeightEventLed",
"CharacterLed": "weights.charWeightCharacterLed"
},
"scaleBonus": "See weights.mass* / duel* / notableSkirmish*",
"directorPolicy": {
"cutInMargin": "weights.cutInMargin",
"rotateSlack": "weights.rotateSlack",
"fillScoreMax": "weights.fillScoreMax",
"dwell": "weights.dwellFill / dwellNormal / dwellHot"
}
},
"workedExamples": [
{
"id": "fight_king_vs_peasant",
"scenario": "Same evt=70 Action fight; king char=40 notables=1 vs peasant char=5 notables=0",
"winner": "FightKing",
"harnessAssert": "ap12 interest_score_order"
},
{
"id": "melee_vs_anon_duel",
"scenario": "Same evt=55; 8-fighter anon melee vs 2-fighter anon duel",
"winner": "Melee",
"harnessAssert": "ap23 interest_score_order"
},
{
"id": "king_duel_vs_nameless_melee",
"scenario": "Same evt=55; king duel notables=2 vs 8-fighter nameless melee",
"winner": "DuelKings",
"harnessAssert": "ap33 interest_score_order"
}
],
"tweakKnobs": [
{
"id": "charWeightEventLed",
"effect": "How much who-you-are matters on event scenes"
},
{
"id": "massBaseBonus",
"effect": "How strongly mass fights beat thin duels"
},
{
"id": "duelNotablePairBonus",
"effect": "How easily king duels outrank nameless melees"
},
{
"id": "duelAnonymousPenalty",
"effect": "Penalty on anonymous 1v1"
},
{
"id": "clusterFighterWeight",
"effect": "Changes battle EventStrength seed"
},
{
"id": "eventLedTarget",
"effect": "Soft mix toward actions vs character vignettes"
}
]
}