morkovmap 0.3.0

A data-driven, Markov Chain-based tilemap generator library and app.
Documentation
use std::marker::PhantomData;
use arrayvec::ArrayVec;
use num::{One, Zero};
use crate::position::MapPosition;


pub trait AdjacencyGenerator<const DIMS: usize>: Sized + Copy + Clone {
    type Input: MapPosition<DIMS>;
    type Output: IntoIterator<Item=Self::Input>;

    fn adjacents(bound_position: Self::Input) -> Self::Output;
}


#[derive(Copy, Clone)]
pub struct CardinalAdjacencyGenerator<MP: MapPosition<2>> {
    bound_position: PhantomData<MP>
}

impl<MP: MapPosition<2>> AdjacencyGenerator<2> for CardinalAdjacencyGenerator<MP>
{
    type Input = MP;
    type Output = ArrayVec<MP, 4>;

    fn adjacents(bound_position: Self::Input) -> Self::Output {
        let mut adjacents: ArrayVec::<MP, 4> = ArrayVec::new();
        let type_unity: MP::Key = num::one();
        let type_three: MP::Key = type_unity + type_unity + type_unity;

        for dim in 0..2 {

            let offset_range = num::range(
                 num::zero(),
                 type_three
            );

            for offset in offset_range {
                if offset == type_unity {
                    continue
                };
                let true_offset = offset - type_unity;

                let mut pos_buffer = bound_position.get_dims();
                pos_buffer[dim] = pos_buffer[dim] + true_offset;

                let new_pos = MP::from_dims(pos_buffer);

                adjacents.push(new_pos);
            }
        }
        adjacents
    }
}

#[derive(Copy, Clone)]
pub struct OctileAdjacencyGenerator<MP: MapPosition<2>> {
    bound_position: PhantomData<MP>
}

impl<MP: MapPosition<2>> AdjacencyGenerator<2> for OctileAdjacencyGenerator<MP>
{
    type Input = MP;
    type Output = ArrayVec<MP, 8>;

    fn adjacents(bound_position: Self::Input) -> Self::Output {
        let mut adjacents: ArrayVec<MP, 8> = ArrayVec::new();

        let type_unity: MP::Key = MP::Key::one();
        let type_three = type_unity + type_unity + type_unity;
        let pos_array = bound_position.get_dims();

        let x_range = num::range(
            MP::Key::zero(),
            type_three
        );

        for raw_x_dim in x_range {
            let x_dim = raw_x_dim - type_unity;

            let y_range = num::range(
                MP::Key::zero(),
                type_three
            );

            for raw_y_dim in y_range {
                if raw_x_dim.is_one() && raw_y_dim.is_one() {
                    continue
                };
                let y_dim = raw_y_dim - type_unity;
                let new_pos = MP::from_dims([
                    pos_array[0] + x_dim,
                    pos_array[1] + y_dim
                ]);
                adjacents.push(new_pos);
            }
        }

        adjacents
    }
}