Пример #1
0
class Battle:
    pokedex = json.loads(open(os.path.join(os.path.dirname(__file__), "./data/pokedex.json"), "r").read())
    pokedex_moves = json.loads(open(os.path.join(os.path.dirname(__file__), "./data/pokedex_moves.json"), "r").read())
    pokedex_effectiveness = json.loads(open(os.path.join(os.path.dirname(__file__), "./data/pokedex_effectiveness.json"), "r").read())
    teams_for_battle = json.loads(open(os.path.join(os.path.dirname(__file__), "./data/pokemon_teams.json"), "r").read())
    moves_that_switch = ["uturn", "voltswitch"]
    status_moves = [{"name":"spore", "type":"grass","effect":"sleep"}]
    status_moves_names = ["spore"]

    def __init__(self, tier, room, bot):
        self.learn = Learn(room)
        self.opponent = {}
        self.generation = "generation 6"
        self.bot = bot
        self.weather = ""
        self.statuses = []
        self.opponent_pokemon_team = []
        self.do_not_switch = False
        self.ws = self.bot.ws
        self.team = None
        self.strongest_move = ""
        self.active = ""
        self.id = ""
        self.tier = tier
        self.room = room
        self.turn = 0


    def __repr__(self):
        return "<Battle: room:{}>".format(self.room)

    def __str__(self):
        return "<Battle: room:{}>".format(self.room)

    def run(self, messages):
        try:
            if messages[1] == "turn":
                return getattr(self, "decide")()
            else:
                return getattr(self, re.sub(r'[^A-z0-9]', '', messages[1]))(messages)
        except (TypeError, AttributeError):
            pass

    def start(self, message):
        self.ws.send("{}|Good Luck, Have Fun".format(self.room))
        self.ws.send("{}|/timer")

    def turn(self, message):
        self.decide()

    def weather(self, message):
        self.weather = message[2].lower()
        # cheesy lines
        if self.weather == "hail":
            self.ws.send("{}|Oh, it's hailing. It's ok though, because the cold never bothered me anyway.".format(self.room))
        elif self.weather == "sandstorm":
            pokemon = message[4].split(": ")[1].lower()
            self.ws.send("{}|Darude Sandstorm?".format(self.room, pokemon))
        elif self.weather == "raindance":
            self.ws.send("{}|Shouldn't it be raining men now?".format(self.room))
        else:
            pass

    def move(self, message):
        if self.id == "p1":
            _id = "p2a"
        else:
            _id = "p1a"

        if _id in message[2]:
            move = message[3].replace("-", "").replace(" ", "").lower()
            self.learn.write(self.opponent["name"], move)


    def update_pokemon_move(self, move, pokemon):
        pokemon_move = {}
        if "hiddenpower" in move:
            pokemon_move["name"] = move[:-2]
            pokemon_move["power"] = 60
            pokemon_move["type"] = move.split("hiddenpower")[1][:-2]
        else:
            pokemon_move["name"] = move
            pokemon_move["power"] = self.pokedex_moves[move]["power"]
            pokemon_move["type"] = self.pokedex_moves[move]["type"]

            if move == "return":
                pokemon_move["power"] = 102

            if move in ["eruption", "waterspout"]:
                pokemon_move["power"] = 150 * float(pokemon["hp"])

        return pokemon_move



    def update_pokemon_team(self, pokemon_team):
        json_data = json.loads(pokemon_team)["side"]["pokemon"]
        team = []
        i = 0
        for pokemon in json_data:
            pkmn = {}
            pkmn["id"] = i + 1
            pkmn["name"] = re.sub(r'[^A-z0-9]', '', json_data[i]["ident"].split(": ")[1]).lower()
            pkmn["moves"] = json_data[i]["moves"]
            pkmn["stats"] = json_data[i]["stats"]
            pkmn["active"] = json_data[i]["active"]
            pkmn["ability"] = json_data[i]["baseAbility"]
            pkmn["type"] = [x.lower() for x in self.pokedex[pkmn["name"]]["types"]]
            pkmn["hp"] = json_data[i]["condition"]
            if " " in pkmn["hp"]: # condition
                pkmn["status"] = pkmn["hp"].split(" ")[1]
                pkmn["hp"] = pkmn["hp"].split(" ")[0]

            if "/" in pkmn["hp"]: # fraction
                pkmn["hp"] = float(Fraction(int(pkmn["hp"].split("/")[0]), int(pkmn["hp"].split("/")[1])))

            team.append(pkmn)
            i += 1

        self.team = team
        return team

    def teampreview(self, message = None):
        self.ws.send("{}|/team {}|1".format(self.room, random.randint(1, 6)))

    def player(self, message):
        if len(message) > 2:
            if self.bot.username == message[3]:
                self.id = message[2]
            else:
                if message[2] == "p1":
                    self.id = "p2"
                else:
                    self.id = "p1"

    def request(self, message):
        self.team = self.update_pokemon_team(message[2])
        self.id = json.loads(message[2])["side"]["id"]
        if "random" in self.tier:
            self.teampreview()

    def faint(self, message):
        if self.id in message[2]:
            pokemon = message[2].split(": ")[1].lower()
            if len([x for x in self.team if x["name"] == pokemon]) > 0:
                self.active["hp"] = 0
                self.switch_pokemon()


    def switch(self, message):
        if self.id == "p1":
            _id = "2a"
        else:
            _id = "1a"
        if _id in message[2]:
            opponent = re.sub(r'[^A-z0-9]', '', message[3].split(",")[0]).lower()
            print("opponent is "+opponent)
            self.opponent["hp"] = float(Fraction(int(message[4].split("/")[0]), int(message[4].split("/")[1])))
            self.opponent["name"] = opponent
            self.do_not_switch = False



    def win(self, message):
        self.ws.send("{}|Good Game.".format(self.room))
        self.ws.send("{}|/part".format(self.room))

    def damage(self, message):
        pokemon = message[2].split(": ")[1].lower()
        if pokemon == self.opponent["name"] and "/" in message[3] and " " not in message[3]:
            self.opponent["hp"] = float(Fraction(int(message[3].split("/")[0]), int(message[3].split("/")[1])))

    def lose(self, message):
        self.win(message)

    def tie(self, message):
        self.win(message)

    def moves_power(self, pokemon = None):

        pokemon_moves = []
        if pokemon is None:
            pokemon = self.active
            moves = self.active["moves"]
        else:
            moves = pokemon["moves"]
            pokemon = pokemon

        for move in moves:


            move = self.update_pokemon_move(move, pokemon)

            move["power"] = self.ability_of_pokemon_modifies_power_of_pokemon_move(pokemon, move)


            if "multihit" in list(self.pokedex_moves[move["name"]].keys()):
                move["power"] *= median(self.pokedex_moves[move["name"]]["multihit"])

            pokemon_moves.append(move)

        moves_power = []
        for move in pokemon_moves:
            modifier = self.pokemon_move_modifier(pokemon, move)

            moves_power.append({"name": move["name"], "power": move["power"] * modifier, "pokemon": pokemon["name"]})

        return moves_power

    def pokemon_move_modifier(self, pokemon, pokemon_move):
        modifier = 1
        if pokemon_move["type"] in pokemon["type"]:
            if pokemon["ability"] == "adaptability":
                modifier = 2
            else:
                modifier = 1.5

        if self.calculate_effectiveness()["weak"].count(pokemon_move["type"]) == 2:
            modifier *= 4
        elif self.calculate_effectiveness()["weak"].count(pokemon_move["type"]) == 1:
            modifier *= 2

        if self.calculate_effectiveness()["resist"].count(pokemon_move["type"]) == 2:
            modifier *= 0.25
        elif self.calculate_effectiveness()["resist"].count(pokemon_move["type"]) == 1:
            modifier *= 0.5

        if pokemon_move["type"] in self.calculate_effectiveness()["immune"]:
            if pokemon["ability"] == "scrappy" and pokemon_move["type"] in ["fighting", "normal"]:
                return modifier
            else:
                return 0

        if pokemon["ability"] in ["teravolt", "moldbreaker"]:
            return modifier

        opponent_pokemon = [x.lower().replace(" ", "") for x in self.pokedex[self.opponent["name"]]["abilities"]]

        if pokemon_move["type"] == "water" and "waterabsorb" in opponent_pokemon:
            return 0
        elif pokemon_move["type"] == "grass" and "sapsipper" in opponent_pokemon:
            return 0
        elif pokemon_move["type"] == "fire" and "flashfire" in opponent_pokemon:
            return 0
        elif pokemon_move["type"] == "electric" and "voltabsorb" in opponent_pokemon:
            return 0
        elif pokemon_move["type"] == "ground" and "levitate" in opponent_pokemon:
            return 0
        else:
            return modifier



    def ability_of_pokemon_modifies_power_of_pokemon_move(self, pokemon, pokemon_move):
        ability = pokemon["ability"]

        if ability == "aerilate" and pokemon_move["type"] == "normal":
            pokemon_move["type"] == "flying"

        if ability in ["blaze", "overgrow", "torrent", "swarm"] and float(pokemon["hp"]) <= 0.33:
            i = {"blaze": "fire", "overgrow": "grass", "torrent": "water", "swarm": "bug"}
            if i[ability] == pokemon_move["type"]:
                pokemon_move["power"] *= 1.5

        if ability == "darkaura" and pokemon_move["type"] == "dark":
            pokemon_move["power"] *= 1.33

        if ability == "fairyaura" and pokemon_move["type"] == "fairy":
            pokemon_move["power"] *= 1.33

        # One Punch Man
        if ability == "ironfist" and "punch_move" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.2

        if ability == "megalauncher" and "pulse_move" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.5

        if ability == "reckless" and "recoil" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.2

        if ability == "sandforce" and self.weather == "sandstorm" and pokemon_move["type"] in ["rock", "ground", "steel"]:
            pokemon_move["power"] *= 1.3

        if ability == "sheerforce" and "secondary_effect" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.3

        if ability == "strongjaw" and "bite_move" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.5

        if ability == "technician" and pokemon_move["power"] <= 60:
            pokemon_move["power"] *= 1.5

        if ability == "tintedlens":
            opponent_pkmn_resistant_against = self.calculate_effectiveness(self.opponent["name"])["resist"]
            if pokemon_move["type"] in opponent_pkmn_resistant_against:
                pokemon_move["power"] *= 2

        if ability == "toughclaws" and "contact_move" in list(self.pokedex_moves[pokemon_move["name"]].keys()):
            pokemon_move["power"] *= 1.3

        return pokemon_move["power"]

    def switch_pokemon(self):
        strongest_moves = [sorted(self.moves_power(pkmn), key=lambda x: x["power"])[::-1][0] for pkmn in self.team if pkmn["active"] != True]
        strongest_move_index = strongest_moves.index(sorted(strongest_moves, key=lambda x: x["power"])[::-1][0])
        strongest_move = sorted(strongest_moves, key=lambda x: x["power"])[::-1][0]
        strongest_pokemon = [x for x in self.team if x["name"] == strongest_move["pokemon"]][0]


        strongest_pokemon_id = strongest_pokemon["id"]
        current_pokemon_id = 1

        strongest_pokemon_index = self.team.index(strongest_pokemon)
        current_pokemon_index = self.team.index([i for i in self.team if i["active"] == True][0])

        self.team[current_pokemon_index]["id"] = strongest_pokemon_id
        self.team[strongest_pokemon_index]["id"] = 1

        opponent_pkmn_type = [x.lower() for x in self.pokedex[self.opponent["name"]]["types"]]
        weak_against = self.calculate_effectiveness(strongest_pokemon["name"])["weak"]

        if len([i for i in weak_against if i in opponent_pkmn_type]) > 0:
            self.do_not_switch = True

        self.ws.send("{}|/switch {}".format(self.room, strongest_pokemon_id))



    def calculate_effectiveness(self, pkmn = None):
        effectiveness = {"weak": [], "resist": [], "immune": []}

        if pkmn is not None:
            pokemon_type = [x.lower() for x in Battle.pokedex[pkmn]["types"]]
        else:
            pokemon_type = [x.lower() for x in Battle.pokedex[self.opponent["name"]]["types"]]


        for pkmn_type in pokemon_type:
            effectiveness["weak"].append(Battle.pokedex_effectiveness[pkmn_type]["weak_against"])
            effectiveness["resist"].append(Battle.pokedex_effectiveness[pkmn_type]["resistant_against"])
            effectiveness["immune"].append(Battle.pokedex_effectiveness[pkmn_type]["immune_against"])


        for x in effectiveness:
            effectiveness[x] = sorted([z for x in effectiveness[x] for z in x]) # flatten the array

        for x in [z for z in effectiveness["weak"] if z in effectiveness["resist"]]:
            effectiveness["weak"].remove(x)
            effectiveness["resist"].remove(x)

        return effectiveness

    def can_use_status_move(self):
        opponent_pkmn_type = self.pokedex[self.opponent["name"]]["types"]
        moves = self.active["moves"]

    def decide(self):
        self.active = [i for i in self.team if i["active"] == True][0]

        opponent_pkmn_type = [x.lower() for x in self.pokedex[self.opponent["name"]]["types"]]
        weak_against = self.calculate_effectiveness(self.active["name"])["weak"]

        if len([i for i in weak_against if i in opponent_pkmn_type]) > 0 and self.do_not_switch == False: # current pokemon is 2x or 4x weak against opponent.
            return self.switch_pokemon()

        if self.active["hp"] == "0 fnt":
            self.do_not_switch = False
            return self.switch_pokemon()

        moves_that_heal = [i for i in list(self.pokedex_moves.keys()) if self.pokedex_moves[i].get("heal_move")]
        if self.active["hp"] < 0.25 and len([i for i in self.active["moves"] if i in moves_that_heal]) > 0:
            move_that_heals = [i for i in self.active["moves"] if i in moves_that_heal][0]
            return self.ws.send("{}|/move {}".format(self.room, move_that_heals))

        data = sorted(self.moves_power(), key=lambda x: x["power"])[::-1]


        self.strongest_move = data[0]
        if self.strongest_move["power"] == 0 or self.strongest_move["name"] in self.moves_that_switch:
            return self.switch_pokemon()

        if len([x for x in self.active["moves"] if x in self.status_moves_names]) > 0:
            _move = [x for x in self.active["moves"] if x in self.status_moves_names][0]
            move = [x for x in self.status_moves if x["name"] == _move][0]
            if move["effect"] not in self.statuses:
                self.statuses.append(move["effect"])
                return self.ws.send("{}|/move {}".format(self.room, move["name"]))

        return self.ws.send("{}|/move {}".format(self.room, data[0]["name"]))