feat: initial commit
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user