예제 #1
0
    def step(self, gamestate, smashbot_state, opponent_state):
        if self.logger:
            self.logger.log("Notes",
                            " right side platform: " +
                            str(self.right_platform) + " ",
                            concat=True)

        platform_center = 0
        platform_height, platform_left, platform_right = melee.side_platform_position(
            self.right_platform, gamestate.stage)
        if platform_height is not None:
            platform_center = (platform_left + platform_right) / 2

        top_platform_height, _, _ = melee.top_platform_position(
            gamestate.stage)

        # Where to dash dance to
        pivot_point = platform_center
        # If opponent is on the platform, get right under them
        if platform_left < opponent_state.position.x < platform_right:
            pivot_point = opponent_state.position.x

        # Unless we don't need to attack them, then it's safe to just board asap
        if not self.attack and (platform_left < smashbot_state.position.x <
                                platform_right):
            pivot_point = smashbot_state.position.x

        # If we're just using the side platform as a springboard, then go closer in than the middle
        if opponent_state.position.y >= top_platform_height:
            if smashbot_state.position.x > 0:
                pivot_point = platform_left + 8
            else:
                pivot_point = platform_right - 8

        if smashbot_state.on_ground:
            self.interruptible = True
            # If we're already on the platform, just do nothing. We shouldn't be here
            if smashbot_state.position.y > 5:
                self.controller.release_all()
                return

        # Are we in position to jump?
        if (abs(smashbot_state.position.x - pivot_point) <
                5) and smashbot_state.action == Action.TURNING:
            self.interruptible = False
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # If we're crouching, keep holding Y
        if smashbot_state.action == Action.KNEE_BEND:
            self.controller.press_button(melee.Button.BUTTON_Y)
            self.interruptible = False
            return

        # Jump out of shine
        if smashbot_state.action in [Action.DOWN_B_AIR]:
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # Can we shine our opponent right now, while we're in the air?
        foxshinerange = 11.8
        shineable = smashbot_state.action in [
            Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD
        ]
        if self.attack and shineable and gamestate.distance < foxshinerange:
            self.controller.press_button(melee.Button.BUTTON_B)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Waveland down
        aerials = [
            Action.NAIR, Action.FAIR, Action.UAIR, Action.BAIR, Action.DAIR
        ]
        if smashbot_state.ecb.bottom.y + smashbot_state.position.y > platform_height and smashbot_state.action not in aerials:
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            # When we're choosing to not attack, just get close to the opponent if we're already
            x = int(
                smashbot_state.position.x < opponent_state.position.x) * 0.8
            if not self.attack and abs(smashbot_state.position.x -
                                       opponent_state.position.x) < 5:
                x = 0.5
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, x, 0)
            return

        # Don't jump into Peach's dsmash or SH early dair spam
        dsmashactive = opponent_state.action == Action.DOWNSMASH and opponent_state.action_frame <= 22
        if shineable and (opponent_state.action == Action.DAIR
                          or dsmashactive):
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # If we see the opponent jump, they cannot protect themselves from uair.
        # Does not look for KNEE_BEND because Smashbot needs to discern between SH and FH
        y_afternineframes = opponent_state.position.y
        gravity = self.framedata.characterdata[
            opponent_state.character]["Gravity"]
        y_speed = opponent_state.speed_y_self
        for i in range(1, 10):
            y_afternineframes += y_speed
            y_speed -= gravity

        aerialsminusdair = [Action.NAIR, Action.FAIR, Action.UAIR, Action.BAIR]
        if shineable and (opponent_state.action
                          in [Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD]
                          or opponent_state.action
                          in aerialsminusdair) and y_afternineframes < 50:
            self.controller.press_button(melee.Button.BUTTON_A)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 1)
            return

        # Last resort, just dash at the center of the platform
        if smashbot_state.on_ground:
            self.interruptible = True
            #If we're starting the turn around animation, keep pressing that way or
            #   else we'll get stuck in the slow turnaround
            if smashbot_state.action == Action.TURNING and smashbot_state.action_frame == 1:
                return

            #Dash back, since we're about to start running
            if smashbot_state.action == Action.DASHING and smashbot_state.action_frame >= 11:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                            int(not smashbot_state.facing), .5)
                return
            else:
                self.controller.tilt_analog(
                    melee.Button.BUTTON_MAIN,
                    int(smashbot_state.position.x < pivot_point), .5)
                return
        # Mash analog L presses to L-cancel if Smashbot is throwing out an aerial
        elif not smashbot_state.on_ground and smashbot_state.action in aerials:
            self.interruptible = False
            if gamestate.frame % 2 == 0:
                self.controller.press_shoulder(Button.BUTTON_L, 1)
            else:
                self.controller.press_shoulder(Button.BUTTON_L, 0)
            return
        else:
            self.controller.empty_input()
