AEquilibrium / Accelerated Accelerated · 12 modules

AshForge Equilibrium · the whole tool, one course

One tick, then another.
Production is always a tick behind.

Equilibrium simulates an economy: resources, recipes, markets and the prices that move between them. Its controls are named for what you want rather than what they set, which is why two of them look broken until you know what they actually do.

Application  AshForge Equilibrium Prerequisites  none Format  one course, 12 modules Time  ~75 min

What it is

A tick-based simulation. Each tick, production runs, trade clears and prices move toward their targets.

Modules 1–4 are the tick, 5–8 are markets and pricing, 9–12 are supply chains and export.

Two that look broken

Bias is a target, not a price, and Buy and Sell do not do what their labels suggest. Neither is a bug.

Modules 5 and 6. They account for most confusion with this tool.

Why this is one course

Equilibrium is a focused tool. Its content is 12 things worth knowing, not three escalating tiers — the old split implied the later material needed the earlier, and it does not. Read straight through, or jump to the module that matches your problem.

01

What ships in the box

The demo economy

Read 3 resources 1 market

The list on the left holds both resources and markets, tagged [R] and [M]. On a fresh project it reads like this, and the numbers in brackets are stock and unit value.

[R] Iron Ore       (200 @ 1.50)
[R] Food Rations   (150 @ 3.00)
[R] Luxury Spices  (40 @ 12.00)
[M] Frontier Outpost (2 offers)

What the list does not show you is the field that decides everything, so it is worth knowing before you press anything: every one of those resources has a Demand of 50. Not because someone chose 50 for iron and again for spices, but because 50 is the model's default and the demo never overrides it.

Hold that next to the stock column. Iron Ore has four times more stock than demand. Food Rations has three times. Luxury Spices has less stock than demand. Those three relationships are the entire plot of what happens next.

Key
A resource's price does not move because of its category, its weight, or how expensive it already is. It moves on the gap between Demand and Stock, and nothing else in this model.
02

Run Sim

One tick

Run one press

Press Run Sim once. The log strip reports two things, and the second one matters as much as the first.

[INFO] (Shell) Economy simulation step executed (nonblock + conditions + cancel support).
[INFO] (EquilibriumStore) Saved Economy project 'Unnamed Mod' to …/equilibrium/economy

So a sim step is also a save. There is no separate "commit this run" — the tick happens and the result is on disk before you have finished reading the line.

Now look at the list again.

ResourceBeforeAfter one tickWhat happened
Iron Ore200 @ 1.50192.5 @ 0.10 Massively oversupplied, so the price fell as far as it is allowed to.
Food Rations150 @ 3.00145 @ 2.00 Oversupplied, so the price fell by a third.
Luxury Spices40 @ 12.0040.5 @ 12.10 Scarce, so the price rose.

Iron Ore lost 93% of its value in a single tick, which looks alarming and is the most common reason someone decides the simulation is broken. It is not. Here is the whole calculation the tool performs on every resource, every tick.

imbalance = Demand − Stock priceAdj = imbalance × 0.01 × elasticity Value = max(0.1, Value + priceAdj) Stock += imbalance × TradeImpact Iron Ore, tick one: imbalance = 50 − 200 = −150  ·  priceAdj = −150 × 0.01 = −1.50 Value = max(0.1, 1.50 − 1.50) = 0.10  ·  Stock = 200 + (−150 × 0.05) = 192.5

Figure 01 — one tick, one resource Elasticity and Global Elasticity both default to 1, and Trade Impact to 0.05, so on a fresh project the price adjustment is simply the imbalance divided by a hundred.

The floor
That max(0.1, …) is a hard floor. Iron Ore's adjustment was exactly −1.50 against a value of 1.50, which lands on zero, and the floor catches it at 0.10. A resource in this model can become nearly worthless but never free.
03

The test that proves you understand it

Predict the next one

Do paper first

Reading a formula is not the same as believing it. So before you press Run Sim a second time, work out what it is going to do and write the numbers down.

On paper

For each resource, in this order

  1. Subtract its current stock from 50. Demand is still 50 — nothing in a sim tick changes it
  2. Divide that by a hundred, and add it to the current value. elasticity and global elasticity are both 1 on a fresh project
  3. If the answer is below 0.1, write 0.1. the floor
  4. Multiply the same imbalance by 0.05 and add it to the stock. Trade Impact — supply drains toward demand as well
