Esempio n. 1
0
    def __init__(self, name: str, level: int):
        self.name = normalize_name(name)
        self.base_name = self.name
        self.level = level

        self.base_stats = pokedex[self.name][constants.BASESTATS]
        self.stats = calculate_stats(self.base_stats, self.level)

        self.max_hp = self.stats.pop(constants.HITPOINTS)
        self.hp = self.max_hp
        if self.name == 'shedinja':
            self.max_hp = 1
            self.hp = 1

        self.ability = normalize_name(
            pokedex[self.name][constants.MOST_LIKELY_ABILITY])
        self.types = pokedex[self.name][constants.TYPES]
        self.item = 'unknown'

        self.fainted = False
        self.moves = []
        self.status = None
        self.volatile_statuses = []
        self.boosts = defaultdict(lambda: 0)
        self.can_mega_evo = False
        self.can_ultra_burst = True
Esempio n. 2
0
def start_volatile_status(battle, split_msg):
    if is_opponent(battle, split_msg):
        pkmn = battle.opponent.active
    else:
        pkmn = battle.user.active

    volatile_status = normalize_name(split_msg[3].split(":")[-1])
    if volatile_status not in pkmn.volatile_statuses:
        logger.debug("Starting the volatile status {} on {}".format(
            volatile_status, pkmn.name))
        pkmn.volatile_statuses.append(volatile_status)

    if volatile_status == constants.DYNAMAX:
        pkmn.hp *= 2
        pkmn.max_hp *= 2
        logger.debug("{} started dynamax - doubling their HP to {}/{}".format(
            pkmn.name, pkmn.hp, pkmn.max_hp))

    if constants.ABILITY in split_msg[3]:
        pkmn.ability = volatile_status

    if len(split_msg) == 6 and constants.ABILITY in normalize_name(
            split_msg[5]):
        pkmn.ability = normalize_name(split_msg[5].split('ability:')[-1])

    if volatile_status == constants.TYPECHANGE:
        new_type = normalize_name(split_msg[4])
        logger.debug("Setting {}'s type to {}".format(pkmn.name, new_type))
        pkmn.types = [new_type]
Esempio n. 3
0
def get_new_spreads(smogon_stats_url):
    """Parses a Smogon stats document, such as: 'https://www.smogon.com/stats/2019-02/moveset/gen7ou-1825.txt'
       Returns a dictionary containing the most common spreads for the pokemon in the file
    """
    r = requests.get(smogon_stats_url)

    split_string = str(r.content).split(new_pokemon_indicator)

    spreads = dict()
    for pokemon_data in split_string:
        segments = pokemon_data.split('|')
        it = iter(segments)
        pokemon_name = normalize_name(segments[1])
        spreads[pokemon_name] = list()
        for segment in it:
            if normalize_name(segment) == spreads_string:
                while section_end_string not in segment:
                    segment = next(it)
                    if ':' in segment:
                        split_segment = segment.split()
                        spread = split_segment[0]
                        nature = normalize_name(spread.split(':')[0])
                        evs = spread.split(':')[1].replace('/', ',')
                        spreads[pokemon_name].append((nature, evs))

    return spreads
Esempio n. 4
0
def heal_or_damage(battle, split_msg):
    """The opponent's active pokemon has healed"""
    if is_opponent(battle, split_msg):
        pkmn = battle.opponent.active

        # opponent hp is given as a percentage
        if constants.FNT in split_msg[3]:
            pkmn.hp = 0
        else:
            new_hp_percentage = float(split_msg[3].split('/')[0]) / 100
            pkmn.hp = pkmn.max_hp * new_hp_percentage

            if len(split_msg) == 5 and constants.TOXIC in split_msg[
                    3] and '[from] psn' in split_msg[4]:
                battle.opponent.side_conditions[constants.TOXIC_COUNT] += 1

        # give that pokemon an item if this string specifies one
        if len(split_msg) == 5 and constants.ITEM in split_msg[4]:
            item = normalize_name(split_msg[4].split(
                constants.ITEM)[-1].strip(": "))
            logger.debug("Setting opponent's item to: {}".format(item))
            pkmn.item = item

        # set the ability if the information is shown
        if len(split_msg) >= 5 and constants.ABILITY in split_msg[4]:
            ability = normalize_name(split_msg[4].split(
                constants.ABILITY)[-1].strip(": "))
            logger.debug("Setting opponent's item ability {}".format(ability))
            pkmn.ability = ability

    else:
        if len(split_msg) == 5 and constants.TOXIC in split_msg[
                3] and '[from] psn' in split_msg[4]:
            battle.user.side_conditions[constants.TOXIC_COUNT] += 1
