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 <noreply@anthropic.com>
This commit is contained in:
parent
84ee726a51
commit
d19ce2821f
@ -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,
|
||||
};
|
||||
|
||||
|
||||
@ -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({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user