Loading...
  OR  Zero-K Name:    Password:   

Post edit history

Locust vs aa analyse

To display differences between versions, select one or more edits in the list using checkboxes and click "diff selected"
Post edit history
Date Editor Before After
8/21/2026 6:21:42 PMCNrankXNTWASD before revert after revert
Before After
1 == Kiting == 1 == Kiting ==
2 \n 2 \n
3 unit a vs b 3 unit a vs b
4 \n 4 \n
5 assume a.range > b.range, a.speed < b.speed 5 assume a.range > b.range, a.speed < b.speed
6 \n 6 \n
7 range advantage: a.range-b.range 7 range advantage: a.range-b.range
8 \n 8 \n
9 speed advantage: a.speed-b.speed 9 speed advantage: a.speed-b.speed
10 \n 10 \n
11 kiting time advantage (KT): (a.range-b.range) / (b.speed-a.speed) 11 kiting time advantage (KT): (a.range-b.range) / (b.speed-a.speed)
12 \n 12 \n
13 kiting damage advantage (KD): KT>0: KT*a.dpspc 13 kiting damage advantage (KD): KT>0: KT*a.dpspc
14 \n 14 \n
15 assume a_cost, b_cost: 15 assume a_cost, b_cost:
16 \n 16 \n
17 when a kite b, first a deal burst damage, then a deal dps for KT time, then b deam burst on a, then a b brawl 17 when a kite b, first a deal burst damage, then a deal dps for KT time, then b deam burst on a, then a b brawl
18 \n 18 \n
19 b_cost = b_cost_0 - a_cost_0* (a.burstpc + tdadv * a.dpspc) / b.hppc 19 b_cost = b_cost_0 - a_cost_0* (a.burstpc + tdadv * a.dpspc) / b.hppc
20 \n 20 \n
21 then a_cost = a_cost_0 - b_cost*b.burstpc / a.hppc 21 then a_cost = a_cost_0 - b_cost*b.burstpc / a.hppc
22 \n 22 \n
23 compare a_cost * a.BF = b_cost *b.BF, we get who win. 23 compare a_cost * a.BF = b_cost *b.BF, we get who win.
24 \n 24 \n
25 by going backward, we can calculate braw percentage of a,b. 25 by going backward, we can calculate braw percentage of a,b.
26 \n 26 \n
27 Asked ai to simplify :) b_cost_0/a_cost_0 = ( KT * a.dpspc + a.burstpc )/b.hppc + 1/ ( b.BF / a.BF + b.burstpc / a.hppc ) 27 Asked ai to simplify :) b_cost_0/a_cost_0 = ( KT * a.dpspc + a.burstpc )/b.hppc + 1/ ( b.BF / a.BF + b.burstpc / a.hppc )
28 \n 28 \n
29 Had written some code to calculate. 29 Had written some code to calculate.
30 \n 30 \n
31 This may soon become generic unit comparer. 31 This may soon become generic unit comparer.
32 \n 32 \n
33 [spoiler] 33 [spoiler]
34 unit.py 34 unit.py
35 {{{ 35 {{{
36 from functools import cache 36 from functools import cache
37 import math 37 import math
38 \n 38 \n
39 class Unit: 39 class Unit:
40 hppc:float # Hp per cost 40 hppc:float # Hp per cost
41 speed:float # speed 41 speed:float # speed
42 dpspc:float # dps per cost 42 dpspc:float # dps per cost
43 range:float # range 43 range:float # range
44 burstpc:float # burst per cost. burst damage is that a unit can done instantly when enemy in range 44 burstpc:float # burst per cost. burst damage is that a unit can done instantly when enemy in range
45 name:str|None 45 name:str|None
46 \n 46 \n
47 def __init__(self,hppc:float,speed:float,dpspc:float, 47 def __init__(self,hppc:float,speed:float,dpspc:float,
48 burstpc:float,range:float,name:str|None=None) -> None: 48 burstpc:float,range:float,name:str|None=None) -> None:
49 self.hppc=hppc 49 self.hppc=hppc
50 self.speed=speed 50 self.speed=speed
51 self.dpspc=dpspc 51 self.dpspc=dpspc
52 self.range=range 52 self.range=range
53 self.burstpc=burstpc 53 self.burstpc=burstpc
54 self.name=name 54 self.name=name
55 pass 55 pass
56 \n 56 \n
57 def to_dict(self): 57 def to_dict(self):
58 return { 58 return {
59 "hppc":self.hppc, 59 "hppc":self.hppc,
60 "dpspc":self.dpspc, 60 "dpspc":self.dpspc,
61 "speed":self.speed, 61 "speed":self.speed,
62 "range":self.range, 62 "range":self.range,
63 "burstpc":self.burstpc, 63 "burstpc":self.burstpc,
64 "name":self.name 64 "name":self.name
65 } 65 }
66 \n 66 \n
67 @cache 67 @cache
68 def brawl_factor_sq(self): 68 def brawl_factor_sq(self):
69 return self.dpspc*self.hppc 69 return self.dpspc*self.hppc
70 \n 70 \n
71 @cache 71 @cache
72 def brawl_factor(self): 72 def brawl_factor(self):
73 return math.sqrt(self.brawl_factor_sq()) 73 return math.sqrt(self.brawl_factor_sq())
74 \n 74 \n
75 BF=brawl_factor 75 BF=brawl_factor
76 \n 76 \n
77 @staticmethod 77 @staticmethod
78 def unit_from_cost(cost:float,hp:float,speed:float, 78 def unit_from_cost(cost:float,hp:float,speed:float,
79 dps:float,burst:float,range:float,name:str|None=None): 79 dps:float,burst:float,range:float,name:str|None=None):
80 return Unit( 80 return Unit(
81 hppc=hp/cost, 81 hppc=hp/cost,
82 speed=speed, 82 speed=speed,
83 dpspc=dps/cost, 83 dpspc=dps/cost,
84 burstpc=burst/cost, 84 burstpc=burst/cost,
85 range=range, 85 range=range,
86 name=name) 86 name=name)
87 \n 87 \n
88 class UnitCompare: 88 class UnitCompare:
89 a:Unit 89 a:Unit
90 b:Unit 90 b:Unit
91 def __init__(self,a:Unit,b:Unit): 91 def __init__(self,a:Unit,b:Unit):
92 self.a=a 92 self.a=a
93 self.b=b 93 self.b=b
94 \n 94 \n
95 @cache 95 @cache
96 def brawl_advantage(self): 96 def brawl_advantage(self):
97 return self.a.brawl_factor()/self.b.brawl_factor() 97 return self.a.brawl_factor()/self.b.brawl_factor()
98 @cache 98 @cache
99 def range_advantage(self): 99 def range_advantage(self):
100 return self.a.range - self.b.range 100 return self.a.range - self.b.range
101 \n 101 \n
102 @cache 102 @cache
103 def speed_advantage(self): 103 def speed_advantage(self):
104 return self.a.speed - self.b.speed 104 return self.a.speed - self.b.speed
105 \n 105 \n
106 @cache 106 @cache
107 def kite_time_advantage(self): 107 def kite_time_advantage(self):
108 speed_adv=self.speed_advantage() 108 speed_adv=self.speed_advantage()
109 range_adv=self.range_advantage() 109 range_adv=self.range_advantage()
110 if range_adv==0: 110 if range_adv==0:
111 return 0 111 return 0
112 elif range_adv>0: 112 elif range_adv>0:
113 if speed_adv<0: 113 if speed_adv<0:
114 return -range_adv/speed_adv 114 return -range_adv/speed_adv
115 else: 115 else:
116 return math.inf 116 return math.inf
117 else: 117 else:
118 if speed_adv>0: 118 if speed_adv>0:
119 return range_adv/speed_adv 119 return range_adv/speed_adv
120 else: 120 else:
121 return -math.inf 121 return -math.inf
122 KT=kite_time_advantage 122 KT=kite_time_advantage
123 @cache 123 @cache
124 def kite_damage_advantage(self): 124 def kite_damage_advantage(self):
125 time_adv=self.KT() 125 time_adv=self.KT()
126 if time_adv==0: 126 if time_adv==0:
127 return 0 127 return 0
128 elif time_adv>0: 128 elif time_adv>0:
129 return time_adv*self.a.dpspc 129 return time_adv*self.a.dpspc
130 else: 130 else:
131 return time_adv*self.b.dpspc 131 return time_adv*self.b.dpspc
132 \n 132 \n
133 KD=kite_damage_advantage 133 KD=kite_damage_advantage
134 def predict_kite_advantage(self,a_b_cost:tuple[float,float])->tuple[float,float]: 134 def predict_kite_advantage(self,a_b_cost:tuple[float,float])->tuple[float,float]:
135 (a_cost,b_cost)=a_b_cost 135 (a_cost,b_cost)=a_b_cost
136 kd=self.KD() 136 kd=self.KD()
137 137
138 if kd>0: 138 if kd>0:
139 b_cost -= a_cost*self.a.burstpc / self.b.hppc 139 b_cost -= a_cost*self.a.burstpc / self.b.hppc
140 b_cost -= kd * a_cost /self.b.hppc 140 b_cost -= kd * a_cost /self.b.hppc
141 if b_cost<0: 141 if b_cost<0:
142 b_cost=0 142 b_cost=0
143 a_cost -= b_cost*self.b.burstpc / self.a.hppc 143 a_cost -= b_cost*self.b.burstpc / self.a.hppc
144 else: 144 else:
145 a_cost -= b_cost*self.b.burstpc / self.a.hppc 145 a_cost -= b_cost*self.b.burstpc / self.a.hppc
146 a_cost -= - kd * b_cost /self.a.hppc 146 a_cost -= - kd * b_cost /self.a.hppc
147 if a_cost<0: 147 if a_cost<0:
148 a_cost=0 148 a_cost=0
149 b_cost -= a_cost*self.a.burstpc / self.b.hppc 149 b_cost -= a_cost*self.a.burstpc / self.b.hppc
150 return (a_cost,b_cost) 150 return (a_cost,b_cost)
151 \n 151 \n
152 @cache 152 @cache
153 def overall_advantage_factor_raw(self): 153 def overall_advantage_factor_raw(self):
154 a_cost = 1 / self.a.BF() 154 a_cost = 1 / self.a.BF()
155 b_cost = 1 / self.b.BF() 155 b_cost = 1 / self.b.BF()
156 \n 156 \n
157 kd=self.kite_damage_advantage() 157 kd=self.kite_damage_advantage()
158 \n 158 \n
159 if kd>0: 159 if kd>0:
160 a_cost += b_cost*self.b.burstpc / self.a.hppc 160 a_cost += b_cost*self.b.burstpc / self.a.hppc
161 b_cost += kd * a_cost /self.b.hppc 161 b_cost += kd * a_cost /self.b.hppc
162 b_cost += a_cost*self.a.burstpc / self.b.hppc 162 b_cost += a_cost*self.a.burstpc / self.b.hppc
163 else: 163 else:
164 b_cost += a_cost*self.a.burstpc / self.b.hppc 164 b_cost += a_cost*self.a.burstpc / self.b.hppc
165 a_cost += - kd * b_cost /self.a.hppc 165 a_cost += - kd * b_cost /self.a.hppc
166 a_cost += b_cost*self.b.burstpc / self.a.hppc 166 a_cost += b_cost*self.b.burstpc / self.a.hppc
167 return b_cost/a_cost 167 return b_cost/a_cost
168 168
169 @cache 169 @cache
170 def overall_advantage_factor(self): 170 def overall_advantage_factor(self):
171 kd=self.KD() 171 kd=self.KD()
172 if kd>0: 172 if kd>0:
173 a = self.a 173 a = self.a
174 b = self.b 174 b = self.b
175 return \ 175 return \
176 kd / b.hppc+ a.burstpc / b.hppc \ 176 kd / b.hppc+ a.burstpc / b.hppc \
177 + 1/ ( b.BF() / a.BF() + b.burstpc / a.hppc ) 177 + 1/ ( b.BF() / a.BF() + b.burstpc / a.hppc )
178 else: 178 else:
179 a = self.b 179 a = self.b
180 b = self.a 180 b = self.a
181 res = \ 181 res = \
182 -kd / b.hppc+ a.burstpc / b.hppc \ 182 -kd / b.hppc+ a.burstpc / b.hppc \
183 + 1/ ( b.BF() / a.BF() + b.burstpc / a.hppc ) 183 + 1/ ( b.BF() / a.BF() + b.burstpc / a.hppc )
184 return 1/ res 184 return 1/ res
185 }}} 185 }}}
186 unit_from_zero_k.py load some data from zero-k 186 unit_from_zero_k.py load some data from zero-k
187 \n 187 \n
188 {{{ 188 {{{
189 for k in typecal_units: 189 for k in typecal_units:
190 print((unit_from_zero_k.unitdefs[k].name or k) + "'s BF: " + str(unit_from_zero_k.unitdefs[k].brawl_factor()) ) 190 print((unit_from_zero_k.unitdefs[k].name or k) + "'s BF: " + str(unit_from_zero_k.unitdefs[k].brawl_factor()) )
191 }}} 191 }}}
192 \n 192 \n
193 {{{ 193 {{{
194 for b_k in overall_compare_units: 194 for b_k in overall_compare_units:
195 cmp_locust_other = unit.UnitCompare( unit_from_zero_k.unitdefs["gunshipraid"] , unit_from_zero_k.unitdefs[b_k] ) 195 cmp_locust_other = unit.UnitCompare( unit_from_zero_k.unitdefs["gunshipraid"] , unit_from_zero_k.unitdefs[b_k] )
196 print( "Locust vs " + ( unit_from_zero_k.unitdefs[b_k].name or b_k ) + " overall advantage: " + str(cmp_locust_other.overall_advantage_factor()) ) 196 print( "Locust vs " + ( unit_from_zero_k.unitdefs[b_k].name or b_k ) + " overall advantage: " + str(cmp_locust_other.overall_advantage_factor()) )
197 }}} 197 }}}
198 \n 198 \n
199 {{{ 199 {{{
200 for b_k in brawl_compare_units: 200 for b_k in brawl_compare_units:
201 cmp_locust_other = unit.UnitCompare( unit_from_zero_k.unitdefs["gunshipraid"] , unit_from_zero_k.unitdefs[b_k] ) 201 cmp_locust_other = unit.UnitCompare( unit_from_zero_k.unitdefs["gunshipraid"] , unit_from_zero_k.unitdefs[b_k] )
202 print( "Locust vs " + ( unit_from_zero_k.unitdefs[b_k].name or b_k ) + " brawl advantage: " + str(cmp_locust_other.brawl_advantage()) ) 202 print( "Locust vs " + ( unit_from_zero_k.unitdefs[b_k].name or b_k ) + " brawl advantage: " + str(cmp_locust_other.brawl_advantage()) )
203 }}} 203 }}}
204 \n 204 \n
205 [/spoiler] 205 [/spoiler]
206 \n 206 \n
207 Reaver's BF: 2.2406267344797315 207 Reaver's BF: 2.2406267344797315
208 Raptor's BF: 1.1055415967851332 208 Raptor's BF: 1.1055415967851332
209 Trident's BF: 0.8608781046763305 209 Trident's BF: 0.8608781046763305
210 Bandit's BF: 2.2639984295243867 210 Bandit's BF: 2.2639984295243867
211 Glaive's BF: 2.390810810449239 211 Glaive's BF: 2.390810810449239
212 Hacksaw's BF: 1.108011094956061 212 Hacksaw's BF: 1.108011094956061
213 Scallop's BF: 2.299216490349261 213 Scallop's BF: 2.299216490349261
214 Toad's BF: 1.4245841498486498 214 Toad's BF: 1.4245841498486498
215 Locust's BF: 1.0020639856840274 215 Locust's BF: 1.0020639856840274
216 Gremlin's BF: 1.5957517385580724 216 Gremlin's BF: 1.5957517385580724
217 Tarantula's BF: 1.1644425790483877 217 Tarantula's BF: 1.1644425790483877
218 Angler's BF: 1.3033274920143167 218 Angler's BF: 1.3033274920143167
219 Stardust's BF: 3.7344719829897692 219 Stardust's BF: 3.7344719829897692
220 \n 220 \n
221 Locust vs Reaver overall advantage: 0.4193698094839383 221 Locust vs Reaver overall advantage: 0.4193698094839383
222 Locust vs Trident overall advantage: 0.5942703442974699 222 Locust vs Trident overall advantage: 0.5942703442974699
223 Locust vs Angler overall advantage: 0.41327089064940464 223 Locust vs Angler overall advantage: 0.41327089064940464
224 Locust vs Hacksaw overall advantage: 0.32941084485932304 224 Locust vs Hacksaw overall advantage: 0.32941084485932304
225 Locust vs Toad overall advantage: 0.5335701178767338 225 Locust vs Toad overall advantage: 0.5335701178767338
226 Locust vs Gremlin overall advantage: 0.4840650632010012 226 Locust vs Gremlin overall advantage: 0.4840650632010012
227 Locust vs Tarantula overall advantage: 0.5394871091728761 227 Locust vs Tarantula overall advantage: 0.5394871091728761
228 Locust vs Scallop overall advantage: 0.37622805053289354 228 Locust vs Scallop overall advantage: 0.37622805053289354
229 Locust vs Stardust overall advantage: 0.2470960327476647 229 Locust vs Stardust overall advantage: 0.2470960327476647
230 \n 230 \n
231 Locust vs Bandit brawl advantage: 0.4426080745535401 231 Locust vs Bandit brawl advantage: 0.4426080745535401
232 Locust vs Glaive brawl advantage: 0.4191314433180672 232 Locust vs Glaive brawl advantage: 0.4191314433180672
233 Locust vs Raptor brawl advantage: 0.906400979029632 233 Locust vs Raptor brawl advantage: 0.906400979029632
234 \n
235 Locust vs Angler is not very correct because angler shot 4 per 12 second while calculation assume they deal continuous dps, which overrate Angler.
236 \n
237 Stardust heat is not counted.
238 \n
239 Aoe are not counted.