1use crate::db::CardId;
2use serde::{Deserialize, Serialize};
3use std::collections::HashSet;
4
5#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
6pub enum ErrorPolicy {
7 Strict,
8 #[default]
9 LenientTerminate,
10 LenientNoop,
11}
12
13#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
14pub enum ObservationVisibility {
15 #[default]
16 Public,
17 Full,
18}
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
21pub struct RewardConfig {
22 pub terminal_win: f32,
23 pub terminal_loss: f32,
24 pub terminal_draw: f32,
25 pub enable_shaping: bool,
26 pub damage_reward: f32,
27}
28
29impl Default for RewardConfig {
30 fn default() -> Self {
31 Self {
32 terminal_win: 1.0,
33 terminal_loss: -1.0,
34 terminal_draw: 0.0,
35 enable_shaping: false,
36 damage_reward: 0.1,
37 }
38 }
39}
40
41#[derive(Clone, Debug, Serialize, Deserialize)]
42pub struct EnvConfig {
43 pub deck_lists: [Vec<CardId>; 2],
44 pub deck_ids: [u32; 2],
45 pub max_decisions: u32,
46 pub max_ticks: u32,
47 pub reward: RewardConfig,
48 #[serde(default)]
49 pub error_policy: ErrorPolicy,
50 #[serde(default)]
51 pub observation_visibility: ObservationVisibility,
52 #[serde(default)]
53 pub end_condition_policy: EndConditionPolicy,
54}
55
56impl EnvConfig {
57 pub fn config_hash(&self, curriculum: &CurriculumConfig) -> u64 {
58 crate::fingerprint::config_fingerprint(self, curriculum)
59 }
60}
61
62#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
63pub enum SimultaneousLossPolicy {
64 ActivePlayerWins,
65 NonActivePlayerWins,
66 #[default]
67 Draw,
68}
69
70#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
71pub struct EndConditionPolicy {
72 #[serde(default)]
73 pub simultaneous_loss: SimultaneousLossPolicy,
74 #[serde(default)]
75 pub allow_draw_on_simultaneous_loss: bool,
76}
77
78impl Default for EndConditionPolicy {
79 fn default() -> Self {
80 Self {
81 simultaneous_loss: SimultaneousLossPolicy::Draw,
82 allow_draw_on_simultaneous_loss: true,
83 }
84 }
85}
86
87#[derive(Clone, Debug, Serialize, Deserialize)]
88pub struct CurriculumConfig {
89 #[serde(default)]
90 pub allowed_card_sets: Vec<String>,
91 #[serde(default = "default_true")]
92 pub allow_character: bool,
93 #[serde(default = "default_true")]
94 pub allow_event: bool,
95 #[serde(default = "default_true")]
96 pub allow_climax: bool,
97 #[serde(default = "default_true")]
98 pub enable_clock_phase: bool,
99 #[serde(default = "default_true")]
100 pub enable_climax_phase: bool,
101 #[serde(default = "default_true")]
102 pub enable_side_attacks: bool,
103 #[serde(default = "default_true")]
104 pub enable_direct_attacks: bool,
105 #[serde(default = "default_true")]
106 pub enable_counters: bool,
107 #[serde(default = "default_true")]
108 pub enable_triggers: bool,
109 #[serde(default = "default_true")]
110 pub enable_trigger_soul: bool,
111 #[serde(default = "default_true")]
112 pub enable_trigger_draw: bool,
113 #[serde(default = "default_true")]
114 pub enable_trigger_shot: bool,
115 #[serde(default = "default_true")]
116 pub enable_trigger_bounce: bool,
117 #[serde(default = "default_true")]
118 pub enable_trigger_treasure: bool,
119 #[serde(default = "default_true")]
120 pub enable_trigger_gate: bool,
121 #[serde(default = "default_true")]
122 pub enable_trigger_standby: bool,
123 #[serde(default = "default_true")]
124 pub enable_on_reverse_triggers: bool,
125 #[serde(default = "default_true")]
126 pub enable_backup: bool,
127 #[serde(default = "default_true")]
128 pub enable_encore: bool,
129 #[serde(default = "default_true")]
130 pub enable_refresh_penalty: bool,
131 #[serde(default = "default_true")]
132 pub enable_level_up_choice: bool,
133 #[serde(default = "default_true")]
134 pub enable_activated_abilities: bool,
135 #[serde(default = "default_true")]
136 pub enable_continuous_modifiers: bool,
137 #[serde(default)]
138 pub enable_priority_windows: bool,
139 #[serde(default)]
140 pub enable_visibility_policies: bool,
141 #[serde(default)]
142 pub use_alternate_end_conditions: bool,
143 #[serde(default = "default_true")]
144 pub priority_autopick_single_action: bool,
145 #[serde(default = "default_true")]
146 pub priority_allow_pass: bool,
147 #[serde(default)]
148 pub strict_priority_mode: bool,
149 #[serde(default)]
150 pub reduced_stage_mode: bool,
151 #[serde(default = "default_true")]
152 pub enforce_color_requirement: bool,
153 #[serde(default = "default_true")]
154 pub enforce_cost_requirement: bool,
155 #[serde(default)]
156 pub allow_concede: bool,
157 #[serde(default = "default_true")]
158 pub memory_is_public: bool,
159 #[serde(skip)]
160 pub allowed_card_sets_cache: Option<HashSet<String>>,
161}
162
163impl Default for CurriculumConfig {
164 fn default() -> Self {
165 Self {
166 allowed_card_sets: Vec::new(),
167 allow_character: true,
168 allow_event: true,
169 allow_climax: true,
170 enable_clock_phase: true,
171 enable_climax_phase: true,
172 enable_side_attacks: true,
173 enable_direct_attacks: true,
174 enable_counters: true,
175 enable_triggers: true,
176 enable_trigger_soul: true,
177 enable_trigger_draw: true,
178 enable_trigger_shot: true,
179 enable_trigger_bounce: true,
180 enable_trigger_treasure: true,
181 enable_trigger_gate: true,
182 enable_trigger_standby: true,
183 enable_on_reverse_triggers: true,
184 enable_backup: true,
185 enable_encore: true,
186 enable_refresh_penalty: true,
187 enable_level_up_choice: true,
188 enable_activated_abilities: true,
189 enable_continuous_modifiers: true,
190 enable_priority_windows: false,
191 enable_visibility_policies: false,
192 use_alternate_end_conditions: false,
193 priority_autopick_single_action: true,
194 priority_allow_pass: true,
195 strict_priority_mode: false,
196 reduced_stage_mode: false,
197 enforce_color_requirement: true,
198 enforce_cost_requirement: true,
199 allow_concede: false,
200 memory_is_public: true,
201 allowed_card_sets_cache: None,
202 }
203 }
204}
205
206impl CurriculumConfig {
207 pub fn rebuild_cache(&mut self) {
208 if self.allowed_card_sets.is_empty() {
209 self.allowed_card_sets_cache = None;
210 } else {
211 self.allowed_card_sets_cache = Some(self.allowed_card_sets.iter().cloned().collect());
212 }
213 }
214}
215
216fn default_true() -> bool {
217 true
218}