Skip to content

Commit

Permalink
Merge branch 'master' of github.com:hsahovic/pokemon-showdown-python-env
Browse files Browse the repository at this point in the history
  • Loading branch information
hsahovic committed May 24, 2020
2 parents 2892fd3 + 38ddb52 commit 27121ee
Show file tree
Hide file tree
Showing 18 changed files with 704 additions and 54 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ repos:
- id: detect-private-key
- id: fix-encoding-pragma
- id: mixed-line-ending
- id: pretty-format-json
- id: requirements-txt-fixer
- id: trailing-whitespace
14 changes: 10 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# The pokemon showdown Python environment

[![CircleCI](https://circleci.com/gh/hsahovic/poke-env.svg?style=svg)](https://circleci.com/gh/hsahovic/poke-env)
[![codecov](https://codecov.io/gh/hsahovic/poke-env/branch/master/graph/badge.svg)](https://codecov.io/gh/hsahovic/poke-env)
[![PyPI version fury.io](https://badge.fury.io/py/poke-env.svg)](https://pypi.python.org/pypi/poke-env/)
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/poke-env.svg)](https://pypi.python.org/pypi/poke-env/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
<a href="https://github.com/ambv/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
[![Documentation Status](https://readthedocs.org/projects/poke-env/badge/?version=stable)](https://poke-env.readthedocs.io/en/stable/?badge=stable)

A Python interface to create battling pokemon agents. `poke-env` offers an easy-to-use interface for creating rule-based or training Reinforcement Learning bots to battle on [pokemon showdown](https://pokemonshowdown.com/).
Expand All @@ -17,11 +16,12 @@ Agents are instance of python classes inheriting from `Player`. Here is what you
```python
class YourFirstAgent(Player):
def choose_move(self, battle):
for move in battle.available:
for move in battle.available_moves:
if move.base_power > 90:
# A powerful move! Let's use it
return self.create_order(move)

# No available move? Let's switch then!
for switch in battle.available_switches:
if switch.current_hp_fraction > battle.active_pokemon.current_hp_fraction:
# This other pokemon has more HP left... Let's switch it in?
Expand Down Expand Up @@ -82,3 +82,9 @@ Data files are adapted version of the `js` data files of [Pokemon Showdown](http

## License
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Other

[![CircleCI](https://circleci.com/gh/hsahovic/poke-env.svg?style=svg)](https://circleci.com/gh/hsahovic/poke-env)
[![codecov](https://codecov.io/gh/hsahovic/poke-env/branch/master/graph/badge.svg)](https://codecov.io/gh/hsahovic/poke-env)
<a href="https://github.com/ambv/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
20 changes: 8 additions & 12 deletions docs/source/max_damage_player.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ We also have to return an order corresponding to a random switch if the player c
Running and testing our agent
*****************************

We can now test our agent by crossing evaluating it with a random agent. The complete code is:
We can now test our agent by making it battle a random agent. The complete code is:

.. code-block:: python
Expand All @@ -92,7 +92,6 @@ We can now test our agent by crossing evaluating it with a random agent. The com
from poke_env.player.player import Player
from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate
class MaxDamagePlayer(Player):
Expand All @@ -119,18 +118,15 @@ We can now test our agent by crossing evaluating it with a random agent. The com
battle_format="gen8randombattle",
)
# Now, let's evaluate our player
cross_evaluation = await cross_evaluate(
[random_player, max_damage_player], n_challenges=100
)
# Now, let's evaluate our player
await max_damage_player.battle_against(random_player, n_battles=100)
print(
"Max damage player won %d / 100 battles [this took %f seconds]"
% (
cross_evaluation[max_damage_player.username][random_player.username] * 100,
time.time() - start,
)
print(
"Max damage player won %d / 100 battles [this took %f seconds]"
% (
max_damage_player.n_won_battles, time.time() - start
)
)
if __name__ == "__main__":
Expand Down
11 changes: 3 additions & 8 deletions docs/source/ou_max_player.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,7 @@ To attribute a team to an agent, you need to pass a ``team`` argument to the age
Running and testing our agent
*****************************

We can now test our agent. To do so, we can use the ``cross_evaluate`` function from ``poke_env.player.utils`` or the ``battle_against`` method from ``Player``. Here, we will use the ``battle_against`` method.

The complete example code is:
We can now test our agent. To do so, we can use the ``cross_evaluate`` function from ``poke_env.player.utils`` or the ``battle_against`` method from ``Player``.

.. code-block:: python
Expand All @@ -315,7 +313,6 @@ The complete example code is:
from poke_env.player.player import Player
from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate
class MaxDamagePlayer(Player):
Expand Down Expand Up @@ -495,13 +492,11 @@ The complete example code is:
)
# Now, let's evaluate our player
cross_evaluation = await cross_evaluate(
[random_player, max_damage_player], n_challenges=50
)
await max_damage_player.battle_against(random_player, n_battles = 100)
print(
"Max damage player won %d / 100 battles"
% (cross_evaluation[max_damage_player.username][random_player.username] * 100)
% max_damage_player.n_won_battles
)
Expand Down
8 changes: 2 additions & 6 deletions docs/source/using_custom_teambuilder.rst
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ Now that we have two players with custom teambuilders, we can make them battle!

.. code-block:: python
await cross_evaluate([player_1, player_2], n_challenges=5)
await player_1.battle_against(player_2, n_battles=5)
The complete example looks like that:

Expand All @@ -203,7 +203,6 @@ The complete example looks like that:
import numpy as np
from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate
from poke_env.teambuilder.teambuilder import Teambuilder
Expand Down Expand Up @@ -347,10 +346,7 @@ The complete example looks like that:
max_concurrent_battles=10,
)
await cross_evaluate([player_1, player_2], n_challenges=5)
for battle in player_1.battles:
print(battle)
await player_1.battle_against(player_2, n_battles=5)
if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion examples/cross_evaluate_random_players.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async def main():

# Now, we can cross evaluate them: every player will player 20 games against every
# other player.
cross_evaluation = await cross_evaluate(players, n_challenges=100)
cross_evaluation = await cross_evaluate(players, n_challenges=20)

# Defines a header for displaying results
table = [["-"] + [p.username for p in players]]
Expand Down
6 changes: 1 addition & 5 deletions examples/custom_teambuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import numpy as np

from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate
from poke_env.teambuilder.teambuilder import Teambuilder


Expand Down Expand Up @@ -143,10 +142,7 @@ async def main():
battle_format="gen8ou", team=custom_builder, max_concurrent_battles=10
)

await cross_evaluate([player_1, player_2], n_challenges=5)

for battle in player_1.battles:
print(battle)
await player_1.battle_against(player_2, n_battles=5)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion examples/gen7/cross_evaluate_random_players.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async def main():

# Now, we can cross evaluate them: every player will player 20 games against every
# other player.
cross_evaluation = await cross_evaluate(players, n_challenges=10)
cross_evaluation = await cross_evaluate(players, n_challenges=20)

# Defines a header for displaying results
table = [["-"] + [p.username for p in players]]
Expand Down
10 changes: 2 additions & 8 deletions examples/max_damage_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from poke_env.player.player import Player
from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate


class MaxDamagePlayer(Player):
Expand All @@ -28,16 +27,11 @@ async def main():
max_damage_player = MaxDamagePlayer(battle_format="gen8randombattle")

# Now, let's evaluate our player
cross_evaluation = await cross_evaluate(
[random_player, max_damage_player], n_challenges=100
)
await max_damage_player.battle_against(random_player, n_battles=100)

print(
"Max damage player won %d / 100 battles [this took %f seconds]"
% (
cross_evaluation[max_damage_player.username][random_player.username] * 100,
time.time() - start,
)
% (max_damage_player.n_won_battles, time.time() - start)
)


Expand Down
10 changes: 2 additions & 8 deletions examples/ou_max_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from poke_env.player.player import Player
from poke_env.player.random_player import RandomPlayer
from poke_env.player.utils import cross_evaluate


class MaxDamagePlayer(Player):
Expand Down Expand Up @@ -180,14 +179,9 @@ async def main():
)

# Now, let's evaluate our player
cross_evaluation = await cross_evaluate(
[random_player, max_damage_player], n_challenges=50
)
await max_damage_player.battle_against(random_player, n_battles=100)

print(
"Max damage player won %d / 100 battles"
% (cross_evaluation[max_damage_player.username][random_player.username] * 100)
)
print("Max damage player won %d / 100 battles" % max_damage_player.n_won_battles)


if __name__ == "__main__":
Expand Down
32 changes: 32 additions & 0 deletions src/poke_env/environment/pokemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Optional
from typing import Set
from typing import Tuple
from typing import Union

from poke_env.data import POKEDEX
from poke_env.environment.effect import Effect
Expand Down Expand Up @@ -59,6 +60,13 @@ def __init__(
self._heightm: int
self._possible_abilities: List[str]
self._species: str
self._stats: Dict[str, Optional[int]] = {
"atk": None,
"def": None,
"spa": None,
"spd": None,
"spe": None,
}
self._type_1: PokemonType
self._type_2: Optional[PokemonType] = None
self._weightkg: int
Expand Down Expand Up @@ -359,6 +367,22 @@ def _was_illusionned(self):
self._status = None
self._switch_out()

def damage_multiplier(self, type_or_move: Union[PokemonType, Move]) -> float:
"""
Returns the damage multiplier associated with a given type or move on this
pokemon.
This method is a shortcut for PokemonType.damage_multiplier with relevant types.
:param type_or_move: The type or move of interest.
:type type_or_move: PokemonType or Move
:return: The damage multiplier associated with given type on the pokemon.
:rtype: float
"""
if isinstance(type_or_move, Move):
type_or_move = type_or_move.type
return type_or_move.damage_multiplier(self._type_1, self._type_2)

@property
def ability(self) -> Optional[str]:
"""
Expand Down Expand Up @@ -565,6 +589,14 @@ def species(self) -> str:
"""
return self._species

@property
def stats(self) -> Dict[str, Optional[int]]:
"""
:return: The pokemon's stats, as a dictionary.
:rtype: Dict[str, Optional[int]]
"""
return self._stats

@property
def status(self) -> Optional[Status]:
"""
Expand Down
Loading

0 comments on commit 27121ee

Please sign in to comment.