1package payout23// rankWeights are the shares of the top three by kills, in basis points.4var rankWeights = [3]int64{6000, 3000, 1000}56// Deathmatch pays the most kills. The pot is every stake; the fee is taken from7// it, and the rest goes to the top three by kills: 60%, 30% and 10%.8//9// - Only players with at least one kill are ranked. With fewer than three10// of them, the shares of the ranks they fill are rescaled to the whole:11// one killer takes everything, two take 2/3 and 1/3.12// - Players with as many kills share the ranks they hold: two tied first13// split 60% + 30%, and the next one is third.14// - When nobody killed anybody, every player gets their stake back and the15// house takes nothing.16//17// Deaths cost nothing here beyond the lives they take. What rounding leaves18// over goes to the fee.19type Deathmatch struct{}2021var _ Rule = Deathmatch{}2223func (Deathmatch) Mode() string { return ModeDeathmatch }2425func (Deathmatch) Settle(g Game, players []address, deaths []Death) (Result, error) {26 t, err := check(g, players, deaths)27 if err != nil {28 return Result{}, err29 }30 pot := g.Stake * int64(len(players))3132 // Killers, most kills first; equal kills keep the order of the players.33 var ranked []int34 for i := range players {35 if t.kills[i] == 0 {36 continue37 }38 at := len(ranked)39 for at > 0 && t.kills[ranked[at-1]] < t.kills[i] {40 at--41 }42 ranked = append(ranked, 0)43 copy(ranked[at+1:], ranked[at:])44 ranked[at] = i45 }46 if len(ranked) == 0 {47 res := Result{}48 for _, p := range players {49 res.Payouts = append(res.Payouts, Payout{Address: p, Amount: g.Stake})50 }51 return res, nil52 }5354 filled := len(ranked)55 if filled > len(rankWeights) {56 filled = len(rankWeights)57 }58 whole := int64(0)59 for _, w := range rankWeights[:filled] {60 whole += w61 }6263 prize := afterFee(pot, g.FeeBps)64 amounts := make([]int64, len(players))65 for pos := 0; pos < filled; {66 end := pos + 167 for end < len(ranked) && t.kills[ranked[end]] == t.kills[ranked[pos]] {68 end++69 }70 weight := int64(0)71 for r := pos; r < end && r < filled; r++ {72 weight += rankWeights[r]73 }74 group := int64(end - pos)75 // prize <= 8e12 and weight <= 1e4: the product stays far below 2^63.76 each := prize * weight / (whole * group)77 for _, i := range ranked[pos:end] {78 amounts[i] = each79 }80 pos = end81 }8283 res := Result{Fee: pot}84 for i, p := range players {85 if amounts[i] > 0 {86 res.Payouts = append(res.Payouts, Payout{Address: p, Amount: amounts[i]})87 res.Fee -= amounts[i]88 }89 }90 return res, nil91}92Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.