async def req_loader(self, req: str): """ Parse and translate json send by server. Reload bot team. Called each turn. :param req: json sent by server. """ jsonobj = json.loads(req) self.turn += 2 self.bot_team = Team() for pkm in jsonobj['side']['pokemon']: try: new_pkm = Pokemon( pkm['ident'].split(': ')[1], pkm['details'].split(',')[0], pkm['condition'], pkm['active'], pkm['details'].split(',')[1].split('L')[1] if len(pkm['details']) > 1 and 'L' in pkm['details'] else 100 ) new_pkm.load_known([pkm['baseAbility']], pkm["item"], pkm['stats'], pkm['moves']) self.bot_team.add(new_pkm) except IndexError as error: print(f'\033[31mIndexError: {error}\n{pkm}\033[0m') exit(2) if 'forceSwitch' in jsonobj.keys(): await self.make_switch() elif 'active' in jsonobj.keys(): self.current_pkm = jsonobj['active']
def effi_pkm(battle, pkm1: Pokemon, pkm2: Pokemon, team1: Team, team2: Team) -> int: """ Efficiency of pokemon against other. Based on move efficiency functions. If efficiency of a pokemon > 150 and is faster, efficiency of the other pokemon is not taken. effi_pkm(a, b, team_a) = - effi_pkm(b, a, team_b) :param battle: Battle object, current battle. :param pkm1: Pokemon that will use move. :param pkm2: Pokemon that will receive move. :param team1: Team of pkm1. :param team2: Team of pkm2. :return: Integer, can be negative. """ pkm1_spe = pkm1.compute_stat(Stats.SPE) pkm2_spe = pkm2.compute_stat(Stats.SPE) effi1 = max( [effi_move(battle, move, pkm1, pkm2, team2) for move in pkm1.moves]) if effi1 >= base_damages(150, pkm1, pkm2) and pkm1_spe > pkm2_spe: return effi1 effi2 = max( [effi_move(battle, move, pkm2, pkm1, team1) for move in pkm2.moves]) if effi2 >= base_damages(150, pkm2, pkm1) and pkm2_spe > pkm1_spe: return -effi2 return effi1 - effi2
async def req_loader(self, req, websocket): """ Parse and translate json send by server. Reload bot team. Called each turn. :param req: json sent by server. :param websocket: Websocket stream. """ jsonobj = json.loads(req) self.turn += 2 objteam = jsonobj['side']['pokemon'] self.bot_team = Team() for pkm in objteam: try: newpkm = Pokemon(pkm['details'].split(',')[0], pkm['condition'], pkm['active'], pkm['details'].split(',')[1].split('L')[1] if len(pkm['details']) > 1 and 'L' in pkm['details'] else 100) newpkm.load_known([pkm['baseAbility']], pkm["item"], pkm['stats'], pkm['moves']) self.bot_team.add(newpkm) except IndexError as e: print("\033[31m" + "IndexError: " + str(e)) print(pkm + "\033[0m") exit(2) if "forceSwitch" in jsonobj.keys(): await self.make_switch(websocket) elif "active" in jsonobj.keys(): self.current_pkm = jsonobj["active"]
def fill_table_for_pokemon(pokemon, all_pokemon, cup): ally_name, ally_fast, ally_charge_1, ally_charge_2 = pokemon ally = Pokemon(ally_name, ally_fast, ally_charge_1, ally_charge_2) to_write = [] for enemy_name, enemy_fast, enemy_charge_1, enemy_charge_2 in all_pokemon: enemy = Pokemon(enemy_name, enemy_fast, enemy_charge_1, enemy_charge_2) results = battle_all_shields(ally, enemy) to_write.append([str(ally), str(enemy)] + list(x[0] for x in results)) command = "INSERT INTO battle_sims(ally, enemy, zeroVzero, zeroVone, zeroVtwo, oneVzero, oneVone, oneVtwo, twoVzero, twoVone, twoVtwo) VALUES (?,?,?,?,?,?,?,?,?,?,?)" conn = sqlite3.connect(f"{path}/data/databases/{cup}.db") cur = conn.cursor() cur.executemany(command, to_write) conn.commit() conn.close()
def effi_boost(move: dict, pkm1: Pokemon, pkm2: Pokemon) -> bool: """ Calculate if boost is worth or not. Currently only working on speed. :param move: Json object, status move. :param pkm1: Pokemon that will use move. :param pkm2: Pokemon that will receive move. :return: Boolean, True if worth, else False """ pkm1_spe = stat_calculation(pkm1.stats[Stats.SPE], pkm1.level, 252) move = next((i for i in pkm1.moves if i['name'] == move['move'])) value = ((move.get('secondary') if move.get('secondary') else move) .get('self', move).get('boosts', {}).get('spe', 0)) if not value: return False return (pkm2.compute_stat(Stats.SPE) > pkm1.compute_stat(Stats.SPE) and pkm1_spe * (value + pkm1.buff_affect(Stats.SPE)) > pkm2.compute_stat(Stats.SPE))
def base_damages(power: float, pkm1: Pokemon, pkm2: Pokemon) -> int: """ Used to compare damage done by pk1 to comparative values (100, 150, etc.). Because we want exact values, modificators, stab, burn and efficiency are not taken into account. :param power: value to compare :param pkm1: Pokemon that will use move. :param pkm2: Pokemon that will receive move. :return: Integer, damage of comparative value after calculation [0, +oo[ """ categories = Stats.SPA, Stats.SPD if pkm1.stats[Stats.ATK] > pkm1.stats[Stats.SPA]: categories = Stats.ATK, Stats.DEF atk = pkm1.compute_stat(categories[0]) defe = pkm2.compute_stat(categories[1]) return floor(((0.4 * pkm1.level + 2) * (atk / defe) * power) / 50 + 2)
def update_enemy(self, pkm_name, level, condition): """ On first turn, and each time enemy switch, update enemy team and enemy current pokemon. :param pkm_name: Pokemon's name :param level: int, Pokemon's level :param condition: str current_hp/total_hp. /100 if enemy pkm. """ if "-mega" in pkm_name.lower(): self.enemy_team.remove(pkm_name.lower().split("-mega")[0]) if "-*" in pkm_name.lower(): pkm_name = re.sub(r"(.+)-\*", r"\1", pkm_name) elif re.compile(r".+-.*").search(pkm_name.lower()): try: self.enemy_team.remove(re.sub(r"(.+)-.+", r"\1", pkm_name)) except NameError: pass if pkm_name not in self.enemy_team: for pkm in self.enemy_team.pokemons: pkm.active = False pkm = Pokemon(pkm_name, condition, True, level) pkm.load_unknown() self.enemy_team.add(pkm) else: for pkm in self.enemy_team.pokemons: if pkm.name.lower() == pkm_name.lower(): pkm.active = True else: pkm.active = False
def update_enemy(self, pkm_name: str, condition: str, pkm_variant: str = None, level: str = None): """ On first turn, and each time enemy switch, update enemy team and enemy current pokemon. :param pkm_name: Pokemon's name :param condition: str current_hp/total_hp. % if enemy pkm. :param level: stringified int, Pokemon's level. Can be None if pokemon already exists. :param pkm_variant: Pokemon's variant name. Can be None if pokemon already exists. """ for pkm in self.enemy_team.pokemons: pkm.active = False if pkm := next((pkm for pkm in self.enemy_team.pokemons if pkm.name == pkm_name), None): pkm.active = True pkm.condition = condition else: pkm = Pokemon(pkm_name, pkm_variant, condition, True, level) pkm.load_unknown() self.enemy_team.add(pkm) @staticmethod def update_status(pokemon, status: str = ''): """ Update status problem. :param pokemon: Pokemon. :param status: String. """ match status: case 'tox': pokemon.status = Status.TOX case 'brn': pokemon.status = Status.BRN
def battle(ally: Pokemon, enemy: Pokemon, ally_shields: int, enemy_shields: int): ally.starting_shields = ally_shields enemy.starting_shields = enemy_shields ally.reset() enemy.reset() turns = 0 # Main Battle Loop while ally.is_alive() and enemy.is_alive(): ally.reduce_cooldown() enemy.reduce_cooldown() turns += 1 if ally.can_act(): if not ally.use_charge_move(enemy): ally.use_move(ally.fast_move, enemy) if enemy.can_act(): if not enemy.use_charge_move(ally): enemy.use_move(enemy.fast_move, ally) # There are 2 points for using enemy shields and 3 for using enemy health. ally_rating = enemy.starting_shields - enemy.get_shields() enemy_rating = ally.starting_shields - ally.get_shields() ally_rating += round( 7 * (enemy.starting_health - enemy.get_health()) / enemy.starting_health, 1) enemy_rating += round( 7 * (ally.starting_health - ally.get_health()) / ally.starting_health, 1) if ally.get_health() > 0: ally_rating += round(3 * ally.energy / 100, 1) if enemy.get_health() > 0: enemy_rating += round(3 * enemy.energy / 100, 1) total_rating = ally_rating + enemy_rating return int(round(1000 * ally_rating / total_rating, 0)), int(round(1000 * enemy_rating / total_rating, 0))
enemy.starting_health, 1) enemy_rating += round( 7 * (ally.starting_health - ally.get_health()) / ally.starting_health, 1) if ally.get_health() > 0: ally_rating += round(3 * ally.energy / 100, 1) if enemy.get_health() > 0: enemy_rating += round(3 * enemy.energy / 100, 1) total_rating = ally_rating + enemy_rating return int(round(1000 * ally_rating / total_rating, 0)), int(round(1000 * enemy_rating / total_rating, 0)) def battle_all_shields(ally: Pokemon, enemy: Pokemon): to_return = [] for ally_shields in range(3): for enemy_shields in range(3): to_return.append(battle(ally, enemy, ally_shields, enemy_shields)) return to_return if __name__ == '__main__': hitmonchan = Pokemon('Hitmonchan', 'Counter', 'Power-Up Punch', 'Ice Punch') medicham = Pokemon('Medicham', 'Counter', 'Power-Up Punch', 'Psychic') results = battle_all_shields(hitmonchan, medicham) for result in results: print(result)
def add_pokemon_to_ranking_table(pokemon, cup, mean, sd, i): conn = sqlite3.connect(f"{path}/data/databases/{cup}.db") cur = conn.cursor() command = f"SELECT fast, charge_1, charge_2, absolute_rank FROM rankings WHERE pokemon = ? ORDER BY absolute_rank DESC" cur.execute(command, (pokemon, )) rows = cur.fetchall() p = Pokemon(pokemon, rows[0][0], rows[0][1], rows[0][2]) best_matchups, worst_matchups, optimal_team = combos(cup, str(p), cur) data = { 'name': pokemon, 'relative_rank': i, 'color': calculate_color(mean, sd, rows[0][3]), 'absolute_rank': rows[0][3], 'level': p.level, 'atk': p.ivs['atk'], 'def': p.ivs['def'], 'sta': p.ivs['hp'], 'optimal_team': ', '.join(optimal_team), 'best_matchups': ', '.join(best_matchups), 'worst_matchups': ', '.join(worst_matchups), 'movesets': [{ 'fast_type': gm.get_move(row[0])['type'], 'fast': row[0], 'charge_1_type': gm.get_move(row[1])['type'], 'charge_1': row[1], 'charge_2_type': gm.get_move(row[2])['type'], 'charge_2': row[2], 'absolute_rank': row[3], 'string': f"{cup}+{pokemon}+{row[0]}+{row[1]}+{row[2]}" } if row[2] else { 'fast_type': gm.get_move(row[0])['type'], 'fast': row[0], 'charge_1_type': gm.get_move(row[1])['type'], 'charge_1': row[1], 'charge_2_type': None, 'charge_2': None, 'absolute_rank': row[3], 'string': f"{cup}+{pokemon}+{row[0]}+{row[1]}" } for row in rows] } conn.close() conn = sqlite3.connect(f"{path}/web/{cup}.db") cur = conn.cursor() cur.execute( "INSERT INTO rankings VALUES (?,?,?,?,?,?,?,?,?,?,?)", (data['name'], data['relative_rank'], data['absolute_rank'], data['color'], data['level'], data['atk'], data['def'], data['sta'], data['best_matchups'], data['worst_matchups'], data['optimal_team'])) command = "INSERT INTO all_pokemon VALUES(?,?,?,?,?,?,?,?,?)" bindings = [ (data['name'], moveset['absolute_rank'], moveset['fast'], moveset['fast_type'], moveset['charge_1'], moveset['charge_1_type'], moveset['charge_2'], moveset['charge_2_type'], moveset['string']) for moveset in data['movesets'] ] cur.executemany(command, bindings) conn.commit() conn.close()