use crate::data::Data;
use crate::helper::{Builder, BuilderError};
use crate::maps::Level;
use crate::math::{Dimension, Point, Rectangle, TwoDimensional};
#[derive(Debug, Clone, PartialEq)]
struct Currencies {}
#[derive(Debug, Clone, PartialEq)]
struct Inventory {}
#[derive(Debug, Clone, PartialEq)]
struct Stats {}
#[derive(Debug, PartialEq, Clone)]
pub struct Abilities(Vec<Ability>);
impl Abilities {
pub fn new() -> Abilities {
Abilities(Vec::new())
}
fn check_for_ability(&self, ability: &Ability) -> bool {
for owned_ability in self.0.iter() {
if ability == owned_ability {
return true;
}
}
false
}
pub fn is_warp(&self) -> Option<(Level, Point)> {
for owned_ability in self.0.iter() {
if let Ability::Warp(l, p) = owned_ability.clone() {
return Some((l, p));
}
}
None
}
pub fn can_speak(&self) -> bool {
if !self.check_for_ability(&Ability::Speak) {
return false;
}
true
}
pub fn can_not_speak(&self) -> bool {
!self.can_speak()
}
pub fn can_move(&self) -> bool {
if !self.check_for_ability(&Ability::Move) {
return false;
}
true
}
pub fn can_not_move(&self) -> bool {
!self.can_move()
}
pub fn add_ability(&mut self, ability: Ability) {
if !self.check_for_ability(&ability) {
self.0.push(ability);
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum Ability {
Move,
Speak,
Warp(Level, Point),
Physical,
Clone,
}
#[derive(Debug, Clone, PartialEq)]
enum Alignment {
Good,
Evil,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Skin {
RGB(u8, u8, u8),
}
impl Skin {
pub fn get_rgb(&self) -> Result<Skin, &'static str> {
match self {
Skin::RGB(r, g, b) => Ok(Skin::RGB(*r, *g, *b)),
}
}
pub fn get_rgb_colors(&self) -> Result<(u8, u8, u8), &'static str> {
match self {
Skin::RGB(r, g, b) => Ok((*r, *g, *b)),
}
}
}
pub struct EntityBuilder {
position: Option<Point>,
size: Dimension,
skin: Skin,
stats: Stats,
abilities: Abilities,
inventory: Option<Inventory>,
alignment: Option<Alignment>,
}
impl EntityBuilder {
pub fn set_position(mut self, point: Point) -> Self {
self.position = Some(point);
self
}
pub fn set_xy(mut self, x: i32, y: i32) -> Self {
self.position = Some(Point::new(x, y));
self
}
pub fn set_dimension(mut self, dimension: Dimension) -> Self {
self.size = dimension;
self
}
pub fn set_size(mut self, width: u32, height: u32) -> Self {
self.size = Dimension::new(width, height);
self
}
pub fn set_abilities(mut self, abilities: Vec<Ability>) -> Self {
for ability in abilities.into_iter() {
self.abilities.add_ability(ability);
}
self
}
}
impl Builder for EntityBuilder {
type product = Entity;
fn new() -> EntityBuilder {
EntityBuilder {
position: None,
size: Dimension::new(1, 1),
skin: Skin::RGB(255, 255, 0),
inventory: None,
stats: Stats {},
abilities: Abilities(Vec::new()),
alignment: None,
}
}
fn build(self) -> Result<Entity, BuilderError> {
if self.position.is_none() {
return Err(BuilderError::new(
"Could not build Entity, no position set. use set_position or set_xy methods to set position.",
));
}
let placement = Rectangle::new(
self.position.unwrap().get_x(),
self.position.unwrap().get_y(),
self.size.get_x(),
self.size.get_y(),
);
Ok(Entity {
placement,
skin: self.skin,
inventory: self.inventory,
stats: self.stats,
abilities: self.abilities,
alignment: self.alignment,
})
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct Entity {
placement: Rectangle,
skin: Skin,
stats: Stats,
abilities: Abilities,
inventory: Option<Inventory>,
alignment: Option<Alignment>,
}
impl Entity {
pub fn new_player(x: i32, y: i32) -> Entity {
Entity {
placement: Rectangle::new(x, y, 1, 1),
skin: Skin::RGB(255, 0, 0),
inventory: None,
stats: Stats {},
abilities: Abilities(Vec::new()),
alignment: Some(Alignment::Good),
}
}
pub fn new_slimer_entity(x: i32, y: i32) -> Entity {
Entity {
placement: Rectangle::new(x, y, 1, 1),
skin: Skin::RGB(30, 215, 30),
inventory: None,
stats: Stats {},
abilities: Abilities(Vec::new()),
alignment: Some(Alignment::Evil),
}
}
pub fn new_wall(x: i32, y: i32, height: u32, width: u32) -> Entity {
Entity {
placement: Rectangle::new(x, y, height, width),
skin: Skin::RGB(90, 90, 90),
inventory: None,
stats: Stats {},
abilities: Abilities(Vec::new()),
alignment: None,
}
}
}
impl Entity {
pub fn get_move(&self, movement: Point) -> Rectangle {
let mut new_rect = self.placement;
new_rect.move_xy(movement);
new_rect
}
pub fn get_move_left(&self) -> Rectangle {
self.get_move(Point::new(-1, 0))
}
pub fn get_move_right(&self) -> Rectangle {
self.get_move(Point::new(1, 0))
}
pub fn get_move_up(&self) -> Rectangle {
self.get_move(Point::new(0, -1))
}
pub fn get_move_down(&self) -> Rectangle {
self.get_move(Point::new(0, 1))
}
pub fn move_left(&mut self) {
self.placement.move_x(-1);
}
pub fn move_right(&mut self) {
self.placement.move_x(1);
}
pub fn move_up(&mut self) {
self.placement.move_y(-1);
}
pub fn move_down(&mut self) {
self.placement.move_y(1);
}
}
impl Entity {
pub fn new() -> EntityBuilder {
EntityBuilder::new()
}
pub fn get_position(&self) -> Point {
self.placement.get_point()
}
pub fn get_size(&self) -> Dimension {
self.placement.get_dimension()
}
pub fn get_rectangle(&self) -> Rectangle {
self.placement
}
pub fn get_skin(&self) -> Skin {
self.skin
}
pub fn get_abilities(&self) -> &Abilities {
&self.abilities
}
}
impl Entity {
pub fn perform_turn(&mut self, data: &mut Data) {
if self.abilities.can_move() {
let new_position = match data
.get_randomness_with(self.get_rectangle().x() * self.get_rectangle().y())
{
v if v > 0.75 => self.get_move_right(),
v if v > 0.5 => self.get_move_left(),
v if v > 0.25 => self.get_move_up(),
_v => self.get_move_down(),
};
self.move_direction(data, new_position);
}
}
fn move_direction(&mut self, data: &mut Data, new_rectangle: Rectangle) {
match data.check_position_both(new_rectangle) {
Some(_e) => {}
None => self.placement = new_rectangle,
};
}
}
pub struct EnemyBuilder {}