1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
//! Goods, stock and a price per good (issue: "basic economics").
//!
//! **The shape is Edgeworth barter, not an auction.** Parunak et al. (corpus doc `10.1007_11678809_10`) note
//! that "a less-studied alternative to auction systems is the pattern of Edgeworth barter, in which buyers
//! and sellers interact directly with each other in repeated pairwise transactions, **without the benefit of
//! an auctioneer**". Twenty-four villagers do not clear a market; they produce, they eat what they produced,
//! and the price is an *observation* of how that went.
//!
//! **The price is read off how full the stores are, not integrated from the flow.** The production/consumption
//! model in *Games and AI* (corpus doc `eth-cgl-ar_games-Zun16a`) states its acceptance test — "if the
//! parameters are chosen such that the inflow of resources into the system equals the outflow, then the
//! economy is **stable and prices fluctuate around a constant value** ... **shortages and oversupply**" move
//! it — and its own Model A satisfies it by pricing from the **storage ratio** rather than from a flow:
//! `p = w · v(r)` with `r = S_cur / S_max`, and *"the price modifier term `v(r)` doubles the price if the
//! storage is empty and halves the price if the storage is full"* (§3.1.1). [`update_prices`] applies
//! exactly that `v`, over village-wide stores and **per head**. The earlier `Δprice ∝ (produced − consumed)`
//! is gone: it integrated net stock, so a village that baked more than it ate saw its price *rise*, and it
//! counted units, so the same six loaves made a glut of one village and a famine of thirty. Both defects are
//! in `docs/research/economics.md` "Open contradictions" and both are repaired by
//! [`storage_price`](crate::model::price::storage_price).
//!
//! **Goods are not fungible.** Henrich et al. 2005 (DOI `10.1017/S0140525X05000142`, in the corpus): "meat
//! and honey are meticulously shared among the Ache, but goods purchased by money are not". There is no
//! money here and no exchange rate; a good is a quantity and nothing more.
//!
//! **Nothing gates, and a short meal is still paid for.** Last iteration measured that putting a new
//! condition on a *dominant* activity wrecks the village (rivals 29 → 55 at seed 42), so having bread
//! changes what a person prefers to do and never what a person is allowed to do: an empty shelf still lets
//! a villager walk to the table and sit down. What it cannot do is feed them. An activity's `satisfies` is
//! paid in proportion to what its `consumes` actually found in `Stock` ([`crate::behavior`]'s
//! `arrive_and_satisfy`), so a meal from an empty larder costs the ticks and pays nothing — the failure is
//! priced, never prevented. Before that, ~77% of this village's meals were eaten out of a store it did not
//! have.
use *;
use craterequire_core;
use crate;
use crateGoodId;
/// Per-person holdings, one level per good in definition order, each in `[0, Tuning::stock_ceiling]`.
///
/// This is the first per-person state added since the save format was written, so it is in
/// [`PersonSave`](crate::PersonSave) and `SocietySave::VERSION` is 2. A person without the component is
/// treated as holding nothing and is given one at spawn by
/// [`size_person_state`](crate::size_person_state).
;
/// The price of each good, in definition order.
///
/// One number per good, starting at 1.0 and clamped to `[Tuning::price_floor, Tuning::price_ceiling]` so a
/// village cannot inflate for ever. A host reads it through `ctx.price("bread")`.
;
/// What one unit of a good is worth to a person holding `held` of it: `1 / (1 + held)`.
///
/// Diminishing marginal value, and the crate's only honest option: a store is a level, so somebody with an
/// empty shelf wants a unit more than somebody with a full one. No curve, no utility function, no new rate —
/// a person with none values a unit at 1.0 and a person at a full store at `1 / (1 + ceiling)`.
///
/// This is what makes a **joint surplus** possible between two people, which is the condition Hall & Milgrom
/// require before a bargain begins at all: "once a qualified worker and an employer have met and found that
/// they would enjoy a joint surplus, the threats to disclaim the match are hollow" (Hall 2005, DOI
/// `10.3386/w11678`, in the corpus, reporting Hall & Milgrom).
/// Applies every finished activity's production and consumption, once.
///
/// Runs after the exchange set, on the tick's own [`ActivityEnded`](crate::ActivityEnded) messages, so a
/// task that was interrupted pays nothing — the same rule `satisfies` follows.
///
/// Iterates [`PersonIndex::sorted`](crate::PersonIndex) so the order is fixed, and draws nothing.
pub
/// Sets each good's price from how full the village's stores are, **per head**.
///
/// `price = storage_price(total_held, people, price_full_store, 1.0)`, clamped to
/// `[Tuning::price_floor, Tuning::price_ceiling]`. The function is the corpus's own `v(r)` — the storage
/// ratio, worth `2.0` at an empty store, `1.0` at half and `0.5` at a full one — and it is in
/// [`crate::model::price`] with its quotes and its test against the paper's three named points.
///
/// **Per head is the whole point.** The ratio is over the **mean** held per person against
/// `Tuning::price_full_store` — a day's supply a head — so the same six loaves price differently in a village
/// of three and a village of thirty. A unit count cannot make that distinction and the previous
/// `Δprice ∝ (produced − consumed)` counted units.
///
/// **Nothing to integrate, so nothing to get wrong.** The old price accumulated a flow counter between
/// updates, which is how it came to price *net stock*: a village that baked more than it ate watched its
/// price rise, and an eater with an empty shelf — who takes nothing, so consumes nothing — made a real
/// shortage invisible. Here the price is a function of the world, so a village whose inflow equals its
/// outflow holds a constant store and therefore a constant price, which is the acceptance test in the
/// module header satisfied by construction rather than by a rate.
///
/// Iterates [`PersonIndex::sorted`](crate::PersonIndex), so the sum is over a fixed order, and draws
/// nothing.
pub
/// Goods, stock and prices.
///
/// Runs after the exchange set so a task's production lands in the tick that finished it. A host with no
/// `goods` in its definitions file pays nothing: every system returns immediately.
;