fix: attunement system spec-vs-code discrepancies (issue #331)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m24s

- Fix conversion rate level scaling from linear (1+level*0.5) to exponential (1.5^(level-1)) in conversion-rates.ts
- Fix getAttunementLevelMultiplier formula to match spec §4.3
- Add level-up logging in attunementStore.ts via combat store addActivityLog
- Clarify getAttunementConversionRate returns flat base rate (level scaling applied separately)
- Update spec §8 to describe time-based puzzle room system matching code implementation
- Add 17 regression tests verifying exponential scaling, base rate behavior, and spec table values
This commit is contained in:
2026-06-08 22:08:17 +02:00
parent 64c1d2f51e
commit 573130cdb1
8 changed files with 199 additions and 13 deletions
+3 -3
View File
@@ -24,7 +24,7 @@ export interface ConversionRateEntry {
pactBase: number;
/** Sum of base rates */
baseRate: number;
/** Attunement level multiplier: 1 + Σ(relevantAttunementLevel × 0.5) */
/** Attunement level multiplier: 1 + Σ(1.5^(attunementLevel-1) - 1) per relevant attunement */
attunementMult: number;
/** Pact level multiplier: 1 + Σ(pactCount_element × invokerLevel × 0.25) */
pactMult: number;
@@ -100,13 +100,13 @@ export function computeConversionRates(params: ConversionRateParams): Conversion
let totalRawDrain = 0;
// ── Step 1: Compute attunement level bonuses per element ──────────
// Each attunement level adds +0.5 to the multiplier for conversions
// Each attunement contributes 1.5^(level-1) exponential scaling to conversions
// where the attunement's primary element is the destination or a component.
const attunementBonuses: Record<string, number> = {};
for (const [id, state] of Object.entries(attunements)) {
if (!state.active) continue;
const level = state.level || 1;
const bonus = level * 0.5;
const bonus = Math.pow(1.5, level - 1) - 1;
// Determine which elements this attunement boosts based on its primary mana type
for (const [elem, cost] of Object.entries(CONVERSION_COSTS)) {