Skip to main content

cardinal_kernel/rules/
schema.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
4pub struct Ruleset {
5    pub game: GameInfo,
6    pub players: PlayerRules,
7    pub zones: Vec<ZoneDef>,
8    pub resources: Vec<ResourceDef>,
9    pub turn: TurnStructure,
10    pub actions: Vec<ActionDef>,
11    pub stack: StackRules,
12    pub trigger_kinds: Vec<TriggerKind>,
13    pub keywords: Vec<Keyword>,
14    pub win_conditions: Vec<WinCondition>,
15    pub loss_conditions: Vec<LossCondition>,
16    #[serde(default)]
17    pub cards: Vec<CardDef>,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct GameInfo {
22    pub id: String,
23    pub name: String,
24    pub version: String,
25    pub description: String,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct PlayerRules {
30    pub min_players: usize,
31    pub max_players: usize,
32    pub starting_life: i32,
33    pub max_life: i32,
34    pub starting_hand_size: usize,
35    pub max_hand_size: usize,
36    pub min_deck_size: usize,
37    pub max_deck_size: usize,
38    pub mulligan_rule: String,
39    pub first_player_rule: String,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct ZoneDef {
44    pub id: String,
45    pub name: String,
46    pub owner_scope: ZoneOwnerScope,
47    pub visibility: ZoneVisibility,
48    pub ordered: bool,
49    pub allow_duplicates: bool,
50    pub default_capacity: Option<usize>,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize)]
54#[serde(rename_all = "lowercase")]
55pub enum ZoneOwnerScope {
56    Player,
57    Shared,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(rename_all = "lowercase")]
62pub enum ZoneVisibility {
63    Public,
64    Private,
65    TopCardPublic,
66}
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct ResourceDef {
70    pub id: String,
71    pub name: String,
72    pub description: String,
73    pub min_value: i32,
74    pub max_value: i32,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct TurnStructure {
79    pub priority_system: bool,
80    pub skip_first_turn_draw_for_first_player: bool,
81    pub phases: Vec<PhaseDef>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct PhaseDef {
86    pub id: String,
87    pub name: String,
88    pub order: usize,
89    pub allow_actions: bool,
90    pub steps: Vec<StepDef>,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct StepDef {
95    pub id: String,
96    pub name: String,
97    pub order: usize,
98    pub allow_actions: bool,
99    pub allow_triggers: bool,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct ActionDef {
104    pub id: String,
105    pub name: String,
106    pub description: String,
107    pub source_zones: Option<Vec<String>>,
108    pub target_zone: Option<String>,
109    pub speed: Option<String>,
110    #[serde(default)]
111    pub requires_empty_stack: bool,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct StackRules {
116    pub enabled: bool,
117    pub resolve_order: String,
118    pub auto_resolve_on_pass: bool,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct TriggerKind {
123    pub id: String,
124    pub description: String,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize)]
128pub struct Keyword {
129    pub id: String,
130    pub name: String,
131    pub description: String,
132}
133
134#[derive(Debug, Clone, Serialize, Deserialize)]
135pub struct WinCondition {
136    pub id: String,
137    pub description: String,
138    pub priority: usize,
139}
140
141#[derive(Debug, Clone, Serialize, Deserialize)]
142pub struct LossCondition {
143    pub id: String,
144    pub description: String,
145    pub priority: usize,
146}
147
148/// Card definition: metadata and abilities for a playable card
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct CardDef {
151    /// Unique card identifier (can be string or number)
152    pub id: String,
153    /// Card name for display
154    pub name: String,
155    /// Card type (e.g., "creature", "spell", "enchantment")
156    pub card_type: String,
157    /// Cost to play (could be mana, resources, etc)
158    pub cost: Option<String>,
159    /// Card text / description
160    pub description: Option<String>,
161    /// Abilities this card has (triggered effects)
162    #[serde(default)]
163    pub abilities: Vec<CardAbility>,
164    /// Optional path to Rhai script file for scripted behavior
165    #[serde(default)]
166    pub script_path: Option<String>,
167    /// Keywords this card has (must reference keyword IDs from rules.keywords)
168    #[serde(default)]
169    pub keywords: Vec<String>,
170    /// Card stats (e.g., power/toughness for creatures, generic key-value pairs)
171    #[serde(default)]
172    pub stats: std::collections::HashMap<String, String>,
173}
174
175/// An ability on a card that can be triggered
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub struct CardAbility {
178    /// What triggers this ability (e.g., "etb", "on_play", "on_damage")
179    pub trigger: String,
180    /// What effect to execute (e.g., "damage_2", "draw_1", "pump_1_1")
181    pub effect: String,
182    /// Optional parameters for the effect (e.g., amount, target)
183    #[serde(default)]
184    pub params: std::collections::HashMap<String, String>,
185}