kipyin / pokemaster

Checkout kipyin/pokemaster2 !
https://github.com/kipyin/pokemaster2
2 stars 2 forks source link

Pokémon forgets HM moves when learning a new move #13

Closed kipyin closed 5 years ago

kipyin commented 5 years ago

Issue Description

When a Pokémon tries to learn a new move (either through level-up or use a machine), if the Pokémon knows an HM move, it will be eventually forgotten.

Minimum Crash Example

>>> from pokemaster import Pokemon
>>> mew = Pokemon('mew', level=10)
>>> for hm in range(101, 105):
...    mew.use_machine(hm)
>>> mew.moves
deque(['cut', 'fly', 'surf', 'strength'], maxlen=4)
>>> mew.use_machine(105)
deque(['fly', 'surf', 'strength', 'flash'], maxlen=4)
kipyin commented 5 years ago

Possible solutions

1. Add a validation in Pokemon._learn_move()

https://github.com/kipyin/pokemaster/blob/2333a4fa9298f02ea7c06e591305a8af42f139ea/pokemaster/pokemon.py#L360-L363

Instead of doing self._moves.append(learn), we can do something like:

forget_machine = database.get_machine(move_identifier=forget)
if forget_machine and not forget_machine.is_hm:
    self._moves.remove(forget)
    self._moves.append(learn)

2. Add a MoveSet class

Another way to solve this problem is adding a MoveSet class, and let it decide whether or not a move should be forgotten:

@attr.s
class MoveSet:
    HM_MOVES: ClassVar[List[str]] = list_of_hm_moves
    moves: List[str]

    def add(self, move: str, remove: str = None):
        """Add a move to the move set."""
        self.remove(remove)
        ...
    def remove(self, move: str):
        """Remove a move from the move set."""
        # Checks if `move` is in `self.moves`, and if `forget` is an HM move.
        ...

And in pokemaster.pokemon.Pokemon._learn_move(), we can just do:

self._moves.add(learn, forget)

I prefer the first solution, until a strong reason for having MoveSet is found.