Add Location, Orientation, Rotation types
This commit is contained in:
parent
91ee995c71
commit
0597b3b538
|
@ -1,7 +1,9 @@
|
|||
#![no_std]
|
||||
|
||||
pub mod location;
|
||||
pub mod matrix;
|
||||
|
||||
pub use location::Location;
|
||||
pub use matrix::Mat;
|
||||
|
||||
/// Allows constructing a `Mat` constant with string literals:
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
//! 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 Location {
|
||||
/// Horizontal coordinate.
|
||||
pub x: i16,
|
||||
/// Vertical coordinate.
|
||||
pub y: i16,
|
||||
/// Orientation.
|
||||
pub r: Orientation,
|
||||
}
|
||||
|
||||
/// Represents an orientation 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 Orientation {
|
||||
/// 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 Orientation {
|
||||
#[inline]
|
||||
fn from(v: i8) -> Self {
|
||||
unsafe { core::mem::transmute(v & 3) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a rotation operation. Includes 180 degree "flips", which are non-standard
|
||||
/// for tetris but exist in many unofficial iterations of the game.
|
||||
///
|
||||
/// Rotations may be combined with orientations using the [addition
|
||||
/// operator](core::ops::Add).
|
||||
///
|
||||
/// ```
|
||||
/// # use mino::location::{Orientation, Rotation};
|
||||
/// assert_eq!(Orientation::N + Rotation::Cw, Orientation::E);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
|
||||
#[repr(i8)]
|
||||
pub enum Rotation {
|
||||
/// Clockwise.
|
||||
Cw = 1,
|
||||
/// 180 degrees.
|
||||
Flip = 2,
|
||||
/// Counterclockwise.
|
||||
Ccw = 3,
|
||||
}
|
||||
|
||||
impl core::ops::Add<Rotation> for Orientation {
|
||||
type Output = Orientation;
|
||||
fn add(self, r: Rotation) -> Orientation {
|
||||
(self as i8).wrapping_add(r as i8).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::AddAssign<Rotation> for Orientation {
|
||||
fn add_assign(&mut self, r: Rotation) {
|
||||
*self = *self + r;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_angle_rotate() {
|
||||
use Orientation::*;
|
||||
use Rotation::*;
|
||||
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 = Orientation::N;
|
||||
for i in 0i8..=127 {
|
||||
assert_eq!(r, i.into(), "i={i}");
|
||||
r += Rotation::Cw;
|
||||
}
|
||||
r = Orientation::N;
|
||||
for i in (-128i8..=-1).rev() {
|
||||
r += Rotation::Ccw;
|
||||
assert_eq!(r, i.into(), "i={i}");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue