213 lines
5.0 KiB
Python
213 lines
5.0 KiB
Python
"""
|
|
Ledger (动态资产与负债账本)
|
|
NovelMaster Core Engine - 状态管理器
|
|
|
|
管理角色资产、负债、Hook/Cool-point 追踪
|
|
"""
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import List, Dict, Set, Optional, Any
|
|
from enum import Enum
|
|
import time
|
|
|
|
|
|
class AssetType(Enum):
|
|
SKILL = "skill"
|
|
ITEM = "item"
|
|
RELATIONSHIP = "relationship"
|
|
STATUS = "status"
|
|
KNOWLEDGE = "knowledge"
|
|
POWER = "power"
|
|
|
|
|
|
class LiabilityType(Enum):
|
|
DEBT = "debt"
|
|
PROMISE = "promise"
|
|
UNRESOLVED_CONFLICT = "unresolved_conflict"
|
|
SECRET = "secret"
|
|
WEAKNESS = "weakness"
|
|
|
|
|
|
@dataclass
|
|
class Asset:
|
|
"""资产"""
|
|
id: str
|
|
type: AssetType
|
|
name: str
|
|
description: str
|
|
value: int # 1-100
|
|
acquired_at_tick: int
|
|
owner_id: str
|
|
tags: List[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass
|
|
class Liability:
|
|
"""负债"""
|
|
id: str
|
|
type: LiabilityType
|
|
name: str
|
|
description: str
|
|
severity: int # 1-100
|
|
created_at_tick: int
|
|
due_tick: Optional[int] = None
|
|
creditor_id: Optional[str] = None
|
|
tags: List[str] = field(default_factory=list)
|
|
|
|
|
|
@dataclass
|
|
class LedgerEntry:
|
|
"""账本条目"""
|
|
asset: Optional[Asset] = None
|
|
liability: Optional[Liability] = None
|
|
delta: float = 0
|
|
reason: str = ""
|
|
tick: int = 0
|
|
|
|
|
|
@dataclass
|
|
class CharacterLedger:
|
|
"""角色账本"""
|
|
character_id: str
|
|
assets: Dict[str, Asset] = field(default_factory=dict)
|
|
liabilities: Dict[str, Liability] = field(default_factory=dict)
|
|
history: List[LedgerEntry] = field(default_factory=list)
|
|
|
|
|
|
class HookType(Enum):
|
|
SETUP = "setup"
|
|
BUILDUP = "buildup"
|
|
CLIFFHANGER = "cliffhanger"
|
|
|
|
|
|
@dataclass
|
|
class Hook:
|
|
"""钩子"""
|
|
id: str
|
|
type: HookType
|
|
description: str
|
|
chapter_introduced: int
|
|
tension_weight: int # 1-100
|
|
resolved: bool = False
|
|
resolution_chapter: Optional[int] = None
|
|
|
|
|
|
@dataclass
|
|
class CoolPoint:
|
|
"""爽点"""
|
|
id: str
|
|
type: str # payoff, subversion, escalation
|
|
description: str
|
|
chapter_delivered: int
|
|
satisfaction_weight: int # 1-100
|
|
|
|
|
|
def create_asset(
|
|
asset_id: str,
|
|
asset_type: AssetType,
|
|
name: str,
|
|
value: int,
|
|
owner_id: str,
|
|
description: str = ""
|
|
) -> Asset:
|
|
"""创建资产"""
|
|
return Asset(
|
|
id=asset_id,
|
|
type=asset_type,
|
|
name=name,
|
|
description=description,
|
|
value=max(1, min(100, value)),
|
|
acquired_at_tick=0,
|
|
owner_id=owner_id,
|
|
tags=[]
|
|
)
|
|
|
|
|
|
def create_liability(
|
|
liability_id: str,
|
|
liability_type: LiabilityType,
|
|
name: str,
|
|
severity: int,
|
|
description: str = ""
|
|
) -> Liability:
|
|
"""创建负债"""
|
|
return Liability(
|
|
id=liability_id,
|
|
type=liability_type,
|
|
name=name,
|
|
description=description,
|
|
severity=max(1, min(100, severity)),
|
|
created_at_tick=0,
|
|
tags=[]
|
|
)
|
|
|
|
|
|
def calculate_net_worth(ledger: CharacterLedger) -> int:
|
|
"""计算角色净值"""
|
|
asset_value = sum(asset.value for asset in ledger.assets.values())
|
|
liability_value = sum(liab.severity for liab in ledger.liabilities.values())
|
|
return asset_value - liability_value
|
|
|
|
|
|
def add_hook(hooks: List[Hook], hook: Hook) -> List[Hook]:
|
|
"""添加钩子"""
|
|
return [*hooks, hook]
|
|
|
|
|
|
def add_cool_point(cool_points: List[CoolPoint], cool_point: CoolPoint) -> List[CoolPoint]:
|
|
"""添加爽点"""
|
|
return [*cool_points, cool_point]
|
|
|
|
|
|
def calculate_hook_pressure(hooks: List[Hook]) -> int:
|
|
"""计算钩子压强"""
|
|
unresolved = [h for h in hooks if not h.resolved]
|
|
return sum(h.tension_weight for h in unresolved)
|
|
|
|
|
|
def resolve_hook(hooks: List[Hook], hook_id: str, resolution_chapter: int) -> List[Hook]:
|
|
"""解决钩子"""
|
|
return [
|
|
{**hook.__dict__, "resolved": True, "resolution_chapter": resolution_chapter}
|
|
if hook.id == hook_id else hook
|
|
for hook in hooks
|
|
]
|
|
|
|
|
|
def check_genesis_compatibility(asset: Asset, ethical_inversion: Dict[str, Any]) -> float:
|
|
"""检查资产与创世契约的兼容性"""
|
|
incompatible_norms = ethical_inversion.get("inverted_norms", [])
|
|
|
|
# 简单检查:资产名称是否与反转的道德规范冲突
|
|
for norm in incompatible_norms:
|
|
if norm.lower() in asset.name.lower():
|
|
return 0.3 # 低兼容
|
|
|
|
return 1.0 # 完全兼容
|
|
|
|
|
|
@dataclass
|
|
class HooksPool:
|
|
"""钩子池"""
|
|
hooks: List[Hook] = field(default_factory=list)
|
|
cool_points: List[CoolPoint] = field(default_factory=list)
|
|
|
|
def add_hook(self, hook: Hook) -> None:
|
|
self.hooks.append(hook)
|
|
|
|
def resolve_hook(self, hook_id: str, chapter: int) -> bool:
|
|
for h in self.hooks:
|
|
if h.id == hook_id:
|
|
h.resolved = True
|
|
h.resolution_chapter = chapter
|
|
return True
|
|
return False
|
|
|
|
@property
|
|
def pressure(self) -> int:
|
|
return calculate_hook_pressure(self.hooks)
|
|
|
|
@property
|
|
def unresolved_count(self) -> int:
|
|
return sum(1 for h in self.hooks if not h.resolved)
|