예제 #2
0
    def step(self, gamestate, smashbot_state, opponent_state):
        self._propagate  = (gamestate, smashbot_state, opponent_state)

        # If we can't interrupt the chain, just continue it
        if self.chain != None and not self.chain.interruptible:
            self.chain.step(gamestate, smashbot_state, opponent_state)
            return

        # If we chose to run, keep running
        if type(self.chain) == Chains.Run and self.keep_running:
            self.pickchain(Chains.Run, [opponent_state.position.x > smashbot_state.position.x])
            return

        edge = melee.stages.EDGE_GROUND_POSITION[gamestate.stage]

        # Dash dance up to the correct spacing
        pivotpoint = opponent_state.position.x
        bufferzone = 30
        if opponent_state.character == Character.CPTFALCON:
            bufferzone = 35
        if opponent_state.character == Character.MARTH:
            bufferzone = 40
        if opponent_state.character == Character.SHEIK:
            bufferzone = 38
        if opponent_state.character == Character.MEWTWO:
            bufferzone = 32
        if opponent_state.character == Character.DK:
            bufferzone = 40
            if opponent_state.facing != (opponent_state.position.x < smashbot_state.position.x):
                bufferzone = 40
        if opponent_state.position.x > smashbot_state.position.x:
            bufferzone *= -1

        side_plat_height, side_plat_left, side_plat_right = melee.side_platform_position(opponent_state.position.x > 0, gamestate.stage)
        on_side_plat = False
        if side_plat_height is not None:
            on_side_plat = opponent_state.on_ground and abs(opponent_state.position.y - side_plat_height) < 5

        if on_side_plat:
            bufferzone = 0

        # Falling spacies
        falling_spacie = False
        if opponent_state.character in [Character.FOX, Character.FALCO]:
            if not opponent_state.on_ground and opponent_state.speed_y_self < 0:
                bufferzone = 0
                falling_spacie = True

        pivotpoint += bufferzone

        # Don't run off the stage though, adjust this back inwards a little if it's off
        edgebuffer = 10
        pivotpoint = min(pivotpoint, edge - edgebuffer)
        pivotpoint = max(pivotpoint, (-edge) + edgebuffer)

        if self.logger:
            self.logger.log("Notes", "pivotpoint: " + str(pivotpoint) + " ", concat=True)

        if on_side_plat and abs(smashbot_state.position.x - pivotpoint) < 2 and smashbot_state.action == Action.TURNING:
            if opponent_state.action_frame < 6:
                self.pickchain(Chains.Shffl, [SHFFL_DIRECTION.UP])
                return

        smash_now = opponent_state.action_frame < 6
        if opponent_state.character == Character.CPTFALCON:
            smash_now = opponent_state.action_frame in [4, 12, 20, 27]
        if opponent_state.character == Character.MARTH:
            smash_now = opponent_state.action_frame < 6
        if opponent_state.character == Character.DK:
            smash_now = False

        shadowball = False
        if opponent_state.character == Character.MEWTWO:
            for projectile in gamestate.projectiles:
                if projectile.type in [ProjectileType.SHADOWBALL] and projectile.subtype == 0:
                    shadowball = True
                    smash_now = True

        spacing_grace_zone = 2
        if falling_spacie:
            spacing_grace_zone = 8

        # If spacing and timing is right, do an attack
        if abs(smashbot_state.position.x - pivotpoint) < spacing_grace_zone:
            if smashbot_state.action == Action.TURNING:
                if smash_now and not on_side_plat and not falling_spacie:
                    # For marth, it's actually more reliable to run between slashes
                    if opponent_state.character == Character.MARTH:
                        self.keep_running = True
                        self.pickchain(Chains.Run, [opponent_state.position.x > smashbot_state.position.x])
                        return

                    self.chain = None
                    if opponent_state.position.x < smashbot_state.position.x:
                        self.pickchain(Chains.SmashAttack, [0, SMASH_DIRECTION.LEFT])
                    else:
                        self.pickchain(Chains.SmashAttack, [0, SMASH_DIRECTION.RIGHT])
                    return
                if falling_spacie and abs(opponent_state.position.y - smashbot_state.position.y) < 36:
                    self.chain = None
                    self.pickchain(Chains.Tilt, [TILT_DIRECTION.UP])
                    return
            elif smashbot_state.action == Action.DASHING:
                # Ground pound
                if opponent_state.character == Character.DK and opponent_state.action in [Action.DK_GROUND_POUND]:
                    if smashbot_state.facing == (smashbot_state.position.x < opponent_state.position.x):
                        self.pickchain(Chains.Shffl, [SHFFL_DIRECTION.DOWN])
                        return
                self.pickchain(Chains.Run, [not smashbot_state.facing])
                return

        # If we're stuck in shield, wavedash back
        if smashbot_state.action in [Action.SHIELD_RELEASE, Action.SHIELD]:
            self.pickchain(Chains.Wavedash, [1.0, False])
            return

        # Otherwise dash dance to the pivot point
        self.pickchain(Chains.DashDance, [pivotpoint, 0, False])
