def f_dbstr_addptr(dst, number): """Print number as string to dst. :param dst: Destination address (Not EPD player) :param number: DWORD to print :returns: dst + strlen(itoa(number)) """ bw1.seekoffset(dst) ch = [0] * 8 # Get digits for i in range(8): number, ch[i] = c.f_div(number, 16) # print digits for i in range(7, -1, -1): if cs.EUDIf()(ch[i] <= 9): bw1.writebyte(ch[i] + b'0'[0]) if cs.EUDElse()(): bw1.writebyte(ch[i] + (b'A'[0] - 10)) cs.EUDEndIf() dst += 1 bw1.writebyte(0) # EOS bw1.flushdword() return dst
def EUDLoopTrigger(player): player = c.EncodePlayer(player) tbegin = tt.TrigTriggerBegin(player) if cs.EUDIfNot()(tbegin == 0): tend = tt.TrigTriggerEnd(player) for ptr, epd in EUDLoopList(tbegin, tend): yield ptr, epd cs.EUDEndIf()
def EUDNot(cond): """ !cond :param conds: Condition to negate """ v = c.EUDVariable() if cs.EUDIf()(cond): v << 0 if cs.EUDElse()(): v << 1 cs.EUDEndIf() return v
def EUDBinaryMin(cond, minv=0, maxv=0xFFFFFFFF): """ Find minimum x satisfying cond(x) using binary search :param cond: Test condition :param minv: Minimum value in domain :param maxv: Maximum value in domain Cond should be binary classifier, meaning that for some N for all x < N, cond(x) is false. for all x >= N, cond(x) is true Then EUDBinaryMin will find such N .. note:: If none of the value satisfies condition, then this function will return maxv. """ x = c.EUDVariable() x << maxv if isinstance(minv, int) and isinstance(maxv, int): r = maxv - minv if r == 0: return minv else: r = None for i in range(31, -1, -1): if r and 2**i > r: continue if cs.EUDIf()([x >= 2**i]): cs.DoActions(x.SubtractNumber(2**i)) if cs.EUDIfNot()([x >= minv, cond(x)]): cs.DoActions(x.AddNumber(2**i)) cs.EUDEndIf() cs.EUDEndIf() return x
def f_getcurpl(): """Get current player value. eudplib internally caches the current player value, so this function uses that value if the value is valid. Otherwise, update the current player cache and return it. """ cpcond = c.curpl.cpcacheMatchCond() cpcache = c.curpl.GetCPCache() if cs.EUDIfNot()(cpcond): _f_updatecpcache() cs.EUDEndIf() return cpcache
def f_randomize(): global _seed # Store switch 1 sw1 = c.EUDVariable() if cs.EUDIf()(c.Switch("Switch 1", c.Set)): sw1 << c.EncodeSwitchAction(c.Set) if cs.EUDElse()(): sw1 << c.EncodeSwitchAction(c.Clear) cs.EUDEndIf() _seed << 0 dseed = c.EUDVariable() dseed << 1 if cs.EUDLoopN()(32): cs.DoActions(c.SetSwitch("Switch 1", c.Random)) if cs.EUDIf()(c.Switch("Switch 1", c.Set)): _seed += dseed cs.EUDEndIf() dseed += dseed cs.EUDEndLoopN() cs.DoActions(c.SetSwitch("Switch 1", sw1))
def EUDOr(cond1, *conds): """ cond1 || cond2 || ... || condn .. warning:: Short circuiting is not supported :param conds: List of conditions """ v = c.EUDVariable() if cs.EUDIf()(cond1): v << 1 for cond in conds: if cs.EUDElseIf()(cond): v << 1 if cs.EUDElse()(): v << 0 cs.EUDEndIf() return v
def f_playerexist(player): """Check if player has not left the game. :returns: 1 if player exists, 0 if not. """ pts = 0x51A280 cs.EUDSwitch(player) for p in range(8): if cs.EUDSwitchCase()(p): if cs.EUDIf()(c.Memory(pts + p * 12 + 8, c.Exactly, ~(pts + p * 12 + 4))): c.EUDReturn(0) if cs.EUDElse()(): c.EUDReturn(1) cs.EUDEndIf() if cs.EUDSwitchDefault()(): c.EUDReturn(0) cs.EUDEndSwitch()
def QueueGameCommand(data, size): """Queue game command to packet queue. Starcraft periodically boradcasts game packets to other player. Game packets are stored to queue, and this function add data to that queue, so that SC can boradcast it. :param data: Data to put in queue :param size: Size of data .. note:: If packet queue is full, this function fails. This behavior is silent without any warning or error, since this behavior shouldn't happen in common situations. So **Don't use this function too much in a frame.** """ prov_maxbuffer = f_dwread_epd(ut.EPD(0x57F0D8)) cmdqlen = f_dwread_epd(ut.EPD(0x654AA0)) if cs.EUDIfNot()(cmdqlen + size + 1 >= prov_maxbuffer): f_memcpy(0x654880 + cmdqlen, data, size) c.SetVariables(ut.EPD(0x654AA0), cmdqlen + size) cs.EUDEndIf()
def EUDAnd(cond1, *conds): """ cond1 && cond2 && ... && condn .. note:: This function computes AND value of various conditions. If you don't want to do much computation, you should better use plain list instead of this function. .. warning:: Short circuiting is not supported. :param conds: List of conditions """ v = c.EUDVariable() if cs.EUDIfNot()(cond1): v << 0 for cond in conds: if cs.EUDElseIfNot()(cond): v << 0 if cs.EUDElse()(): v << 1 cs.EUDEndIf() return v
def f_atan2(y, x): signflags = c.EUDVariable() signflags << 0 # Check x sign if cs.EUDIf()(x >= 0x80000000): x << -x signflags += 1 # set xsign cs.EUDEndIf() # Check y sign if cs.EUDIf()(y >= 0x80000000): y << -y signflags += 2 # set ysign cs.EUDEndIf() # Check x/y order if cs.EUDIf()(y >= x): z = c.EUDVariable() # Swap x, y so that y <= x z << x x << y y << z signflags += 4 # set xyabscmp cs.EUDEndIf() # To prevent overflow, we limit values of y and x. # atan value is maximized when x = y, then atan_value = 45 * x**3 # 45 * x**3 <= 0xFFFFFFFF : x <= 456.99.... if cs.EUDIf()(x >= 400): # Normalize below 400 divn = x // 400 + 1 x //= divn y //= divn cs.EUDEndIf() # Calculate arctan value # arctan(z) ~= z * (45 - (z-1) * (14 + 4*z)), 0 <= z <= 1 # arctan(y/x) ~= y/x * (45 - (y-x)/x * (14x + 4y)/x)) # arctan(y/x) ~= y * (45*x*x - (y-x)(14x+4y)) / (x*x*x) t1 = x * x t2 = y * (45 * t1 - (y - x) * (14 * x + 4 * y)) t3 = x * t1 atan_value = t2 // t3 # Translate angles by sign flags # # | 0 | 1 | xsign | 0 | 1 | xsign # -----+----+----+----- -----+----+----+----- # 0 | 0+|180-| 0 | 90-| 90+| # -----+----+----+ -----+----+----+ # 1 |360-|180+| 1 |270+|270-| # -----+----+----+ -----+----+----+ # ysign| xyabscmp=0 ysign| xyabscmp=1 cs.EUDSwitch(signflags) cs.EUDSwitchCase()(0) # xsign, ysign, xyabscmp = 0, 0, 0 c.EUDReturn(atan_value) cs.EUDSwitchCase()(1) # xsign, ysign, xyabscmp = 1, 0, 0 c.EUDReturn(180 - atan_value) cs.EUDSwitchCase()(2) # xsign, ysign, xyabscmp = 0, 1, 0 c.EUDReturn(360 - atan_value) cs.EUDSwitchCase()(3) # xsign, ysign, xyabscmp = 1, 1, 0 c.EUDReturn(180 + atan_value) cs.EUDSwitchCase()(4) # xsign, ysign, xyabscmp = 0, 0, 1 c.EUDReturn(90 - atan_value) cs.EUDSwitchCase()(5) # xsign, ysign, xyabscmp = 1, 0, 1 c.EUDReturn(90 + atan_value) cs.EUDSwitchCase()(6) # xsign, ysign, xyabscmp = 0, 1, 1 c.EUDReturn(270 + atan_value) cs.EUDSwitchCase()(7) # xsign, ysign, xyabscmp = 1, 1, 1 c.EUDReturn(270 - atan_value) cs.EUDEndSwitch()
def f_lengthdir(length, angle): # sin, cos table clist = [] slist = [] for i in range(91): cosv = math.floor(math.cos(math.pi / 180 * i) * 65536 + 0.5) sinv = math.floor(math.sin(math.pi / 180 * i) * 65536 + 0.5) clist.append(ut.i2b4(cosv)) slist.append(ut.i2b4(sinv)) cdb = c.Db(b''.join(clist)) sdb = c.Db(b''.join(slist)) # MAIN LOGIC if cs.EUDIf()(angle >= 360): angle << c.f_div(angle, 360)[1] cs.EUDEndIf() ldir_x, ldir_y = c.EUDVariable(), c.EUDVariable() # cos, sin * 65536 # sign of cos, sin csign, ssign = c.EUDLightVariable(), c.EUDLightVariable() tableangle = c.EUDVariable() # get cos, sin from table if cs.EUDIf()(angle <= 89): tableangle << angle csign << 1 ssign << 1 if cs.EUDElseIf()(angle <= 179): tableangle << 180 - angle csign << -1 ssign << 1 if cs.EUDElseIf()(angle <= 269): tableangle << angle - 180 csign << -1 ssign << -1 if cs.EUDElse()(): tableangle << 360 - angle csign << 1 ssign << -1 cs.EUDEndIf() tablecos = f_dwread_epd(ut.EPD(cdb) + tableangle) tablesin = f_dwread_epd(ut.EPD(sdb) + tableangle) # calculate lengthdir ldir_x << c.f_div(c.f_mul(tablecos, length), 65536)[0] ldir_y << c.f_div(c.f_mul(tablesin, length), 65536)[0] # restore sign of cos, sin if cs.EUDIf()(csign == -1): ldir_x << 0xFFFFFFFF - ldir_x + 1 cs.EUDEndIf() if cs.EUDIf()(ssign == -1): ldir_y << 0xFFFFFFFF - ldir_y + 1 cs.EUDEndIf() return ldir_x, ldir_y