ResourceStanding atYou should predictThe tool produced
Iron Ore192.5 @ 0.100185.375 @ 0.100 185.375 @ 0.100
Food Rations145.0 @ 2.000140.250 @ 1.050 140.250 @ 1.050
Luxury Spices40.5 @ 12.10040.975 @ 12.195 40.975 @ 12.195
Verified
Those predictions were written down before the second tick was run, and the tool matched every one of them to three decimal places. The model is fully deterministic, which means from here on you are not guessing at your economy — you can work out where it is heading and check whether that is what you wanted.
03b

The one thing that isn't deterministic

Each tick, before any of the above, the tool rolls once against Shock Prob0.3 by default. On a hit it picks one resource at random and multiplies its stock by 0.6, then writes an Event row into the trade ledger reading “Shortage on <resource>!”.

Neither of the two ticks above rolled a shock, which is why the arithmetic came out clean. If your numbers disagree with your prediction by a suspiciously round 40%, check the ledger before you check your maths.

Key
If you want a predictable economy while you are learning the tool, set Shock Prob to 0 in Sim Settings. Put it back when you want to find out whether your design survives a bad harvest.
Corrected
The heading above is not quite true, and the intermediate tutorial is where it breaks. A shock is the only thing that disturbs a price — which is what this page is about, so every prediction here holds. But once you reach markets you will find that every offer's Available quantity also takes a random step of up to ±1.5 per tick, in a line that runs outside the shock branch entirely. Setting Shock Prob to 0 makes prices deterministic and leaves quantities wandering. See The Second Market.
04

On disk

Where it all lives

Read 3 files

Equilibrium does not keep your economy in one blob. It splits it three ways, under equilibrium/economy in the tool's data folder, and the split is worth knowing because it tells you what the tool thinks the parts are.

FileHoldsUseful because
resources.economy.json Every resource: stock, value, demand, elasticity, weight, category. This is where you can read the real numbers when the list's rounding hides them.
markets.economy.json Markets, their price bias, and their offers. Offers reference a resource by name, so renaming a resource matters here.
state.economy.json The wallet, player stock, sim parameters, price history, recipes, trade ledger. Price history is a plain series per resource — the raw material for a chart.

The list on the left rounds for display: Iron Ore reads 185 @ 0.10 while the file holds 185.375. For a first tutorial that does not matter, but the moment you start checking your own predictions it does, and the file is where the honest number is.

Careful
Everything above is written by an autosave. An Undo is the one action that changes the window without changing those files — see the warning at the top of this page.
05

The silent no-op

Why Buy and Sell look broken

Do selection matters

Select Iron Ore in the list, set the quantity to 5, and press Buy. Nothing happens. No purchase, no error, no line in the log — the wallet still reads 1000.00.

This is the single most common reason someone decides the trade panel is unfinished, and it is worth being precise about what is going on, because the tool is doing exactly what it was written to do and telling you nothing about it.

Buy and Sell act on a market, never on a resource. The handler's first line checks that the current selection is a market and returns immediately if it is not. There is no message on that path, so a resource selection and a broken button look identical from the outside.

Key
The trade panel is not asking what you want to buy. It is asking where. Select the market, and the buttons come alive.

Now select [M] Frontier Outpost and press Buy again with the same quantity of 5.

[INFO] (Shell) Bought 5 Iron Ore for 5.94 (wallet 994.06)

Which raises the obvious question, since you never told it you wanted iron: where did Iron Ore come from?

From the market's first offer. The handler takes Offers[0] and trades that, whatever else the market carries and whatever is highlighted in the list. Frontier Outpost happens to list iron first, so iron is what you bought. Reorder the offers and the same button spends your money on something else.

Careful
There is no resource picker on the trade panel. If you want to buy the second thing a market sells, you cannot — not from here. The first offer is the only one the buttons can reach, which makes offer order a functional decision rather than a cosmetic one.

Drill01

Prove the selection rule to yourself
  1. Select a resource, press Buy, and read the wallet.
  2. Select the market, press Buy, read it again.
  3. Watch the log line name the resource you never chose.

Done when you can predict which of the two presses moves the wallet before you make it.

Drill02

Make the first offer something else
  1. With the market selected, use the offer rows in the inspector.
  2. Change the resource on the top row.
  3. Press Buy and read the log.

Done when the purchase follows the top row rather than the selection.

06

Regional pricing

