rabukasim / compiler /canonical_schema.py
trioskosmos's picture
Upload folder using huggingface_hub
463f868 verified
from __future__ import annotations
from typing import Annotated, Any, Dict, List, Literal, Optional, Union
from pydantic import BaseModel, ConfigDict, Field, TypeAdapter
from engine.models.generated_metadata import COSTS, CONDITIONS, OPCODES, TRIGGERS, TARGETS, ZONES
KNOWN_TRIGGERS = frozenset(TRIGGERS.keys())
KNOWN_COSTS = frozenset(COSTS.keys())
KNOWN_EFFECTS = frozenset(OPCODES.keys())
KNOWN_CONDITIONS = frozenset(CONDITIONS.keys())
KNOWN_TARGETS = frozenset(TARGETS.keys())
KNOWN_ZONES = frozenset(ZONES.keys())
ALLOWED_STEP_KINDS = frozenset(
{
"cost",
"condition",
"effect",
"select",
"assign",
"if",
"choose_one",
"repeat",
}
)
RESERVED_BINDINGS = frozenset(
{
"SELF",
"PLAYER",
"OPPONENT",
"TARGET",
"TARGET_MEMBER",
"TARGET_STAGE",
"TARGET_DISCARD",
}
)
ALLOWED_REVIEW_MARKERS = frozenset(
{
"needs_review",
"unknown_operand",
"unknown_filter_fragment",
"unknown_binding",
"unsupported_pattern",
}
)
class StrictBaseModel(BaseModel):
model_config = ConfigDict(extra="forbid")
class ReferenceExpr(StrictBaseModel):
kind: Literal["reference"] = "reference"
name: str
class LiteralExpr(StrictBaseModel):
kind: Literal["literal"] = "literal"
value: Union[int, bool, str]
class BinaryExpr(StrictBaseModel):
kind: Literal["binary"] = "binary"
op: Literal["add", "sub", "eq", "gt", "lt", "ge", "le"]
left: "ValueExpr"
right: "ValueExpr"
ValueExpr = Annotated[Union[ReferenceExpr, LiteralExpr, BinaryExpr], Field(discriminator="kind")]
class FilterClause(StrictBaseModel):
field: str
op: Literal["eq", "ne", "gt", "lt", "ge", "le", "contains", "in", "exists"]
value: Optional[Union[int, bool, str, List[Union[int, str]]]] = None
class FilterSpec(StrictBaseModel):
all_of: List[FilterClause] = Field(default_factory=list)
any_of: List[FilterClause] = Field(default_factory=list)
review_markers: List[str] = Field(default_factory=list)
class StepBase(StrictBaseModel):
kind: str
notes: List[str] = Field(default_factory=list)
review_markers: List[str] = Field(default_factory=list)
class CostStep(StepBase):
kind: Literal["cost"] = "cost"
op: str
count: Optional[ValueExpr] = None
optional: bool = False
target: Optional[str] = None
zone: Optional[str] = None
filter: Optional[FilterSpec] = None
store_as: Optional[str] = None
class ConditionStep(StepBase):
kind: Literal["condition"] = "condition"
op: str
args: Dict[str, Union[ValueExpr, int, bool, str, List[Union[int, str]]]] = Field(default_factory=dict)
negated: bool = False
store_as: Optional[str] = None
class EffectStep(StepBase):
kind: Literal["effect"] = "effect"
op: str
count: Optional[ValueExpr] = None
target: Optional[str] = None
zone: Optional[str] = None
duration: Optional[str] = None
filter: Optional[FilterSpec] = None
store_as: Optional[str] = None
args: Dict[str, Union[ValueExpr, int, bool, str, List[Union[int, str]]]] = Field(default_factory=dict)
class SelectStep(StepBase):
kind: Literal["select"] = "select"
op: str
count: Optional[ValueExpr] = None
target: Optional[str] = None
zone: Optional[str] = None
filter: Optional[FilterSpec] = None
store_as: str
class AssignStep(StepBase):
kind: Literal["assign"] = "assign"
store_as: str
expr: ValueExpr
class IfStep(StepBase):
kind: Literal["if"] = "if"
condition: ConditionStep
then: List["CanonicalStep"]
else_: List["CanonicalStep"] = Field(default_factory=list, alias="else")
class ChoiceBranch(StrictBaseModel):
label: Optional[str] = None
icon: Optional[str] = None
steps: List["CanonicalStep"]
class ChooseOneStep(StepBase):
kind: Literal["choose_one"] = "choose_one"
choose: Literal["one"] = "one"
target: Optional[str] = None
branches: List[ChoiceBranch]
store_as: Optional[str] = None
class RepeatStep(StepBase):
kind: Literal["repeat"] = "repeat"
times: Optional[ValueExpr] = None
while_condition: Optional[ConditionStep] = None
body: List["CanonicalStep"]
CanonicalStep = Annotated[
Union[CostStep, ConditionStep, EffectStep, SelectStep, AssignStep, IfStep, ChooseOneStep, RepeatStep],
Field(discriminator="kind"),
]
class CanonicalAbilityModel(StrictBaseModel):
schema_version: Literal["v0"] = "v0"
trigger: str
once_per_turn: bool = False
pseudocode: str = ""
raw_text: str = ""
confidence: Literal["high", "medium", "low"] = "medium"
review_reasons: List[str] = Field(default_factory=list)
steps: List[CanonicalStep]
CanonicalAbilityAdapter = TypeAdapter(CanonicalAbilityModel)
def parse_canonical_ability_model(data: Dict[str, Any]) -> CanonicalAbilityModel:
return CanonicalAbilityAdapter.validate_python(data)
ReferenceExpr.model_rebuild()
LiteralExpr.model_rebuild()
BinaryExpr.model_rebuild()
ConditionStep.model_rebuild()
IfStep.model_rebuild()
ChoiceBranch.model_rebuild()
ChooseOneStep.model_rebuild()
RepeatStep.model_rebuild()
CanonicalAbilityModel.model_rebuild()