Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

v0 source realm

Package idle is a mine that keeps working while you are not looking at it.

Readme View source

gno.land/r/moul/x/games/idle/v0

A mine that keeps working while you are not looking at it: Start, Claim, Upgrade, Prestige.

maketx call ... -func Start      # open a mine at level 1
maketx call ... -func Claim      # bank what it dug
maketx call ... -func Upgrade    # spend the bank to dig faster
maketx call ... -func Prestige   # at level 10: reset for a permanent multiplier

Ore accrues at a rate set by your level. There are no turns, no block hook and no keeper: the realm stores what you had and when, and everything else is arithmetic done at the moment somebody asks. Render("") is the board, Render("<address>") is one mine's card.

The numbers move on their own. Refresh the page a minute later and the mine has dug more, with no transaction in between, because every figure comes from the read-only projection rather than from stored state. That is a live dashboard with no frontend, no indexer and no JavaScript, which is the one thing this chain gives you that the others charge for separately.

Three decisions make it a game rather than a counter:

  • The mine is small. It holds 120 periods of production and then spills. Without a ceiling the optimal play is to never log in and claim once at the end, which is a savings account. The ceiling scales with the rate, so the fill time stays two hours at every level and showing up is the only skill. Removing it turns five tests red.
  • Upgrades are quadratic against linear production. Level L costs 10*L*L and pays L per period, so the next level always takes about 10*L periods to afford. Linear against linear never ends; exponential against linear dies at level four.
  • Prestige exists. Without a reset the leaderboard is settled by whoever started first and nobody else has a reason to join. Trading a level-10 mine for a permanent multiplier means a player starting today has a reachable ceiling. Banked and pending ore burn; the lifetime total does not.

Nothing rolls dice. Every outcome is a pure function of when you acted, so there is no block hash to grind and no ordering to front-run, and the card can tell you exactly what an action produces before you sign it. Combat games reach for randomness and inherit a validator-manipulable seed; this one does not need to.

Time is unix seconds from the block, not block height: a height-denominated economy silently reprices itself whenever the chain's block time moves.

The arithmetic is p/moul/x/games/accrual, which owns the rule that makes lazy time honest. Claiming every period and claiming once pay exactly the same, right up to the point where the mine fills, and that limit is the design rather than the arithmetic.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/r/moul/x/games/idle/v0 dependency graph

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.

Overview

Package idle is a mine that keeps working while you are not looking at it.

Ore accrues at a rate set by your level. Claim banks it, Upgrade spends the bank to dig faster, and at level 10 you may Prestige: start over at level 1 carrying a permanent multiplier. There are no turns, no block hook and no keeper. The realm stores what you had and when, and everything else is arithmetic done at the moment somebody asks.

The three decisions that make it a game rather than a counter:

  1. THE MINE IS SMALL. It holds two hours of production and then spills. Without a ceiling the optimal play is to never log in and claim once at the end, which is not a game, it is a savings account. The ceiling is what makes showing up the skill, and it scales with the rate, so two hours stays two hours at every level.
  2. UPGRADES ARE QUADRATIC AGAINST LINEAR PRODUCTION. Level L costs UpgradeBase*L*L and pays L per period, so the next level always takes about UpgradeBase*L periods to afford: the curve bends without ever stalling. Linear against linear never ends, and exponential against linear dies at level four.
  3. PRESTIGE EXISTS. Without a reset the leaderboard is settled by whoever started first and nobody else has a reason to join. Trading a level-10 mine for a permanent multiplier means a player who starts today has a reachable ceiling.

Time is unix seconds from the block, not block height. A height-denominated economy silently repriced itself every time the chain's block time moved, and gno.land's has moved from about 4.1s to 3.405s inside a month.

Nothing here rolls dice. Everything a player can do is a pure function of when they did it, so there is no block hash to grind and no ordering to front-run, and the page can tell you exactly what an action will produce before you sign it.

The arithmetic is p/moul/x/games/accrual(/p/moul/x/games/accrual/v0), which owns the one rule that makes lazy time honest: how often you claim must not change what you end up with.

Constants 1

const Period, CapPeriods, UpgradeBase, PrestigeAt, MaxLevel, MaxPrestige

 1const (
 2	// Period is one minute of unix time. A level-1 mine digs one ore a minute.
 3	Period = int64(60)
 4	// CapPeriods is how much production the mine holds before it spills, in
 5	// periods. It multiplies the rate, so the fill time is level-independent.
 6	CapPeriods = int64(120)
 7	// UpgradeBase sets the cost curve: level L costs UpgradeBase*L*L to leave.
 8	UpgradeBase = int64(10)
 9	// PrestigeAt is the level at which a reset becomes available.
10	PrestigeAt = int64(10)
11	// MaxLevel is a safety rail on the cost curve, not a mechanic: it is far
12	// beyond anything reachable, and keeps every product inside int64.
13	MaxLevel = int64(1000)
14	// MaxPrestige bounds the multiplier for the same reason.
15	MaxPrestige = int64(100)
16)
source

The economy. Ore is a bare integer: there is no token here, and nothing leaves the realm.

Functions 9

func Banked

Action
1func Banked(owner address) int64
source

Banked reports an address's spendable ore.

func Claim

crossing Action
1func Claim(cur realm) string
source

Claim banks whatever the mine has dug since the last claim. Claiming often and claiming rarely pay exactly the same, by construction: see accrual.

func FullAt

Action
1func FullAt(owner address) int64
source

FullAt reports the unix second at which an address's mine starts wasting what it digs, which is the only deadline in this game.

func Level

Action
1func Level(owner address) (int64, int64)
source

Level reports an address's level and prestige.

func Pending

Action
1func Pending(owner address) int64
source

Pending reports what is sitting in an address's mine right now, unclaimed.

func Prestige

crossing Action
1func Prestige(cur realm) string
source

Prestige resets a level-10 mine to level 1 for a permanent +1 multiplier. Banked and pending ore are burned; the lifetime total is not.

func Render

1func Render(path string) string
source

Render shows every mine, or one mine's card at /r/.../idle:<address>.

The numbers move on their own: the same URL renders differently a minute later because the mine kept digging, and nothing wrote to the chain in between. That is the whole point of the accrual pair, and it is why every figure here comes from the read-only view rather than from stored state.

func Start

crossing Action
1func Start(cur realm) string
source

Start opens a mine for the caller. One per address, forever: Prestige is the only way to start over, and it keeps your lifetime total.

func Upgrade

crossing Action
1func Upgrade(cur realm) string
source

Upgrade spends banked ore to raise the level, which raises both the rate and the ceiling.

Imports 8

Source Files 6