Esempio n. 5
0
def set_opponent_ability(battle, split_msg):
    if is_opponent(battle, split_msg):
        for msg in split_msg:
            if constants.ABILITY in normalize_name(msg):
                ability = normalize_name(msg.split(':')[-1])
                logger.debug("Setting opponent ability to {}".format(ability))
                battle.opponent.active.ability = ability
Esempio n. 6
0
def heal_or_damage(battle, split_msg):
    if is_opponent(battle, split_msg):
        side = battle.opponent
        other_side = battle.user
        pkmn = battle.opponent.active

        # opponent hp is given as a percentage
        if constants.FNT in split_msg[3]:
            pkmn.hp = 0
        else:
            new_hp_percentage = float(split_msg[3].split('/')[0]) / 100
            pkmn.hp = pkmn.max_hp * new_hp_percentage

    else:
        side = battle.user
        other_side = battle.opponent
        pkmn = battle.user.active
        if constants.FNT in split_msg[3]:
            pkmn.hp = 0
        else:
            pkmn.hp = float(split_msg[3].split('/')[0])
            pkmn.max_hp = float(split_msg[3].split('/')[1].split()[0])

    # increase the amount of turns toxic has been active
    if len(split_msg) == 5 and constants.TOXIC in split_msg[
            3] and '[from] psn' in split_msg[4]:
        side.side_conditions[constants.TOXIC_COUNT] += 1

    if len(split_msg) == 6 and split_msg[4].startswith(
            '[from] item:') and other_side.name in split_msg[5]:
        item = normalize_name(split_msg[4].split('item:')[-1])
        logger.debug("Setting {}'s item to: {}".format(other_side.active.name,
                                                       item))
        other_side.active.item = item

    # set the ability for the other side (the side not taking damage, '-damage' only)
    if len(split_msg) == 6 and split_msg[4].startswith(
            '[from] ability:'
    ) and other_side.name in split_msg[5] and split_msg[1] == '-damage':
        ability = normalize_name(split_msg[4].split('ability:')[-1])
        logger.debug("Setting {}'s ability to: {}".format(
            other_side.active.name, ability))
        other_side.active.ability = ability

    # set the ability of the side (the side being healed, '-heal' only)
    if len(split_msg) == 6 and constants.ABILITY in split_msg[
            4] and other_side.name in split_msg[5] and split_msg[1] == '-heal':
        ability = normalize_name(split_msg[4].split(
            constants.ABILITY)[-1].strip(": "))
        logger.debug("Setting {}'s ability to: {}".format(pkmn.name, ability))
        pkmn.ability = ability

    # give that pokemon an item if this string specifies one
    if len(split_msg
           ) == 5 and constants.ITEM in split_msg[4] and pkmn.item is not None:
        item = normalize_name(split_msg[4].split(
            constants.ITEM)[-1].strip(": "))
        logger.debug("Setting {}'s item to: {}".format(pkmn.name, item))
        pkmn.item = item
