Add MatBuf::fill_row(), Piece::fill()

This commit is contained in:
tali 2022-12-18 19:15:47 -05:00
parent 21f6b25de0
commit 4240c91a34
2 changed files with 100 additions and 8 deletions

View File

@ -178,12 +178,8 @@ where
data[..self.rows].copy_from_slice(mat.data());
}
/// Fills in the cell at the given (x,y) coordinate. Adds new rows to the top of the
/// matrix if necessary.
///
/// Panics if the buffer space cannot fit the new rows.
pub fn set(&mut self, x: i16, y: i16) {
if y < 0 || !(0..COLUMNS).contains(&x) {
pub fn fill_row(&mut self, y: i16, mask: u16) {
if y < 0 {
// OOB coordinates are considered already set
return;
}
@ -195,7 +191,18 @@ where
.expect("y should be within available buffer space") = EMPTY_ROW;
self.rows += 1;
}
data[y] |= 1 << x;
data[y] |= mask;
}
/// Fills in the cell at the given (x,y) coordinate. Adds new rows to the top of the
/// matrix if necessary.
///
/// Panics if the buffer space cannot fit the new rows.
#[inline]
pub fn set(&mut self, x: i16, y: i16) {
if (0..COLUMNS).contains(&x) {
self.fill_row(y, 1 << x);
}
}
/// Removes any rows that are completely filled, shifting rows above down. Returns a
@ -378,10 +385,37 @@ mod test {
assert_eq!(buf, mat);
}
#[test]
fn test_fill() {
let mut buf: MatBuf<[u16; 5]> = MatBuf::new();
buf.fill_row(1, 0b110111); // a
let mat = mat! {
"aaa.aa....";
"..........";
};
assert_eq!(buf, mat);
buf.fill_row(3, 0b1000000000); // b
buf.fill_row(0, u16::MAX); // c
let mat = mat! {
".........b";
"..........";
"aaa.aa....";
"cccccccccc";
};
assert_eq!(buf, mat);
}
#[test]
#[should_panic]
fn test_set_oob() {
let mut buf: MatBuf<[u16; 4]> = MatBuf::new();
buf.set(0, 4);
}
#[test]
#[should_panic]
fn test_fill_oob() {
let mut buf: MatBuf<[u16; 4]> = MatBuf::new();
buf.fill_row(4, 0b1001);
}
}

View File

@ -1,6 +1,6 @@
//! Data structures for representing pieces and shapes.
use crate::matrix::Mat;
use crate::matrix::{Mat, MatBuf};
use core::ops::Range;
@ -150,6 +150,23 @@ impl<'c> Cells<'c> {
false
}
/// Fills in all of the cells onto the given matrix. Panics if the piece is out of
/// bounds.
pub fn fill<T>(&self, mat: &mut MatBuf<T>)
where
T: AsRef<[u16]> + AsMut<[u16]>,
{
assert!(
self.x >= 0 && self.x + self.w <= mat.cols() && self.y >= 0,
"fill() cells oob"
);
for (dy, &row) in self.data().iter().enumerate() {
let y = self.y + dy as i16;
let mask = row << self.x; // should never overflow
mat.fill_row(y, mask);
}
}
/// Translates the cells by the given amount in both directions.
#[inline]
pub fn translate(&self, dx: i16, dy: i16) -> Self {
@ -330,4 +347,45 @@ pub mod test {
assert_eq!(isects(1..=9, 2, W), [__, __, __, __, __, __, __, __, xx]);
assert_eq!(isects(1..=9, 3, W), [__; 9]);
}
fn filled<I>(locs: I) -> MatBuf
where
I: IntoIterator,
Loc: From<I::Item>,
{
let mut mat = MatBuf::new();
for loc in locs {
let piece = Piece {
ty: Tri,
loc: loc.into(),
};
piece.cells().fill(&mut mat);
}
mat
}
#[test]
fn test_fill() {
let act = filled([(0, 0)]);
let exp = mat! {
"x.........";
"xx........";
};
assert_eq!(act, exp);
let act = filled([(1, 1, Rot::N), (5, 0, Rot::W)]);
let exp = mat! {
".n........";
".nn..w....";
"....ww....";
};
assert_eq!(act, exp);
let act = filled([(1, 1, Rot::S), (1, 1, Rot::E)]);
let exp = mat! {
"sxe.......";
".x........";
};
assert_eq!(act, exp);
}
}