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 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 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 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_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