diff options
-rw-r--r-- | src/entities.rs | 447 | ||||
-rw-r--r-- | src/tiling.rs | 60 | ||||
-rw-r--r-- | src/world.rs | 14 |
3 files changed, 259 insertions, 262 deletions
diff --git a/src/entities.rs b/src/entities.rs index 5908092..1be3594 100644 --- a/src/entities.rs +++ b/src/entities.rs @@ -1,223 +1,224 @@ -use std::cmp;
-
-use crate::tiling::{Tile, TileType};
-use crate::world::{apply_movement, Movement, Point};
-
-pub trait Entity {
- /// Get information about the entity
- fn info(&self) -> String;
- /// Initial placement of the entity
- fn place(&mut self, location: Point);
- /// Get the tiletype for the entity
- fn tile(&self) -> &Tile;
- /// Get the entity's current location
- fn location(&self) -> &Point;
- /// Get the entity's previous location (before it moved)
- fn previous_location(&self) -> &Point;
- /// Move the entity to another point
- fn move_to(&mut self, location: Point);
- /// Move the entity with a movement differential
- fn move_by(&mut self, movement: Movement) -> Result<(), String>;
- /// Know if the entity needs to be re-rendered
- fn is_dirty(&self) -> bool;
- /// Declare the entity clean
- fn clean(&mut self);
- fn visibility(&mut self, visible: bool);
- fn is_visible(&self) -> bool;
-}
-
-#[derive(Clone)]
-pub struct Character {
- pub name: String,
- pub class: String,
- pub health: i32,
- pub level: i32,
- location: Point,
- previous_location: Point,
- dirty: bool,
- max_health: i32,
- attack: i32,
- dodge: i32,
- luck: i32,
- xp: i32,
- tile: Tile,
-}
-
-pub trait Enemy {
- fn new(
- class: String,
- health: i32,
- attack: i32,
- dodge: i32,
- luck: i32,
- location: Point,
- tile_str: &'static str,
- ) -> Self;
-
- fn set_tile(&mut self, tile: Tile);
-}
-
-pub trait Player {
- fn new(name: String, class: String, health: i32, attack: i32, dodge: i32, luck: i32) -> Self;
- fn damage(&mut self, damage_amount: i32);
- fn heal(&mut self, heal_amount: i32);
- fn attack(&self) -> i32;
- fn dodge(&self) -> i32;
- fn stats(&self) -> String;
-}
-
-impl Entity for Character {
- fn place(&mut self, location: Point) {
- self.location = location;
- self.previous_location = location;
- self.dirty = true;
- }
-
- fn info(&self) -> String {
- format!(
- "{} \thp: {} attack: {} dodge: {} luck: {}",
- self.class, self.health, self.attack, self.dodge, self.luck
- )
- }
-
- fn tile(&self) -> &Tile {
- &self.tile
- }
-
- fn location(&self) -> &Point {
- &self.location
- }
-
- fn previous_location(&self) -> &Point {
- &self.previous_location
- }
-
- fn move_to(&mut self, location: Point) {
- self.previous_location = self.location;
- self.location = location;
- self.dirty = true;
- }
-
- fn move_by(&mut self, movement: Movement) -> Result<(), String> {
- self.previous_location = self.location;
- self.location = apply_movement(self.location, movement)?;
- Ok(())
- }
-
- fn is_dirty(&self) -> bool {
- self.dirty
- }
-
- fn clean(&mut self) {
- self.dirty = false;
- }
-
- fn visibility(&mut self, visible: bool) {
- if visible != self.is_visible() {
- self.dirty = true;
- }
- self.tile.visibility(visible)
- }
-
- fn is_visible(&self) -> bool {
- self.tile.is_visible()
- }
-}
-
-impl Enemy for Character {
- fn new(
- class: String,
- health: i32,
- attack: i32,
- dodge: i32,
- luck: i32,
- location: Point,
- tile_str: &'static str,
- ) -> Character {
- Character {
- name: class.clone(),
- class: class.clone(),
- max_health: health,
- health,
- attack,
- dodge,
- luck,
- level: 0,
- xp: 0,
- location,
- previous_location: location,
- tile: Tile::from(TileType::Character(tile_str)),
- dirty: false,
- }
- }
-
- fn set_tile(&mut self, tile: Tile) {
- self.tile = tile
- }
-}
-
-impl Player for Character {
- fn new(
- name: String,
- class: String,
- health: i32,
- attack: i32,
- dodge: i32,
- luck: i32,
- ) -> Character {
- Character {
- name,
- class,
- max_health: health,
- health,
- attack,
- dodge,
- luck,
- xp: 0,
- level: 0,
- location: (0, 0),
- previous_location: (0, 0),
- tile: Tile::new(
- TileType::Player,
- true, // player is visible by default
- false,
- true
- ),
- dirty: false,
- }
- }
-
- fn damage(&mut self, damage_amount: i32) {
- self.health = cmp::max(0, self.health - damage_amount);
- self.xp += 2;
- }
-
- fn heal(&mut self, heal_amount: i32) {
- if (self.health) <= self.max_health {
- self.health = cmp::min(self.health + heal_amount, self.max_health);
- self.xp += 1;
- }
- }
-
- fn attack(&self) -> i32 {
- self.xp + self.attack + self.luck / 2
- }
-
- fn dodge(&self) -> i32 {
- self.xp + self.dodge + self.luck / 2
- }
-
- fn stats(&self) -> String {
- format!(
- "{}({}) - hp: {}/{} attack: {} dodge: {} luck: {} experience: {}",
- self.name,
- self.class,
- self.health,
- self.max_health,
- self.attack,
- self.dodge,
- self.luck,
- self.xp
- )
- }
-}
+use std::cmp; + +use crate::tiling::{Tile, TileType}; +use crate::world::{apply_movement, Movement, Point}; + +pub trait Entity { + /// Get information about the entity + fn info(&self) -> String; + /// Initial placement of the entity + fn place(&mut self, location: Point); + /// Get the tiletype for the entity + fn tile(&self) -> &Tile; + /// Get the entity's current location + fn location(&self) -> &Point; + /// Get the entity's previous location (before it moved) + fn previous_location(&self) -> &Point; + /// Move the entity to another point + fn move_to(&mut self, location: Point); + /// Move the entity with a movement differential + fn move_by(&mut self, movement: Movement) -> Result<(), String>; + /// Know if the entity needs to be re-rendered + fn is_dirty(&self) -> bool; + /// Declare the entity clean + fn clean(&mut self); + fn visibility(&mut self, visible: bool); + fn is_visible(&self) -> bool; +} + +#[derive(Clone)] +pub struct Character { + pub name: String, + pub class: String, + pub health: i32, + pub level: i32, + location: Point, + previous_location: Point, + dirty: bool, + max_health: i32, + attack: i32, + dodge: i32, + luck: i32, + xp: i32, + tile: Tile, +} + +pub trait Enemy { + fn new( + class: String, + health: i32, + attack: i32, + dodge: i32, + luck: i32, + location: Point, + tile_str: &'static str, + ) -> Self; + + fn set_tile(&mut self, tile: Tile); +} + +pub trait Player { + fn new(name: String, class: String, health: i32, attack: i32, dodge: i32, luck: i32) -> Self; + fn damage(&mut self, damage_amount: i32); + fn heal(&mut self, heal_amount: i32); + fn attack(&self) -> i32; + fn dodge(&self) -> i32; + fn stats(&self) -> String; +} + +impl Entity for Character { + fn place(&mut self, location: Point) { + self.location = location; + self.previous_location = location; + self.dirty = true; + } + + fn info(&self) -> String { + format!( + "{} \thp: {} attack: {} dodge: {} luck: {}", + self.class, self.health, self.attack, self.dodge, self.luck + ) + } + + fn tile(&self) -> &Tile { + &self.tile + } + + fn location(&self) -> &Point { + &self.location + } + + fn previous_location(&self) -> &Point { + &self.previous_location + } + + fn move_to(&mut self, location: Point) { + self.previous_location = self.location; + self.location = location; + self.dirty = true; + } + + fn move_by(&mut self, movement: Movement) -> Result<(), String> { + self.previous_location = self.location; + self.location = apply_movement(self.location, movement)?; + Ok(()) + } + + fn is_dirty(&self) -> bool { + self.dirty + } + + fn clean(&mut self) { + self.dirty = false; + } + + fn visibility(&mut self, visible: bool) { + if visible != self.is_visible() { + self.dirty = true; + } + self.tile.visibility(visible) + } + + fn is_visible(&self) -> bool { + self.tile.is_visible() + } +} + +impl Enemy for Character { + fn new( + class: String, + health: i32, + attack: i32, + dodge: i32, + luck: i32, + location: Point, + tile_str: &'static str, + ) -> Character { + Character { + name: class.clone(), + class: class.clone(), + max_health: health, + health, + attack, + dodge, + luck, + level: 0, + xp: 0, + location, + previous_location: location, + tile: Tile::from(TileType::Character(tile_str)), + dirty: false, + } + } + + fn set_tile(&mut self, tile: Tile) { + self.tile = tile + } +} + +impl Player for Character { + fn new( + name: String, + class: String, + health: i32, + attack: i32, + dodge: i32, + luck: i32, + ) -> Character { + Character { + name, + class, + max_health: health, + health, + attack, + dodge, + luck, + xp: 0, + level: 0, + location: (0, 0), + previous_location: (0, 0), + tile: Tile::new( + TileType::Player, + true, // player is visible by default + false, + true, + false + ), + dirty: false, + } + } + + fn damage(&mut self, damage_amount: i32) { + self.health = cmp::max(0, self.health - damage_amount); + self.xp += 2; + } + + fn heal(&mut self, heal_amount: i32) { + if (self.health) <= self.max_health { + self.health = cmp::min(self.health + heal_amount, self.max_health); + self.xp += 1; + } + } + + fn attack(&self) -> i32 { + self.xp + self.attack + self.luck / 2 + } + + fn dodge(&self) -> i32 { + self.xp + self.dodge + self.luck / 2 + } + + fn stats(&self) -> String { + format!( + "{}({}) - hp: {}/{} attack: {} dodge: {} luck: {} experience: {}", + self.name, + self.class, + self.health, + self.max_health, + self.attack, + self.dodge, + self.luck, + self.xp + ) + } +} diff --git a/src/tiling.rs b/src/tiling.rs index 06aa037..e21c02a 100644 --- a/src/tiling.rs +++ b/src/tiling.rs @@ -1,4 +1,3 @@ -use log::debug; use std::convert::From; #[derive(Copy, Clone, Debug)] @@ -10,6 +9,7 @@ pub enum TileType { StairsDown, Character(&'static str), Player, + Door, } #[derive(Clone, Debug)] @@ -18,15 +18,17 @@ pub struct Tile { visible: bool, opaque: bool, lit: bool, + open: bool, } impl Tile { - pub fn new(tile_type: TileType, visible: bool, opaque: bool, lit: bool) -> Self { + pub fn new(tile_type: TileType, visible: bool, opaque: bool, open: bool, lit: bool) -> Self { Tile { tile_type, visible, opaque, lit, + open, } } @@ -57,6 +59,18 @@ impl Tile { pub fn opacity(&mut self, opaque: bool) { self.opaque = opaque } + + pub fn is_open(&self) -> bool { + self.open + } + + pub fn open(&mut self) { + self.open = true; + } + + pub fn clos(&mut self) { + self.open = false; + } } impl From<TileType> for Tile { @@ -72,6 +86,7 @@ impl From<TileType> for Tile { _ => false, }, lit: false, + open: false, } } } @@ -183,6 +198,10 @@ pub fn tile_to_str(tile: &Tile) -> &str { TileType::StairsUp => "<", TileType::Player => "@", TileType::Character(t) => t, + TileType::Door => match tile.is_open() { + true => "'", + false => "+", + }, } } else { " " @@ -193,43 +212,6 @@ pub trait Tileable { fn tile(&self, grid: &mut TileGrid) -> Result<(), String>; } -// fn circle(center: &(usize, usize), radius: usize) -> Vec<(usize, usize)> { -// let mut x: i32 = radius as i32; -// let mut y: i32 = 0; -// let mut err: i32 = 0; - -// let signs: [i32; 2] = [-1, 1]; -// let mut points: Vec<(usize, usize)> = vec![]; - -// while x >= y { -// for xsign in signs.iter() { -// for ysign in signs.iter() { -// points.push(( -// (center.0 as i32 + xsign * x).max(0) as usize, -// (center.1 as i32 + ysign * y).max(0) as usize, -// )); -// points.push(( -// (center.0 as i32 + xsign * y).max(0) as usize, -// (center.1 as i32 + ysign * x).max(0) as usize, -// )); -// } -// } - -// if err <= 0 { -// y += 1; -// err += 2 * y + 1; -// } - -// if err > 0 { -// x -= 1; -// err -= 2 * x + 1; -// } -// } -// points.sort(); -// points.dedup(); -// points -// } - #[cfg(test)] mod tests { use super::*; diff --git a/src/world.rs b/src/world.rs index c577680..6d0c097 100644 --- a/src/world.rs +++ b/src/world.rs @@ -175,6 +175,7 @@ impl Corridor { fn tile_vertical(&self, grid: &mut TileGrid) { let x = self.start.0; let endy = self.start.1 + self.length; + for y in self.start.1..endy { grid.set_empty_tile(x - 1, y, Tile::from(TileType::Wall)); grid.set_tile(x, y, Tile::from(TileType::Floor)); @@ -187,11 +188,18 @@ impl Corridor { grid.set_empty_tile(x - 1, endy, Tile::from(TileType::Wall)); grid.set_empty_tile(x, endy, Tile::from(TileType::Wall)); grid.set_empty_tile(x + 1, endy, Tile::from(TileType::Wall)); + + // Have a door at the start? + let mut rng = rand::thread_rng(); + if rng.gen_bool(0.5) { + grid.set_tile(self.start.0, self.start.1, Tile::from(TileType::Door)); + } } fn tile_horizontal(&self, grid: &mut TileGrid) { let y = self.start.1; let endx = self.start.0 + self.length; + for x in self.start.0..endx { grid.set_empty_tile(x, y - 1, Tile::from(TileType::Wall)); grid.set_tile(x, y, Tile::from(TileType::Floor)); @@ -204,6 +212,12 @@ impl Corridor { grid.set_empty_tile(endx, y - 1, Tile::from(TileType::Wall)); grid.set_empty_tile(endx, y, Tile::from(TileType::Wall)); grid.set_empty_tile(endx, y + 1, Tile::from(TileType::Wall)); + + // Have a door at the start? + let mut rng = rand::thread_rng(); + if rng.gen_bool(0.5) { + grid.set_tile(self.start.0, self.start.1, Tile::from(TileType::Door)); + } } } |