Spaces:
Runtime error
Runtime error
PPP commited on
Commit ·
07f6446
1
Parent(s): 40c24a7
feat(rest): fill missing recovery effects for valid rest actions
Browse files- state_manager.py +32 -0
- story_engine.py +36 -4
state_manager.py
CHANGED
|
@@ -1882,3 +1882,35 @@ class GameState:
|
|
| 1882 |
changes["status_effects_removed"] = ["中毒"]
|
| 1883 |
|
| 1884 |
return changes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1882 |
changes["status_effects_removed"] = ["中毒"]
|
| 1883 |
|
| 1884 |
return changes
|
| 1885 |
+
|
| 1886 |
+
def get_rest_rule_effects(self) -> dict[str, int]:
|
| 1887 |
+
"""Return conservative default recovery when resting at a valid location."""
|
| 1888 |
+
loc = self.world.locations.get(self.player.location)
|
| 1889 |
+
if loc is None or not loc.rest_available:
|
| 1890 |
+
return {}
|
| 1891 |
+
|
| 1892 |
+
if loc.shop_available:
|
| 1893 |
+
base_recovery = {
|
| 1894 |
+
"hp_change": 20,
|
| 1895 |
+
"mp_change": 10,
|
| 1896 |
+
"morale_change": 10,
|
| 1897 |
+
"sanity_change": 6,
|
| 1898 |
+
}
|
| 1899 |
+
else:
|
| 1900 |
+
base_recovery = {
|
| 1901 |
+
"hp_change": 12,
|
| 1902 |
+
"mp_change": 6,
|
| 1903 |
+
"morale_change": 6,
|
| 1904 |
+
"sanity_change": 4,
|
| 1905 |
+
}
|
| 1906 |
+
|
| 1907 |
+
filtered: dict[str, int] = {}
|
| 1908 |
+
if self.player.hp < self.player.max_hp:
|
| 1909 |
+
filtered["hp_change"] = base_recovery["hp_change"]
|
| 1910 |
+
if self.player.mp < self.player.max_mp:
|
| 1911 |
+
filtered["mp_change"] = base_recovery["mp_change"]
|
| 1912 |
+
if self.player.morale < 100:
|
| 1913 |
+
filtered["morale_change"] = base_recovery["morale_change"]
|
| 1914 |
+
if self.player.sanity < 100:
|
| 1915 |
+
filtered["sanity_change"] = base_recovery["sanity_change"]
|
| 1916 |
+
return filtered
|
story_engine.py
CHANGED
|
@@ -582,6 +582,7 @@ class StoryEngine:
|
|
| 582 |
event_type = outline.get("event_type", "")
|
| 583 |
state_changes, sanitize_warnings = self._sanitize_state_changes(state_changes, event_type)
|
| 584 |
state_changes, item_rule_notes = self._fill_missing_consumable_effects(state_changes, player_intent)
|
|
|
|
| 585 |
if sanitize_warnings:
|
| 586 |
logger.info(f"状态变更清理: {sanitize_warnings}")
|
| 587 |
|
|
@@ -622,7 +623,7 @@ class StoryEngine:
|
|
| 622 |
# 合并 tick_log 和 change_log 中的重复属性条目
|
| 623 |
merged_log = _merge_change_logs(
|
| 624 |
tick_log,
|
| 625 |
-
change_log + validation_issues + item_rule_notes,
|
| 626 |
)
|
| 627 |
|
| 628 |
return {
|
|
@@ -1115,9 +1116,39 @@ class StoryEngine:
|
|
| 1115 |
|
| 1116 |
return merged_changes, applied_notes
|
| 1117 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1118 |
def _strip_invalid_item_effects(self, state_changes: dict) -> dict:
|
| 1119 |
-
"""
|
| 1120 |
-
当 LLM 生成了涉及不存在物品的状态变更时,移除相关效果(安全网)。
|
| 1121 |
|
| 1122 |
例如:LLM 生成了"吃了包子" → hunger_change: +10, items_lost: ["包子"],
|
| 1123 |
但包子不在背包中。此方法移除 items_lost 和相关的属性效果。
|
|
@@ -1496,6 +1527,7 @@ class StoryEngine:
|
|
| 1496 |
event_type = outline.get("event_type", "")
|
| 1497 |
state_changes, sanitize_warnings = self._sanitize_state_changes(state_changes, event_type)
|
| 1498 |
state_changes, item_rule_notes = self._fill_missing_consumable_effects(state_changes, player_intent)
|
|
|
|
| 1499 |
|
| 1500 |
# 应用状态变更
|
| 1501 |
change_log = self.game_state.apply_changes(state_changes)
|
|
@@ -1529,7 +1561,7 @@ class StoryEngine:
|
|
| 1529 |
# 合并日志
|
| 1530 |
merged_log = _merge_change_logs(
|
| 1531 |
tick_log,
|
| 1532 |
-
change_log + validation_issues + item_rule_notes,
|
| 1533 |
)
|
| 1534 |
|
| 1535 |
yield {
|
|
|
|
| 582 |
event_type = outline.get("event_type", "")
|
| 583 |
state_changes, sanitize_warnings = self._sanitize_state_changes(state_changes, event_type)
|
| 584 |
state_changes, item_rule_notes = self._fill_missing_consumable_effects(state_changes, player_intent)
|
| 585 |
+
state_changes, rest_rule_notes = self._fill_missing_rest_effects(state_changes, player_intent)
|
| 586 |
if sanitize_warnings:
|
| 587 |
logger.info(f"状态变更清理: {sanitize_warnings}")
|
| 588 |
|
|
|
|
| 623 |
# 合并 tick_log 和 change_log 中的重复属性条目
|
| 624 |
merged_log = _merge_change_logs(
|
| 625 |
tick_log,
|
| 626 |
+
change_log + validation_issues + item_rule_notes + rest_rule_notes,
|
| 627 |
)
|
| 628 |
|
| 629 |
return {
|
|
|
|
| 1116 |
|
| 1117 |
return merged_changes, applied_notes
|
| 1118 |
|
| 1119 |
+
def _fill_missing_rest_effects(
|
| 1120 |
+
self,
|
| 1121 |
+
state_changes: dict,
|
| 1122 |
+
player_intent: dict,
|
| 1123 |
+
) -> tuple[dict, list[str]]:
|
| 1124 |
+
"""
|
| 1125 |
+
Fill missing rest recovery with conservative defaults at rest-enabled locations.
|
| 1126 |
+
"""
|
| 1127 |
+
if str(player_intent.get("intent", "")).upper() != "REST":
|
| 1128 |
+
return state_changes, []
|
| 1129 |
+
|
| 1130 |
+
recovery_keys = (
|
| 1131 |
+
"hp_change",
|
| 1132 |
+
"mp_change",
|
| 1133 |
+
"morale_change",
|
| 1134 |
+
"sanity_change",
|
| 1135 |
+
"hunger_change",
|
| 1136 |
+
)
|
| 1137 |
+
if any(key in state_changes for key in recovery_keys):
|
| 1138 |
+
return state_changes, []
|
| 1139 |
+
|
| 1140 |
+
inferred = self.game_state.get_rest_rule_effects()
|
| 1141 |
+
if not inferred:
|
| 1142 |
+
return state_changes, []
|
| 1143 |
+
|
| 1144 |
+
merged_changes = dict(state_changes)
|
| 1145 |
+
merged_changes.update(inferred)
|
| 1146 |
+
logger.info("按休息规则补全缺失效果: %s", inferred)
|
| 1147 |
+
return merged_changes, ["休息规则补全"]
|
| 1148 |
+
|
| 1149 |
def _strip_invalid_item_effects(self, state_changes: dict) -> dict:
|
| 1150 |
+
"""
|
| 1151 |
+
当 LLM 生成了涉及不存在物品的状态变更时,移除相关效果(安全网)。
|
| 1152 |
|
| 1153 |
例如:LLM 生成了"吃了包子" → hunger_change: +10, items_lost: ["包子"],
|
| 1154 |
但包子不在背包中。此方法移除 items_lost 和相关的属性效果。
|
|
|
|
| 1527 |
event_type = outline.get("event_type", "")
|
| 1528 |
state_changes, sanitize_warnings = self._sanitize_state_changes(state_changes, event_type)
|
| 1529 |
state_changes, item_rule_notes = self._fill_missing_consumable_effects(state_changes, player_intent)
|
| 1530 |
+
state_changes, rest_rule_notes = self._fill_missing_rest_effects(state_changes, player_intent)
|
| 1531 |
|
| 1532 |
# 应用状态变更
|
| 1533 |
change_log = self.game_state.apply_changes(state_changes)
|
|
|
|
| 1561 |
# 合并日志
|
| 1562 |
merged_log = _merge_change_logs(
|
| 1563 |
tick_log,
|
| 1564 |
+
change_log + validation_issues + item_rule_notes + rest_rule_notes,
|
| 1565 |
)
|
| 1566 |
|
| 1567 |
yield {
|