Esempio n. 7
0
def move(battle, split_msg):
    move_name = normalize_name(split_msg[3].strip().lower())

    if is_opponent(battle, split_msg):
        side = battle.opponent
        pkmn = battle.opponent.active
    else:
        side = battle.user
        pkmn = battle.user.active

    # add the move to it's moves if it hasn't been seen
    # decrement the PP by one
    # if the move is unknown, do nothing
    move_object = pkmn.get_move(move_name)
    if move_object is None:
        new_move = pkmn.add_move(move_name)
        if new_move is not None:
            new_move.current_pp -= 1
    else:
        move_object.current_pp -= 1
        logger.debug("{} already has the move {}. Decrementing the PP by 1".format(pkmn.name, move_name))

    # if this pokemon used two different moves without switching,
    # set a flag to signify that it cannot have a choice item
    if (
            is_opponent(battle, split_msg) and
            side.last_used_move.pokemon_name == side.active.name and
            side.last_used_move.move != move_name
    ):
        logger.debug("{} used two different moves - it cannot have a choice item".format(pkmn.name))
        pkmn.can_have_choice_item = False
        if pkmn.item in constants.CHOICE_ITEMS:
            logger.warning("{} has a choice item, but used two different moves - setting it's item to UNKNOWN".format(pkmn.name))
            pkmn.item = constants.UNKNOWN_ITEM

    try:
        category = all_move_json[move_name][constants.CATEGORY]
        logger.debug("Setting {}'s last used move: {}".format(pkmn.name, move_name))
        side.last_used_move = LastUsedMove(
            pokemon_name=pkmn.name,
            move=move_name
        )
    except KeyError:
        category = None
        side.last_used_move = LastUsedMove(
            pokemon_name=pkmn.name,
            move=constants.DO_NOTHING_MOVE
        )

    # if this pokemon used a damaging move, eliminate the possibility of it having a lifeorb
    # the lifeorb will reveal itself if it has it
    if category in constants.DAMAGING_CATEGORIES and not any([normalize_name(a) in ['sheerforce', 'magicguard'] for a in pokedex[pkmn.name][constants.ABILITIES].values()]):
        logger.debug("{} used a damaging move - not guessing lifeorb anymore".format(pkmn.name))
        pkmn.can_have_life_orb = False

    # there is nothing special in the protocol for "wish" - it must be extracted here
    if move_name == constants.WISH and 'still' not in split_msg[4]:
        logger.debug("{} used wish - expecting {} health of recovery next turn".format(side.active.name, side.active.max_hp/2))
        side.wish = (2, side.active.max_hp/2)
Esempio n. 8
0
 def get_move_information(m):
     try:
         return m.split('|')[2], all_move_json[normalize_name(
             m.split('|')[3])]
     except KeyError:
         logger.debug(
             "Unknown move {} - using standard 0 priority move".format(
                 normalize_name(m.split('|')[3])))
         return m.split('|')[2], {constants.PRIORITY: 0}
Esempio n. 9
0
def weather(battle, split_msg):
    """Set the battle's weather"""
    weather_name = normalize_name(split_msg[2].split(':')[-1].strip())
    logger.debug("Weather {} started".format(weather_name))
    battle.weather = weather_name

    if len(split_msg) >= 5 and battle.opponent.name in split_msg[4]:
        ability = normalize_name(split_msg[3].split(':')[-1].strip())
        logger.debug("Setting opponent ability to {}".format(ability))
        battle.opponent.active.ability = ability
Esempio n. 10
0
def set_ability(battle, split_msg):
    if is_opponent(battle, split_msg):
        side = battle.opponent
    else:
        side = battle.user

    for msg in split_msg:
        if constants.ABILITY in normalize_name(msg):
            ability = normalize_name(msg.split(':')[-1])
            logger.debug("Setting {}'s ability to {}".format(side.active.name, ability))
            side.active.ability = ability