예제 #3
0
    def step(self, gamestate, smashbot_state, opponent_state):
        self._propagate = (gamestate, smashbot_state, opponent_state)

        # If we can't interrupt the chain, just continue it
        if self.chain != None and not self.chain.interruptible:
            self.chain.step(gamestate, smashbot_state, opponent_state)
            return

        # Get over to where they will end up at the end of hitstun
        end_x, end_y = self.framedata.project_hit_location(opponent_state)
        frames_left = opponent_state.hitstun_frames_left

        if self.framedata.is_roll(opponent_state.character,
                                  opponent_state.action):
            end_x = self.framedata.roll_end_position(opponent_state,
                                                     gamestate.stage)
            frames_left = self.framedata.last_roll_frame(
                opponent_state.character,
                opponent_state.action) - opponent_state.action_frame

        facing_away = (smashbot_state.position.x <
                       end_x) != smashbot_state.facing
        if smashbot_state.action == Action.TURNING and smashbot_state.action_frame == 1:
            facing_away = not facing_away

        on_ground = opponent_state.on_ground or opponent_state.position.y < 1 or opponent_state.action in [
            Action.TECH_MISS_UP, Action.TECH_MISS_DOWN
        ]

        # Make sure we don't dashdance off the platform during a juggle
        side_platform_height, side_platform_left, side_platform_right = melee.side_platform_position(
            smashbot_state.position.x > 0, gamestate.stage)
        top_platform_height, top_platform_left, top_platform_right = melee.top_platform_position(
            gamestate.stage)
        if smashbot_state.position.y < 5:
            end_x = min(end_x, melee.EDGE_GROUND_POSITION[gamestate.stage] - 5)
            end_x = max(end_x,
                        -melee.EDGE_GROUND_POSITION[gamestate.stage] + 5)
        elif (side_platform_height is not None
              ) and abs(smashbot_state.position.y - side_platform_height) < 5:
            end_x = min(end_x, side_platform_right - 5)
            end_x = max(end_x, side_platform_left + 5)
        elif (top_platform_height is not None
              ) and abs(smashbot_state.position.y - top_platform_height) < 5:
            end_x = min(end_x, top_platform_right - 5)
            end_x = max(end_x, top_platform_left + 5)

        # TODO Slideoff detection

        if self.logger:
            self.logger.log("Notes",
                            " Predicted End Position: " + str(end_x) + " " +
                            str(end_y) + " ",
                            concat=True)
            self.logger.log("Notes",
                            " on_ground: " + str(on_ground),
                            concat=True)
            self.logger.log("Notes",
                            " frames left: " + str(frames_left) + " ",
                            concat=True)

        # Need to pivot the uptilt
        # Uptilt's hitbox is pretty forgiving if we do it a few frames early, so no big deal there
        if not on_ground:
            # If we can just throw out an uptilt and hit now, do it. No need to wait for them to fall further
            end_early_x, end_early_y = self.framedata.project_hit_location(
                opponent_state, 7)
            if self.logger:
                self.logger.log("Notes",
                                " uptilt early End Position: " +
                                str(end_early_x) + " " + str(end_early_y) +
                                " ",
                                concat=True)
            in_range = (abs(end_early_x - smashbot_state.position.x) < 8) and (
                abs(end_early_y - smashbot_state.position.y) < 12)
            if smashbot_state.action == Action.TURNING and in_range and (
                    7 <= frames_left <= 9):
                self.pickchain(Chains.Tilt, [TILT_DIRECTION.UP])
                return
            # Check each height level, can we do an up-air right now?
            for height_level in AirAttack.height_levels():
                height = AirAttack.attack_height(height_level)
                commitment = AirAttack.frame_commitment(height)
                end_early_x, end_early_y = self.framedata.project_hit_location(
                    opponent_state, commitment)
                if (commitment < frames_left) and (
                        abs(smashbot_state.position.x - end_early_x) <
                        20) and (abs(end_early_y - height) < 5):
                    if self.logger:
                        self.logger.log("Notes",
                                        " Early End Position: " +
                                        str(end_early_x) + " " +
                                        str(end_early_y) + " ",
                                        concat=True)
                        self.logger.log("Notes",
                                        " height: " + str(height),
                                        concat=True)
                        self.logger.log("Notes",
                                        " commitment: " + str(commitment),
                                        concat=True)
                    self.chain = None
                    self.pickchain(
                        Chains.AirAttack,
                        [end_early_x, end_early_y, AIR_ATTACK_DIRECTION.UP])
                    return
            # Just dash dance to where they will end up
            # TODO board platform to get closer?
            if frames_left > 9:
                self.chain = None
                self.pickchain(Chains.DashDance, [end_x])
                return
        else:
            if self.framedata.is_roll(opponent_state.character,
                                      opponent_state.action):
                # We still have plenty of time, so just get closer to the DD spot
                #   Even if we're already close
                if frames_left > 10:
                    # Do we need to jump up to the side platform?
                    side_plat_height, side_plat_left, side_plat_right = melee.side_platform_position(
                        opponent_state.position.x > 0, gamestate.stage)
                    # TODO 13 is the fastest getup attack of the legal character, do a lookup for the actual one
                    if opponent_state.action in [
                            Action.TECH_MISS_UP, Action.TECH_MISS_DOWN
                    ]:
                        frames_left += 13
                    if side_plat_height is not None and (
                            frames_left >
                            25) and abs(side_plat_height -
                                        opponent_state.position.y) < 5:
                        # But only if we're already mostly there
                        smashbot_on_side_plat = smashbot_state.on_ground and abs(
                            smashbot_state.position.y - side_plat_height) < 5
                        if side_plat_left < smashbot_state.position.x < side_plat_right:
                            self.chain = None
                            self.pickchain(
                                Chains.BoardSidePlatform,
                                [opponent_state.position.x > 0, False])
                            return

                    if self.logger:
                        self.logger.log("Notes",
                                        " DD at: " + str(end_x),
                                        concat=True)
                        self.logger.log("Notes",
                                        " plat at: " + str(side_plat_left) +
                                        " " + str(side_plat_right),
                                        concat=True)
                    self.chain = None
                    self.pickchain(Chains.DashDance, [end_x])
                    return
                # We need to get to a position where our back is to the end position. We'll do a pivot stand to get there
                if (abs(smashbot_state.position.x - end_x) < 5):
                    # Pivot
                    if smashbot_state.action == Action.DASHING:
                        self.chain = None
                        self.pickchain(Chains.Run, [not smashbot_state.facing])
                        return
                    if smashbot_state.action in [
                            Action.TURNING, Action.STANDING
                    ]:
                        if 7 <= frames_left <= 9:
                            if facing_away and gamestate.distance < 20:
                                self.pickchain(Chains.Tilt,
                                               [TILT_DIRECTION.UP])
                                return
                            # Can't grab a tech miss. Don't try
                            elif opponent_state.action not in [
                                    Action.TECH_MISS_UP, Action.TECH_MISS_DOWN
                            ] and gamestate.distance < 10:
                                self.pickchain(Chains.GrabAndThrow,
                                               [THROW_DIRECTION.UP])
                                return
                        if frames_left == 1 and gamestate.distance < 10:
                            self.pickchain(Chains.Waveshine)
                            return
                        else:
                            self.pickchain(Chains.Nothing)
                            return

                # If we're a little further away than 5 units, but still in range
                elif (abs(smashbot_state.position.x - end_x) < 10):
                    # Don't dashdance here. Just stand still
                    if smashbot_state.action == Action.TURNING and smashbot_state.action_frame > 1:
                        self.pickchain(Chains.Nothing)
                        return

                    self.chain = None
                    self.pickchain(Chains.DashDance, [end_x])
                    return

                # We're further than 5 units away, so DD into their end position
                self.chain = None
                self.pickchain(Chains.DashDance, [end_x])
                return

        self.chain = None
        self.pickchain(Chains.DashDance, [end_x])
