add actual action space

This commit is contained in:
bridge
2025-09-03 22:32:42 +08:00
parent 9fd7dfd471
commit 490e973283
5 changed files with 62 additions and 55 deletions

View File

@@ -128,12 +128,21 @@ class ActualActionMixin():
"""
pass
@property
@abstractmethod
def is_doable(self) -> bool:
"""
判断动作是否可以执行
"""
pass
class Move(DefineAction, ChunkActionMixin):
"""
最基础的移动动作在tile之间进行切换。
"""
COMMENT = "移动到某个相对位置"
PARAMS = {"delta_x": "int", "delta_y": "int"}
def _execute(self, delta_x: int, delta_y: int) -> None:
"""
移动到某个tile
@@ -157,6 +166,7 @@ class MoveToRegion(DefineAction, ActualActionMixin):
移动到某个region
"""
COMMENT = "移动到某个区域"
PARAMS = {"region": "region_name"}
def _execute(self, region: Region|str) -> None:
"""
移动到某个region
@@ -194,12 +204,20 @@ class MoveToRegion(DefineAction, ActualActionMixin):
region_name = str(region)
return Event(self.world.month_stamp, f"{self.avatar.name} 开始移动向 {region_name}")
@property
def is_doable(self) -> bool:
"""
判断移动到区域动作是否可以执行
"""
return True
@long_action(step_month=10)
class Cultivate(DefineAction, ActualActionMixin):
"""
修炼动作,可以增加修仙进度。
"""
COMMENT = "修炼,增进修为"
PARAMS = {}
def _execute(self) -> None:
"""
修炼
@@ -226,6 +244,13 @@ class Cultivate(DefineAction, ActualActionMixin):
"""
return Event(self.world.month_stamp, f"{self.avatar.name}{self.avatar.tile.region.name} 开始修炼")
@property
def is_doable(self) -> bool:
"""
判断修炼动作是否可以执行
"""
return self.avatar.cultivation_progress.can_cultivate()
# 突破境界class
@long_action(step_month=1)
@@ -234,6 +259,7 @@ class Breakthrough(DefineAction, ActualActionMixin):
突破境界
"""
COMMENT = "尝试突破境界"
PARAMS = {}
def calc_success_rate(self) -> float:
"""
计算突破境界的成功率
@@ -255,12 +281,20 @@ class Breakthrough(DefineAction, ActualActionMixin):
"""
return Event(self.world.month_stamp, f"{self.avatar.name} 开始尝试突破境界")
@property
def is_doable(self) -> bool:
"""
判断突破动作是否可以执行
"""
return self.avatar.cultivation_progress.can_break_through()
@long_action(step_month=6)
class Play(DefineAction, ActualActionMixin):
"""
游戏娱乐动作,持续半年时间
"""
COMMENT = "游戏娱乐,放松身心"
PARAMS = {}
def _execute(self) -> None:
"""
@@ -276,12 +310,11 @@ class Play(DefineAction, ActualActionMixin):
"""
return Event(self.world.month_stamp, f"{self.avatar.name} 开始玩耍")
@property
def is_doable(self) -> bool:
return True
ALL_ACTION_CLASSES = [Move, Cultivate, Breakthrough, MoveToRegion, Play]
ACTION_SPACE = [
# {"action": "Move", "params": {"delta_x": int, "delta_y": int}, "comment": Move.COMMENT},
{"action": "Cultivate", "params": {}, "comment": Cultivate.COMMENT},
{"action": "Breakthrough", "params": {}, "comment": Breakthrough.COMMENT},
{"action": "MoveToRegion", "params": {"region": "region_name"}, "comment": MoveToRegion.COMMENT},
{"action": "Play", "params": {}, "comment": Play.COMMENT},
]
ACTION_SPACE_STR = json.dumps(ACTION_SPACE, ensure_ascii=False)
ALL_ACTUAL_ACTION_CLASSES = [Cultivate, Breakthrough, MoveToRegion, Play]
ALL_ACTION_NAMES = ["Move", "Cultivate", "Breakthrough", "MoveToRegion", "Play"]
ALL_ACTUAL_ACTION_NAMES = ["Cultivate", "Breakthrough", "MoveToRegion", "Play"]

View File

@@ -11,7 +11,6 @@ import random
from src.classes.world import World
from src.classes.tile import Region
from src.classes.root import corres_essence_type
from src.classes.action import ACTION_SPACE_STR
from src.classes.event import Event, NULL_EVENT
from src.utils.llm import get_ai_prompt_and_call_llm_async
from src.classes.typings import ACTION_NAME, ACTION_PARAMS, ACTION_PAIR
@@ -84,9 +83,7 @@ class RuleAI(AI):
class LLMAI(AI):
"""
LLM AI
"""
# TODO动作链
"""
一些思考:
AI动作应该分两类
1. 动作链,一定时间内的长期规划,动作按照这个动作链来执行(以及何时终止并执行下一个动作)
2. 突发情况比如突然有人要攻击NPC这个时候的反应
@@ -97,7 +94,7 @@ class LLMAI(AI):
"""
异步决策逻辑通过LLM决定执行什么动作和参数
"""
action_space_str = ACTION_SPACE_STR
action_space_str = self.avatar.get_action_space_str()
avatar_infos_str = str(self.avatar)
regions_str = "\n".join([str(region) for region in world.map.regions.values()])
avatar_persona = self.avatar.persona.prompt

View File

@@ -2,9 +2,10 @@ import random
from dataclasses import dataclass, field
from enum import Enum
from typing import Optional
import json
from src.classes.calendar import MonthStamp
from src.classes.action import Action, ALL_ACTION_CLASSES
from src.classes.action import Action, ALL_ACTUAL_ACTION_CLASSES, ALL_ACTION_CLASSES, ALL_ACTUAL_ACTION_NAMES
from src.classes.world import World
from src.classes.tile import Tile, Region
from src.classes.cultivation import CultivationProgress
@@ -190,6 +191,20 @@ class Avatar:
"""
return "\n".join([f"{action.__class__.__name__}: {action_params}" for action, action_params in self.history_action_pairs])
def get_action_space_str(self) -> str:
action_space = self.get_action_space()
action_space_str = json.dumps(action_space, ensure_ascii=False)
return action_space_str
def get_action_space(self) -> list[dict]:
"""
获取动作空间
"""
actual_actions = [self.create_action(action_cls_name) for action_cls_name in ALL_ACTUAL_ACTION_NAMES]
doable_actions = [action for action in actual_actions if action.is_doable]
action_space = [{"action": action.__class__.__name__, "params": action.PARAMS, "comment": action.COMMENT} for action in doable_actions]
return action_space
def get_new_avatar_from_ordinary(world: World, current_month_stamp: MonthStamp, name: str, age: Age):
"""
从凡人中来的新修士