jonnify·codemojex /codemojex/the-economy/three-currencies

Codemojex · C5.1 · a dive of The Economy and the Bank

Three currencies.

Three currencies move through the game, each in its own lane. A player row carries them as separate integer columns, and the rules that spend and earn them never cross: keys pay in paid rooms, clips pay in free rooms and carry no value, and diamonds are the prize, convertible to keys at a fixed 10:1.

Grounding — echo/…/codemojex/wallet.ex (charge_guess/3, convert_to_keys/2, balance/1) · economy.ex (diamonds_per_key, keys_from_diamonds/1, to_usd/1) · the wallet + economy stories.

Three currencies, three lanes — select one
KeyShop Telegram Stars KEYS purchased, spendable paid-room guess guess_fee, default 1 free play granted, no purchase CLIPS no value, not spendable free-room guess clip_cost, default 1 won pool prize at settlement DIAMONDS the prize currency convert to keys fixed 10:1
keys → the purchased, spendable currency. Keys come from the KeyShop (paid externally via Telegram Stars) and pay for a guess in a paid room — guess_fee, default 1. The wallet story: a paid-room guess debits one key and leaves clips untouched.
§1

Keys, clips, diamonds

wallet.ex · charge_guess/3

One function keeps the paid and free paths from crossing. charge_guess/3 is a cond over the game: a free game debits clips, a Golden Room’s paid guess is the two-sided keys charge that also funds the pool, and an ordinary paid game debits keys. A player can never spend a key in a free room or a clip in a paid one.

echo/…/codemojex/wallet.ex · charge_guess/3 source
def charge_guess(player, game_map, ref) do
  cond do
    Map.get(game_map, :free, false) ->
      debit(player, :clips, Map.get(game_map, :clip_cost, 1), "guess", ref)

    Map.get(game_map, :golden, false) ->
      charge_guess_golden(player, Map.get(game_map, :guess_fee, 1), ref)   # two-sided

    true ->
      debit(player, :keys, Map.get(game_map, :guess_fee, 1), "guess", ref)
  end
end

Clips carry no value by design — they are the free-play currency, excluded from the spendable balance and never converted to keys or diamonds. The wallet story pins both halves: a paid-room guess spends a key and never a clip; a free-room guess spends a clip and never a key.

§2

The fixed, public conversion

economy.ex

Diamonds convert to keys at a fixed 10:1, and the rate is public. The valuation is pure arithmetic — keys_from_diamonds/1 floors, and to_cents/1 prices a diamond at 1.2 US cents. Pick a diamond amount and watch what it is worth.

Diamonds valued in keys and USD — select an amount
diamonds 100 div(d, 10) floored rem 0 keys 10 USD @ 1.2¢ $1.20 a non-multiple of 10 is refused by convert_to_keys — the valuation still floors
100 dia → keys_from_diamonds(100) = div(100, 10) = 10, and to_usd(100) = $1.20. An exact multiple of 10 — converts cleanly with no remainder.
echo/…/codemojex/economy.ex · the valuation source
@diamonds_per_key 10
@cents_per_diamond 1.2

def keys_from_diamonds(d) when d >= 0, do: div(d, @diamonds_per_key)   # floored
def to_cents(d), do: round(d * @cents_per_diamond)                    # 1 dia = 1.2¢
def to_usd(d), do: "$" <> :erlang.float_to_binary(to_cents(d) / 100, decimals: 2)

The economy story pins the numbers: 283 diamonds are worth 28 keys — the remainder does not round up — and render as $3.40; 100 diamonds render as $1.20. The actual convert_to_keys/2 is stricter than the valuation: it refuses a non-multiple of 10 (rem(diamonds, 10) != 0 rolls back :bad_amount), so a conversion always moves whole keys and strands no diamonds.

§3

Spendable versus held

wallet.ex · balance/1

balance/1 sets the spendable figures apart from the raw columns. Keys are spendable as-is. Diamonds are spendable minus what is held: available_diamonds: p.diamonds − p.locked_diamonds. Clips are excluded from the spendable balance entirely, because they carry no value.

So the balance a player is shown to spend is never more than the money that is actually free to move. A diamond that is locked — reserved against an obligation — still sits in the diamonds column, but it is subtracted from the available figure, so it cannot be spent twice.

Next — C5.2 shows how each of these moves is made atomic: the row lock, the non-negative check, and the paired TXN ledger row.

§4

References

sources · related

Sources

Related