textris 0.2.0

Tetris on terminal!
Documentation
use std::ops::{Add, AddAssign};

#[derive(Debug, Clone, Copy)]
pub struct Coord(pub i8, pub i8);

impl Coord {
    pub fn new(x: i8, y: i8) -> Self {
        Coord(x, y)
    }

    pub fn x(&self) -> i8 {
        self.0
    }

    pub fn y(&self) -> i8 {
        self.1
    }
}

impl Add for Coord {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        Coord(self.0 + rhs.0, self.1 + rhs.1)
    }
}

impl AddAssign for Coord {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
        self.1 += rhs.1;
    }
}

impl Default for Coord {
    fn default() -> Self {
        Coord(0, 0)
    }
}

pub type Dirs = [Dir; 4];

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Dir {
    Up,
    Right,
    Down,
    Left,
}

impl Dir {
    pub fn all() -> Dirs {
        [Dir::Up, Dir::Right, Dir::Down, Dir::Left]
    }

    pub fn to_coord(&self) -> Coord {
        match self {
            Dir::Up => Coord(0, -1),
            Dir::Right => Coord(1, 0),
            Dir::Down => Coord(0, 1),
            Dir::Left => Coord(-1, 0),
        }
    }

    pub fn next_dir(&self) -> Dir {
        match self {
            Dir::Up => Dir::Right,
            Dir::Right => Dir::Down,
            Dir::Down => Dir::Left,
            Dir::Left => Dir::Up,
        }
    }

    pub fn opponent(&self) -> Dir {
        match self {
            Dir::Up => Dir::Down,
            Dir::Right => Dir::Left,
            Dir::Down => Dir::Up,
            Dir::Left => Dir::Right,
        }
    }
}

impl Default for Dir {
    fn default() -> Self {
        Dir::Up
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RotateDir {
    Clockwise,
    AntiClockwise,
}

impl RotateDir {
    pub fn rotate(&self, dir: Dir) -> Dir {
        let dir = dir.next_dir();
        match self {
            RotateDir::Clockwise => dir,
            RotateDir::AntiClockwise => dir.opponent(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Dir::*;
    use super::*;

    #[test]
    fn rotate_dir_rotate() {
        struct Case<'a> {
            title: &'a str,
            rd: RotateDir,
            dirs: (Dir, Dir),
        }
        let cases = [
            Case {
                title: "clockwise: Right -> Down",
                rd: RotateDir::Clockwise,
                dirs: (Right, Down),
            },
            Case {
                title: "clockwise: Left -> Up",
                rd: RotateDir::Clockwise,
                dirs: (Left, Up),
            },
            Case {
                title: "anti: Right -> Up",
                rd: RotateDir::AntiClockwise,
                dirs: (Right, Up),
            },
            Case {
                title: "anti: Left -> Down",
                rd: RotateDir::AntiClockwise,
                dirs: (Left, Down),
            },
        ];

        for Case {
            title,
            rd,
            dirs: (from, to),
        } in cases.iter()
        {
            assert_eq!(rd.rotate(*from), *to, "{}", title);
        }
    }
}