From d19ce2821f73ce30c51060042c6ee1d4de3fc510 Mon Sep 17 00:00:00 2001 From: dejvino Date: Sun, 9 Aug 2026 07:08:30 +0200 Subject: [PATCH] Cut baseline wear to something the parts economy can pay for Tyres shed 8e-5 per metre, so twelve kilometres of clean driving - no crashes at all - took them from new to ruined. A two-kilometre round trip paid ~0.3 parts against ~0.24 of condition spent: driving perfectly barely broke even, and any knock put you permanently behind. That is not a decision about how hard to push the car, it is a decline with no way to arrest it. At a quarter of the old rates the same trip spends about 0.06, so roughly two clean runs pay for one bad crash. Enough slack to gamble with, not enough to ignore. Co-Authored-By: Claude Opus 5 --- src/sim/car.ts | 16 +++++++++++++--- src/sim/sim.test.ts | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/sim/car.ts b/src/sim/car.ts index 610d9d3..3d5ef2b 100644 --- a/src/sim/car.ts +++ b/src/sim/car.ts @@ -149,13 +149,23 @@ const MAX_DAMAGE_PER_STEP = 0.25; * * Baseline wear is deliberately quicker than real life so decline is legible * within a session, but it has to stay inside what the parts economy can pay - * for — see the reasoning on the two constants above. + * for. The old figures did not: tyres shed 8e-5 per metre, so twelve clean + * kilometres — no crashes at all — took them from new to ruined, while a + * two-kilometre round trip paid about 0.3 parts against 0.24 of condition + * spent. Driving perfectly barely broke even and one knock put you permanently + * behind, which is a decline with no way to arrest it rather than a decision + * about how hard to push the car. + * + * At a quarter of that a typical mission spends about 0.06 condition against + * ~0.3 parts earned, so roughly two clean runs pay for one bad crash. That is + * the ratio the whole risk/reward loop rests on: enough slack to gamble with, + * not enough to ignore. */ export function applyWear(c: CarCondition, w: WearInput): CarCondition { const impact = w.impactForce / IMPACT_REFERENCE; const damage: Subsystems = { - engine: w.throttle * w.dt * 6e-4 + impact * 0.32, - tires: w.distance * 8e-5 + impact * 0.5, + engine: w.throttle * w.dt * 1.5e-4 + impact * 0.32, + tires: w.distance * 2e-5 + impact * 0.5, chassis: impact * 1.0, }; diff --git a/src/sim/sim.test.ts b/src/sim/sim.test.ts index f27238b..cf41af9 100644 --- a/src/sim/sim.test.ts +++ b/src/sim/sim.test.ts @@ -85,6 +85,20 @@ describe('car condition', () => { expect(crashes).toBeGreaterThan(5); }); + it('lets a careful driver come out ahead of the parts they are paid', () => { + // Two kilometres at 20 m/s with nothing hit: the shape of an ordinary + // mission. It has to cost distinctly less than the ~0.3 parts one pays, or + // driving perfectly is a losing move and the economy has no floor. + let c = freshCondition(); + const steps = Math.round((2000 / 20) * 60); + for (let i = 0; i < steps; i++) { + c = applyWear(c, { dt: 1 / 60, distance: 20 / 60, throttle: 1, impactForce: 0 }); + } + const spent = 3 - (c.level.engine + c.level.tires + c.level.chassis); + expect(spent).toBeGreaterThan(0.02); + expect(spent).toBeLessThan(0.12); + }); + it('makes a worn car measurably worse to drive', () => { const fresh = deriveHandling(freshCondition()); const worn = deriveHandling({