Price identification
3.6 · 3.7 · 5.0
Work a shop price backwards to the base costs that could have produced it, then to the
items that carry those base costs. The arithmetic is a straight port of
get_cost() and set_cost() from src/shk.c — integer
division, round-half-up, artifact and anger surcharges applied after the rounding,
which is where most price calculators drift.
Observations
One price rarely pins an item down. Add a second reading — the sell price for the same item, or the same item quoted at another shop or another Charisma — and the candidate sets are intersected.
Price identification narrows an item to a base-cost bucket, never to a single item. Base cost 100 alone covers dozens of objects. Combine the bucket with what you already know — the object class, the appearance, what you have already identified — and, where possible, with a second observation.
The algorithm, exactly
Buying (get_cost) — base cost, 0 becomes 5;
a 1-in-4 unidentified surcharge (×4/3, keyed off the object's ID, unknowable to you);
then at most one of dunce cap / Tourist below XL14 / visible tourist shirt (×4/3, they are
if / else-if in the C, so they never stack); then the Charisma ladder;
then the rounding tweak
tmp = floor((floor(tmp×10 / divisor) + 5) / 10); clamp up to 1; then
artifact ×4; then the angry-shopkeeper + floor((tmp+2)/3). Those last two
land after the rounding, on purpose.
Selling (set_cost) — the shopkeeper keeps
half (÷2), or two thirds (÷3) if you look like a rube; a separate 1-in-4 markdown (×3/4,
keyed off the shopkeeper's ID, and only when base cost > 1); the same rounding tweak;
never rounded down to zero. Charisma and shopkeeper anger do not affect what you are
offered.
The reverse lookup brute-forces every base cost from 1 to 30000 forward through the algorithm along both branches of the unknowable surcharge and keeps exact matches. It does not try to invert the arithmetic — round-half-up is not invertible.
Probability footnotes
Percentages are the item's generation probability within its own object class, using the class totals from the object table as the denominator — never a hardcoded 1000. In 5.0 the weapon probabilities sum to 1002, because silver mace was added without rebalancing the rest.
In 3.6 every ring carries prob 0 in
objects.c — that is genuinely what the table says; the ring class is filled
by picking uniformly instead. Ring probabilities for 3.6 are therefore shown as a uniform
1/28 and marked uniform. 3.7 and 5.0 give every ring an
explicit probability of 1.
The other class lumps several C object classes together
(coins, iron balls, chains, venom), so its total is not a meaningful denominator and no
probability is shown for it.
Objects with base cost 0 are kept in the data so the denominators stay right, but they are never offered as candidates.