cardinal_kernel/engine/
init.rs1use crate::{
2 state::gamestate::GameState,
3 util::rng::GameRng,
4 ids::{CardId, PlayerId},
5 rules::schema::Ruleset,
6};
7
8pub fn initialize_game(
14 mut state: GameState,
15 rules: &Ruleset,
16 seed: u64,
17) -> GameState {
18 let mut rng = GameRng::new(seed);
19 let num_players = state.players.len() as u32;
20
21 for i in 0..num_players {
23 let player_id = PlayerId(i as u8);
24 shuffle_player_deck(&mut state, player_id, &mut rng, rules);
25 }
26
27 let first_player = determine_first_player(&rules.players.first_player_rule, num_players, &mut rng);
29 state.turn.active_player = first_player;
30 state.turn.priority_player = first_player;
31
32 let skip_first_draw = rules.turn.skip_first_turn_draw_for_first_player;
34 for i in 0..num_players {
35 let player_id = PlayerId(i as u8);
36 let should_skip = skip_first_draw && player_id == first_player;
37
38 if !should_skip {
39 draw_cards(&mut state, player_id, rules.players.starting_hand_size as u32, rules);
40 }
41 }
42
43 state
44}
45
46fn shuffle_player_deck(
48 state: &mut GameState,
49 player: PlayerId,
50 rng: &mut GameRng,
51 _rules: &Ruleset,
52) {
53 let deck_zone_id_string = format!("deck@{}", player.0);
55 let deck_zone = state.zones.iter_mut()
56 .find(|z| z.id.0 == deck_zone_id_string);
57
58 if let Some(zone) = deck_zone {
59 for i in (1..zone.cards.len()).rev() {
61 let j: usize = rng.generate::<u32>() as usize % (i + 1);
62 zone.cards.swap(i, j);
63 }
64 }
65}
66
67fn determine_first_player(
69 rule: &str,
70 num_players: u32,
71 rng: &mut GameRng,
72) -> PlayerId {
73 match rule {
74 "random" => {
75 let idx: u32 = rng.generate::<u32>() % num_players;
76 PlayerId(idx as u8)
77 }
78 "player_0" | "first" => PlayerId(0),
79 "player_1" | "second" => {
80 if num_players > 1 {
81 PlayerId(1)
82 } else {
83 PlayerId(0)
84 }
85 }
86 _ => {
87 let idx: u32 = rng.generate::<u32>() % num_players;
89 PlayerId(idx as u8)
90 }
91 }
92}
93
94fn draw_cards(
96 state: &mut GameState,
97 player: PlayerId,
98 count: u32,
99 rules: &Ruleset,
100) {
101 let deck_zone_id_string = format!("deck@{}", player.0);
102 let hand_zone_id_string = format!("hand@{}", player.0);
103
104 let deck_cards: Vec<CardId> = state.zones.iter()
106 .find(|z| z.id.0 == deck_zone_id_string)
107 .map(|z| z.cards.clone())
108 .unwrap_or_default();
109
110 let cards_to_draw = deck_cards.iter()
112 .take(count as usize)
113 .cloned()
114 .collect::<Vec<_>>();
115
116 if let Some(deck_zone) = state.zones.iter_mut()
118 .find(|z| z.id.0 == deck_zone_id_string)
119 {
120 for _ in 0..cards_to_draw.len() {
121 if !deck_zone.cards.is_empty() {
122 deck_zone.cards.remove(0);
123 }
124 }
125 }
126
127 if let Some(hand_zone) = state.zones.iter_mut()
129 .find(|z| z.id.0 == hand_zone_id_string)
130 {
131 for card in cards_to_draw {
132 if hand_zone.cards.len() < rules.players.max_hand_size {
133 hand_zone.cards.push(card);
134 }
135 }
136 }
137}