Bias is a target, not a price

Derive 20% per tick

A market's Price Bias is a multiplier on what it thinks a resource is worth — above 1.0 it is an expensive place, below it a cheap one. What it does not do is set the price. It sets a destination.

Each tick, every offer moves one fifth of the remaining distance toward the market's biased view of the resource's current value. The sell side chases the same target scaled to 85%, and that gap between the two targets is where the market's spread comes from — it is not configured anywhere, it falls out of the multiplier.

target = BaseValue × PriceBias Buy += (target − Buy) × 0.2 Sell += (target×0.85 − Sell) × 0.2 the 15% gap between the two targets is the market's spread Measured, bias 2.0 on a resource sitting at the 0.10 price floor: target = 0.1000 × 2.00 = 0.2000 Buy  1.1880 + (0.2000 − 1.1880) × 0.2 = 0.9904 Sell 0.7986 + (0.1700 − 0.7986) × 0.2 = 0.6729 A price never arrives at its target — it halves the gap, then halves it again. Raising bias once moves a price for many ticks afterwards.

Figure 01 — one tick, one offer Both prices are clamped to the same 0.1 floor the resource itself has, so a market cannot price a collapsed resource below it either.

Key
Because the approach is proportional, a bias change is not a price change. It is a change in where the price is heading, and you need to run several ticks before the market reflects it. If you set a bias and nothing appears to happen, you have not run enough ticks.
Watch out
The target follows BaseValue, which tier one taught you is itself moving every tick. You are chasing a moving destination, so an offer's price and its resource's value converge on each other rather than one settling onto the other.
07

Two opinions of one resource

The second market

Build arbitrage

With one market the trade panel has nothing to say. It reads, permanently:

Arbitrage: add 2+ markets trading the same resource.

That line is not a placeholder waiting on a simulation run — it is a hard precondition. Arbitrage is defined as a route between markets, so a single market can never produce one however long you run it.

Build

Give the economy somewhere to trade with

  1. Press New Market and name it Far Depot. a route needs two ends, and the tool checks the count before anything else
  2. Set its Price Bias to 2.5, leaving Frontier Outpost at 1.0. identical opinions produce identical prices, and identical prices have no gap to trade on
  3. Add an offer for a resource Frontier Outpost already sells. the route is computed per resource, so the two markets must overlap or there is nothing to compare
  4. Press Run Sim a dozen times. at a fifth of the gap per tick, the two markets need several ticks to visibly diverge

The tool now compares, for each resource, the cheapest buy price across every market against the dearest sell price, discards the pairing if both fall in the same market, and subtracts the transport cost. What survives with a positive number is a route.

profit per unit = dearest sellcheapest buyTransportCost
Key
Note which side of each market the calculation uses. You buy at a market's buy price and sell at another's sell price — and the sell price is chasing a target 15% lower than the buy price is. The spread you learned about in lesson 02 is working against you here, on top of the toll.
08

Why half your economy cannot be traded

The toll is flat

Diagnose the payoff

Here are two runs of the build you just made. Same two markets, same bias of 1.0 against 2.5, same 0.50 transport cost. The only thing that changes is which resource is on the shelf.

ResourceCheapest buyDearest sellProfit / unitWhat the tool says
Iron Ore at 0.100.25430.2441 −0.5102no profitable routes (after transport)
Luxury Spices at 13.7213.640328.9231 +14.7828Frontier Outpost → Far Depot  +14.78

The bias spread did not change. The toll did not change. The price of the thing being moved changed, and that was enough to flip the route from impossible to worth 14.78 a unit.

The reason is that TransportCost is an absolute figure, not a percentage. Moving one unit of anything costs 0.50. On a resource whose entire value is 0.10 that toll is five times the goods, and no regional bias can ever recover it — the prices simply do not have room to differ by more than half a coin. On a resource worth 13.72, the same toll is less than 4% of the value and is trivially cleared.

