From 67d6396e607a3061f62e1687d5ac3893b01909fa Mon Sep 17 00:00:00 2001 From: Alex Page Date: Sat, 29 Jan 2022 01:02:33 -0500 Subject: [PATCH 1/3] Update README --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 31d65ad..3f789c8 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,6 @@ The goal is to closely mimic the look and behavior of the original game, but not ## License -"Kroz" is a registered trademark of Apogee Software, Ltd. -The original "Kroz" copyright 1987 - 2009 Apogee Software, Ltd. All trademarks and copyrights reserved. +The original "Kroz" copyright 1987 - 2022 Apogee Entertainment Inc. All trademarks and copyrights reserved. -This project has no affiliation with Apogee Software, Ltd and its code is licensed under the [GNU General Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html). +This project has no affiliation with Apogee Entertainment Inc. and the code within is licensed under the [GNU General Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html). From b417c53a012306a80bbca7afe047f8f60186b7a9 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Sat, 29 Jan 2022 01:55:06 -0500 Subject: [PATCH 2/3] Add method to remove gems with bounds check --- src/main.rs | 7 ++++++- src/resources/mod.rs | 15 +++++++++++++++ src/state.rs | 4 +--- src/systems/monster_ai_system.rs | 4 +--- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2e29d1c..23f4e94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,7 +61,12 @@ fn main() -> BError { for (i, tile) in &mut map.get_tiles().iter().enumerate() { if rng.roll_dice(1, 16) < 2 && *tile == TileType::Floor { let position = map.index_to_point2d(i); - let kind = MonsterKind::Slow; + let kind = match rng.range(0, 3) { + 0 => MonsterKind::Slow, + 1 => MonsterKind::Medium, + 2 => MonsterKind::Fast, + _ => MonsterKind::Slow, + }; ecs.create_entity() .with(Position { x: position.x, diff --git a/src/resources/mod.rs b/src/resources/mod.rs index f497725..330b80e 100644 --- a/src/resources/mod.rs +++ b/src/resources/mod.rs @@ -48,3 +48,18 @@ pub struct Stats { pub teleports: u32, pub keys: u32, } + +type PlayerSurvived = bool; + +impl Stats { + pub fn take_gems(&mut self, num_gems: u32) -> PlayerSurvived { + let new_num_gems = self.gems as i64 - num_gems as i64; + if new_num_gems <= 0 { + self.gems = 0; + false + } else { + self.gems = new_num_gems as u32; + true + } + } +} diff --git a/src/state.rs b/src/state.rs index afa3d62..e69f991 100644 --- a/src/state.rs +++ b/src/state.rs @@ -111,9 +111,7 @@ impl State { } else { if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) { if let Some(monster) = monsters.get(e) { - if stats.gems > 0 { - stats.gems -= damage_for_kind(monster.kind); - } + stats.take_gems(damage_for_kind(monster.kind)); let _ = entities.delete(e); } } diff --git a/src/systems/monster_ai_system.rs b/src/systems/monster_ai_system.rs index 9b0eeb2..0457789 100644 --- a/src/systems/monster_ai_system.rs +++ b/src/systems/monster_ai_system.rs @@ -77,9 +77,7 @@ impl<'a> System<'a> for MonsterAiSystem { if let Some(e) = map.get_tile_content(map.point2d_to_index(destination)) { if let Some(_player) = players.get(e) { // TODO: Sound - if stats.gems > 0 { - stats.gems -= damage_for_kind(monster.kind); - } + stats.take_gems(damage_for_kind(monster.kind)); let _ = entities.delete(*entity); } } else { From 1dd15c4c8f7f6d1aefd71ef2dba237d50d1254b5 Mon Sep 17 00:00:00 2001 From: Alex Page Date: Sat, 29 Jan 2022 05:28:06 -0500 Subject: [PATCH 3/3] Fill in data about each tile type --- src/main.rs | 3 +- src/resources/map.rs | 52 +--- src/systems/monster_ai_system.rs | 6 +- src/tile_data.rs | 405 +++++++++++++++++++++++++++++++ 4 files changed, 421 insertions(+), 45 deletions(-) create mode 100644 src/tile_data.rs diff --git a/src/main.rs b/src/main.rs index 23f4e94..136d7d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ pub mod resources; mod sidebar; mod state; pub mod systems; +pub mod tile_data; pub mod vga_color; use bracket_lib::prelude::*; @@ -13,11 +14,11 @@ use components::{ monster::{color_for_kind, glyphs_for_kind, ticks_for_kind, MonsterKind}, Monster, Player, Position, Renderable, }; -use resources::map::TileType; use resources::{Clock, LevelNumber, Map, ShowDebugInfo, SoundEffects, SoundOutput, Stats}; use specs::prelude::*; use state::State; use std::time::Instant; +use tile_data::TileType; use vga_color as vga; diff --git a/src/resources/map.rs b/src/resources/map.rs index 5ac0194..3e72d57 100644 --- a/src/resources/map.rs +++ b/src/resources/map.rs @@ -1,17 +1,11 @@ use crate::{ constants::{MAP_HEIGHT, MAP_SIZE, MAP_WIDTH, MAP_X, MAP_Y}, + tile_data::{self, TileType}, vga_color as vga, }; use bracket_lib::{prelude::*, random::RandomNumberGenerator}; use specs::Entity; -#[derive(PartialEq, Copy, Clone)] -pub enum TileType { - Wall, - BreakableWall, - Floor, -} - pub struct Map { tiles: Vec, tile_content: Vec>, @@ -41,7 +35,7 @@ impl Map { if rng.roll_dice(1, 16) < 2 { *tile = TileType::Wall; } else if rng.roll_dice(1, 16) < 2 { - *tile = TileType::BreakableWall; + *tile = TileType::Block; } } Self { @@ -88,35 +82,14 @@ impl Map { let point = self.index_to_point2d(i); let (x, y) = (point.x as usize, point.y as usize); - match tile { - TileType::Floor => { - ctx.set( - x + MAP_X, - y + MAP_Y, - RGB::named(vga::BLACK), - RGB::named(vga::BLACK), - to_cp437(' '), - ); - } - TileType::BreakableWall => { - ctx.set( - x + MAP_X, - y + MAP_Y, - RGB::named(vga::YELLOW), - RGB::named(vga::BLACK), - to_cp437('▓'), - ); - } - TileType::Wall => { - ctx.set( - x + MAP_X, - y + MAP_Y, - RGB::named(vga::YELLOW), - RGB::named(vga::BLACK), - to_cp437('█'), - ); - } - } + let data = tile_data::tile_data(*tile); + ctx.set( + x + MAP_X, + y + MAP_Y, + data.color_fg, + data.color_bg, + data.glyph, + ); } } @@ -130,9 +103,6 @@ impl Map { } pub fn is_solid(&self, point: Point) -> bool { - matches!( - self.get_tile_at(point), - TileType::Wall | TileType::BreakableWall - ) + matches!(self.get_tile_at(point), TileType::Wall | TileType::Block) } } diff --git a/src/systems/monster_ai_system.rs b/src/systems/monster_ai_system.rs index 0457789..243aaeb 100644 --- a/src/systems/monster_ai_system.rs +++ b/src/systems/monster_ai_system.rs @@ -3,8 +3,8 @@ use crate::{ monster::{self, damage_for_kind, ticks_for_kind}, Monster, Player, Position, Renderable, }, - resources::map::TileType, resources::{Clock, Map, Stats}, + tile_data::TileType, }; use bracket_lib::{prelude::*, random::RandomNumberGenerator}; use specs::prelude::*; @@ -83,11 +83,11 @@ impl<'a> System<'a> for MonsterAiSystem { } else { match map.get_tile_at(destination) { TileType::Wall => {} - TileType::BreakableWall => { + TileType::Block => { // TODO: Sound let _ = entities.delete(*entity); } - TileType::Floor => { + _ => { position.x = destination.x; position.y = destination.y; } diff --git a/src/tile_data.rs b/src/tile_data.rs new file mode 100644 index 0000000..6fe105d --- /dev/null +++ b/src/tile_data.rs @@ -0,0 +1,405 @@ +use bracket_lib::prelude::*; + +use crate::vga_color as vga; + +#[derive(PartialEq, Copy, Clone)] +pub struct TileData { + pub glyph: u16, + pub color_fg: (u8, u8, u8), + pub color_bg: (u8, u8, u8), + pub serialized_char: char, + pub blink: bool, +} + +#[derive(PartialEq, Copy, Clone)] +pub enum TileType { + Floor, // 0 + Block, // 4 + Whip, // 5 + Stairs, // 6 + Chest, // 7 + SlowTime, // 8 + Gem, // 9 + Invisible, // 10 + Teleport, // 11 + Key, // 12 + Door, // 13 + Wall, // 14 + SpeedTime, // 15 + Trap, // 16 + River, // 17 + Power, // 18 + Forest, // 19 + Tree, // 20, 252 + Bomb, // 21 + Lava, // 22 + Pit, // 23 + Tome, // 24 + Tunnel, // 25 + Freeze, // 26 + Nugget, // 27 + Quake, // 28 + InvisibleBlock, // 29 + InvisibleWall, // 30 + InvisibleDoor, // 31 + Stop, // 32 + Zap, // 34 + Create, // 35 + Generator, // 36 + Trap2, // 33 + Trap3, // 37 + Trap4, // 39 + Trap5, // 67 + Trap6, // 224 + Trap7, // 225 + Trap8, // 226 + Trap9, // 227 + Trap10, // 228 + Trap11, // 229 + Trap12, // 230 + Trap13, // 231 + Player, // 40 + Punctuation, // 222 + Letter(char), +} + +pub fn tile_data(tile: TileType) -> TileData { + match tile { + TileType::Floor => TileData { + glyph: 0, + serialized_char: ' ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Block => TileData { + glyph: to_cp437('▓'), + serialized_char: 'X', + color_fg: vga::YELLOW, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Whip => TileData { + glyph: to_cp437('⌠'), + serialized_char: 'W', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Stairs => TileData { + glyph: to_cp437('≡'), + serialized_char: 'L', + color_fg: vga::BLACK, + color_bg: vga::WHITE, + blink: true, + }, + TileType::Chest => TileData { + glyph: to_cp437('C'), + serialized_char: 'C', + color_fg: vga::YELLOW_BRIGHT, + color_bg: vga::RED, + blink: false, + }, + TileType::SlowTime => TileData { + glyph: to_cp437('Φ'), + serialized_char: 'S', + color_fg: vga::CYAN_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Gem => TileData { + glyph: to_cp437('♦'), + serialized_char: '+', + color_fg: vga::WHITE, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Invisible => TileData { + glyph: to_cp437('¡'), + serialized_char: 'I', + color_fg: vga::GREEN, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Teleport => TileData { + glyph: to_cp437('↑'), + serialized_char: 'T', + color_fg: vga::MAGENTA_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Key => TileData { + glyph: to_cp437('î'), + serialized_char: 'K', + color_fg: vga::RED_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Door => TileData { + glyph: to_cp437('∞'), + serialized_char: 'D', + color_fg: vga::CYAN, + color_bg: vga::MAGENTA, + blink: false, + }, + TileType::Wall => TileData { + glyph: to_cp437('█'), + serialized_char: '#', + color_fg: vga::YELLOW, + color_bg: vga::BLACK, + blink: false, + }, + TileType::SpeedTime => TileData { + glyph: to_cp437('Θ'), + serialized_char: 'F', + color_fg: vga::CYAN_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap => TileData { + glyph: to_cp437('∙'), + serialized_char: '.', + color_fg: vga::WHITE, + color_bg: vga::BLACK, + blink: false, + }, + TileType::River => TileData { + glyph: to_cp437('≈'), + serialized_char: 'R', + color_fg: vga::BLUE_BRIGHT, + color_bg: vga::BLUE, + blink: false, + }, + TileType::Power => TileData { + glyph: to_cp437('○'), + serialized_char: 'Q', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Forest => TileData { + glyph: to_cp437('█'), + serialized_char: '/', + color_fg: vga::GREEN, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Tree => TileData { + glyph: to_cp437('♣'), + serialized_char: '\\', + color_fg: vga::YELLOW, + color_bg: vga::GREEN, + blink: false, + }, + TileType::Bomb => TileData { + glyph: to_cp437('¥'), + serialized_char: 'B', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Lava => TileData { + glyph: to_cp437('▓'), + serialized_char: 'V', + color_fg: vga::RED_BRIGHT, + color_bg: vga::RED, + blink: false, + }, + TileType::Pit => TileData { + glyph: to_cp437('░'), + serialized_char: '=', + color_fg: vga::WHITE, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Tome => TileData { + glyph: to_cp437('♀'), + serialized_char: 'A', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: true, + }, + TileType::Tunnel => TileData { + glyph: to_cp437('∩'), + serialized_char: 'U', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Freeze => TileData { + glyph: to_cp437('ƒ'), + serialized_char: 'Z', + color_fg: vga::CYAN_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Nugget => TileData { + glyph: to_cp437('☼'), + serialized_char: '*', + color_fg: vga::YELLOW_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Quake => TileData { + glyph: 0, + serialized_char: 'E', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::InvisibleBlock => TileData { + glyph: 0, + serialized_char: ';', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::InvisibleWall => TileData { + glyph: 0, + serialized_char: ':', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::InvisibleDoor => TileData { + glyph: 0, + serialized_char: '`', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Stop => TileData { + glyph: 0, + serialized_char: '-', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Zap => TileData { + glyph: to_cp437('▲'), + serialized_char: '%', + color_fg: vga::RED_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Create => TileData { + glyph: to_cp437('▼'), + serialized_char: ']', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Generator => TileData { + glyph: to_cp437('♠'), + serialized_char: 'G', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap2 => TileData { + glyph: 0, + serialized_char: '@', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap3 => TileData { + glyph: 0, + serialized_char: ')', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap4 => TileData { + glyph: 0, + serialized_char: '(', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap5 => TileData { + glyph: 0, + serialized_char: '$', // Unsure about this + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap6 => TileData { + glyph: 0, + serialized_char: 'α', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap7 => TileData { + glyph: 0, + serialized_char: 'ß', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap8 => TileData { + glyph: 0, + serialized_char: 'Γ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap9 => TileData { + glyph: 0, + serialized_char: 'π', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap10 => TileData { + glyph: 0, + serialized_char: 'Σ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap11 => TileData { + glyph: 0, + serialized_char: 'σ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap12 => TileData { + glyph: 0, + serialized_char: 'µ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Trap13 => TileData { + glyph: 0, + serialized_char: 'τ', + color_fg: vga::BLACK, + color_bg: vga::BLACK, + blink: false, + }, + TileType::Player => TileData { + glyph: to_cp437('≡'), + serialized_char: 'P', + color_fg: vga::BLACK, + color_bg: vga::WHITE, + blink: true, + }, + TileType::Punctuation => TileData { + glyph: to_cp437('!'), + serialized_char: '!', + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::YELLOW, + blink: false, + }, + TileType::Letter(c) => TileData { + glyph: to_cp437(c), + serialized_char: c, + color_fg: vga::WHITE_BRIGHT, + color_bg: vga::YELLOW, + blink: false, + }, + } +}