merosity 0.1.0

(wip) competitive stacker game
// merosity, online stacker game
//
// Copyright (c) 2023 rini
// SPDX-License-Identifier: Apache-2.0

#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum Tile {
    #[default]
    Empty,
    Mino(Mino),
    Garbage,
}

impl From<char> for Tile {
    fn from(value: char) -> Self {
        match value {
            ' ' | '.' => Self::Empty,
            _ => Mino::try_from(value).map_or(Self::Garbage, Self::Mino),
        }
    }
}

impl From<&Tile> for bevy::prelude::Color {
    fn from(value: &Tile) -> Self {
        match value {
            Tile::Empty => Self::BLACK.with_a(0.0),
            Tile::Mino(m) => m.into(),
            Tile::Garbage => Self::rgb_u8(0x28, 0x28, 0x28),
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Mino {
    I,
    L,
    J,
    S,
    Z,
    T,
    O,
}

impl TryFrom<char> for Mino {
    type Error = ();

    fn try_from(value: char) -> Result<Self, Self::Error> {
        match value.to_ascii_lowercase() {
            'i' => Ok(Self::I),
            'l' => Ok(Self::L),
            'j' => Ok(Self::J),
            's' => Ok(Self::S),
            'z' => Ok(Self::Z),
            't' => Ok(Self::T),
            'o' => Ok(Self::O),
            _ => Err(()),
        }
    }
}

impl Mino {
    pub fn shape(&self) -> &[(isize, isize)] {
        static I: &[(isize, isize)] = &[(-1, 0), (0, 0), (1, 0), (2, 0)];
        static L: &[(isize, isize)] = &[(-1, 0), (0, 0), (1, 0), (1, 1)];
        static J: &[(isize, isize)] = &[(-1, 0), (0, 0), (1, 0), (-1, 1)];
        static S: &[(isize, isize)] = &[(-1, 0), (0, 0), (0, 1), (1, 1)];
        static Z: &[(isize, isize)] = &[(0, 0), (1, 0), (-1, 1), (0, 1)];
        static T: &[(isize, isize)] = &[(-1, 0), (0, 0), (1, 0), (0, 1)];
        static O: &[(isize, isize)] = &[(0, 0), (1, 0), (0, 1), (1, 1)];

        match self {
            Self::I => I,
            Self::L => L,
            Self::J => J,
            Self::S => S,
            Self::Z => Z,
            Self::T => T,
            Self::O => O,
        }
    }
}

impl From<&Mino> for bevy::prelude::Color {
    fn from(value: &Mino) -> Self {
        match value {
            Mino::I => Self::rgb_u8(0x6e, 0xcb, 0xf2),
            Mino::L => Self::rgb_u8(0xf7, 0xaa, 0x86),
            Mino::J => Self::rgb_u8(0x8e, 0xa2, 0xee),
            Mino::S => Self::rgb_u8(0x92, 0xdd, 0x8f),
            Mino::Z => Self::rgb_u8(0xf2, 0x88, 0x8c),
            Mino::T => Self::rgb_u8(0xc1, 0x8a, 0xe1),
            Mino::O => Self::rgb_u8(0xfb, 0xde, 0x9a),
        }
    }
}