Design
This is the lever you have over trade in your mod, and it is worth stating plainly: raising TransportCost does not slow trade down evenly, it deletes the bottom of your economy first. Cheap bulk goods stop being routable long before luxuries feel anything. If you want a hauling economy where ore matters, the toll has to be small relative to ore — not small relative to your most valuable resource.
SymptomWhat it meansFix
Arbitrage line never leaves "add 2+ markets" Fewer than two markets exist, or no two of them list the same resource. Add the resource as an offer in both markets.
"No profitable routes" on a cheap resource Working as designed. The spread cannot exceed a flat toll. Lower TransportCost, or accept that bulk goods are local.
Bias changed but prices did not Bias sets a target approached 20% a tick; one tick moves very little. Run more ticks before judging it.
Buy spends money on the wrong resource The panel always trades Offers[0]. Reorder the offer rows so the intended one is first.
Quantities drift with Shock Prob at 0 Offer availability has its own ±1.5 random step every tick. Nothing to fix — do not build a design that needs stock to hold still.
09

Rate

A rate, not an order

Build fractional batches

Press New Recipe and build the simplest useful thing: ten Iron Ore in, one bar out, at a Rate of 2.

Build

One conversion

  1. Add an input of 10 Iron Ore. quantities are per batch, not per tick — the rate multiplies them
  2. Add an output of 1 of another resource. outputs are matched by name against the resource list, exactly
  3. Set Rate to 2 and leave it Enabled. rate is the most batches this recipe may attempt in one tick
  4. Give the input plenty of stock, then run one tick. with 100 ore there is room for both batches, so you see the clean case first
Input stockBatches it can runOre consumedOutput made
1002 (the full Rate)202.0
151.515 — all of it1.5

The second row is the one worth sitting with. With only 15 ore against a batch size of 10, the recipe did not refuse to run and it did not run once — it ran one and a half times, drained the input to exactly zero, and produced 1.5 of the output.

The rate is a ceiling. What actually runs is the smallest of the rate and what each input can cover, and that quantity is a real number rather than a whole one. So a recipe never stalls for want of a full batch; it simply runs smaller and smaller as its input runs down.

Key
You will not get whole numbers out of a supply chain, and there is nowhere to ask for them. If your design depends on producing exactly one of something, the model cannot express that — plan for fractional stock, or keep inputs comfortably above the batch size so the ceiling is what binds.
10

Diagnosis

Four ways to make nothing

Break on purpose

Break the recipe you just built, four times, and watch what each break does to the stock. Three of them are harmless. One of them is not, and you cannot tell which from the window — only from the numbers.

The breakInputs consumedOutputs madeVerdict
Enabled untickednonenoneInert. Safe.
Rate set to 0nonenoneInert. Safe.
Input names a resource that does not existnonenoneInert. Safe.
Output names a resource that does not existall of themnoneDestructive. Every tick.

The asymmetry is in the order the tool does things. It resolves every input before it commits to anything, and abandons the recipe if one of them is missing. It resolves each output only when it comes to add it, long after the inputs have already been taken away — and an output it cannot resolve is skipped rather than rolled back.

resolve ALL inputs and cap the batches consume the inputs (the point of no return) resolve each output one at a time missing input → abandon, nothing spent missing output → skip, inputs ALREADY spent Measured: output renamed to something that does not exist, one tick. Ore 100 → 80  ·  output stock unchanged at 7  ·  no log line, no warning.

Figure 01 — why one typo is worse than the other The check that saves you on the input side has no equivalent on the output side.

Renames
Recipes match resources by name, exactly. Renaming a resource silently breaks every recipe that referred to it — and which kind of break you get depends on which side it was on. A renamed input makes the recipe inert; a renamed output turns it into a drain. This is the same name-coupling that market offers have, and it is worth grepping your economy after any rename.

Drill01

Watch the destructive case happen
  1. Point your recipe's output at a name you never created.
  2. Note the input's stock, run one tick, note it again.
  3. Confirm nothing was created anywhere.

Done when you have seen stock leave the world with nothing to show for it, and know that the window never said so.

Drill02

Tell the four breaks apart blind
  1. Have someone break the recipe one of the four ways.
  2. Run one tick and read only the stock numbers.
  3. Say which break it was.

Done when you can separate the destructive case from the three inert ones using stock alone.

11

Ordering

Production is one tick late

Derive the lag

Enable a healthy recipe, run one tick, and check the input's price against what tier one taught you to predict. It will not match — and the mismatch is not a bug.

Within a single tick the tool prices everything first and produces second. The price loop reads the stock as it stood at the start of the tick, works out every resource's new value from that, and only then do the recipes move any stock around.

Measured on a recipe consuming 20 ore a tick: the ore's stock went from 100 to 77.5 during the tick, while its price was calculated from 100. The drop the recipe caused shows up in the price on the next tick.

