cardinal_kernel/state/
gamestate.rs1use crate::ids::{PlayerId, ZoneId, PhaseId, StepId, CardId};
2use crate::model::command::{PendingChoice, StackItem};
3use crate::rules::schema::Ruleset;
4
5#[derive(Debug, Clone)]
6pub struct GameState {
7 pub turn: TurnState,
8 pub players: Vec<PlayerState>,
9 pub zones: Vec<ZoneState>,
10 pub stack: Vec<StackItem>,
11 pub pending_choice: Option<PendingChoice>,
12 pub ended: Option<GameEnd>,
13}
14
15#[derive(Debug, Clone)]
16pub struct TurnState {
17 pub number: u32,
18 pub active_player: PlayerId,
19 pub priority_player: PlayerId,
20 pub phase: PhaseId,
21 pub step: StepId,
22 pub priority_passes: u32, }
24
25#[derive(Debug, Clone)]
26pub struct PlayerState {
27 pub id: PlayerId,
28 pub life: i32,
29 }
31
32#[derive(Debug, Clone)]
33pub struct ZoneState {
34 pub id: ZoneId,
35 pub owner: Option<PlayerId>, pub cards: Vec<CardId>,
37}
38
39#[derive(Debug, Clone)]
40pub struct GameEnd {
41 pub winner: Option<PlayerId>,
42 pub reason: String,
43}
44
45impl GameState {
46 pub fn from_ruleset(rules: &Ruleset) -> Self {
49 let min_players = rules.players.min_players as usize;
50 let mut players = Vec::new();
51 for i in 0..min_players {
52 players.push(PlayerState { id: PlayerId(i as u8), life: rules.players.starting_life });
53 }
54
55 let mut zones = Vec::new();
57 for z in &rules.zones {
58 match z.owner_scope {
59 crate::rules::schema::ZoneOwnerScope::Player => {
60 for i in 0..min_players {
61 let zid_string = format!("{}@{}", z.id, i);
62 let boxed = zid_string.into_boxed_str();
63 let static_str: &'static str = Box::leak(boxed);
64 zones.push(ZoneState { id: ZoneId(static_str), owner: Some(PlayerId(i as u8)), cards: Vec::new() });
65 }
66 }
67 crate::rules::schema::ZoneOwnerScope::Shared => {
68 let boxed = z.id.clone().into_boxed_str();
69 let static_str: &'static str = Box::leak(boxed);
70 zones.push(ZoneState { id: ZoneId(static_str), owner: None, cards: Vec::new() });
71 }
72 }
73 }
74
75 let (phase_id, step_id) = if let Some(first_phase) = rules.turn.phases.first() {
77 let ph_box: Box<str> = first_phase.id.clone().into_boxed_str();
78 let ph_static: &'static str = Box::leak(ph_box);
79 if let Some(first_step) = first_phase.steps.first() {
80 let st_box: Box<str> = first_step.id.clone().into_boxed_str();
81 let st_static: &'static str = Box::leak(st_box);
82 (PhaseId(ph_static), StepId(st_static))
83 } else {
84 (PhaseId(ph_static), StepId("start"))
85 }
86 } else {
87 (PhaseId("start"), StepId("untap"))
88 };
89
90 GameState {
91 turn: TurnState { number: 1, active_player: PlayerId(0), priority_player: PlayerId(0), phase: phase_id, step: step_id, priority_passes: 0 },
92 players,
93 zones,
94 stack: Vec::new(),
95 pending_choice: None,
96 ended: None,
97 }
98 }
99}