"""This module defines the Field class, which represents a battle field.
"""# 导入必要的模块from __future__ import annotations
import logging
from enum import Enum, auto, unique
# 定义 Field 类,表示战斗中的一个场地@uniqueclassField(Enum):"""Enumeration, represent a non null field in a battle."""
UNKNOWN = auto()
ELECTRIC_TERRAIN = auto()
GRASSY_TERRAIN = auto()
GRAVITY = auto()
HEAL_BLOCK = auto()
MAGIC_ROOM = auto()
MISTY_TERRAIN = auto()
MUD_SPORT = auto()
MUD_SPOT = auto()
PSYCHIC_TERRAIN = auto()
TRICK_ROOM = auto()
WATER_SPORT = auto()
WONDER_ROOM = auto()def__str__(self)->str:returnf"{self.name} (field) object"@staticmethoddeffrom_showdown_message(message:str)-> Field:"""Returns the Field object corresponding to the message.
:param message: The message to convert.
:type message: str
:return: The corresponding Field object.
:rtype: Field
"""# 处理消息,将空格替换为下划线
message = message.replace("move: ","")
message = message.replace(" ","_")# 处理特殊情况,将以 terrain 结尾的消息转换为以 _TERRAIN 结尾if message.endswith("terrain")andnot message.endswith("_terrain"):
message = message.replace("terrain","_terrain")try:return Field[message.upper()]except KeyError:# 如果无法找到对应的 Field 对象,则记录警告信息并返回 Field.UNKNOWN
logging.getLogger("poke-env").warning("Unexpected field '%s' received. Field.UNKNOWN will be used instead. ""If this is unexpected, please open an issue at ""https://github.com/hsahovic/poke-env/issues/ along with this error ""message and a description of your program.",
message,)return Field.UNKNOWN
@propertydefis_terrain(self)->bool:"""Wheter this field is a terrain."""return self.name.endswith("_TERRAIN")
.\PokeLLMon\poke_env\environment\helper.py
# 导入 math 模块,用于数学运算import math
.\PokeLLMon\poke_env\environment\move.py
# 导入 copy 模块,用于深拷贝对象import copy
# 导入 lru_cache 装饰器,用于缓存函数的结果from functools import lru_cache
# 导入 Any、Dict、List、Optional、Set、Tuple、Union 类型提示from typing import Any, Dict, List, Optional, Set, Tuple, Union
# 导入 GenData、to_id_str 函数from poke_env.data import GenData, to_id_str
# 导入 Field 类from poke_env.environment.field import Field
# 导入 MoveCategory 枚举from poke_env.environment.move_category import MoveCategory
# 导入 PokemonType 枚举from poke_env.environment.pokemon_type import PokemonType
# 导入 Status 枚举from poke_env.environment.status import Status
# 导入 Weather 枚举from poke_env.environment.weather import Weather
# 特殊招式集合,包含 "struggle" 和 "recharge"
SPECIAL_MOVES: Set[str]={"struggle","recharge"}# 保护招式集合
_PROTECT_MOVES ={"protect","detect","endure","spikyshield","kingsshield","banefulbunker","obstruct","maxguard",}# 辅助保护招式集合
_SIDE_PROTECT_MOVES ={"wideguard","quickguard","matblock"}# 总保护招式集合,包含保护招式和辅助保护招式
_PROTECT_COUNTER_MOVES = _PROTECT_MOVES | _SIDE_PROTECT_MOVES
# 招式类classMove:# 杂项标志列表
_MISC_FLAGS =["onModifyMove","onEffectiveness","onHitField","onAfterMoveSecondarySelf","onHit","onTry","beforeTurnCallback","onAfterMove","onTryHit","onTryMove","hasCustomRecoil","onMoveFail","onPrepareHit","onAfterHit","onBasePower","basePowerCallback","damageCallback","onTryHitSide","beforeMoveCallback",]# 每种宝可梦类型对应的招式类别预分配字典
_MOVE_CATEGORY_PER_TYPE_PRE_SPLIT ={
PokemonType.BUG: MoveCategory.PHYSICAL,
PokemonType.DARK: MoveCategory.SPECIAL,
PokemonType.DRAGON: MoveCategory.SPECIAL,
PokemonType.ELECTRIC: MoveCategory.SPECIAL,
PokemonType.FIGHTING: MoveCategory.PHYSICAL,
PokemonType.FIRE: MoveCategory.SPECIAL,
PokemonType.FLYING: MoveCategory.PHYSICAL,
PokemonType.GHOST: MoveCategory.PHYSICAL,
PokemonType.GRASS: MoveCategory.SPECIAL,
PokemonType.GROUND: MoveCategory.PHYSICAL,
PokemonType.ICE: MoveCategory.SPECIAL,
PokemonType.NORMAL: MoveCategory.PHYSICAL,
PokemonType.POISON: MoveCategory.PHYSICAL,
PokemonType.PSYCHIC: MoveCategory.SPECIAL,
PokemonType.ROCK: MoveCategory.PHYSICAL,
PokemonType.STEEL: MoveCategory.PHYSICAL,
PokemonType.WATER: MoveCategory.SPECIAL,}# 招式对象的属性列表
__slots__ =("_id","_base_power_override","_current_pp","_dynamaxed_move","_gen","_is_empty","_moves_dict","_request_target",)# 初始化招式对象def__init__(self, move_id:str, gen:int, raw_id: Optional[str]=None):
self._id = move_id
self._base_power_override =None
self._gen = gen
self._moves_dict = GenData.from_gen(gen).moves
# 处理隐藏力招式if move_id.startswith("hiddenpower")and raw_id isnotNone:
base_power ="".join([c for c in raw_id if c.isdigit()])
self._id ="".join([c for c in to_id_str(raw_id)ifnot c.isdigit()])if base_power:try:
base_power =int(base_power)
self._base_power_override = base_power
except ValueError:pass
self._current_pp = self.max_pp
self._is_empty:bool=False
self._dynamaxed_move =None
self._request_target =None# 返回招式对象的字符串表示def__repr__(self)->str:returnf"{self._id} (Move object)"# 减少当前 PP 值defuse(self):
self._current_pp -=1# 判断给定的招式 ID 是否为 Z 招式@staticmethoddefis_id_z(id_:str, gen:int)->bool:if id_.startswith("z")and id_[1:]in GenData.from_gen(gen).moves:returnTruereturn"isZ"in GenData.from_gen(gen).moves[id_]# 判断给定的招式 ID 是否为 Max 招式@staticmethoddefis_max_move(id_:str, gen:int)->bool:if id_.startswith("max"):returnTrueelif(
GenData.from_gen(gen).moves[id_].get("isNonstandard",None)=="Gigantamax"):returnTrueelif GenData.from_gen(gen).moves[id_].get("isMax",None)isnotNone:returnTruereturnFalse# 判断给定的招式是否应该被存储@staticmethod@lru_cache(4096)defshould_be_stored(move_id:str, gen:int)->bool:if move_id in SPECIAL_MOVES:returnFalseif move_id notin GenData.from_gen(gen).moves:returnFalseif Move.is_id_z(move_id, gen):returnFalseif Move.is_max_move(move_id, gen):returnFalsereturnTrue# 获取招式的命中率(0 到 1 的范围)@propertydefaccuracy(self)->float:"""
:return: The move's accuracy (0 to 1 scale).
:rtype: float
"""
accuracy = self.entry["accuracy"]if accuracy isTrue:return1.0return accuracy /100# 获取招式的基础威力@propertydefbase_power(self)->int:"""
:return: The move's base power.
:rtype: int
"""if self._base_power_override isnotNone:return self._base_power_override
return self.entry.get("basePower",0)# 获取招式对目标的增益效果@propertydefboosts(self)-> Optional[Dict[str,int]]:"""
:return: Boosts conferred to the target by using the move.
:rtype: Dict[str, float] | None
"""return self.entry.get("boosts",None)# 返回移动是否打破类似保护的防御defbreaks_protect(self)->bool:"""
:return: Whether the move breaks proect-like defenses.
:rtype: bool
"""return self.entry.get("breaksProtect",False)# 返回是否存在此移动的 Z-移动版本@propertydefcan_z_move(self)->bool:"""
:return: Wheter there exist a z-move version of this move.
:rtype: bool
"""return self.idnotin SPECIAL_MOVES
# 返回移动的类别@propertydefcategory(self)-> MoveCategory:"""
:return: The move category.
:rtype: MoveCategory
"""# 如果条目中没有类别信息,则打印出当前移动和条目if"category"notin self.entry:print(self, self.entry)# 如果世代小于等于3且类别为"PHYSICAL"或"SPECIAL",则返回对应的移动类别if self._gen <=3and self.entry["category"].upper()in{"PHYSICAL","SPECIAL",}:return self._MOVE_CATEGORY_PER_TYPE_PRE_SPLIT[self.type]return MoveCategory[self.entry["category"].upper()]# 返回移动的暴击率。如果移动保证暴击,则返回6@propertydefcrit_ratio(self)->int:"""
:return: The move's crit ratio. If the move is guaranteed to crit, returns 6.
:rtype:
"""if"critRatio"in self.entry:returnint(self.entry["critRatio"])elif"willCrit"in self.entry:return6return0# 返回当前剩余的PP@propertydefcurrent_pp(self)->int:"""
:return: Remaining PP.
:rtype: int
"""return self._current_pp
# 返回移动的固定伤害。可以是整数或'level',例如Seismic Toss@propertydefdamage(self)-> Union[int,str]:"""
:return: The move's fix damages. Can be an int or 'level' for moves such as
Seismic Toss.
:rtype: Union[int, str]
"""return self.entry.get("damage",0)defdeduced_target(self)-> Optional[str]:"""
:return: Move deduced target, based on Move.target and showdown's request
messages.
:rtype: str, optional
"""# 如果移动在特殊移动列表中,则返回移动的目标if self.idin SPECIAL_MOVES:return self.target
# 如果有请求目标,则返回请求目标elif self.request_target:return self.request_target
# 如果目标是"randomNormal",则返回请求目标elif self.target =="randomNormal":return self.request_target
# 否则返回移动的目标return self.target
@propertydefdefensive_category(self)-> MoveCategory:"""
:return: Move's defender category.
:rtype: MoveCategory
"""# 如果存在"overrideDefensiveStat"在条目中if"overrideDefensiveStat"in self.entry:# 如果"overrideDefensiveStat"为"def",则返回物理类别if self.entry["overrideDefensiveStat"]=="def":return MoveCategory["PHYSICAL"]# 如果"overrideDefensiveStat"为"spd",则返回特殊类别elif self.entry["overrideDefensiveStat"]=="spd":return MoveCategory["SPECIAL"]# 否则抛出值错误异常else:raise ValueError(f"Unsupported value for overrideDefensiveStat: {self.entry['overrideDefensiveStat']}")# 否则返回移动的类别return self.category
@propertydefdrain(self)->float:"""
:return: Ratio of HP of inflicted damages, between 0 and 1.
:rtype: float
"""# 如果存在"drain"在条目中,则返回伤害的HP比例if"drain"in self.entry:return self.entry["drain"][0]/ self.entry["drain"][1]# 否则返回0.0return0.0@propertydefdynamaxed(self):"""
:return: The dynamaxed version of the move.
:rtype: DynamaxMove
"""# 如果存在动态移动,则返回动态移动if self._dynamaxed_move:return self._dynamaxed_move
# 否则创建动态移动并返回
self._dynamaxed_move = DynamaxMove(self)return self._dynamaxed_move
@propertydefentry(self)-> Dict[str, Any]:"""
Should not be used directly.
:return: The data entry corresponding to the move
:rtype: Dict
"""# 检查是否存在与当前移动ID对应的数据条目,如果存在则返回该数据条目if self._id in self._moves_dict:return self._moves_dict[self._id]# 如果移动ID以"z"开头且去掉"z"后的部分在数据字典中存在,则返回对应的数据条目elif self._id.startswith("z")and self._id[1:]in self._moves_dict:return self._moves_dict[self._id[1:]]# 如果移动ID为"recharge",则返回一个预定义的数据条目elif self._id =="recharge":return{"pp":1,"type":"normal","category":"Special","accuracy":1}else:# 抛出数值错误,表示未知的移动IDraise ValueError("Unknown move: %s"% self._id)@propertydefexpected_hits(self)->float:"""
:return: Expected number of hits, between 1 and 5. Equal to n_hits if n_hits is
constant.
:rtype: float
"""# 对于特定的移动ID,返回预期的击中次数if self._id =="triplekick"or self._id =="tripleaxel":# 对于Triple Kick和Triple Axel,每次击中都有准确性检查,并且每次击中的威力逐渐增加return1+2*0.9+3*0.81
min_hits, max_hits = self.n_hit
if min_hits == max_hits:return min_hits
else:# 如果击中次数不固定,则返回一个范围内的预期值assert(
min_hits ==2and max_hits ==5),f"Move {self._id} expected to hit 2-5 times. Got {min_hits}-{max_hits}"return(2+3)/3+(4+5)/6@propertydefflags(self)-> Set[str]:"""
This property is not well defined, and may be missing some information.
If you need more information on some flag, please open an issue in the project.
:return: Flags associated with this move. These can come from the data or be
custom.
:rtype: Set[str]
"""# 获取与该移动相关的标志,可能来自数据或自定义
flags =set(self.entry["flags"])
flags.update(set(self.entry.keys()).intersection(self._MISC_FLAGS))return flags
@propertydefforce_switch(self)->bool:"""
:return: Whether this move forces switches.
:rtype: bool
"""# 返回该移动是否强制交换精灵的布尔值return self.entry.get("forceSwitch",False)@propertydefheal(self)->float:"""
:return: Proportion of the user's HP recovered.
:rtype: float
"""# 如果"heal"在self.entry中if"heal"in self.entry:# 返回用户恢复的HP比例return self.entry["heal"][0]/ self.entry["heal"][1]return0.0@propertydefid(self)->str:"""
:return: Move id.
:rtype: str
"""# 返回移动的idreturn self._id
@propertydefignore_ability(self)->bool:"""
:return: Whether the move ignore its target's ability.
:rtype: bool
"""# 返回该移动是否忽略目标精灵的能力return self.entry.get("ignoreAbility",False)@propertydefignore_defensive(self)->bool:"""
:return: Whether the opponent's stat boosts are ignored.
:rtype: bool
"""# 返回对手的属性提升是否被忽略return self.entry.get("ignoreDefensive",False)@propertydefignore_evasion(self)->bool:"""
:return: Wheter the opponent's evasion is ignored.
:rtype: bool
"""# 返回对手的闪避是否被忽略return self.entry.get("ignoreEvasion",False)@propertydefignore_immunity(self)-> Union[bool, Set[PokemonType]]:"""
:return: Whether the opponent's immunity is ignored, or a list of ignored
immunities.
:rtype: bool or set of Types
"""# 如果"ignoreImmunity"在self.entry中if"ignoreImmunity"in self.entry:# 如果self.entry["ignoreImmunity"]是布尔值ifisinstance(self.entry["ignoreImmunity"],bool):return self.entry["ignoreImmunity"]else:# 返回被忽略的免疫类型的集合return{
PokemonType[t.upper().replace("'","")]for t in self.entry["ignoreImmunity"].keys()}returnFalse@propertydefis_empty(self)->bool:"""
:return: Whether the move is an empty move.
:rtype: bool
"""# 返回移动是否为空的布尔值return self._is_empty
@propertydefis_protect_counter(self)->bool:"""
:return: Wheter this move increments a mon's protect counter.
:rtype: int
"""# 返回移动是否增加宝可梦的保护计数器的布尔值return self._id in _PROTECT_COUNTER_MOVES
@propertydefis_protect_move(self)->bool:"""
:return: Wheter this move is a protect-like move.
:rtype: int
"""# 返回移动是否类似于保护的布尔值return self._id in _PROTECT_MOVES
@propertydefis_side_protect_move(self)->bool:"""
:return: Wheter this move is a side-protect move.
:rtype: int
"""# 返回移动是否是侧面保护的布尔值return self._id in _SIDE_PROTECT_MOVES
@propertydefis_z(self)->bool:"""
:return: Whether the move is a z move.
:rtype: bool
"""# 返回移动是否是 Z 移动的布尔值return Move.is_id_z(self.id, gen=self._gen)@propertydefmax_pp(self)->int:"""
:return: The move's max pp.
:rtype: int
"""# 返回移动的最大 PP 值return self.entry["pp"]*8//5@propertydefn_hit(self)-> Tuple[int,int]:"""
:return: How many hits this move lands. Tuple of the form (min, max).
:rtype: Tuple
"""# 返回移动命中的次数。返回形式为 (最小值, 最大值) 的元组if"multihit"in self.entry:ifisinstance(self.entry["multihit"],list):assertlen(self.entry["multihit"])==2
min_hits, max_hits = self.entry["multihit"]return min_hits, max_hits
else:return self.entry["multihit"], self.entry["multihit"]return1,1@propertydefno_pp_boosts(self)->bool:"""
:return: Whether the move uses PPs.
:rtype: bool
"""# 返回移动是否使用 PPs 的布尔值return"noPPBoosts"in self.entry
defnon_ghost_target(self)->bool:"""
:return: True if the move targets non-ghost Pokemon.
:rtype: bool
"""# Check if the key "nonGhostTarget" exists in the entry dictionaryreturn"nonGhostTarget"in self.entry
@propertydefpriority(self)->int:"""
:return: Priority of the move.
:rtype: int
"""# Return the value associated with the key "priority" in the entry dictionaryreturn self.entry["priority"]@propertydefpseudo_weather(self)->str:"""
:return: Pseudo-weather triggered by this move.
:rtype: str
"""# Return the value associated with the key "pseudoWeather" in the entry dictionary, or None if not foundreturn self.entry.get("pseudoWeather",None)@propertydefrecoil(self)->float:"""
:return: Percentage of damage inflicted by the move as recoil.
:rtype: float
"""# Calculate and return the recoil proportion based on the values in the entry dictionaryif"recoil"in self.entry:return self.entry["recoil"][0]/ self.entry["recoil"][1]elif"struggleRecoil"in self.entry:return0.25return0.0@propertydefrequest_target(self)-> Optional[str]:"""
:return: Target information provided by Showdown in a request message, if any.
:rtype: str, optional
"""# Return the stored request target informationreturn self._request_target
@request_target.setterdefrequest_target(self, request_target: Optional[str]):"""
:param request_target: Target information received from Showdown in a request message.
:type request_target: str, optional
"""# Set the request target information received from Showdown
self._request_target = request_target
@staticmethod@lru_cache(maxsize=4096)defretrieve_id(move_name:str)->str:"""Retrieve the id of a move based on its full name.
:param move_name: The string to convert into a move id.
:type move_name: str
:return: The corresponding move id.
:rtype: str
"""# 将移动名称转换为标识符字符串
move_name = to_id_str(move_name)# 如果移动名称以"return"开头,则返回"return"if move_name.startswith("return"):return"return"# 如果移动名称以"frustration"开头,则返回"frustration"if move_name.startswith("frustration"):return"frustration"# 如果移动名称以"hiddenpower"开头,则返回"hiddenpower"if move_name.startswith("hiddenpower"):return"hiddenpower"# 否则返回移动名称return move_name
@propertydefsecondary(self)-> List[Dict[str, Any]]:"""
:return: Secondary effects. At this point, the precise content of this property
is not too clear.
:rtype: Optional[Dict]
"""# 如果属性中包含"secondary"且不为空,则返回包含"secondary"的列表if"secondary"in self.entry and self.entry["secondary"]:return[self.entry["secondary"]]# 如果属性中包含"secondaries",则返回"secondaries"elif"secondaries"in self.entry:return self.entry["secondaries"]# 否则返回空列表return[]@propertydefself_boost(self)-> Optional[Dict[str,int]]:"""
:return: Boosts applied to the move's user.
:rtype: Dict[str, int]
"""# 如果属性中包含"selfBoost",则返回"selfBoost"中的"boosts",否则返回Noneif"selfBoost"in self.entry:return self.entry["selfBoost"].get("boosts",None)# 如果属性中包含"self"且"boosts"在"self"中,则返回"self"中的"boosts"elif"self"in self.entry and"boosts"in self.entry["self"]:return self.entry["self"]["boosts"]# 否则返回NonereturnNone@propertydefself_destruct(self)-> Optional[str]:"""
:return: Move's self destruct consequences.
:rtype: str | None
"""# 返回属性中的"selfdestruct",如果不存在则返回Nonereturn self.entry.get("selfdestruct",None)@propertydefself_switch(self)-> Union[str,bool]:"""
:return: What kind of self swtich this move implies for the user.
:rtype: str | None
"""# 返回属性中的"selfSwitch",如果不存在则返回Falsereturn self.entry.get("selfSwitch",False)@propertydefside_condition(self)-> Optional[str]:"""
:return: Side condition inflicted by the move.
:rtype: str | None
"""# 返回移动造成的副作用条件return self.entry.get("sideCondition",None)@propertydefsleep_usable(self)->bool:"""
:return: Whether the move can be user by a sleeping pokemon.
:rtype: bool
"""# 返回移动是否可以被睡眠的宝可梦使用return self.entry.get("sleepUsable",False)@propertydefslot_condition(self)-> Optional[str]:"""
:return: Which slot condition is started by this move.
:rtype: str | None
"""# 返回由此招式引发的槽位条件return self.entry.get("slotCondition",None)@propertydefstalling_move(self)->bool:"""
:return: Showdown classification of the move as a stalling move.
:rtype: bool
"""# 返回招式作为拖延招式的Showdown分类return self.entry.get("stallingMove",False)@propertydefstatus(self)-> Optional[Status]:"""
:return: The status inflicted by the move.
:rtype: Optional[Status]
"""# 如果字典中包含"status"键,则返回对应的Status枚举值,否则返回Noneif"status"in self.entry:return Status[self.entry["status"].upper()]returnNone@propertydefsteals_boosts(self)->bool:"""
:return: Whether the move steals its target's boosts.
:rtype: bool
"""# 返回招式是否偷取目标的增益效果return self.entry.get("stealsBoosts",False)# 返回移动的目标类型deftarget(self)->str:"""
:return: Move target. Possible targets (copied from PS codebase):
* adjacentAlly - Only relevant to Doubles or Triples, the move only
targets an ally of the user.
* adjacentAllyOrSelf - The move can target the user or its ally.
* adjacentFoe - The move can target a foe, but not (in Triples)
a distant foe.
* all - The move targets the field or all Pokémon at once.
* allAdjacent - The move is a spread move that also hits the user's ally.
* allAdjacentFoes - The move is a spread move.
* allies - The move affects all active Pokémon on the user's team.
* allySide - The move adds a side condition on the user's side.
* allyTeam - The move affects all unfainted Pokémon on the user's team.
* any - The move can hit any other active Pokémon, not just those adjacent.
* foeSide - The move adds a side condition on the foe's side.
* normal - The move can hit one adjacent Pokémon of your choice.
* randomNormal - The move targets an adjacent foe at random.
* scripted - The move targets the foe that damaged the user.
* self - The move affects the user of the move.
:rtype: str
"""return self.entry["target"]# 返回由移动引发的地形@propertydefterrain(self)-> Optional[Field]:"""
:return: Terrain started by the move.
:rtype: Optional[Field]
"""# 获取移动引发的地形,如果存在则转换成 Field 对象
terrain = self.entry.get("terrain",None)if terrain isnotNone:
terrain = Field.from_showdown_message(terrain)return terrain
# 返回移动是否解冻目标@propertydefthaws_target(self)->bool:"""
:return: Whether the move thaws its target.
:rtype: bool
"""return self.entry.get("thawsTarget",False)@propertydeftype(self)-> PokemonType:"""
:return: Move type.
:rtype: PokemonType
"""# 返回移动的类型,通过从名称获取 PokemonType 对象return PokemonType.from_name(self.entry["type"])@propertydefuse_target_offensive(self)->bool:"""
:return: Whether the move uses the target's offensive statistics.
:rtype: bool
"""# 返回移动是否使用目标的进攻统计信息return self.entry.get("overrideOffensivePokemon",False)=="target"@propertydefvolatile_status(self)-> Optional[str]:"""
:return: Volatile status inflicted by the move.
:rtype: str | None
"""# 返回移动造成的短暂状态return self.entry.get("volatileStatus",None)@propertydefweather(self)-> Optional[Weather]:"""
:return: Weather started by the move.
:rtype: Optional[Weather]
"""# 返回由移动引起的天气if"weather"in self.entry:return Weather[self.entry["weather"].upper()]returnNone@propertydefz_move_boost(self)-> Optional[Dict[str,int]]:"""
:return: Boosts associated with the z-move version of this move.
:rtype: Dict[str, int]
"""# 返回与 z-move 版本的移动相关联的增益if"zMove"in self.entry and"boost"in self.entry["zMove"]:return self.entry["zMove"]["boost"]returnNone@propertydefz_move_effect(self)-> Optional[str]:"""
:return: Effects associated with the z-move version of this move.
:rtype: str | None
"""# 返回与 z-move 版本的移动相关联的效果if"zMove"in self.entry and"effect"in self.entry["zMove"]:return self.entry["zMove"]["effect"]returnNone@property# 返回该招式的 Z 招式版本的基础威力defz_move_power(self)->int:"""
:return: Base power of the z-move version of this move.
:rtype: int
"""# 如果该招式有 Z 招式属性,并且包含基础威力信息,则返回基础威力if"zMove"in self.entry and"basePower"in self.entry["zMove"]:return self.entry["zMove"]["basePower"]# 如果该招式为状态招式,则基础威力为 0elif self.category == MoveCategory.STATUS:return0# 获取基础威力值
base_power = self.base_power
# 如果招式命中次数不是 (1, 1),则基础威力乘以 3if self.n_hit !=(1,1):
base_power *=3# 根据基础威力值返回对应的 Z 招式威力值elif base_power <=55:return100elif base_power <=65:return120elif base_power <=75:return140elif base_power <=85:return160elif base_power <=95:return175elif base_power <=100:return180elif base_power <=110:return185elif base_power <=125:return190elif base_power <=130:return195# 基础威力大于 130,则返回 200return200classEmptyMove(Move):# 定义一个空招式类,继承自Move类def__init__(self, move_id:str):# 初始化方法,接受一个招式ID参数
self._id = move_id
self._is_empty:bool=True# 设置_is_empty属性为Truedef__getattribute__(self, name:str):# 重写__getattribute__方法try:returnsuper(Move, self).__getattribute__(name)except(AttributeError, TypeError, ValueError):return0# 尝试获取属性,如果出现异常则返回0def__deepcopy__(self, memodict: Optional[Dict[int, Any]]={}):# 重写__deepcopy__方法,实现深拷贝return EmptyMove(copy.deepcopy(self._id, memodict))# 返回一个深拷贝的EmptyMove对象classDynamaxMove(Move):# 定义一个DynamaxMove类,继承自Move类
BOOSTS_MAP ={# 定义BOOSTS_MAP字典,存储属性提升信息
PokemonType.BUG:{"spa":-1},
PokemonType.DARK:{"spd":-1},
PokemonType.DRAGON:{"atk":-1},
PokemonType.GHOST:{"def":-1},
PokemonType.NORMAL:{"spe":-1},}
SELF_BOOSTS_MAP ={# 定义SELF_BOOSTS_MAP字典,存储自身属性提升信息
PokemonType.FIGHTING:{"atk":+1},
PokemonType.FLYING:{"spe":+1},
PokemonType.GROUND:{"spd":+1},
PokemonType.POISON:{"spa":+1},
PokemonType.STEEL:{"def":+1},}
TERRAIN_MAP ={# 定义TERRAIN_MAP字典,存储地形信息
PokemonType.ELECTRIC: Field.ELECTRIC_TERRAIN,
PokemonType.FAIRY: Field.MISTY_TERRAIN,
PokemonType.GRASS: Field.GRASSY_TERRAIN,
PokemonType.PSYCHIC: Field.PSYCHIC_TERRAIN,}
WEATHER_MAP ={# 定义WEATHER_MAP字典,存储天气信息
PokemonType.FIRE: Weather.SUNNYDAY,
PokemonType.ICE: Weather.HAIL,
PokemonType.ROCK: Weather.SANDSTORM,
PokemonType.WATER: Weather.RAINDANCE,}def__init__(self, parent: Move):# 初始化方法,接受一个Move对象作为参数
self._parent: Move = parent
def__getattr__(self, name:str):# 重写__getattr__方法if name[:2]=="__":raise AttributeError(name)returngetattr(self._parent, name)# 获取父类Move对象的属性@propertydefaccuracy(self):# 定义accuracy属性return1# 返回值为1@property# 定义一个属性# 返回技能的基础威力,如果技能类型不是状态技能defbase_power(self)->int:# 如果技能类型不是状态技能,则获取父类的基础威力
base_power = self._parent.base_power
# 如果技能属性是毒或格斗if self.typein{PokemonType.POISON, PokemonType.FIGHTING}:# 根据基础威力的不同范围返回不同的威力值if base_power <40:return70if base_power <50:return75if base_power <60:return80if base_power <70:return85if base_power <100:return90if base_power <140:return95return100else:# 根据基础威力的不同范围返回不同的威力值if base_power <40:return90if base_power <50:return100if base_power <60:return110if base_power <70:return120if base_power <100:return130if base_power <140:return140return150# 如果技能类型是状态技能,则返回0return0# 返回技能的增益效果,如果技能类型不是状态技能@propertydefboosts(self)-> Optional[Dict[str,int]]:if self.category != MoveCategory.STATUS:return self.BOOSTS_MAP.get(self.type,None)returnNone# 返回技能是否能破坏保护@propertydefbreaks_protect(self):returnFalse# 返回技能的暴击率@propertydefcrit_ratio(self):return0# 返回技能造成的伤害值@propertydefdamage(self):return0# 返回技能的防御类别@propertydefdefensive_category(self):return self.category
# 返回技能预期的命中次数@propertydefexpected_hits(self):return1# 返回是否强制交换精灵@propertydefforce_switch(self):returnFalse# 返回技能的治疗效果@propertydefheal(self):return0# 返回技能是否是保护技能的反击@propertydefis_protect_counter(self):return self.category == MoveCategory.STATUS
# 返回技能是否是保护技能@propertydefis_protect_move(self):return self.category == MoveCategory.STATUS
# 返回技能的命中次数范围@propertydefn_hit(self):return1,1# 返回技能的优先级,这里默认为0defpriority(self):return0# 返回技能的反冲值,这里默认为0@propertydefrecoil(self):return0# 返回技能对自身的增益效果,如果技能不是状态技能,则返回对应类型的增益效果字典,否则返回None@propertydefself_boost(self)-> Optional[Dict[str,int]]:if self.category != MoveCategory.STATUS:return self.SELF_BOOSTS_MAP.get(self.type,None)returnNone# 返回技能的状态效果,这里默认为None@propertydefstatus(self):returnNone# 返回技能对场地的影响,如果技能不是状态技能,则返回对应类型的场地效果,否则返回None@propertydefterrain(self)-> Optional[Field]:if self.category != MoveCategory.STATUS:return self.TERRAIN_MAP.get(self.type,None)returnNone# 返回技能对天气的影响,如果技能不是状态技能,则返回对应类型的天气效果,否则返回None@propertydefweather(self)-> Optional[Weather]:if self.category != MoveCategory.STATUS:return self.WEATHER_MAP.get(self.type,None)returnNone