예제 #4
0
    def step(self, gamestate, smashbot_state, opponent_state):

        platform_center = 0
        platform_height = 0

        position = melee.side_platform_position(self.right_platform, gamestate)
        if position:
            platform_center = (position[1] + position[2]) / 2
            platform_height = position[0]

        under_platform = abs(smashbot_state.position.x - platform_center) < 10

        if smashbot_state.on_ground:
            self.interruptible = True

        # Are we in position to jump?
        if under_platform and smashbot_state.action == Action.TURNING:
            self.interruptible = False
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # If we're crouching, keep holding Y
        if smashbot_state.action == Action.KNEE_BEND:
            self.controller.press_button(melee.Button.BUTTON_Y)
            self.interruptible = False
            return

        # Jump out of shine
        if smashbot_state.action in [Action.DOWN_B_AIR]:
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # Can we shine our opponent right now, while we're in the air?
        foxshinerange = 11.8
        shineable = smashbot_state.action in [
            Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD
        ]
        if shineable and gamestate.distance < foxshinerange:
            self.controller.press_button(melee.Button.BUTTON_B)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Waveland down
        aerials = [
            Action.NAIR, Action.FAIR, Action.UAIR, Action.BAIR, Action.DAIR
        ]
        if smashbot_state.ecb.bottom.y + smashbot_state.position.y > platform_height and smashbot_state.action not in aerials:
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Don't jump into Peach's dsmash or SH early dair spam
        dsmashactive = opponent_state.action == Action.DOWNSMASH and opponent_state.action_frame <= 22
        if shineable and (opponent_state.action == Action.DAIR
                          or dsmashactive):
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # If we see the opponent jump, they cannot protect themselves from uair.
        # Does not look for KNEE_BEND because Smashbot needs to discern between SH and FH
        y_afternineframes = opponent_state.position.y
        gravity = self.framedata.characterdata[
            opponent_state.character]["Gravity"]
        y_speed = opponent_state.speed_y_self
        for i in range(1, 10):
            y_afternineframes += y_speed
            y_speed -= gravity

        aerialsminusdair = [Action.NAIR, Action.FAIR, Action.UAIR, Action.BAIR]
        if shineable and (opponent_state.action
                          in [Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD]
                          or opponent_state.action
                          in aerialsminusdair) and y_afternineframes < 50:
            self.controller.press_button(melee.Button.BUTTON_A)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 1)
            return

        # Last resort, just dash at the center of the platform
        if smashbot_state.on_ground:
            self.interruptible = True
            #If we're starting the turn around animation, keep pressing that way or
            #   else we'll get stuck in the slow turnaround
            if smashbot_state.action == Action.TURNING and smashbot_state.action_frame == 1:
                return

            #Dash back, since we're about to start running
            if smashbot_state.action == Action.DASHING and smashbot_state.action_frame >= 11:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                            int(not smashbot_state.facing), .5)
                return
            if smashbot_state.position.x > platform_center + 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0, .5)
                return
            if smashbot_state.position.x < platform_center - 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 1, .5)
                return
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                        int(smashbot_state.facing), .5)
            return
        # Mash analog L presses to L-cancel if Smashbot is throwing out an aerial
        elif not smashbot_state.on_ground and smashbot_state.action in aerials:
            self.interruptible = False
            if gamestate.frame % 2 == 0:
                self.controller.press_shoulder(Button.BUTTON_L, 1)
            else:
                self.controller.press_shoulder(Button.BUTTON_L, 0)
            return
        else:
            self.controller.empty_input()
