diff --git a/Cargo.lock b/Cargo.lock index a5f1a0d..5a699ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,9 +484,12 @@ dependencies = [ name = "tidepool" version = "0.1.0" dependencies = [ + "fish", "mino", "rand", "rand_xoshiro", + "tracing", + "tracing-subscriber", ] [[package]] @@ -497,9 +500,21 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.30" diff --git a/tidepool/Cargo.toml b/tidepool/Cargo.toml index a005240..1450ef9 100644 --- a/tidepool/Cargo.toml +++ b/tidepool/Cargo.toml @@ -6,5 +6,10 @@ edition = "2021" [dependencies] mino = { path = "../mino" } +fish = { path = "../fish" } + rand = "0.8" -rand_xoshiro = "0.6" \ No newline at end of file +rand_xoshiro = "0.6" + +tracing = { version = "0.1" } +tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"]} diff --git a/tidepool/src/main.rs b/tidepool/src/main.rs new file mode 100644 index 0000000..75f6a07 --- /dev/null +++ b/tidepool/src/main.rs @@ -0,0 +1,91 @@ +use fish::ai; +use rand::Rng as _; +use tidepool::sim; + +struct RngSeed([u8; 32]); + +impl rand::distributions::Distribution for rand::distributions::Standard { + fn sample(&self, rng: &mut R) -> RngSeed { + RngSeed(self.sample(rng)) + } +} + +impl std::fmt::Display for RngSeed { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.iter().try_for_each(|&b| write!(f, "{b:02x}")) + } +} + +pub fn main() -> std::io::Result<()> { + const AI_CYCLES: usize = 5_000; + const GOAL: usize = 50; + + tracing_subscriber::fmt::fmt() + .with_writer(std::io::stderr) + .with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env()) + .init(); + + let seed = rand::thread_rng().gen::(); + println!("using seed: {seed}"); + + let mut sim = sim::Simul::new(seed.0, sim::Options::jstris(GOAL)); + + let mut ds = 0; + let mut ps = 0; + + loop { + let (hold, next) = sim.queue(); + let hold_str = hold.map_or("", |p| p.name()); + let next_str = next.iter().map(|p| p.as_char()).collect::(); + println!("Q: [{hold_str}]{next_str}"); + + let mat = sim.matrix(); + for y in (0..mat.rows() + 1).rev() { + print!("{y:2} |"); + for x in 0..10 { + print!("{}", if mat.get(x, y) { '#' } else { '.' }); + } + println!(); + } + + let ll = sim.lines_left(); + + let mut ai = ai::Ai::new(mat, &next, hold); + for i in 0..AI_CYCLES { + if i > 0 && i % 1000 == 0 { + tracing::debug!("iteration {i}"); + } + + if ai.think().is_err() { + break; + } + } + + let mut best = ai.suggestion(); + let best = best.nth(0); + + if let Some(pc) = best { + sim.play(pc); + } else { + println!("no suggestion!"); + break; + } + + ds += ll - sim.lines_left(); + ps += 1; + print!("#{ps}, ds: {ds}"); + if ds > 0 { + print!(", ppd: {:.2}", ps as f64 / ds as f64); + } + println!(); + + if ll == 0 { + break; + } + } + + println!(); + println!("pieces: {ps}"); + + Ok(()) +}