Move Loc, Rot types to inside piece.rs
This commit is contained in:
parent
c5ca155ad2
commit
2dc972c756
|
@ -1,11 +1,10 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub mod location;
|
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod piece;
|
pub mod piece;
|
||||||
|
|
||||||
pub use location::Loc;
|
|
||||||
pub use matrix::Mat;
|
pub use matrix::Mat;
|
||||||
|
pub use piece::{Loc, Piece, Rot};
|
||||||
|
|
||||||
#[cfg(feature = "srs")]
|
#[cfg(feature = "srs")]
|
||||||
pub mod srs;
|
pub mod srs;
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
//! Data structures and operations for representing piece locations and rotations.
|
|
||||||
|
|
||||||
/// Represents a location for a piece, including its orientation.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
||||||
pub struct Loc {
|
|
||||||
/// Horizontal coordinate.
|
|
||||||
pub x: i16,
|
|
||||||
/// Vertical coordinate.
|
|
||||||
pub y: i16,
|
|
||||||
/// Rotation state.
|
|
||||||
pub r: Rot,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a rotation state for a piece. The initial state is "north" (`N`), and there
|
|
||||||
/// are 4 total orientations to represent each 90 degree turn possible.
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default)]
|
|
||||||
#[repr(i8)]
|
|
||||||
pub enum Rot {
|
|
||||||
/// North. The initial state.
|
|
||||||
#[default]
|
|
||||||
N = 0,
|
|
||||||
/// Clockwise ("cw") from north.
|
|
||||||
E = 1,
|
|
||||||
/// Two rotations in any direction from north.
|
|
||||||
S = 2,
|
|
||||||
/// Counterclockwise ("ccw") from north.
|
|
||||||
W = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<i8> for Rot {
|
|
||||||
#[inline]
|
|
||||||
fn from(v: i8) -> Self {
|
|
||||||
unsafe { core::mem::transmute(v & 3) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents a rotating operation. Includes 180 degree "flips", which are non-standard
|
|
||||||
/// for tetris but exist in many unofficial iterations of the game.
|
|
||||||
///
|
|
||||||
/// Rotations may be performed on [rotation states](Rot) using the [addition
|
|
||||||
/// operator](core::ops::Add).
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use mino::location::{Rot, Spin};
|
|
||||||
/// assert_eq!(Rot::N + Spin::Cw, Rot::E);
|
|
||||||
/// ```
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
|
|
||||||
#[repr(i8)]
|
|
||||||
pub enum Spin {
|
|
||||||
/// Clockwise.
|
|
||||||
Cw = 1,
|
|
||||||
/// 180 degrees.
|
|
||||||
Flip = 2,
|
|
||||||
/// Counterclockwise.
|
|
||||||
Ccw = 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::Add<Spin> for Rot {
|
|
||||||
type Output = Rot;
|
|
||||||
fn add(self, r: Spin) -> Rot {
|
|
||||||
(self as i8).wrapping_add(r as i8).into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::ops::AddAssign<Spin> for Rot {
|
|
||||||
fn add_assign(&mut self, r: Spin) {
|
|
||||||
*self = *self + r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_angle_rotate() {
|
|
||||||
use Rot::*;
|
|
||||||
use Spin::*;
|
|
||||||
assert_eq!(N + Cw, E);
|
|
||||||
assert_eq!(N + Ccw, W);
|
|
||||||
assert_eq!(N + Flip, S);
|
|
||||||
assert_eq!(E + Cw, S);
|
|
||||||
assert_eq!(E + Ccw, N);
|
|
||||||
assert_eq!(E + Flip, W);
|
|
||||||
assert_eq!(S + Cw, W);
|
|
||||||
assert_eq!(S + Ccw, E);
|
|
||||||
assert_eq!(S + Flip, N);
|
|
||||||
assert_eq!(W + Cw, N);
|
|
||||||
assert_eq!(W + Ccw, S);
|
|
||||||
assert_eq!(W + Flip, E);
|
|
||||||
|
|
||||||
let mut r = N;
|
|
||||||
r += Ccw;
|
|
||||||
assert_eq!(r, W);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_angle_from_i8() {
|
|
||||||
let mut r = Rot::N;
|
|
||||||
for i in 0i8..=127 {
|
|
||||||
assert_eq!(r, i.into(), "i={i}");
|
|
||||||
r += Spin::Cw;
|
|
||||||
}
|
|
||||||
r = Rot::N;
|
|
||||||
for i in (-128i8..=-1).rev() {
|
|
||||||
r += Spin::Ccw;
|
|
||||||
assert_eq!(r, i.into(), "i={i}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +1,43 @@
|
||||||
//! Data structures for representing pieces and shapes.
|
//! Data structures for representing pieces and shapes.
|
||||||
|
|
||||||
use crate::location::{Loc, Rot, Spin};
|
|
||||||
use crate::matrix::Mat;
|
use crate::matrix::Mat;
|
||||||
|
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
|
||||||
|
/// Represents a location for a piece, including its orientation.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
|
pub struct Loc {
|
||||||
|
/// Horizontal coordinate.
|
||||||
|
pub x: i16,
|
||||||
|
/// Vertical coordinate.
|
||||||
|
pub y: i16,
|
||||||
|
/// Rotation state.
|
||||||
|
pub r: Rot,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents a rotation state for a piece. The initial state is "north" (`N`), and there
|
||||||
|
/// are 4 total orientations to represent each 90 degree turn possible.
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Default)]
|
||||||
|
#[repr(i8)]
|
||||||
|
pub enum Rot {
|
||||||
|
/// North; the initial state.
|
||||||
|
#[default]
|
||||||
|
N = 0,
|
||||||
|
/// East; clockwise ("cw") from north.
|
||||||
|
E = 1,
|
||||||
|
/// South; two rotations in any direction from north.
|
||||||
|
S = 2,
|
||||||
|
/// West; counterclockwise ("ccw") from north.
|
||||||
|
W = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i8> for Rot {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: i8) -> Self {
|
||||||
|
unsafe { core::mem::transmute(v & 3) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Interface for representations of shapes in the abstract, not tied to any particular
|
/// Interface for representations of shapes in the abstract, not tied to any particular
|
||||||
/// position or orientation.
|
/// position or orientation.
|
||||||
pub trait Shape<'c> {
|
pub trait Shape<'c> {
|
||||||
|
@ -128,17 +161,6 @@ impl<'c, S: Shape<'c>> Piece<S> {
|
||||||
cells.translate(self.loc.x, self.loc.y);
|
cells.translate(self.loc.x, self.loc.y);
|
||||||
cells
|
cells
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates this piece by the given amount in both directions.
|
|
||||||
pub fn translate(&mut self, dx: i16, dy: i16) {
|
|
||||||
self.loc.x = self.loc.x.checked_add(dx).expect("overflow/underflow");
|
|
||||||
self.loc.y = self.loc.y.checked_add(dy).expect("overflow/underflow");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Rotates this piece in the given direction.
|
|
||||||
pub fn rotate(&mut self, dr: Spin) {
|
|
||||||
self.loc.r += dr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -149,6 +171,20 @@ mod test {
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::ops::RangeInclusive;
|
use core::ops::RangeInclusive;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_angle_from_i8() {
|
||||||
|
let rots = core::iter::repeat([Rot::N, Rot::E, Rot::S, Rot::W]).flatten();
|
||||||
|
let ints = 0i8..=127;
|
||||||
|
for (i, r) in ints.zip(rots) {
|
||||||
|
assert_eq!(r, i.into(), "fwd,i={i}");
|
||||||
|
}
|
||||||
|
let rots = core::iter::repeat([Rot::W, Rot::S, Rot::E, Rot::N]).flatten();
|
||||||
|
let ints = (-128i8..=-1).rev(); // -1,-2,...,-128
|
||||||
|
for (i, r) in ints.zip(rots) {
|
||||||
|
assert_eq!(r, i.into(), "bwd,i={i}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// .X.
|
// .X.
|
||||||
// .XX origin at (1,1)
|
// .XX origin at (1,1)
|
||||||
// ...
|
// ...
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
//! Implementation of SRS shapes and movement quirks.
|
//! Implementation of SRS shapes and movement quirks.
|
||||||
|
|
||||||
use crate::location::Rot;
|
use crate::piece::{Cells, Rot, Shape as ShapeTrait};
|
||||||
use crate::piece::{Cells, Shape as GenericShape};
|
|
||||||
|
|
||||||
mod code_gen {
|
mod code_gen {
|
||||||
include!(concat!(env!("OUT_DIR"), "/srs.rs"));
|
include!(concat!(env!("OUT_DIR"), "/srs.rs"));
|
||||||
|
@ -19,7 +18,7 @@ pub enum Shape {
|
||||||
Z = code_gen::shape_indices::Z as u8,
|
Z = code_gen::shape_indices::Z as u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericShape<'static> for Shape {
|
impl ShapeTrait<'static> for Shape {
|
||||||
fn cells(&self, r: Rot) -> Cells<'static> {
|
fn cells(&self, r: Rot) -> Cells<'static> {
|
||||||
let i = (*self as usize) * 4 + r as usize;
|
let i = (*self as usize) * 4 + r as usize;
|
||||||
let xs = code_gen::extents::X0[i]..code_gen::extents::X1[i];
|
let xs = code_gen::extents::X0[i]..code_gen::extents::X1[i];
|
||||||
|
@ -35,7 +34,7 @@ pub type Piece = crate::piece::Piece<Shape>;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::location::Loc;
|
use crate::piece::Loc;
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::ops::Range;
|
use core::ops::Range;
|
||||||
|
|
Loading…
Reference in New Issue