-
Notifications
You must be signed in to change notification settings - Fork 1
/
pkmntypes.py
194 lines (163 loc) · 6.27 KB
/
pkmntypes.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
import json
from dataclasses import dataclass
from typing import Any, Optional
import logging
from bson.objectid import ObjectId
from motor.motor_asyncio import AsyncIOMotorClientSession
def _case_insensitive_pop(
kwargs: dict[str, Any], name: str, default: Optional[Any] = None
) -> Any:
if name in kwargs:
return kwargs.pop(name)
if name.lower() in kwargs:
return kwargs.pop(name.lower())
if default != None:
return default
raise KeyError(name)
@dataclass(init=False, repr=False)
class Pokemon():
"""A Pokemon.
FIXME: make all props snake case
:param Name: The name of the Pokemon
:param NatDex: The National Pokedex number for the Pokemon
:param Level: The Pokemon's level
:param Ability: The Pokemon's ability
:param TotalExperience: The total amount of experience points gained by the Pokemon
:param Gender: The Pokemon's gender
:param IVs: The individual values for the Pokemon in an array that represent HP, Attack, Defense, Special Attack, Special Defense, and Speed
:param EVs: The effort values associated with the Pokemon
:param Nature: The Pokemon's nature represented by a value
:param Stats: The stats for the Pokemon
:param StatModifiers: The stat modifiers that could affect the Pokemon's stats
:param StatusEffects: The value representing if the Pokemon has an status effects on it
:param CurrentHP: The amount of health the Pokemon has
:param HeldItem: Any item the Pokemon may be holding
:param Moves: The move set of the Pokemon
:param Friendship: A value representing the friendship of the Pokemon
:param OriginalTrainerID: The ID of the trainer of the Pokemon
:param Type: The type of Pokemon
"""
_id: Optional[ObjectId]
Name: str
NatDex: int
Level: int
Ability: int
TotalExperience: int
Gender: int
IVs: list[int]
EVs: list[int]
Nature: int
Stats: list[int]
StatModifiers: list[int]
StatusEffects: int
CurrentHP: int
HeldItem: dict
Moves: list[dict]
Friendship: int
OriginalTrainerID: int
Type: int
def __init__(self, **kwargs):
if "_id" in kwargs:
self._id = kwargs.pop("_id")
else:
self._id = kwargs.pop("id", None)
if len(kwargs) == 0:
return
self.Name: str = _case_insensitive_pop(kwargs, 'Name')
self.NatDex: int = _case_insensitive_pop(kwargs, 'NatDex')
self.Level: int = _case_insensitive_pop(kwargs, 'Level')
self.Ability: int = _case_insensitive_pop(kwargs, 'Ability')
self.TotalExperience: int = _case_insensitive_pop(kwargs, 'TotalExperience')
self.Gender: int = _case_insensitive_pop(kwargs, 'Gender')
self.IVs: list[int] = _case_insensitive_pop(kwargs, 'IVs')
self.EVs: list[int] = _case_insensitive_pop(kwargs, 'EVs')
self.Nature: int = _case_insensitive_pop(kwargs, 'Nature')
self.Stats: list[int] = _case_insensitive_pop(kwargs, 'Stats')
self.StatModifiers: list[int] = _case_insensitive_pop(kwargs, 'StatModifiers')
self.StatusEffects: int = _case_insensitive_pop(kwargs, 'StatusEffects')
self.CurrentHP: int = _case_insensitive_pop(kwargs, 'CurrentHP')
self.HeldItem: dict = _case_insensitive_pop(kwargs, 'HeldItem')
self.Moves: list[dict] = _case_insensitive_pop(kwargs, 'Moves')
self.Friendship: int = _case_insensitive_pop(kwargs, 'Friendship')
self.OriginalTrainerID: int = _case_insensitive_pop(kwargs, 'OriginalTrainerID')
self.Type: int = _case_insensitive_pop(kwargs, 'Type')
async def save(self, session: AsyncIOMotorClientSession = None):
"""Alias for `storage.save_object(pokemon)`."""
import storage # avoid circular import
await storage.save_object(self, session=session)
@dataclass(init=False)
class Party():
"""Represents a party of pokemon."""
pokemon: list[Pokemon]
def __init__(self, **kwargs):
self.pokemon = [
pkmn if isinstance(pkmn, Pokemon) else Pokemon(**pkmn)
for pkmn in _case_insensitive_pop(kwargs, "pokemon", [])
]
@dataclass
class Team():
"""Represents a list of parties of pokemon."""
parties: list[Party]
@dataclass(init=False)
class Target():
"""Represents a target identified by it's party and slot."""
party: int
slot: int
team: int
pokemon: Pokemon
def __init__(self, **kwargs):
self.party: int = _case_insensitive_pop(kwargs, "Party", -1)
self.slot: int = _case_insensitive_pop(kwargs, "Slot", -1)
self.team: int = _case_insensitive_pop(kwargs, "Team", -1)
self.pokemon: Pokemon = Pokemon(
**_case_insensitive_pop(kwargs, "Pokemon")
) if "Pokemon" in kwargs or "pokemon" in kwargs else None
@dataclass(init=False)
class BattleContext():
"""Describes the point of view of a given Pokemon on the battlefield. It provides enough information for a user to make an informed decision about what turn to make next.
:param battle: The state of the battlefield
:param pokemon: The pokemon that this context belongs to
:param team: The team ID of the `Pokemon`
:param targets: All pokemon on the battlefield
:param allies: Ally targets in relation to the `Pokemon`
:param opponents: Enemy targets in relation to the `Pokemon`
"""
battle: dict
pokemon: Pokemon
team: int
targets: list[Target]
allies: list[Target]
opponents: list[Target]
def __init__(self, **kwargs):
self.battle: dict = _case_insensitive_pop(kwargs, 'Battle')
self.pokemon: Pokemon = Pokemon(**_case_insensitive_pop(kwargs, 'Pokemon'))
self.team: int = _case_insensitive_pop(kwargs, 'Team')
self.targets: list[Target] = [
Target(**d) for d in _case_insensitive_pop(kwargs, 'Targets', [])
]
self.allies: list[Target] = [
Target(**d) for d in _case_insensitive_pop(kwargs, 'Allies', [])
]
self.opponents: list[Target] = [
Target(**d) for d in _case_insensitive_pop(kwargs, 'Opponents', [])
]
class Transaction:
"""Describes something that happened during a battle."""
def __init__(self, **kwargs):
self.type: int = kwargs["type"]
self.name: str = kwargs["name"]
self.args: dict[str, Any] = kwargs["args"]
def pretty(self) -> str:
"""Get a human-readable representation of this transaction."""
if self.type == 0:
user = Pokemon(**self.args["User"])
target = Target(**self.args["Target"])
move = self.args["Move"]
return f"{user.Name} used {move['Name']} on {target.pokemon.Name} for {self.args['Damage']} damage."
elif self.type == 8:
target = Target(**self.args["Target"])
return f"{target.pokemon.Name} fainted."
elif self.type == 11:
return f"The battle has ended."
else:
return f"TODO: {self.name}<{self.type}> {self.args}"