life.gno
3.82 Kb · 185 lines
1package fish
2
3import (
4 "chain/runtime"
5 "crypto/sha256"
6 "strconv"
7 "time"
8
9 "gno.land/r/g1n4pl5uc4yt5r96m9w6fmdznx3x0jyg8l6arhmt/shoal/shoaltoken"
10)
11
12func Register(cur realm, id int, stake int64) {
13 caller := requireUser(cur)
14 body := must(id)
15 if body.owner != caller {
16 panic("fish: owner")
17 }
18 if body.inMatch {
19 panic("fish: match")
20 }
21 if body.mustHeal {
22 panic("fish: heal")
23 }
24 guardMovable(body)
25 if tooHurt(body) {
26 panic("fish: hp")
27 }
28 if walletInSea(caller) {
29 panic("fish: one")
30 }
31 if !arenaStake(stake) {
32 panic("fish: stake")
33 }
34 takeExact(stake)
35 now := time.Now().Unix()
36 body.pool = stake
37 body.inMatch = true
38 body.boutPaid = false
39 body.startUnix = now
40 body.endUnix = 0
41 body.lastCombatMilli = -1
42 body.nextMoveMilli = 0
43 body.burstUntil = 0
44 body.nextBurstAt = 0
45 body.springBorn = -1
46 placeSwimmer(body)
47 clearDamage(id)
48}
49
50func Leave(cur realm, id int) {
51 caller := requireUser(cur)
52 takeExact(0)
53 body := must(id)
54 if body.owner != caller {
55 panic("fish: owner")
56 }
57 if !body.inMatch {
58 panic("fish: match")
59 }
60 nowMs := time.Now().UnixMilli()
61 if body.lastCombatMilli >= 0 && nowMs < body.lastCombatMilli+combatLockMs {
62 panic("fish: stay")
63 }
64 returnCheers(body, cur)
65 stake := body.pool
66 body.pool = 0
67 body.inMatch = false
68 body.boutPaid = false
69 clearDamage(id)
70 send(caller, stake, cur)
71}
72
73func SettleMatch(cur realm, id int) {
74 requireUser(cur)
75 takeExact(0)
76 body := must(id)
77 if !body.inMatch {
78 panic("fish: match")
79 }
80 _ = body
81 panic("fish: sea")
82}
83
84func CommitLay(cur realm, id int) {
85 caller := requireUser(cur)
86 body := must(id)
87 if body.owner != caller {
88 panic("fish: owner")
89 }
90 guardMovable(body)
91 left := body.bouts - body.layBoutsUsed
92 if left < 3 {
93 panic("fish: bouts")
94 }
95 takeExact(layFee)
96 payMint(layFee, cur)
97 body.layBoutsUsed = body.bouts
98 body.layOpen = true
99 body.layHeight = runtime.ChainHeight()
100}
101
102func SettleLay(cur realm, id int) int {
103 requireUser(cur)
104 takeExact(0)
105 body := must(id)
106 if !body.layOpen {
107 panic("fish: lay")
108 }
109 height := runtime.ChainHeight()
110 if height < body.layHeight+layBlocks {
111 panic("fish: early")
112 }
113 trait := traitFrom(body.id, body.layHeight, height, time.Now().Unix())
114 body.layOpen = false
115 return issue(body.owner, body.name+" fry", body.rarity, body.size, trait)
116}
117
118// Upgrade spends 15 FISH to step two played Common fish to Uncommon.
119// The FISH fee burns. The team takes none of it. No GNOT moves.
120// Higher tiers stay closed until a commit-reveal roll exists.
121func Upgrade(cur realm, keep, food int) int {
122 caller := requireUser(cur)
123 if keep == food {
124 panic("fish: upgrade")
125 }
126 a := must(keep)
127 b := must(food)
128 if a.owner != caller || b.owner != caller {
129 panic("fish: owner")
130 }
131 guardMovable(a)
132 guardMovable(b)
133 if a.rarity != b.rarity || a.size != b.size || a.trait != b.trait {
134 panic("fish: pair")
135 }
136 if a.bouts < 1 || b.bouts < 1 {
137 panic("fish: bouts")
138 }
139 if a.rarity != "common" {
140 panic("fish: roll")
141 }
142 takeExact(0)
143 if !fishTokenReady() {
144 panic("fish: fish")
145 }
146 got := shoaltoken.Draw(cross(cur), caller, burnSink, upgradeFishFee)
147 if got != upgradeFishFee {
148 panic("fish: fish")
149 }
150 name := a.name
151 size := a.size
152 trait := a.trait
153 burnBody(a)
154 burnBody(b)
155 return issue(caller, name, "uncommon", size, trait)
156}
157
158func burnBody(body *fishBody) {
159 burnGRC(body.id)
160 body.burned = true
161 body.owner = address("")
162 body.seller = address("")
163 body.price = 0
164 body.listed = false
165 body.pool = 0
166 body.inMatch = false
167 body.layOpen = false
168}
169
170func traitFrom(id int, commitHeight, settleHeight, unix int64) string {
171 raw := strconv.Itoa(id) + ":" + strconv.FormatInt(commitHeight, 10) + ":" + strconv.FormatInt(settleHeight, 10) + ":" + strconv.FormatInt(unix, 10)
172 sum := sha256.Sum256([]byte(raw))
173 var n int64
174 for i := 0; i < len(sum); i++ {
175 n = (n*256 + int64(sum[i])) % 3
176 }
177 switch n {
178 case 0:
179 return "swift"
180 case 1:
181 return "fang"
182 default:
183 return "hide"
184 }
185}