diff --git a/card_game/src/lib.rs b/card_game/src/lib.rs index 1613142..40193da 100644 --- a/card_game/src/lib.rs +++ b/card_game/src/lib.rs @@ -321,6 +321,9 @@ impl SessionStats { } } +#[derive(Debug)] +pub struct Oom; + #[derive(Clone, Debug)] pub struct Session { stats: SessionStats, @@ -402,10 +405,15 @@ where pub fn is_win(&self) -> bool { self.state.is_win() } - pub fn is_winnable(&self) -> Option>> { - let mut state_moves = std::collections::HashMap::new(); + pub fn is_winnable(&self) -> Result>>, Oom> { + const HUGE_CAP: usize = 1 << 25; + let mut state_moves = std::collections::HashMap::with_capacity(HUGE_CAP); let mut state = self.clone(); while !state.is_win() { + if HUGE_CAP <= state_moves.len() { + return Err(Oom); + } + // Continue existing iterator if it exists let it = state_moves .entry(state.state().clone()) @@ -419,7 +427,7 @@ where // No more moves. If we can't undo we're done if state.history().is_empty() { - return None; + return Ok(None); } else { state.undo(); } @@ -451,7 +459,7 @@ where } } - Some(state.state.history) + Ok(Some(state.state.history)) } } impl Game for SessionState diff --git a/klondike-cli/src/test.rs b/klondike-cli/src/test.rs index 9e0229b..445f338 100644 --- a/klondike-cli/src/test.rs +++ b/klondike-cli/src/test.rs @@ -3,7 +3,7 @@ use klondike::Klondike; #[test] fn test_is_winnable() { // is winnable - let is_winnable = Session::new_default(Klondike::with_seed(124)).is_winnable(); + let is_winnable = Session::new_default(Klondike::with_seed(0)).is_winnable().unwrap(); if let Some(win_moves) = is_winnable { // for (i, ins) in win_moves.into_iter().enumerate() { // println!("{i} = {:?}", ins.instruction());