Esempio n. 11
0
def single_pokemon_export_to_dict(pkmn_export_string):
    def get_species(s):
        if '(' in s and ')' in s:
            species = s[s.find("(") + 1:s.find(")")]
            return species
        return None

    pkmn_dict = {
        "name": "",
        "species": "",
        "level": "",
        "gender": "",
        "item": "",
        "ability": "",
        "moves": [],
        "nature": "",
        "evs": {
            "hp": "",
            "atk": "",
            "def": "",
            "spa": "",
            "spd": "",
            "spe": "",
        },
    }
    pkmn_info = pkmn_export_string.split('\n')
    name = pkmn_info[0].split('@')[0]
    if "(M)" in name:
        pkmn_dict["gender"] = "M"
        name = name.replace('(M)', '')
    if "(F)" in name:
        pkmn_dict["gender"] = "F"
        name = name.replace('(F)', '')
    species = get_species(name)
    if species:
        pkmn_dict["species"] = normalize_name(species)
        pkmn_dict["name"] = name.split('(')[0].strip()
    else:
        pkmn_dict["name"] = normalize_name(name.strip())
    if '@' in pkmn_info[0]:
        pkmn_dict["item"] = normalize_name(pkmn_info[0].split('@')[1])
    for line in pkmn_info[1:]:
        if line.startswith('Ability: '):
            pkmn_dict["ability"] = normalize_name(line.split('Ability: ')[-1])
        elif line.startswith('Level: '):
            pkmn_dict["level"] = normalize_name(line.split('Level: ')[-1])
        elif line.startswith('EVs: '):
            evs = line.split('EVs: ')[-1]
            for ev in evs.split('/'):
                ev = ev.strip()
                amount = normalize_name(ev.split(' ')[0])
                stat = normalize_name(ev.split(' ')[1])
                pkmn_dict['evs'][stat] = amount
        elif line.endswith('Nature'):
            pkmn_dict["nature"] = normalize_name(line.split('Nature')[0])
        elif line.startswith('-'):
            pkmn_dict["moves"].append(normalize_name(line[1:]))
    return pkmn_dict
Esempio n. 12
0
def weather(battle, split_msg):
    if is_opponent(battle, split_msg):
        side = battle.opponent
    else:
        side = battle.user

    weather_name = normalize_name(split_msg[2].split(':')[-1].strip())
    logger.debug("Weather {} started".format(weather_name))
    battle.weather = weather_name

    if len(split_msg) >= 5 and side.name in split_msg[4]:
        ability = normalize_name(split_msg[3].split(':')[-1].strip())
        logger.debug("Setting {} ability to {}".format(side.active.name, ability))
        side.active.ability = ability
Esempio n. 13
0
 def add_move(self, move_name: str):
     if normalize_name(move_name) in [m.name for m in self.moves]:
         return
     try:
         self.moves.append(Move(move_name))
     except KeyError:
         logger.warning("{} is not a known move".format(move_name))
Esempio n. 14
0
    def __init__(self, name: str, level: int):
        self.name = normalize_name(name)
        self.base_name = self.name
        self.level = level

        try:
            self.base_stats = pokedex[self.name][constants.BASESTATS]
        except KeyError:
            logger.info("Could not pokedex entry for {}".format(self.name))
            self.name = [k for k in pokedex if self.name.startswith(k)][0]
            logger.info("Using {} instead".format(self.name))
            self.base_stats = pokedex[self.name][constants.BASESTATS]

        self.stats = calculate_stats(self.base_stats, self.level)

        self.max_hp = self.stats.pop(constants.HITPOINTS)
        self.hp = self.max_hp
        if self.name == 'shedinja':
            self.max_hp = 1
            self.hp = 1

        self.ability = None
        self.types = pokedex[self.name][constants.TYPES]
        self.item = constants.UNKNOWN_ITEM

        self.fainted = False
        self.moves = []
        self.status = None
        self.volatile_statuses = []
        self.boosts = defaultdict(lambda: 0)
        self.can_mega_evo = False
        self.can_ultra_burst = False
        self.is_mega = False
        self.can_have_choice_item = True
Esempio n. 15
0
def transform(battle, split_msg):
    if is_opponent(battle, split_msg):
        transformed_into_name = normalize_name(split_msg[3].split(':')[1])

        battle_copy = deepcopy(battle)
        battle.opponent.active.boosts = deepcopy(battle.user.active.boosts)

        battle_copy.user.from_json(battle_copy.request_json)

        if battle_copy.user.active.name == transformed_into_name or battle_copy.user.active.name.startswith(
                transformed_into_name):
            transformed_into = battle_copy.user.active
        else:
            transformed_into = find_pokemon_in_reserves(
                transformed_into_name, battle_copy.user.reserve)

        logger.debug("Opponent {} transformed into {}".format(
            battle.opponent.active.name, battle.user.active.name))
        battle.opponent.active.stats = deepcopy(transformed_into.stats)
        battle.opponent.active.ability = deepcopy(transformed_into.ability)
        battle.opponent.active.moves = deepcopy(transformed_into.moves)
        battle.opponent.active.types = deepcopy(transformed_into.types)

        if constants.TRANSFORM not in battle.opponent.active.volatile_statuses:
            battle.opponent.active.volatile_statuses.append(
                constants.TRANSFORM)