예제 #5
0
    def step(self, gamestate, smashbot_state, opponent_state):
        self._propagate = (gamestate, smashbot_state, opponent_state)

        #If we can't interrupt the chain, just continue it
        if self.chain != None and not self.chain.interruptible:
            self.chain.step(gamestate, smashbot_state, opponent_state)
            return

        needswavedash = smashbot_state.action in [Action.DOWN_B_GROUND, Action.DOWN_B_STUN, \
            Action.DOWN_B_GROUND_START, Action.LANDING_SPECIAL, Action.SHIELD, Action.SHIELD_START, \
            Action.SHIELD_RELEASE, Action.SHIELD_STUN, Action.SHIELD_REFLECT]
        if needswavedash:
            self.pickchain(Chains.Wavedash, [1, False])
            return

        bufferzone = 30
        if opponent_state.character == Character.SHEIK and opponent_state.action == Action.SWORD_DANCE_2_HIGH:
            bufferzone = 55

        # Samus bomb?
        samus_bomb = False
        for projectile in gamestate.projectiles:
            if projectile.type in [
                    melee.ProjectileType.SAMUS_BOMB,
                    melee.ProjectileType.PIKACHU_THUNDER
            ]:
                if smashbot_state.position.x < projectile.x < opponent_state.position.x or smashbot_state.position.x > projectile.x > opponent_state.position.x:
                    samus_bomb = True
        if samus_bomb:
            bufferzone = 60
        if opponent_state.action == Action.LOOPING_ATTACK_MIDDLE:
            bufferzone += 15

        onright = opponent_state.position.x < smashbot_state.position.x
        if not onright:
            bufferzone *= -1

        if Retreat.is_rapid_jab(opponent_state):
            bufferzone = 60

        pivotpoint = opponent_state.position.x + bufferzone
        # Don't run off the stage though, adjust this back inwards a little if it's off

        edgebuffer = 10
        edge = melee.stages.EDGE_GROUND_POSITION[gamestate.stage] - edgebuffer
        # If we are about to pivot near the edge, just grab the edge instead
        if abs(pivotpoint) > edge and opponent_state.position.y < 20:
            self.pickchain(Chains.Grabedge)
            return

        pivotpoint = min(pivotpoint, edge)
        pivotpoint = max(pivotpoint, -edge)

        # TODO make this a general function for all projectiles
        missle_approaching = False
        for projectile in gamestate.projectiles:
            if projectile.type in [
                    melee.ProjectileType.SAMUS_MISSLE,
                    melee.ProjectileType.SAMUS_CHARGE_BEAM
            ]:
                missle_approaching = True

        # Only do this laser if we are on the same level as the opponent
        if abs(opponent_state.position.y -
               smashbot_state.position.y) < 5 and not missle_approaching:
            if samus_bomb and opponent_state.action == Action.SWORD_DANCE_4_MID and opponent_state.action_frame < 10:
                self.pickchain(Chains.Laser)
                return

        # If opponent is on a side platform, board the opposite platform and laser
        #   They don't need to be standing on the plat, just sort of shortly above it
        side_plat_height, side_plat_left, side_plat_right = melee.side_platform_position(
            opponent_state.position.x > 0, gamestate.stage)
        other_side_plat_height, other_side_plat_left, other_side_plat_right = melee.side_platform_position(
            opponent_state.position.x < 0, gamestate.stage)
        if (side_plat_height is not None
            ) and (opponent_state.position.y + 1 > side_plat_height) and (
                side_plat_left < opponent_state.position.x < side_plat_right):
            # If we're already on the platform
            if smashbot_state.position.y > 5 and smashbot_state.on_ground:
                # Make sure we're in the center-ish of the platform
                if (other_side_plat_left + 5 < smashbot_state.position.x <
                        other_side_plat_right - 5) and not missle_approaching:
                    self.pickchain(Chains.Laser)
                    return
                else:
                    self.chain = None
                    self.pickchain(Chains.DashDance, [
                        other_side_plat_left +
                        (other_side_plat_right - other_side_plat_left / 2)
                    ])
                    return
            else:
                self.pickchain(Chains.BoardSidePlatform,
                               [opponent_state.position.x < 0])
                return

        self.chain = None
        self.pickchain(Chains.DashDance, [pivotpoint])
