finish animal and plants
This commit is contained in:
@@ -7,8 +7,9 @@ import inspect
|
||||
|
||||
from src.classes.essence import Essence, EssenceType
|
||||
from src.classes.root import Root, corres_essence_type
|
||||
from src.classes.region import Region, CultivateRegion
|
||||
from src.classes.region import Region, CultivateRegion, NormalRegion
|
||||
from src.classes.event import Event, NULL_EVENT
|
||||
from src.classes.item import Item
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from src.classes.avatar import Avatar
|
||||
@@ -319,7 +320,118 @@ class Play(DefineAction, ActualActionMixin):
|
||||
def is_doable(self) -> bool:
|
||||
return True
|
||||
|
||||
ALL_ACTION_CLASSES = [Move, Cultivate, Breakthrough, MoveToRegion, Play]
|
||||
ALL_ACTUAL_ACTION_CLASSES = [Cultivate, Breakthrough, MoveToRegion, Play]
|
||||
ALL_ACTION_NAMES = ["Move", "Cultivate", "Breakthrough", "MoveToRegion", "Play"]
|
||||
ALL_ACTUAL_ACTION_NAMES = ["Cultivate", "Breakthrough", "MoveToRegion", "Play"]
|
||||
|
||||
@long_action(step_month=6)
|
||||
class Hunt(DefineAction, ActualActionMixin):
|
||||
"""
|
||||
狩猎动作,在有动物的区域进行狩猎,持续6个月
|
||||
可以获得动物对应的物品
|
||||
"""
|
||||
COMMENT = "在当前区域狩猎动物,获取动物材料"
|
||||
PARAMS = {}
|
||||
|
||||
def _execute(self) -> None:
|
||||
"""
|
||||
执行狩猎动作
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
success_rate = self.get_success_rate()
|
||||
|
||||
if random.random() < success_rate:
|
||||
# 成功狩猎,从avatar境界足够的动物中随机选择一种
|
||||
avatar_realm = self.avatar.cultivation_progress.realm
|
||||
available_animals = [animal for animal in region.animals if avatar_realm >= animal.realm]
|
||||
target_animal = random.choice(available_animals)
|
||||
# 随机选择该动物的一种物品
|
||||
item = random.choice(target_animal.items)
|
||||
self.avatar.add_item(item, 1)
|
||||
|
||||
def get_success_rate(self) -> float:
|
||||
"""
|
||||
获取狩猎成功率,预留接口,目前固定为100%
|
||||
"""
|
||||
return 1.0 # 100%成功率
|
||||
|
||||
def get_event(self) -> Event:
|
||||
"""
|
||||
获取狩猎动作开始时的事件
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 在 {region.name} 开始狩猎")
|
||||
|
||||
@property
|
||||
def is_doable(self) -> bool:
|
||||
"""
|
||||
判断是否可以狩猎:必须在有动物的普通区域,且avatar的境界必须大于等于动物的境界
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, NormalRegion) or len(region.animals) == 0:
|
||||
return False
|
||||
|
||||
# 检查avatar的境界是否足够狩猎区域内的动物
|
||||
avatar_realm = self.avatar.cultivation_progress.realm
|
||||
for animal in region.animals:
|
||||
if avatar_realm >= animal.realm:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@long_action(step_month=6)
|
||||
class Harvest(DefineAction, ActualActionMixin):
|
||||
"""
|
||||
采集动作,在有植物的区域进行采集,持续6个月
|
||||
可以获得植物对应的物品
|
||||
"""
|
||||
COMMENT = "在当前区域采集植物,获取植物材料"
|
||||
PARAMS = {}
|
||||
|
||||
def _execute(self) -> None:
|
||||
"""
|
||||
执行采集动作
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
success_rate = self.get_success_rate()
|
||||
|
||||
if random.random() < success_rate:
|
||||
# 成功采集,从avatar境界足够的植物中随机选择一种
|
||||
avatar_realm = self.avatar.cultivation_progress.realm
|
||||
available_plants = [plant for plant in region.plants if avatar_realm >= plant.realm]
|
||||
target_plant = random.choice(available_plants)
|
||||
# 随机选择该植物的一种物品
|
||||
item = random.choice(target_plant.items)
|
||||
self.avatar.add_item(item, 1)
|
||||
|
||||
def get_success_rate(self) -> float:
|
||||
"""
|
||||
获取采集成功率,预留接口,目前固定为100%
|
||||
"""
|
||||
return 1.0 # 100%成功率
|
||||
|
||||
def get_event(self) -> Event:
|
||||
"""
|
||||
获取采集动作开始时的事件
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
return Event(self.world.month_stamp, f"{self.avatar.name} 在 {region.name} 开始采集")
|
||||
|
||||
@property
|
||||
def is_doable(self) -> bool:
|
||||
"""
|
||||
判断是否可以采集:必须在有植物的普通区域,且avatar的境界必须大于等于植物的境界
|
||||
"""
|
||||
region = self.avatar.tile.region
|
||||
if not isinstance(region, NormalRegion) or len(region.plants) == 0:
|
||||
return False
|
||||
|
||||
# 检查avatar的境界是否足够采集区域内的植物
|
||||
avatar_realm = self.avatar.cultivation_progress.realm
|
||||
for plant in region.plants:
|
||||
if avatar_realm >= plant.realm:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
ALL_ACTION_CLASSES = [Move, Cultivate, Breakthrough, MoveToRegion, Play, Hunt, Harvest]
|
||||
ALL_ACTUAL_ACTION_CLASSES = [Cultivate, Breakthrough, MoveToRegion, Play, Hunt, Harvest]
|
||||
ALL_ACTION_NAMES = ["Move", "Cultivate", "Breakthrough", "MoveToRegion", "Play", "Hunt", "Harvest"]
|
||||
ALL_ACTUAL_ACTION_NAMES = ["Cultivate", "Breakthrough", "MoveToRegion", "Play", "Hunt", "Harvest"]
|
||||
@@ -1,6 +1,10 @@
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from src.utils.df import game_configs
|
||||
from src.utils.config import CONFIG
|
||||
from src.classes.item import Item, items_by_id
|
||||
from src.classes.cultivation import Realm
|
||||
|
||||
@dataclass
|
||||
class Animal:
|
||||
@@ -10,13 +14,35 @@ class Animal:
|
||||
id: int
|
||||
name: str
|
||||
desc: str
|
||||
grade: int
|
||||
realm: Realm
|
||||
item_ids: list[int] = field(default_factory=list) # 该动物对应的物品IDs
|
||||
|
||||
# 这些字段将在__post_init__中设置
|
||||
items: list[Item] = field(init=False, default_factory=list) # 该动物对应的物品实例
|
||||
|
||||
def __post_init__(self):
|
||||
"""初始化物品实例"""
|
||||
for item_id in self.item_ids:
|
||||
if item_id in items_by_id:
|
||||
self.items.append(items_by_id[item_id])
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
def get_info(self) -> str:
|
||||
"""
|
||||
获取动物的详细信息,包括名字、描述、境界和材料
|
||||
"""
|
||||
info_parts = [f"【{self.name}】({self.realm.value})", self.desc]
|
||||
|
||||
if self.items:
|
||||
item_names = [item.name for item in self.items]
|
||||
info_parts.append(f"可获得材料:{', '.join(item_names)}")
|
||||
|
||||
return " - ".join(info_parts)
|
||||
|
||||
def _load_animals() -> tuple[dict[int, Animal], dict[str, Animal]]:
|
||||
"""从配表加载animal数据"""
|
||||
@@ -25,11 +51,19 @@ def _load_animals() -> tuple[dict[int, Animal], dict[str, Animal]]:
|
||||
|
||||
animal_df = game_configs["animal"]
|
||||
for _, row in animal_df.iterrows():
|
||||
# 处理item_ids
|
||||
item_ids_list = []
|
||||
item_ids = row.get("item_ids")
|
||||
if item_ids is not None and str(item_ids).strip() and str(item_ids) != 'nan':
|
||||
for item_id_str in str(item_ids).split(CONFIG.df.ids_separator):
|
||||
item_ids_list.append(int(float(item_id_str.strip())))
|
||||
|
||||
animal = Animal(
|
||||
id=int(row["id"]),
|
||||
name=str(row["name"]),
|
||||
desc=str(row["desc"]),
|
||||
grade=int(row["grade"])
|
||||
realm=Realm.from_id(int(row["stage_id"])),
|
||||
item_ids=item_ids_list
|
||||
)
|
||||
animals_by_id[animal.id] = animal
|
||||
animals_by_name[animal.name] = animal
|
||||
|
||||
@@ -26,6 +26,14 @@ level_to_stage = {
|
||||
20: Stage.Late_Stage,
|
||||
}
|
||||
|
||||
# realm_id到Realm的映射(用于物品等级系统)
|
||||
realm_id_to_realm = {
|
||||
1: Realm.Qi_Refinement,
|
||||
2: Realm.Foundation_Establishment,
|
||||
3: Realm.Core_Formation,
|
||||
4: Realm.Nascent_Soul,
|
||||
}
|
||||
|
||||
level_to_break_through = {
|
||||
30: Realm.Foundation_Establishment,
|
||||
60: Realm.Core_Formation,
|
||||
@@ -57,9 +65,9 @@ class CultivationProgress:
|
||||
return realm
|
||||
return Realm.Qi_Refinement
|
||||
|
||||
def get_stage(self, level: int) -> str:
|
||||
def get_stage(self, level: int) -> Stage:
|
||||
"""获取阶段"""
|
||||
_level = self.level % levels_per_realm
|
||||
_level = level % levels_per_realm
|
||||
for level_threshold, stage in reversed(list(level_to_stage.items())):
|
||||
if _level >= level_threshold:
|
||||
return stage
|
||||
@@ -155,4 +163,65 @@ class CultivationProgress:
|
||||
return self.exp >= exp_required
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.realm.value}{self.stage.value}({self.level}级)。可以突破:{self.can_break_through()}"
|
||||
return f"{self.realm.value}{self.stage.value}({self.level}级)。可以突破:{self.can_break_through()}"
|
||||
|
||||
|
||||
# 为Realm类添加from_id类方法
|
||||
def _realm_from_id(cls, realm_id: int) -> Realm:
|
||||
"""
|
||||
根据realm_id获取对应的Realm
|
||||
|
||||
Args:
|
||||
realm_id: 境界ID (1-4)
|
||||
|
||||
Returns:
|
||||
对应的Realm枚举值
|
||||
|
||||
Raises:
|
||||
ValueError: 如果realm_id不存在
|
||||
"""
|
||||
if realm_id not in realm_id_to_realm:
|
||||
raise ValueError(f"Unknown realm_id: {realm_id}")
|
||||
return realm_id_to_realm[realm_id]
|
||||
|
||||
# 将from_id方法绑定到Realm类
|
||||
Realm.from_id = classmethod(_realm_from_id)
|
||||
|
||||
# 境界顺序映射
|
||||
_realm_order = {
|
||||
Realm.Qi_Refinement: 1,
|
||||
Realm.Foundation_Establishment: 2,
|
||||
Realm.Core_Formation: 3,
|
||||
Realm.Nascent_Soul: 4,
|
||||
}
|
||||
|
||||
# 为Realm类添加比较操作符
|
||||
def _realm_ge(self, other):
|
||||
"""大于等于比较"""
|
||||
if not isinstance(other, Realm):
|
||||
return NotImplemented
|
||||
return _realm_order[self] >= _realm_order[other]
|
||||
|
||||
def _realm_le(self, other):
|
||||
"""小于等于比较"""
|
||||
if not isinstance(other, Realm):
|
||||
return NotImplemented
|
||||
return _realm_order[self] <= _realm_order[other]
|
||||
|
||||
def _realm_gt(self, other):
|
||||
"""大于比较"""
|
||||
if not isinstance(other, Realm):
|
||||
return NotImplemented
|
||||
return _realm_order[self] > _realm_order[other]
|
||||
|
||||
def _realm_lt(self, other):
|
||||
"""小于比较"""
|
||||
if not isinstance(other, Realm):
|
||||
return NotImplemented
|
||||
return _realm_order[self] < _realm_order[other]
|
||||
|
||||
# 将比较方法绑定到Realm类
|
||||
Realm.__ge__ = _realm_ge
|
||||
Realm.__le__ = _realm_le
|
||||
Realm.__gt__ = _realm_gt
|
||||
Realm.__lt__ = _realm_lt
|
||||
@@ -1,6 +1,7 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from src.utils.df import game_configs
|
||||
from src.classes.cultivation import Realm
|
||||
|
||||
@dataclass
|
||||
class Item:
|
||||
@@ -10,7 +11,7 @@ class Item:
|
||||
id: int
|
||||
name: str
|
||||
desc: str
|
||||
grade: int
|
||||
realm: Realm
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
@@ -29,7 +30,7 @@ def _load_items() -> tuple[dict[int, Item], dict[str, Item]]:
|
||||
id=int(row["id"]),
|
||||
name=str(row["name"]),
|
||||
desc=str(row["desc"]),
|
||||
grade=int(row["grade"])
|
||||
realm=Realm.from_id(int(row["stage_id"]))
|
||||
)
|
||||
items_by_id[item.id] = item
|
||||
items_by_name[item.name] = item
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from src.utils.df import game_configs
|
||||
from src.utils.config import CONFIG
|
||||
from src.classes.item import Item, items_by_id
|
||||
from src.classes.cultivation import Realm
|
||||
|
||||
@dataclass
|
||||
class Plant:
|
||||
@@ -10,13 +14,35 @@ class Plant:
|
||||
id: int
|
||||
name: str
|
||||
desc: str
|
||||
grade: int
|
||||
realm: Realm
|
||||
item_ids: list[int] = field(default_factory=list) # 该植物对应的物品IDs
|
||||
|
||||
# 这些字段将在__post_init__中设置
|
||||
items: list[Item] = field(init=False, default_factory=list) # 该植物对应的物品实例
|
||||
|
||||
def __post_init__(self):
|
||||
"""初始化物品实例"""
|
||||
for item_id in self.item_ids:
|
||||
if item_id in items_by_id:
|
||||
self.items.append(items_by_id[item_id])
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
def get_info(self) -> str:
|
||||
"""
|
||||
获取植物的详细信息,包括名字、描述、境界和材料
|
||||
"""
|
||||
info_parts = [f"【{self.name}】({self.realm.value})", self.desc]
|
||||
|
||||
if self.items:
|
||||
item_names = [item.name for item in self.items]
|
||||
info_parts.append(f"可获得材料:{', '.join(item_names)}")
|
||||
|
||||
return " - ".join(info_parts)
|
||||
|
||||
def _load_plants() -> tuple[dict[int, Plant], dict[str, Plant]]:
|
||||
"""从配表加载plant数据"""
|
||||
@@ -25,11 +51,19 @@ def _load_plants() -> tuple[dict[int, Plant], dict[str, Plant]]:
|
||||
|
||||
plant_df = game_configs["plant"]
|
||||
for _, row in plant_df.iterrows():
|
||||
# 处理item_ids
|
||||
item_ids_list = []
|
||||
item_ids = row.get("item_ids")
|
||||
if item_ids is not None and str(item_ids).strip() and str(item_ids) != 'nan':
|
||||
for item_id_str in str(item_ids).split(CONFIG.df.ids_separator):
|
||||
item_ids_list.append(int(float(item_id_str.strip())))
|
||||
|
||||
plant = Plant(
|
||||
id=int(row["id"]),
|
||||
name=str(row["name"]),
|
||||
desc=str(row["desc"]),
|
||||
grade=int(row["grade"])
|
||||
realm=Realm.from_id(int(row["stage_id"])),
|
||||
item_ids=item_ids_list
|
||||
)
|
||||
plants_by_id[plant.id] = plant
|
||||
plants_by_name[plant.name] = plant
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Union, TypeVar, Type
|
||||
from typing import Union, TypeVar, Type, Optional
|
||||
from enum import Enum
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
from src.utils.df import game_configs
|
||||
from src.utils.config import CONFIG
|
||||
from src.classes.essence import EssenceType, Essence
|
||||
from src.classes.animal import Animal, animals_by_id
|
||||
from src.classes.plant import Plant, plants_by_id
|
||||
|
||||
|
||||
def get_tiles_from_shape(shape: 'Shape', north_west_cor: str, south_east_cor: str) -> list[tuple[int, int]]:
|
||||
@@ -182,13 +185,59 @@ class Shape(Enum):
|
||||
class NormalRegion(Region):
|
||||
"""
|
||||
普通区域 - 平原、大河之类的,没有灵气或灵气很低
|
||||
包含该区域分布的动植物物种信息
|
||||
"""
|
||||
animal_ids: list[int] = field(default_factory=list) # 该区域分布的动物物种IDs
|
||||
plant_ids: list[int] = field(default_factory=list) # 该区域分布的植物物种IDs
|
||||
|
||||
# 这些字段将在__post_init__中设置
|
||||
animals: list[Animal] = field(init=False, default_factory=list) # 该区域的动物实例
|
||||
plants: list[Plant] = field(init=False, default_factory=list) # 该区域的植物实例
|
||||
|
||||
def __post_init__(self):
|
||||
"""初始化动植物实例"""
|
||||
# 先调用父类的__post_init__
|
||||
super().__post_init__()
|
||||
|
||||
# 加载动物实例
|
||||
for animal_id in self.animal_ids:
|
||||
if animal_id in animals_by_id:
|
||||
self.animals.append(animals_by_id[animal_id])
|
||||
|
||||
# 加载植物实例
|
||||
for plant_id in self.plant_ids:
|
||||
if plant_id in plants_by_id:
|
||||
self.plants.append(plants_by_id[plant_id])
|
||||
|
||||
def get_region_type(self) -> str:
|
||||
return "normal"
|
||||
|
||||
def get_species_info(self) -> str:
|
||||
"""获取该区域动植物物种的描述信息"""
|
||||
info_parts = []
|
||||
if self.animals:
|
||||
animal_infos = [animal.get_info() for animal in self.animals]
|
||||
info_parts.extend(animal_infos)
|
||||
|
||||
if self.plants:
|
||||
plant_infos = [plant.get_info() for plant in self.plants]
|
||||
info_parts.extend(plant_infos)
|
||||
|
||||
return "; ".join(info_parts) if info_parts else "暂无特色物种"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"普通区域:{self.name} - {self.desc}"
|
||||
species_info = self.get_species_info()
|
||||
return f"普通区域:{self.name} - {self.desc} | 物种分布:{species_info}"
|
||||
|
||||
@property
|
||||
def is_huntable(self) -> bool:
|
||||
# 如果该区域有动物,则可以狩猎
|
||||
return len(self.animals) > 0
|
||||
|
||||
@property
|
||||
def is_harvestable(self) -> bool:
|
||||
# 如果该区域有植物,则可以采集
|
||||
return len(self.plants) > 0
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -262,6 +311,24 @@ def _load_regions(region_type: Type[T], config_name: str) -> tuple[dict[int, T],
|
||||
base_params["essence_type"] = EssenceType.from_str(str(row["root_type"]))
|
||||
base_params["essence_density"] = int(row["root_density"])
|
||||
|
||||
# 如果是普通区域,添加动植物ID参数
|
||||
elif region_type == NormalRegion:
|
||||
# 处理动物IDs
|
||||
animal_ids_list = []
|
||||
animal_ids = row.get("animal_ids")
|
||||
if animal_ids is not None and str(animal_ids).strip() and str(animal_ids) != 'nan':
|
||||
for animal_id_str in str(animal_ids).split(CONFIG.df.ids_separator):
|
||||
animal_ids_list.append(int(float(animal_id_str.strip())))
|
||||
base_params["animal_ids"] = animal_ids_list
|
||||
|
||||
# 处理植物IDs
|
||||
plant_ids_list = []
|
||||
plant_ids = row.get("plant_ids")
|
||||
if plant_ids is not None and str(plant_ids).strip() and str(plant_ids) != 'nan':
|
||||
for plant_id_str in str(plant_ids).split(CONFIG.df.ids_separator):
|
||||
plant_ids_list.append(int(float(plant_id_str.strip())))
|
||||
base_params["plant_ids"] = plant_ids_list
|
||||
|
||||
region = region_type(**base_params)
|
||||
regions_by_id[region.id] = region
|
||||
regions_by_name[region.name] = region
|
||||
|
||||
Reference in New Issue
Block a user