tick N   price ← stock at start of tick N      then recipes change stock
tick N+1 price ← stock the recipes left behind  ← the recipe's effect appears here
Key
When you are predicting a supply chain on paper, predict the price from last tick's stock, not this one. Every consumer of a resource pushes its price up a tick after it actually ate anything, so a chain of recipes takes as many ticks to settle as it has links.
Use it
This lag is what makes a supply chain feel like one. Because the price signal trails production, an economy driven by recipes oscillates toward balance rather than snapping to it — which is usually what you want, and is worth leaving alone.
12

The artefact

Ship it

Ship one file

Everything so far has lived in the tool's own three working files. Press Export Runtime and the whole economy is written out as a single document for the game to read.

[INFO] (Shell) Runtime exported: …/AshForge Equilibrium/output/unnamed_mod_economy_runtime.json

The name comes from your mod name, lowercased and made filename-safe, so an unnamed project exports as unnamed_mod_…set the mod name before you ship or you will hand someone a file called unnamed. The destination is the tool's output folder, beside the equilibrium folder you have been working in the whole time.

Unlike the three working files, which split the economy into resources, markets and state, the runtime export is one document containing all of it — resources, markets and their offers, the sim parameters, the player wallet, the trade ledger and your recipes. The demo economy with one recipe comes to about two kilobytes.

Before you exportWhy
Set the mod nameIt becomes the filename. unnamed_mod is the default and it ships.
Run a tick and read the stockA destructive recipe is invisible until you look at what it consumed.
Check every recipe output resolvesThe one failure mode that costs resources rather than doing nothing.
Decide on Shock ProbIt exports with the project. Leaving it at 0 ships a world with no bad harvests.
Check TransportCost against your cheapest tradeableA flat toll silently makes bulk goods untradeable — see tier two.
Careful
Export is a snapshot, not a link. Editing the economy afterwards does not update an exported file — you press the button again. If the game is reading a stale export, it is reading a stale export, and nothing in the tool will tell you.

Course complete

What you now know

Check yourself

  • Price moves on the gap between Demand and Stock, and on nothing else in this model.
  • The demo ships every resource at the default Demand of 50 against stocks of 200, 150 and 40, which is why two prices collapse on the first tick and one rises.
  • The adjustment is imbalance × 0.01 × elasticity, and the result is clamped to a floor of 0.1.
  • Stock moves too, by imbalance × TradeImpact, so supply drains toward demand as well as price falling toward it.
  • You can predict a tick on paper and be right to three decimal places, provided no shock fires.
  • A shock has a 30% chance per tick and multiplies one random resource's stock by 0.6, logged in the ledger as an Event.
  • Run Sim also saves. The economy lives in three files, and the list rounds where the files do not.
  • Undo restores the window but not the file, so follow an undo that matters with a save.
  • Buy and Sell act on a market, never on a resource, and they fail silently when the selection is wrong.
  • They always trade the market's first offer, so offer order is a functional decision.
  • Price Bias sets a target, not a price. Each tick an offer moves a fifth of the way toward BaseValue × PriceBias.
  • The sell side chases 85% of the same target, and that is where a market's spread comes from.
  • Arbitrage needs two markets listing the same resource; one market can never produce a route.
  • A route pays dearest sell − cheapest buy − TransportCost, and the spread works against you inside that sum.
  • TransportCost is flat, so it prices cheap goods out of trade entirely while barely touching expensive ones.
  • Offer availability is random every tick regardless of Shock Prob — correcting what tier one told you.
  • A recipe converts stock once per tick. There is no queue, no worker and no duration.
  • Rate is a ceiling. A short recipe runs a fractional batch and drains its input to zero rather than refusing.
  • Fractional stock is unavoidable; the model cannot be asked for whole numbers.
  • Disabled, Rate 0, and an unresolvable input are all inert.
  • An unresolvable output is destructive — inputs are consumed, nothing is made, silently, every tick.
  • Recipes match resources by name, so a rename breaks them, and which side it was on decides whether the break is harmless.
  • Pricing runs before production, so a recipe's effect on price arrives one tick late.
  • Export Runtime writes the entire economy as one JSON document named after the mod, and it is a snapshot you must re-take after every change.

That is Equilibrium. Its recipes and resources reach the game as recipe and item definitions; ⛔ the market simulation itself does not — there is no trade, price or currency definition for it to become. An economy can inform what a mod ships; it cannot itself be shipped.