App multigiocatore
I giochi da tavolo e i giochi di dadi su ZooBC si giocano da due a quattro persone, e ogni mossa è una transazione che ogni nodo verifica con le stesse regole. Le puntate formano un piatto, che il protocollo paga quando la partita finisce, meno un rake dell'1 % per il pool delle app, a meno che la partita non finisca in pareggio.
Aprire e unirsi
Un giocatore apre una partita con CreateApp, scegliendo il tipo e da 2 a 4 posti (la battaglia navale ha sempre esattamente 2 posti), e paga la prima puntata. La partita è Open. Ogni JoinApp paga una puntata uguale, e quando l'ultimo posto viene occupato la partita diventa Active. Un avversario indicato facoltativo trasforma la partita in una sfida diretta a cui può unirsi solo quell'account.
Un posto richiede un account di 36 byte, come un account nativo ZooBC. Gli account con indirizzi di 24 byte, i tipi Ethereum e quelli Bitcoin basati su hash, non possono occupare un posto, anche se il messaggio di errore dice «multiplayer apps require a ZBC account» (chiavi e tipi di account). Le scommesse in solitaria accettano qualsiasi account.
Chi muove per primo
Chi inizia può fare la differenza, quindi nessuno può saperlo o influenzarlo in anticipo. Quando l'ultimo posto viene occupato, il turno è in sospeso: nessuno è sull'orologio, e ogni mossa è una no-op. Due blocchi dopo il risolutore estrae il posto di apertura, come hash del seed di quel blocco e dell'id dell'app, modulo il numero di posti. Il produttore del blocco con l'ultimo ingresso conosce il proprio seed ma non il seed di due blocchi dopo, quindi non può includere o escludere l'ingresso in base a chi inizierebbe. Né il creatore né l'ultimo a unirsi iniziano per regola. La battaglia navale è l'eccezione: muove per primo chi si unisce, impegnando la propria griglia.
Nei quattro giochi di dadi (ludo, pig, gara e monopoly-lite) una mossa non viene applicata nel blocco che la include. Viene memorizzata come in sospeso e applicata dal blocco successivo, con il seed di quel blocco e indicizzata dall'id della transazione della mossa, così il produttore che ha incluso la mossa non vede mai il lancio. È consentita una sola mossa in sospeso alla volta, e una mossa che nel frattempo è diventata illegale viene scartata.
L'orologio delle mosse
Quando si unisce l'ultimo posto, e di nuovo dopo ogni mossa accettata, la scadenza viene fissata 240 blocchi più avanti, circa un'ora. Il giocatore di turno deve muovere prima di allora, oppure inviare un AppMove con una mossa vuota: un segnale di presenza a pagamento che sposta la scadenza di altri 240 blocchi. Una mossa di un giocatore che non è sull'orologio, o una mossa illegale, viene rifiutata quando viene inviata; se arriva comunque in un blocco, è una no-op che non costa alcuna commissione.
Come finisce una partita
| Esito | Come | Pagamento |
|---|---|---|
| Vittoria | una mossa vince la partita | il piatto meno il rake dell'1 %, al vincitore |
| Pareggio | una mossa chiude la partita in parità | ogni posto riottiene la propria puntata; nessun rake |
| Abbandono | un giocatore invia ResignApp | il piatto meno il rake, diviso in parti uguali tra gli altri posti, l'eventuale resto al primo di loro |
| Tempo scaduto | un giocatore seduto che non è sull'orologio invia ClaimAppTimeout, dalla scadenza + 1 | il piatto meno il rake, diviso tra tutti i posti tranne quello sull'orologio |
Il rake è floor(piatto × 100 ÷ 10.000), l'1 % del piatto: due giocatori che puntano 1 ZBC ciascuno formano un piatto di 2 ZBC, e il vincitore riceve 1,98 ZBC nel blocco della mossa vincente. Il produttore del blocco non prende nulla dal piatto. Niente finisce da solo: dopo una scadenza mancata la partita aspetta finché un giocatore non sceglie di inviare il reclamo, e nessuno, ZooBC Foundation compresa, può annullare una partita.
I motori di gioco
Il motore di ogni gioco fa parte del nodo, con alcune semplificazioni che conviene conoscere:
- negli scacchi non ci sono arrocco né presa en passant, e i pedoni vengono sempre promossi a regina;
- nella dama la presa è obbligatoria e le prese multiple proseguono;
- a reversi si passa il turno di un posto che non ha mosse legali;
- a dots-and-boxes si ottiene un'altra mossa dopo aver completato un quadrato;
- a pig si vince a 100, e la gara, il gioco di scale e serpenti, termina a 49;
- a ludo ogni posto muove quattro pedine;
- a monopoly-lite ogni posto parte con 1.500 e riceve 200 passando dal VIA.
Battaglia navale: segreti su una catena pubblica
La battaglia navale ha bisogno di informazioni nascoste su una catena in cui tutto è pubblico, e le ottiene con commit e reveal. Prima di giocare, ogni giocatore sceglie un sale segreto di 32 byte per ciascuna delle 100 caselle di una griglia 10 × 10 e pubblica SHA3-256(is_ship ‖ salt) per ogni casella: 100 hash, 3.200 byte in tutto. Il creatore invia il proprio impegno con CreateApp, e chi si unisce invia il proprio come prima mossa. Poiché ogni sale è casuale, gli hash non rivelano nulla.
Un giocatore spara con la mossa [0, cell]. Il proprietario di quella griglia deve rivelare la casella in sospeso con [1, is_ship, salt], e ogni nodo verifica che questi valori diano, con l'hash, il valore impegnato. Una bugia dà un hash diverso e viene rifiutata, quindi il proprietario può solo dire la verità, oppure esaurire il tempo e perdere per un ClaimAppTimeout. Vince il primo giocatore che colpisce 17 caselle di navi. Impegnare meno caselle di navi non dà alcun vantaggio: una volta che chi spara ha sparato tutti i 100 colpi e sono state rivelate meno di 17 caselle di navi, vince chi spara.