fix: Changing way to sell with demand

This commit is contained in:
gauvainboiche
2026-10-08 12:34:33 +02:00
parent 1734487f1e
commit c98995f310
7 changed files with 103 additions and 38 deletions
+38 -7
View File
@@ -13,7 +13,7 @@ import {
simulateOffline,
upgradeVisible,
} from '../public/js/engine/engine.js';
import { bulkCost, demandPerSecond, maxAffordable } from '../public/js/engine/formulas.js';
import { balancedPrice, bulkCost, demandPerSecond, maxAffordable } from '../public/js/engine/formulas.js';
import { createState, sanitizeState, serializeState } from '../public/js/engine/state.js';
import { loadContext } from './helpers.js';
@@ -35,11 +35,24 @@ test('maxAffordable never overspends and is maximal', () => {
}
});
test('demand is flat at/below the fair price and drops above it', () => {
test('lower prices sell more, higher prices sell less, with no ceiling at the reference price', () => {
const { market } = ctx.rules;
const atFair = demandPerSecond(market, market.fairPrice, 1);
assert.equal(demandPerSecond(market, market.fairPrice / 5, 1), atFair);
assert.ok(demandPerSecond(market, market.fairPrice * 2, 1) < atFair / 3);
const at = (price, mult = 1) => demandPerSecond(market, price, mult);
const ref = at(market.referencePrice);
assert.equal(ref, market.baseDemand);
assert.ok(at(market.referencePrice / 2) > ref * 2, 'half price sells more than double');
assert.ok(at(market.minPrice) > at(market.referencePrice / 2));
assert.ok(at(market.referencePrice * 2) < ref / 2);
assert.equal(at(market.referencePrice, 3), ref * 3, 'bonuses scale demand');
});
test('the balanced price moves with output and demand bonuses', () => {
const { market } = ctx.rules;
const balanced = (supply, mult) => balancedPrice(market, supply, mult);
const p = balanced(10, 1);
assert.ok(Math.abs(demandPerSecond(market, p, 1) - 10) < 1e-9, 'demand equals supply there');
assert.ok(balanced(100, 1) < p, 'more output -> lower balanced price');
assert.ok(balanced(10, 4) > p, 'more demand -> higher balanced price');
});
test('click makes a unit from material', () => {
@@ -139,12 +152,12 @@ test('auto-buy restocks material when funds allow', () => {
});
test('material is costly at first and cheaper relative to the sale price as production grows', () => {
const { fairPrice } = ctx.rules.market;
const { referencePrice } = ctx.rules.market;
const costShare = (totalProduced) => {
const s = fresh();
s.totalProduced = totalProduced;
const d = derive(s, ctx);
return d.batchCost / d.batchSize / fairPrice;
return d.batchCost / d.batchSize / referencePrice;
};
assert.ok(costShare(0) > 0.25, 'expensive at the start');
assert.ok(costShare(1e4) < costShare(0));
@@ -178,6 +191,24 @@ test('the material market is erratic but stays within its bounds', () => {
assert.ok(new Set(seen.map((f) => f.toFixed(2))).size > 100, 'does not sit still');
});
test('material prices have cents, not just whole numbers', () => {
const s = fresh();
s.materialFactor = 0.8137;
const { batchCost } = derive(s, ctx);
assert.notEqual(batchCost, Math.round(batchCost));
assert.equal(batchCost, Math.round(batchCost * 100) / 100);
});
test('the material price changes every 10 seconds, not before', () => {
const m = ctx.rules.materialMarket;
assert.equal(m.updateEverySeconds, 10);
const s = fresh();
advance(s, ctx, 9.5, () => 0.9);
assert.equal(s.materialFactor, 1);
advance(s, ctx, 1, () => 0.9);
assert.notEqual(s.materialFactor, 1);
});
test('auto-buy waits for a fair price unless stock is nearly gone', () => {
const s = fresh();
s.upgrades = ['auto_buy'];