shrimplify: remove FindLocationsBuffers
we will add some sort of similar functionality back later, after we have performance data to justify it
This commit is contained in:
parent
71efd222eb
commit
7637f892ae
|
@ -12,8 +12,7 @@ use alloc::vec::Vec;
|
|||
use bumpalo::Bump;
|
||||
|
||||
use crate::eval::evaluate;
|
||||
use crate::find::cap::All;
|
||||
use crate::find::{FindLocations, FindLocationsBuffers};
|
||||
use crate::find::{cap::All, find_locations};
|
||||
|
||||
use self::search::ModifiedAStar;
|
||||
|
||||
|
@ -57,7 +56,6 @@ impl Ai {
|
|||
struct Graph {
|
||||
arena: *const Bump,
|
||||
root: Node,
|
||||
find_buf: Option<FindLocationsBuffers>,
|
||||
children_buf: Vec<Node>,
|
||||
}
|
||||
|
||||
|
@ -67,7 +65,6 @@ impl Graph {
|
|||
Self {
|
||||
arena,
|
||||
root,
|
||||
find_buf: None,
|
||||
children_buf: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -84,14 +81,11 @@ impl search::Graph for Graph {
|
|||
self.children_buf.clear();
|
||||
|
||||
for ty in node.queue.current() {
|
||||
let find_buf = self.find_buf.take().unwrap_or_default();
|
||||
let mut locs = FindLocations::with_buffers(&node.mat, ty, All, find_buf);
|
||||
for loc in &mut locs {
|
||||
for loc in find_locations(&node.mat, ty, All) {
|
||||
let piece = Piece { ty, loc };
|
||||
let node = node.succ(self.arena, piece);
|
||||
self.children_buf.push(node);
|
||||
}
|
||||
self.find_buf = Some(locs.into_buffers());
|
||||
}
|
||||
|
||||
tracing::trace!("expanded to create {} children", self.children_buf.len());
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
//! Find locations.
|
||||
|
||||
use alloc::vec::Vec;
|
||||
use core::hash::BuildHasherDefault;
|
||||
use hashbrown::hash_set::HashSet;
|
||||
use mino::input::Kicks;
|
||||
use mino::piece::{Shape, Spawn};
|
||||
|
@ -22,7 +21,7 @@ pub fn find_locations<'a, 'c, 'k, T, C>(
|
|||
matrix: &'a Mat,
|
||||
piece_ty: T,
|
||||
capabilities: C,
|
||||
) -> impl Iterator<Item = Loc> + 'a
|
||||
) -> FindLocations<T, C>
|
||||
where
|
||||
T: Shape<'c> + Kicks<'k> + Spawn + Clone + 'a,
|
||||
C: Capabilities + 'a,
|
||||
|
@ -69,31 +68,9 @@ pub struct FindLocations<'m, T, C> {
|
|||
matrix: &'m Mat,
|
||||
piece_ty: T,
|
||||
capabilities: C,
|
||||
buffers: FindLocationsBuffers,
|
||||
}
|
||||
|
||||
/// Contains the underlying buffers used by `FindLocations`. This structure may be used to
|
||||
/// preallocate space or reuse buffers for multiple runs of the search algorithm.
|
||||
///
|
||||
/// See [`FindLocations::with_buffers`] and [`FindLocations::into_buffers`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FindLocationsBuffers {
|
||||
pub stack: Vec<Loc>,
|
||||
pub visited: HashSet<Loc, BuildHasher>,
|
||||
// TODO: useful for profiling?
|
||||
// pub max_height: usize,
|
||||
}
|
||||
|
||||
type BuildHasher = BuildHasherDefault<ahash::AHasher>;
|
||||
|
||||
impl Default for FindLocationsBuffers {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
stack: Vec::with_capacity(64),
|
||||
visited: HashSet::with_capacity(400),
|
||||
// max_height: 0,
|
||||
}
|
||||
}
|
||||
// TODO: allow these two collections to be extracted and reused
|
||||
stack: Vec<Loc>,
|
||||
visited: HashSet<Loc, core::hash::BuildHasherDefault<ahash::AHasher>>,
|
||||
}
|
||||
|
||||
impl<'m, 'c, 'k, T, C> FindLocations<'m, T, C>
|
||||
|
@ -103,40 +80,22 @@ where
|
|||
{
|
||||
/// Constructs a new instance of the location finding algorithm.
|
||||
pub fn new(matrix: &'m Mat, piece_ty: T, capabilities: C) -> Self {
|
||||
let bufs = FindLocationsBuffers::default();
|
||||
Self::with_buffers(matrix, piece_ty, capabilities, bufs)
|
||||
}
|
||||
|
||||
/// Constructs a new instance of the location finding algorithm. Uses `buffers` for
|
||||
/// storage needed by the algorithm. The buffers will be cleared on initialization so
|
||||
/// it does not matter if they previously contained data.
|
||||
pub fn with_buffers(
|
||||
matrix: &'m Mat,
|
||||
piece_ty: T,
|
||||
capabilities: C,
|
||||
buffers: FindLocationsBuffers,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
matrix,
|
||||
piece_ty,
|
||||
capabilities,
|
||||
buffers,
|
||||
// TODO: set initial capacity
|
||||
stack: Vec::default(),
|
||||
visited: HashSet::default(),
|
||||
};
|
||||
this.init();
|
||||
this
|
||||
}
|
||||
|
||||
/// Aborts the search algorithm and relinquishes ownership of the underlying
|
||||
/// buffers. This is useful for reusing the buffers by passing them to
|
||||
/// [`Self::with_buffers`] the next time the algorithm is run.
|
||||
pub fn into_buffers(self) -> FindLocationsBuffers {
|
||||
self.buffers
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
self.buffers.stack.clear();
|
||||
self.buffers.visited.clear();
|
||||
// self.buffers.max_height = 0;
|
||||
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) {
|
||||
|
@ -148,16 +107,15 @@ where
|
|||
|
||||
fn push(&mut self, loc: Loc) {
|
||||
// 'visited' set prevents cycles
|
||||
if self.buffers.visited.insert(loc) {
|
||||
self.buffers.stack.push(loc);
|
||||
// self.buffers.max_height =
|
||||
// core::cmp::max(self.buffers.max_height, self.buffers.stack.len());
|
||||
if self.visited.insert(loc) {
|
||||
self.stack.push(loc);
|
||||
// self.stats.max_height = max(self.stats.max_height, self.stack.len());
|
||||
}
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<Piece<T>> {
|
||||
let ty = self.piece_ty.clone();
|
||||
self.buffers.stack.pop().map(|loc| Piece { ty, loc })
|
||||
self.stack.pop().map(|loc| Piece { ty, loc })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,6 +125,7 @@ where
|
|||
C: Capabilities,
|
||||
{
|
||||
type Item = Loc;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
while let Some(pc0) = self.pop() {
|
||||
// push all locations reachable by performing an input
|
||||
|
@ -176,11 +135,12 @@ where
|
|||
self.push(pc.loc);
|
||||
}
|
||||
}
|
||||
|
||||
let mut pc = pc0;
|
||||
if input::drop(&mut pc, self.matrix) {
|
||||
// piece was floating, so drop it and analyze that later
|
||||
// TODO: configure capability to do soft drop
|
||||
self.push(pc.loc);
|
||||
// TODO: don't push if soft drops are denied by self.capabilities
|
||||
} else {
|
||||
// piece was not floating so it's a valid final piece location.
|
||||
return Some(pc.loc);
|
||||
|
@ -193,7 +153,7 @@ where
|
|||
impl<'m, 'c, 'k, T: Shape<'c> + Kicks<'k> + Spawn + Clone, C: Capabilities>
|
||||
core::iter::FusedIterator for FindLocations<'m, T, C>
|
||||
{
|
||||
// When `buffers.stack` is empty, the iterator will constanty return `None`.
|
||||
// CORRECTNESS: once `self.stack` is empty, `next()` will always return `None`.
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
Loading…
Reference in New Issue