Esempio n. 16
0
def move(battle, split_msg):
    """The opponent's pokemon has made a move - add it to that pokemon's move list if necessary"""
    move_name = normalize_name(split_msg[3].strip().lower())
    if is_opponent(battle, split_msg):
        pkmn = battle.opponent.active
        move = pkmn.get_move(move_name)
        if move is None:
            new_move = pkmn.add_move(move_name)
            if new_move is not None:
                new_move.current_pp -= 1
        else:
            move.current_pp -= 1
            logger.debug(
                "{} already has the move {}. Decrementing the PP by 1".format(
                    pkmn.name, move_name))

        logger.debug("Setting opponent's last used move: {} - {}".format(
            battle.opponent.active.name, move_name))

        # if this pokemon used two different moves without switching,
        # set a flag to signify that it cannot have a choice item
        if (battle.opponent.last_used_move.pokemon_name
                == battle.opponent.active.name
                and battle.opponent.last_used_move.move != move_name):
            logger.debug(
                "Opponent's {} used two different moves - it cannot have a choice item"
                .format(battle.opponent.active.name))
            battle.opponent.active.can_have_choice_item = False

        battle.opponent.last_used_move = LastUsedMove(
            pokemon_name=battle.opponent.active.name, move=move_name)
Esempio n. 17
0
def get_damage_dealt(battle, split_msg, next_messages):
    move_name = normalize_name(split_msg[3])
    critical_hit = False

    if is_opponent(battle, split_msg):
        attacking_side = battle.opponent
        defending_side = battle.user
    else:
        attacking_side = battle.user
        defending_side = battle.opponent

    for line in next_messages:
        next_line_split = line.split('|')
        # if one of these strings appears in index 1 then
        # exit out since we are done with this pokemon's move
        if len(next_line_split) < 2 or next_line_split[1] in MOVE_END_STRINGS:
            break

        elif next_line_split[1] == '-crit':
            critical_hit = True

        # if '-damage' appears, we want to parse the percentage damage dealt
        elif next_line_split[1] == '-damage' and defending_side.name in next_line_split[2]:
            final_health, maxhp, _ = get_pokemon_info_from_condition(next_line_split[3])
            # maxhp can be 0 if the targetted pokemon fainted
            # the message would be: "0 fnt"
            if maxhp == 0:
                maxhp = defending_side.active.max_hp

            damage_dealt = (defending_side.active.hp / defending_side.active.max_hp)*maxhp - final_health
            damage_percentage = round(damage_dealt / maxhp, 4)

            logger.debug("{} did {}% damage to {} with {}".format(attacking_side.active.name, damage_percentage * 100, defending_side.active.name, move_name))
            return DamageDealt(attacker=attacking_side.active.name, defender=defending_side.active.name, move=move_name, percent_damage=damage_percentage, crit=critical_hit)
Esempio n. 18
0
def set_opponent_ability_from_ability_tag(battle, split_msg):
    if is_opponent(battle, split_msg):
        side = battle.opponent
    else:
        side = battle.user

    ability = normalize_name(split_msg[3])
    logger.debug("Setting {}'s ability to {}".format(side.active.name, ability))
    side.active.ability = ability
Esempio n. 19
0
    def __init__(self, name):
        name = normalize_name(name)
        move_json = all_move_json[name]
        self.name = name
        self.max_pp = int(move_json.get(constants.PP) * 1.6)

        self.disabled = False
        self.can_z = False
        self.current_pp = self.max_pp
