I am having a strange error where battle.availablemoves is an empty list, despite in the same battle object, i can see the active pokemon and its moves in that list. This is active for an entire battle.
Here is the Player class I am using and observing this error.
class SmartPlayer(Player):
prevDamagePercent = 100
currentdamagePercent = 100
usedMovePreviously = False
currentOpponent = None
previousOpponent = None
def choose_move(self, battle):
self.currentOpponent = battle.opponent_active_pokemon
if self.currentOpponent != self.previousOpponent:
self.currentDamagePercent = 100
self.previousDamagePercent = 100
# print(f"New opponent is {self.currentOpponent}")
else:
self.currentDamagePercent = battle.opponent_active_pokemon.current_hp
# if self.usedMovePreviously:
# print(f'Actual damage % done was {(self.prevDamagePercent - self.currentDamagePercent)}, previous health % was {self.prevDamagePercent}, current health percentage is {self.currentDamagePercent}%')
self.prevDamagePercent = self.currentDamagePercent
self.usedMovePreviously = False
self.previousOpponent = self.currentOpponent
best_switch = self.choose_best_switch(battle, -1000)
self.create_order(best_switch)
# If Pokemon is out of moves, switch to best option
if not battle.available_moves:
matchup_score = self.get_matchup_score(battle.active_pokemon, battle.opponent_active_pokemon, battle)
best_switch = self.choose_best_switch(battle, matchup_score)
if best_switch is None:
return self.choose_default_move()
return self.create_order(best_switch)
# Use info such as type matchup and relative speed to determine who to switch to
matchup_score = self.get_matchup_score(battle.active_pokemon, battle.opponent_active_pokemon, battle)
# If negative situation exceeds threshold, switch Pokemon
if matchup_score >= 1:
best_switch = self.choose_best_switch(battle, matchup_score)
if best_switch is not None:
return self.create_order(best_switch)
# finds the best move among available ones
self.usedMovePreviously = True
best_move = max(battle.available_moves, key=lambda move: BattleUtilities.calculate_damage(move, battle.active_pokemon, battle.opponent_active_pokemon, True, True))
#print(f'Best move was {best_move}, Calculated damage value was {BattleUtilities.calculate_damage(best_move, battle.active_pokemon, battle.opponent_active_pokemon, True, True)}')
return self.create_order(best_move)
def choose_best_switch(self, battle, preswitch_score):
if not battle.available_switches:
return None
# Go through each Pokemon that can be switched to, and choose one with the best type matchup
# (smaller multipliers are better)
best_score = float('inf')
best_switch = battle.available_switches[0]
for switch in battle.available_switches:
score = self.get_matchup_score(switch, battle.opponent_active_pokemon, battle)
if score < best_score:
best_score = score
best_switch = switch
if best_score < preswitch_score:
return best_switch
else:
return None
# Gets a number that determines how well the Pokemon matches up with opponent. Lower scores are better
def get_matchup_score(self, my_pokemon, opponent_pokemon, battle):
if my_pokemon is None or opponent_pokemon is None:
return 0
score = 0
defensive_multiplier = BattleUtilities.get_defensive_type_multiplier(my_pokemon, opponent_pokemon)
# A multiplier greater than 1 means we are at a type disadvantage. If there is a better type match, switch
if defensive_multiplier == 4:
score += 1
elif defensive_multiplier == 2:
score += 0.5
elif defensive_multiplier == 0.5:
score -= 0.5
elif defensive_multiplier == 0.25:
score -= 1
if BattleUtilities.opponent_can_outspeed(my_pokemon, opponent_pokemon):
score += 0.5
if my_pokemon.current_hp / my_pokemon.max_hp < 0.25:
score += 0.25
effectiveness = 0
for move in battle.available_moves:
if BattleUtilities.calculate_damage(move, my_pokemon, opponent_pokemon, True, True) > 0:
calceffectiveness = opponent_pokemon.damage_multiplier(move.type)
if calceffectiveness > effectiveness:
effectiveness = calceffectiveness
score -= (effectiveness - 1) # Effectiveness of 1 means no change, so subtract 0
return score
I am having a strange error where battle.availablemoves is an empty list, despite in the same battle object, i can see the active pokemon and its moves in that list. This is active for an entire battle.
Here is the Player class I am using and observing this error.
class SmartPlayer(Player):
prevDamagePercent = 100
currentdamagePercent = 100
usedMovePreviously = False
currentOpponent = None
previousOpponent = None
def choose_move(self, battle):
self.currentOpponent = battle.opponent_active_pokemon
if self.currentOpponent != self.previousOpponent:
self.currentDamagePercent = 100
self.previousDamagePercent = 100
# print(f"New opponent is {self.currentOpponent}")
else:
self.currentDamagePercent = battle.opponent_active_pokemon.current_hp
# if self.usedMovePreviously:
# print(f'Actual damage % done was {(self.prevDamagePercent - self.currentDamagePercent)}, previous health % was {self.prevDamagePercent}, current health percentage is {self.currentDamagePercent}%')
self.prevDamagePercent = self.currentDamagePercent
self.usedMovePreviously = False
self.previousOpponent = self.currentOpponent
best_switch = self.choose_best_switch(battle, -1000)
self.create_order(best_switch)
# If Pokemon is out of moves, switch to best option
if not battle.available_moves:
matchup_score = self.get_matchup_score(battle.active_pokemon, battle.opponent_active_pokemon, battle)
best_switch = self.choose_best_switch(battle, matchup_score)
if best_switch is None:
return self.choose_default_move()
return self.create_order(best_switch)
# Use info such as type matchup and relative speed to determine who to switch to
matchup_score = self.get_matchup_score(battle.active_pokemon, battle.opponent_active_pokemon, battle)
# If negative situation exceeds threshold, switch Pokemon
if matchup_score >= 1:
best_switch = self.choose_best_switch(battle, matchup_score)
if best_switch is not None:
return self.create_order(best_switch)
# finds the best move among available ones
self.usedMovePreviously = True
best_move = max(battle.available_moves, key=lambda move: BattleUtilities.calculate_damage(move, battle.active_pokemon, battle.opponent_active_pokemon, True, True))
#print(f'Best move was {best_move}, Calculated damage value was {BattleUtilities.calculate_damage(best_move, battle.active_pokemon, battle.opponent_active_pokemon, True, True)}')
return self.create_order(best_move)
def choose_best_switch(self, battle, preswitch_score):
if not battle.available_switches:
return None
# Go through each Pokemon that can be switched to, and choose one with the best type matchup
# (smaller multipliers are better)
best_score = float('inf')
best_switch = battle.available_switches[0]
for switch in battle.available_switches:
score = self.get_matchup_score(switch, battle.opponent_active_pokemon, battle)
if score < best_score:
best_score = score
best_switch = switch
if best_score < preswitch_score:
return best_switch
else:
return None
# Gets a number that determines how well the Pokemon matches up with opponent. Lower scores are better
def get_matchup_score(self, my_pokemon, opponent_pokemon, battle):
if my_pokemon is None or opponent_pokemon is None:
return 0
score = 0
defensive_multiplier = BattleUtilities.get_defensive_type_multiplier(my_pokemon, opponent_pokemon)
# A multiplier greater than 1 means we are at a type disadvantage. If there is a better type match, switch
if defensive_multiplier == 4:
score += 1
elif defensive_multiplier == 2:
score += 0.5
elif defensive_multiplier == 0.5:
score -= 0.5
elif defensive_multiplier == 0.25:
score -= 1
if BattleUtilities.opponent_can_outspeed(my_pokemon, opponent_pokemon):
score += 0.5
if my_pokemon.current_hp / my_pokemon.max_hp < 0.25:
score += 0.25
effectiveness = 0
for move in battle.available_moves:
if BattleUtilities.calculate_damage(move, my_pokemon, opponent_pokemon, True, True) > 0:
calceffectiveness = opponent_pokemon.damage_multiplier(move.type)
if calceffectiveness > effectiveness:
effectiveness = calceffectiveness
score -= (effectiveness - 1) # Effectiveness of 1 means no change, so subtract 0
return score