func ArenaJSON
ActionArenaJSON returns one arena in the shape of ArenasJSON, or null.
v0 - Unaudited: This is an initial version that has not yet been formally audited. Use in production at your own risk.
v0 - Unaudited: This is an initial version that has not yet been formally audited. Use in production at your own risk.
Package arena holds the paid games of gnofly, a multiplayer plane game. A player pays an entry price in ugnot to join a game, the realm keeps the stakes until the game is over, then credits them by a rule it applies itself. Winners take what they are owed with Claim.
Games are created off chain, by the game server at a player's request, and described by a spec (see spec.gno): mode, entry price, seats, lives, game time and kill target. The realm only stores a game once someone paid for it, and forgets it when it is over or its lobby empties: no game nobody played is ever left on chain.
Four kinds of callers write to it:
The realm keeps no roles of its own: the owner, the admins, the referees and the treasury are those of gno.land/r/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/game/v0, asked at the time of each call.
The referee is trusted for facts only: who died, and by whom. What these facts are worth is decided by a rule of gno.land/p/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/arena/payout/v0, picked by the mode of the game, and the realm checks what the rule returns before it sends anything.
The realm owes exactly the stakes of its lobbies and of its running games, and the winnings not claimed yet, and counts them in one number, see Escrowed. Every coin that leaves goes to a player of the game it came from, or to the treasury of the game realm:
1Enter +stake the envelope of the call stays in the realm
2Leave -stake back to the player
3ExpireLobby -stakes back to the players of the lobby
4StartRound 0 stakes move from the lobby to the game
5SettleRound -fee the fee leaves, the rest is credited to the winners
6Claim -owed everything credited to the caller, every game at once
7CancelRound -pot back to the players of the game
8RefundRound -pot back to the players of the game
A game is closed by exactly one of SettleRound, CancelRound and RefundRound, once.
What a settlement does not pay to the players is the house's cut, a fee of 5% sent to the treasury of the game realm, rounding included.
Reads are plain functions meant for vm/qeval. The ones ending in JSON return a single string holding a JSON document. Render exposes the same data as markdown for gnoweb.
ArenaJSON returns one arena in the shape of ArenasJSON, or null.
ArenasJSON returns every arena someone paid into and whose game is not over, as a JSON array sorted by id:
1[
2 { "id": "3f2a...", "mode": "deathmatch", "stake": 10000000,
3 "minSeats": 2, "maxSeats": 8, "lives": 3, "seconds": 900, "killTarget": 5,
4 "creator": "g1...", "created": 1790950000, "nonce": "k3x9",
5 "lobby": [ { "address": "g1...", "ticket": "9f86d0...00a08" } ],
6 "round": { "startedAt": 1790950300, "players": [ "g1...", "g1..." ] } }
7]
The output has no whitespace. "round" is null until the game starts. The fields from "mode" to "nonce" are the arena's spec: the game server rebuilds the spec string, and so the id, from them.
CancelRound closes the game of an arena without a result: every player gets their stake back in full. Referee only.
The game server uses it for a game it cannot referee, for example one it finds running when it starts.
Claim sends the caller everything the realm owes them from settled games, and returns the amount in ugnot. It panics when there is nothing to claim.
Claimable returns what a player can claim, in ugnot.
ClaimsJSON returns what a player can claim, game by game, oldest first:
1{ "address": "g1...", "total": 19000000, "games": [ { "id": "...", "amount": 19000000 } ] }
The output has no whitespace. An address with nothing to claim returns the same shape with a zero total and no game.
EarningsJSON returns the top winners as a JSON array, best first, at most 10 entries:
1[ { "address": "g1...", "won": 19000000, "rounds": 3 } ]
The output has no whitespace. "won" adds up, round after round, what the player was paid above their own stake, never less than zero for a round. "rounds" is how many settled rounds they played. With equal winnings, the player who got there first stays ahead.
Enter puts the caller in the lobby of the arena that spec describes, and returns its id. The exact stake must be attached to the transaction (-send "<stake>ugnot") and stays in the realm until the player leaves or the game is over.
The first entry creates the arena, the next ones join it: the realm recomputes the id from the spec every time. An arena takes entries for an hour after it was created, and until its game starts.
ticket is 64 lowercase hex characters, the SHA-256 of a secret the player's client made up: the game server gives the seat to whoever shows the secret.
It must be called directly by a user (maketx call): a call relayed by another realm or by a maketx run script is refused.
Escrowed returns what the realm owes to players, in ugnot: the stakes of every lobby and of every running round. The balance of the realm's address is never below it.
ExpireLobby closes an arena whose game never started: every player in the lobby gets their stake back, and the arena is deleted. Anyone can call it once the arena stopped taking entries, an hour after it was created.
Leave takes the caller out of the lobby of an arena and sends their stake back. It works until the game starts. The last player out deletes the arena: nothing is left on chain of a game nobody played.
PlayerJSON returns one player's totals as a JSON object:
1{ "address": "g1...", "won": 19000000, "rounds": 3 }
The output has no whitespace. An unknown address returns the same shape with zero won and zero rounds.
RefundDelay returns the refund delay, in seconds.
RefundRound closes the game of an arena without a result, like CancelRound, and can be called by anyone, once
1startedAt + seconds + RefundDelay()
has passed on the block clock. It is the players' way out when the referee never settles: no stake depends on a server staying up.
Render returns the state of the arenas as markdown, for gnoweb:
1"" the open arenas and the last games played
2"arena/<id>" one arena: its rules, lobby and game, or its result
3"earnings" the top winners
Everything printed here was validated against a narrow charset when it was written (see spec.gno and validate.gno), or is an address the chain gave the realm. The only caller-supplied value, the id of an arena page, is printed only if it is a valid id. Nothing needs markdown escaping.
ResultJSON returns the result of one closed game in the shape of ResultsJSON, or null when the realm does not have it (still running, or too old).
SetRefundDelay sets how long after a game's time limit anyone may refund it. Admin only.
SettleRound closes the game of an arena: it applies the rule of its mode to what happened, pays the players, and pays the fee to the treasury. Referee only.
deaths is "victim:killer" entries separated by ";", in the order they happened, "victim:" when nobody shot the victim down, and the empty string when nobody died. A player dies at most as often as the arena has lives.
The referee is trusted for these facts and for nothing else. The rule refuses a victim or a killer who is not a player of the round, and decides the amounts. The realm then checks them (see settle) before it pays.
StartRound starts the game of an arena with every player of its lobby. Referee only. The lobby must hold at least minSeats players; it holds at most maxSeats, Enter sees to that. No coin moves: the stakes that were owed to the lobby are now owed to the round. It returns how many play.
Version returns a counter that bumps on every admin write: the refund delay. Player and referee actions do not bump it.