Esempio n. 20
0
def curestatus(battle, split_msg):
    if is_opponent(battle, split_msg):
        pkmn_name = split_msg[2].split(':')[-1].strip()

        if normalize_name(pkmn_name) == battle.opponent.active.name:
            pkmn = battle.opponent.active
        else:
            try:
                pkmn = next(
                    filter(lambda x: x.name == normalize_name(pkmn_name),
                           battle.opponent.reserve))
            except StopIteration:
                logger.warning(
                    "The pokemon {} does not exist in the opponent's party, defaulting to the active pokemon"
                    .format(normalize_name(pkmn_name)))
                pkmn = battle.opponent.active

        pkmn.status = None
Esempio n. 21
0
def status(battle, split_msg):
    if is_opponent(battle, split_msg):
        status_name = split_msg[3].strip()
        logger.debug("Opponent got status {}".format(status_name))
        battle.opponent.active.status = status_name

        if len(split_msg) > 4 and 'item: ' in split_msg[4]:
            battle.opponent.active.item = normalize_name(
                split_msg[4].split('item:')[-1])
Esempio n. 22
0
    def __init__(self, name: str, level: int):
        # Single Number, Should be 1-hot (1136)
        self.name = normalize_name(name)
        self.base_name = self.name
        # Single Number, ignore the level because we assume Lv100
        # if it's not level 100, it would be encoded in name (e.g. Rattata)
        self.level = level

        try:
            self.base_stats = pokedex[self.name][constants.BASESTATS]
        except KeyError:
            logger.info("Could not pokedex entry for {}".format(self.name))
            self.name = [k for k in pokedex if self.name.startswith(k)][0]
            logger.info("Using {} instead".format(self.name))
            self.base_stats = pokedex[self.name][constants.BASESTATS]

        # 6 numbers
        self.stats = calculate_stats(self.base_stats, self.level)

        # can ignore max_hp because it's noisy (hp% is pretty much all we care/know)
        self.max_hp = self.stats.pop(constants.HITPOINTS)
        # 1 number as percent
        self.hp = self.max_hp
        if self.name == 'shedinja':
            self.max_hp = 1
            self.hp = 1

        # TODO: Encode, currently not neccessary
        self.ability = None
        # Number between 1-17
        self.types = pokedex[self.name][constants.TYPES]
        # should be ignored in the vector since we have no list of items available
        # closest item encoding we have is in that boolean below for life orb / choice
        self.item = constants.UNKNOWN_ITEM

        # Single number (0,1)
        self.fainted = False
        # for now, ignore. maybe one-hot encode moves later?
        self.moves = []
        # one hot encoding for all statuses (0 or 1)
        # burn, freeze, sleep, paralysis, poison, badly poison (6 total)
        # badly poison ranges from 0-6, since there are poison stages
        self.status = None
        # 5 total volatile statuses
        # confusion, leech seed, substitute, taunt, partially trapped, transformed
        self.volatile_statuses = []
        # 7 stat boost numbers (-6 to 6 for each stat)
        self.boosts = defaultdict(lambda: 0)
        # ignore
        self.can_mega_evo = False
        self.can_ultra_burst = False
        self.can_dynamax = False
        self.is_mega = False
        # either choice or life orb, so these are opposing or both 0
        self.can_have_choice_item = True
        self.can_have_life_orb = True
Esempio n. 23
0
def activate(battle, split_msg):
    if is_opponent(battle, split_msg):
        pkmn = battle.opponent.active
    else:
        pkmn = battle.user.active

    if split_msg[3].lower() == 'move: poltergeist':
        item = normalize_name(split_msg[4])
        logger.debug("{} has the item {}".format(pkmn.name, item))
        pkmn.item = item
Esempio n. 24
0
def set_item(battle, split_msg):
    """Set the opponent's item"""
    if is_opponent(battle, split_msg):
        side = battle.opponent
    else:
        side = battle.user

    item = normalize_name(split_msg[3].strip())
    logger.debug("Setting {}'s item to {}".format(side.active.name, item))
    side.active.item = item