예제 #6
0
    def step(self, gamestate, smashbot_state, opponent_state):
        platform_center = 0
        platform_height = 0

        position = melee.top_platform_position(gamestate.stage)
        if position:
            platform_center = (position[1] + position[2]) / 2
            platform_height = position[0]

        on_side_platform = smashbot_state.on_ground and smashbot_state.position.y > 5
        above_top_platform = (not smashbot_state.on_ground) and (smashbot_state.position.y + smashbot_state.ecb.bottom.y > platform_height) and \
            position[1] < smashbot_state.position.x < position[2]

        if smashbot_state.on_ground and smashbot_state.action != Action.KNEE_BEND:
            self.interruptible = True

        # Stage 1, get to the inside edge of the side platform
        #   Are we in position to jump? We want to be dashing inwards on a side plat
        if on_side_platform:
            # Get the x coord of the inner edge of the plat
            right_edge = (melee.side_platform_position(True,
                                                       gamestate.stage))[2]
            if right_edge - abs(smashbot_state.position.x) < 8:
                if smashbot_state.action in [
                        Action.DASHING, Action.RUNNING
                ] and (smashbot_state.facing
                       == (smashbot_state.position.x < 0)):
                    self.interruptible = False
                    self.controller.press_button(melee.Button.BUTTON_Y)
                    return
                else:
                    # Dash inwards
                    self.interruptible = False
                    self.controller.tilt_analog(
                        melee.Button.BUTTON_MAIN,
                        int(smashbot_state.position.x < 0), 0.5)
                    return
            else:
                # Dash inwards
                self.interruptible = False
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                            int(smashbot_state.position.x < 0),
                                            0.5)
                return

        # If we're crouching, keep holding Y
        if smashbot_state.action == Action.KNEE_BEND:
            self.controller.press_button(melee.Button.BUTTON_Y)
            self.interruptible = False
            return

        # Jump when falling
        if smashbot_state.action == Action.FALLING and smashbot_state.jumps_left > 0 and smashbot_state.action_frame > 6:
            self.interruptible = False
            self.controller.press_button(melee.Button.BUTTON_Y)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                        int(smashbot_state.position.x < 0),
                                        0.5)
            return

        # Jump out of shine
        if smashbot_state.action in [Action.DOWN_B_AIR]:
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # Can we shine our opponent right now, while we're in the air?
        foxshinerange = 11.8
        shineable = smashbot_state.action in [
            Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD
        ]
        if shineable and gamestate.distance < foxshinerange:
            self.controller.press_button(melee.Button.BUTTON_B)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Waveland down
        aerials = [
            Action.NAIR, Action.FAIR, Action.UAIR, Action.BAIR, Action.DAIR
        ]
        if above_top_platform and smashbot_state.action not in aerials:
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            # If opponent is in front of us, waveland towards them
            if smashbot_state.facing == (smashbot_state.position.x <
                                         opponent_state.position.x):
                self.controller.tilt_analog(
                    melee.Button.BUTTON_MAIN,
                    int(smashbot_state.position.x < opponent_state.position.x),
                    0.2)
            else:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Don't jump into Peach's dsmash or SH early dair spam
        dsmashactive = opponent_state.action == Action.DOWNSMASH and opponent_state.action_frame <= 22
        if shineable and (opponent_state.action == Action.DAIR
                          or dsmashactive):
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Hold inwards while we're jumping
        if shineable:
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                        int(smashbot_state.position.x < 0),
                                        0.5)
            return

        # Last resort, just dash at the center of the platform
        if smashbot_state.on_ground:
            self.interruptible = True
            #If we're starting the turn around animation, keep pressing that way or
            #   else we'll get stuck in the slow turnaround
            if smashbot_state.action == Action.TURNING and smashbot_state.action_frame == 1:
                return

            #Dash back, since we're about to start running
            if smashbot_state.action == Action.DASHING and smashbot_state.action_frame >= 11:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                            int(not smashbot_state.facing), .5)
                return
            if smashbot_state.position.x > platform_center + 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0, .5)
                return
            if smashbot_state.position.x < platform_center - 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 1, .5)
                return
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                        int(smashbot_state.facing), .5)
            return
        # Mash analog L presses to L-cancel if Smashbot is throwing out an aerial
        elif not smashbot_state.on_ground and smashbot_state.action in aerials:
            self.interruptible = False
            if gamestate.frame % 2 == 0:
                self.controller.press_shoulder(Button.BUTTON_L, 1)
            else:
                self.controller.press_shoulder(Button.BUTTON_L, 0)
            return
        else:
            self.controller.empty_input()
