From 002c0ba37cc6bc8685543e425fb75eadbb75a7fa Mon Sep 17 00:00:00 2001 From: tali Date: Tue, 11 Apr 2023 12:17:44 -0400 Subject: [PATCH] shrimplify: remove "capabilities" interface this is also going to be reassessed later --- fish/src/ai.rs | 4 +- fish/src/bin/cli.rs | 2 +- fish/src/find.rs | 105 +++++++++++++++----------------------------- 3 files changed, 38 insertions(+), 73 deletions(-) diff --git a/fish/src/ai.rs b/fish/src/ai.rs index bd4b9b1..fa389c2 100644 --- a/fish/src/ai.rs +++ b/fish/src/ai.rs @@ -12,7 +12,7 @@ use alloc::vec::Vec; use bumpalo::Bump; use crate::eval::evaluate; -use crate::find::{cap::All, find_locations}; +use crate::find::find_locations; use self::search::ModifiedAStar; @@ -81,7 +81,7 @@ impl search::Graph for Graph { self.children_buf.clear(); for ty in node.queue.current() { - for loc in find_locations(&node.mat, ty, All) { + for loc in find_locations(&node.mat, ty) { let piece = Piece { ty, loc }; let node = node.succ(self.arena, piece); self.children_buf.push(node); diff --git a/fish/src/bin/cli.rs b/fish/src/bin/cli.rs index 9b85580..eca70ea 100644 --- a/fish/src/bin/cli.rs +++ b/fish/src/bin/cli.rs @@ -94,7 +94,7 @@ fn list_moves() -> anyhow::Result<()> { let front = input.queue.previews.get(0).copied(); let hold = input.queue.hold; for ty in [front, hold].into_iter().flatten() { - for loc in fish::find_locations(&mat, ty, fish::find::cap::All) { + for loc in fish::find_locations(&mat, ty) { output.moves.push(fish::io::OutputMove { location: mino::Piece { ty, loc }.into(), spin: fish::io::Spin::None, diff --git a/fish/src/find.rs b/fish/src/find.rs index a6d6bdd..a939b35 100644 --- a/fish/src/find.rs +++ b/fish/src/find.rs @@ -9,53 +9,25 @@ use mino::{input, Loc, Mat, Movement, Piece}; // Generic arguments legend // ======================== // - T: piece type (e.g. srs::PieceType) -// - C: capabilities (e.g. cap::All) // - 'm: matrix lifetime // - 'c: T::cells() lifetime // - 'k: T::kicks() lifetime // - 'a: general purpose lifetime -/// Helper function to just yield all of the locations reachable on `matrix` for the shape -/// `shape`, given input capabilities `capabilities`. -pub fn find_locations<'a, 'c, 'k, T, C>( - matrix: &'a Mat, - piece_ty: T, - capabilities: C, -) -> FindLocations +static ALL_INPUTS: &[Movement] = &[ + Movement::LEFT, + Movement::RIGHT, + Movement::CW, + Movement::CCW, + Movement::FLIP, +]; + +/// Yields all of the locations reachable by the given peice on the given matrix. +pub fn find_locations<'a, 'c, 'k, T>(matrix: &'a Mat, piece_ty: T) -> FindLocations where T: Shape<'c> + Kicks<'k> + Spawn + Clone + 'a, - C: Capabilities + 'a, { - FindLocations::new(matrix, piece_ty, capabilities) -} - -/// Interface to describe what inputs the location finder is capable of performing in -/// order to reach target locations. This can be used, for instance, to prevent soft-drops -/// or 180 spins. -pub trait Capabilities { - /// Iterator type returned by `all_inputs`. - type InputsIter: IntoIterator; - - /// Returns a list of all of the inputs that can be performed. - fn all_inputs(&self) -> Self::InputsIter; - - // TODO: flags for soft drop or kicks -} - -/// Different implementations of the `Capabilities` trait. -pub mod cap { - use super::Capabilities; - use mino::Movement; - - /// Find all possible reachable locations; no restrictions. - pub struct All; - - impl Capabilities for All { - type InputsIter = [Movement; 4]; - fn all_inputs(&self) -> Self::InputsIter { - [Movement::LEFT, Movement::RIGHT, Movement::CW, Movement::CCW] - } - } + FindLocations::new(matrix, piece_ty) } /// Algorithm used to search for reachable locations on a given board state. The current @@ -64,45 +36,37 @@ pub mod cap { /// /// [`FindLocations`] is an [`Iterator`], so you can use that interface to obtain the next /// available location or loop over all of them. -pub struct FindLocations<'m, T, C> { +pub struct FindLocations<'m, T> { matrix: &'m Mat, piece_ty: T, - capabilities: C, // TODO: allow these two collections to be extracted and reused stack: Vec, visited: HashSet>, } -impl<'m, 'c, 'k, T, C> FindLocations<'m, T, C> +impl<'m, 'c, 'k, T> FindLocations<'m, T> where T: Shape<'c> + Kicks<'k> + Spawn + Clone, - C: Capabilities, { /// Constructs a new instance of the location finding algorithm. - pub fn new(matrix: &'m Mat, piece_ty: T, capabilities: C) -> Self { - let mut this = Self { + fn new(matrix: &'m Mat, piece_ty: T) -> Self { + // TODO: use with_capacity + let mut stack = Vec::default(); + let mut visited = HashSet::default(); + + let init_pc = Piece::spawn(piece_ty.clone()); + let game_over = init_pc.cells().intersects(matrix); + if !game_over { + stack.push(init_pc.loc); + visited.insert(init_pc.loc); + } + + Self { matrix, piece_ty, - capabilities, - // TODO: set initial capacity - stack: Vec::default(), - visited: HashSet::default(), - }; - this.init(); - this - } - - fn init(&mut self) { - self.stack.clear(); - self.visited.clear(); - // self.stats.max_height = 0; - - let init_pc = Piece::spawn(self.piece_ty.clone()); - if init_pc.cells().intersects(self.matrix) { - // game over - return; + stack, + visited, } - self.push(init_pc.loc); } fn push(&mut self, loc: Loc) { @@ -119,17 +83,18 @@ where } } -impl<'m, 'c, 'k, T, C> Iterator for FindLocations<'m, T, C> +impl<'m, 'c, 'k, T> Iterator for FindLocations<'m, T> where T: Shape<'c> + Kicks<'k> + Spawn + Clone, - C: Capabilities, { type Item = Loc; fn next(&mut self) -> Option { while let Some(pc0) = self.pop() { + // TODO: configure capabilities, e.g. is 180 enabled, are kicks enabled + // push all locations reachable by performing an input - for inp in self.capabilities.all_inputs() { + for &inp in ALL_INPUTS.iter() { let mut pc = pc0.clone(); if inp.perform(&mut pc, self.matrix) { self.push(pc.loc); @@ -150,8 +115,8 @@ where } } -impl<'m, 'c, 'k, T: Shape<'c> + Kicks<'k> + Spawn + Clone, C: Capabilities> - core::iter::FusedIterator for FindLocations<'m, T, C> +impl<'m, 'c, 'k, T: Shape<'c> + Kicks<'k> + Spawn + Clone> core::iter::FusedIterator + for FindLocations<'m, T> { // CORRECTNESS: once `self.stack` is empty, `next()` will always return `None`. } @@ -185,7 +150,7 @@ mod test { Loc: From, { let expected = expected.into_iter().map(Loc::from).collect::>(); - let found = find_locations(matrix, ty, cap::All).collect::>(); + let found = find_locations(matrix, ty).collect::>(); if let Some(exp) = find_missing(ty, &expected, &found) { panic!("{exp:?} expected but not found"); } else if let Some(fnd) = find_missing(ty, &found, &expected) {