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

battleroyale.gno

1.57 Kb · 58 lines
 1package payout
 2
 3// BattleRoyale is the winner-takes-all rule. The pot is every stake; the fee is
 4// taken from it, and the rest goes to:
 5//
 6//   - the last player in;
 7//   - when the clock ran out with several in, the one of them with the most
 8//     kills, and players still in with as many kills share it equally;
 9//   - and when everyone is out, the player who went out last.
10//
11// It is won by staying in the air, not by scoring: the kill target is
12// ignored, and the arena realm refuses a battle-royale spec that has one.
13//
14// What the split leaves over goes to the fee.
15type BattleRoyale struct{}
16
17var _ Rule = BattleRoyale{}
18
19func (BattleRoyale) Mode() string { return ModeBattleRoyale }
20
21func (BattleRoyale) Settle(g Game, players []address, deaths []Death) (Result, error) {
22	t, err := check(g, players, deaths)
23	if err != nil {
24		return Result{}, err
25	}
26	// The most kills among the players still in.
27	best := int64(-1)
28	for i := range players {
29		if !t.out(i, g.Lives) && t.kills[i] > best {
30			best = t.kills[i]
31		}
32	}
33	won := make([]bool, len(players))
34	winners := int64(0)
35	for i := range players {
36		if !t.out(i, g.Lives) && t.kills[i] == best {
37			won[i] = true
38			winners++
39		}
40	}
41	if winners == 0 {
42		won[t.lastOut] = true
43		winners = 1
44	}
45
46	pot := g.Stake * int64(len(players))
47	share := afterFee(pot, g.FeeBps) / winners
48	res := Result{Fee: pot - share*winners}
49	if share == 0 {
50		return res, nil // a pot too small to split: nobody is paid
51	}
52	for i, p := range players {
53		if won[i] {
54			res.Payouts = append(res.Payouts, Payout{Address: p, Amount: share})
55		}
56	}
57	return res, nil
58}