예제 #7
0
    def step(self, gamestate, smashbot_state, opponent_state):

        platform_center = 0
        platform_height = 0

        position = melee.side_platform_position(self.right_platform, gamestate)
        if position:
            platform_center = (position[1] + position[2]) / 2
            platform_height = position[0]

        under_platform = abs(smashbot_state.x - platform_center) < 10

        if smashbot_state.on_ground:
            self.interruptible = True

        # Are we in position to jump?
        if under_platform and smashbot_state.action == Action.TURNING:
            self.interruptible = False
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # If we're crouching, keep holding Y
        if smashbot_state.action == Action.KNEE_BEND:
            self.controller.press_button(melee.Button.BUTTON_Y)
            self.interruptible = False
            return

        # Jump out of shine
        if smashbot_state.action in [Action.DOWN_B_AIR]:
            self.controller.press_button(melee.Button.BUTTON_Y)
            return

        # Can we shine our opponent right now, while we're in the air?
        foxshinerange = 11.8
        shineable = smashbot_state.action in [
            Action.JUMPING_FORWARD, Action.JUMPING_BACKWARD
        ]
        if shineable and gamestate.distance < foxshinerange:
            self.controller.press_button(melee.Button.BUTTON_B)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Waveland down
        if smashbot_state.ecb_bottom[1] + smashbot_state.y > platform_height:
            self.interruptible = True
            self.controller.press_button(melee.Button.BUTTON_L)
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0.5, 0)
            return

        # Last resort, just dash at the center of the platform
        if smashbot_state.on_ground:
            self.interruptible = True
            #If we're starting the turn around animation, keep pressing that way or
            #   else we'll get stuck in the slow turnaround
            if smashbot_state.action == Action.TURNING and smashbot_state.action_frame == 1:
                return

            #Dash back, since we're about to start running
            if smashbot_state.action == Action.DASHING and smashbot_state.action_frame >= 11:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                            int(not smashbot_state.facing), .5)
                return
            if smashbot_state.x > platform_center + 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 0, .5)
                return
            if smashbot_state.x < platform_center - 2:
                self.controller.tilt_analog(melee.Button.BUTTON_MAIN, 1, .5)
                return
            self.controller.tilt_analog(melee.Button.BUTTON_MAIN,
                                        int(smashbot_state.facing), .5)
            return
        else:
            self.controller.empty_input()