Esempio n. 25
0
def check_choicescarf(battle, msg_lines):
    def get_move_information(m):
        try:
            return m.split('|')[2], all_move_json[normalize_name(
                m.split('|')[3])]
        except KeyError:
            logger.debug(
                "Unknown move {} - using standard 0 priority move".format(
                    normalize_name(m.split('|')[3])))
            return m.split('|')[2], {constants.PRIORITY: 0}

    if (battle.opponent.active is None
            or battle.opponent.active.item != constants.UNKNOWN_ITEM
            or 'prankster' in [
                normalize_name(a) for a in pokedex[battle.opponent.active.name]
                [constants.ABILITIES].values()
            ]):
        return

    moves = [
        get_move_information(m) for m in msg_lines if m.startswith('|move|')
    ]
    if len(moves) != 2 or moves[0][0].startswith(
            battle.user.name
    ) or moves[0][1][constants.PRIORITY] != moves[1][1][constants.PRIORITY]:
        return

    battle_copy = deepcopy(battle)
    battle_copy.user.from_json(battle_copy.request_json)
    if battle.battle_type == constants.RANDOM_BATTLE:
        battle_copy.opponent.active.set_spread(
            'serious',
            '85,85,85,85,85,85')  # random battles have known spreads
    else:
        if battle.trick_room:
            battle_copy.opponent.active.set_spread(
                'quiet',
                '0,0,0,0,0,0')  # assume as slow as possible in trickroom
        else:
            battle_copy.opponent.active.set_spread(
                'jolly', '0,0,0,0,0,252')  # assume as fast as possible
    state = battle_copy.create_state()
    opponent_effective_speed = get_effective_speed(state, state.opponent)
    bot_effective_speed = get_effective_speed(state, state.self)

    if battle.trick_room:
        has_scarf = opponent_effective_speed > bot_effective_speed
    else:
        has_scarf = bot_effective_speed > opponent_effective_speed

    if has_scarf:
        logger.debug(
            "Opponent {} could not have gone first - setting it's item to choicescarf"
            .format(battle.opponent.active.name))
        battle.opponent.active.item = 'choicescarf'
Esempio n. 26
0
def start_volatile_status(battle, split_msg):
    if is_opponent(battle, split_msg):
        pkmn = battle.opponent.active
    else:
        pkmn = battle.user.active

    volatile_status = normalize_name(split_msg[3].split(":")[-1])
    if volatile_status not in pkmn.volatile_statuses:
        logger.debug("Starting the volatile status {} on {}".format(
            volatile_status, pkmn.name))
        pkmn.volatile_statuses.append(volatile_status)
Esempio n. 27
0
def singleturn(battle, split_msg):
    if is_opponent(battle, split_msg):
        side = battle.opponent
    else:
        side = battle.user

    move_name = normalize_name(split_msg[3].split(':')[-1])
    if move_name in constants.PROTECT_VOLATILE_STATUSES:
        # set to 2 because the `upkeep` function will decrement by 1 on every end-of-turn
        side.side_conditions[constants.PROTECT] = 2
        logger.debug("{} used protect".format(side.active.name))
Esempio n. 28
0
def sideend(battle, split_msg):
    """Remove a side effect such as stealth rock or sticky web"""
    condition = split_msg[3].split(':')[-1].strip()
    condition = normalize_name(condition)

    if is_opponent(battle, split_msg):
        logger.debug("Side condition {} ending for opponent".format(condition))
        battle.opponent.side_conditions[condition] = 0
    else:
        logger.debug("Side condition {} ending for bot".format(condition))
        battle.user.side_conditions[condition] = 0
Esempio n. 29
0
def fieldend(battle, split_msg):
    """Remove the battle's field condition"""
    field_name = normalize_name(split_msg[2].split(':')[-1].strip())

    # trick room shows up as a `-fieldend` item but is separate from the other fields
    if field_name == constants.TRICK_ROOM:
        logger.debug("Removing trick room")
        battle.trick_room = False
    else:
        logger.debug("Setting the field to None")
        battle.field = None
Esempio n. 30
0
def fieldstart(battle, split_msg):
    """Set the battle's field condition"""
    field_name = normalize_name(split_msg[2].split(':')[-1].strip())

    # trick room shows up as a `-fieldstart` item but is separate from the other fields
    if field_name == constants.TRICK_ROOM:
        logger.debug("Setting trickroom")
        battle.trick_room = True
    else:
        logger.debug("Setting the field to {}".format(field_name))
        battle.field = field_name