From 427595edb14cebf61a568c154b432b465c2149f4 Mon Sep 17 00:00:00 2001 From: Niko Abeler Date: Sat, 7 Jan 2023 10:08:42 +0100 Subject: [PATCH] refactoring EntityId --- src/creature.rs | 29 ++++++++++++++++------------- src/entity.rs | 29 ++++++++++++++++++++++++++--- src/events/found_town.rs | 6 ++---- src/events/tavern_built.rs | 3 ++- src/game.rs | 8 ++++---- src/item.rs | 24 +++++++++++++++++++++--- src/site.rs | 3 ++- src/state.rs | 23 +++++++++++++---------- src/ui/mod.rs | 18 +++++++++--------- src/world.rs | 9 +++++---- 10 files changed, 100 insertions(+), 52 deletions(-) diff --git a/src/creature.rs b/src/creature.rs index d40b09a..79c38d6 100644 --- a/src/creature.rs +++ b/src/creature.rs @@ -1,7 +1,7 @@ use std::{fmt::Display}; use rand::prelude::*; -use crate::{time::Time, world::{World}, generators::PersonNameGenerator, state::{GameState, Action}, entity::{Entity, Location, EntityId}, item::ItemGenerator, events::ItemCrafted}; +use crate::{time::Time, world::{World}, generators::PersonNameGenerator, state::{GameState, Action}, entity::{Entity, Location, EntityId, EntityType}, item::ItemGenerator, events::ItemCrafted}; #[derive(Clone, Copy)] pub enum Profession { @@ -20,6 +20,7 @@ pub enum Agenda { #[derive(Clone)] pub struct Creature { pub entity: Entity, + pub loc: Location, pub name: String, pub birth_date: Time, pub profession: Profession, @@ -44,7 +45,8 @@ impl Display for Profession { impl Creature { pub fn new(birth_date: Time, location: Location, profession: Profession) -> Creature { Creature { - entity: Entity { id: 0, loc: location }, + entity: Entity::new_creature(), + loc: location, name: PersonNameGenerator::name(), birth_date: birth_date, profession: profession, @@ -109,17 +111,17 @@ impl Creature { Agenda::Traveling(destination) => { // TDOO: A* pathfinding with terrain costs // move towards destination - if self.entity.loc.x < destination.x { - self.entity.loc.x += 1; - } else if self.entity.loc.x > destination.x { - self.entity.loc.x -= 1; + if self.loc.x < destination.x { + self.loc.x += 1; + } else if self.loc.x > destination.x { + self.loc.x -= 1; } - if self.entity.loc.y < destination.y { - self.entity.loc.y += 1; - } else if self.entity.loc.y > destination.y { - self.entity.loc.y -= 1; + if self.loc.y < destination.y { + self.loc.y += 1; + } else if self.loc.y > destination.y { + self.loc.y -= 1; } - if self.entity.loc == *destination { + if self.loc == *destination { self.agenda = Agenda::Idle(10); } Vec::new() @@ -199,7 +201,7 @@ mod tests { let mut person = Creature::new(Time { time: 0 }, Location{x: 0, y: 0}, Profession::Peasant); person.agenda = Agenda::Traveling(Location{x: 10, y: 0}); person.step(&World::new(32)); - assert_eq!(person.entity.loc, Location{x: 1, y: 0}); + assert_eq!(person.loc, Location{x: 1, y: 0}); } #[test] @@ -208,7 +210,8 @@ mod tests { person.agenda = Agenda::Idle(0); let mut world = World::new(32); world.add_site(Site{ - entity: Entity { id: 0, loc: Location{x: 10, y: 10} }, + entity: Entity::new_creature(), + loc: Location{x: 10, y: 10}, structure: Structure::Town(Town::new()), }); person.step(&world); diff --git a/src/entity.rs b/src/entity.rs index bb92a31..cd1cdac 100644 --- a/src/entity.rs +++ b/src/entity.rs @@ -1,7 +1,16 @@ use std::fmt; -pub type EntityId = u32; +pub type EntityId = (EntityType, u32); + + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum EntityType { + Creature, + Site, + Item, +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct Location { @@ -12,11 +21,25 @@ pub struct Location { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub struct Entity { pub id: EntityId, - pub loc: Location } +impl Entity { + pub fn new_creature() -> Entity { + Entity { id: (EntityType::Creature, 0) } + } + + pub fn new_site() -> Entity { + Entity { id: (EntityType::Site, 0) } + } + + pub fn new_item() -> Entity { + Entity { id: (EntityType::Item, 0) } + } +} + + impl fmt::Display for Location { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "({}, {})", self.x, self.y) } -} \ No newline at end of file +} diff --git a/src/events/found_town.rs b/src/events/found_town.rs index 7a7e4a5..470416c 100644 --- a/src/events/found_town.rs +++ b/src/events/found_town.rs @@ -9,10 +9,8 @@ impl Action for FoundTown { fn apply(&self, state: &mut GameState) { state.world.add_site( Site{ - entity: Entity{ - loc: self.loc, - id: 0, - }, + entity: Entity::new_site(), + loc: self.loc, structure: Structure::Town(self.town.clone()), } ); diff --git a/src/events/tavern_built.rs b/src/events/tavern_built.rs index 2130373..825f701 100644 --- a/src/events/tavern_built.rs +++ b/src/events/tavern_built.rs @@ -9,7 +9,8 @@ pub struct TavernBuilt { impl Action for TavernBuilt { fn apply(&self, state: &mut GameState) { let tavern_id = state.world.add_site(Site{ - entity: Entity{ loc: self.loc, id: 0}, + entity: Entity::new_site(), + loc: self.loc, structure: Structure::Tavern(self.tavern.clone()), }); state.set_tavern(tavern_id); diff --git a/src/game.rs b/src/game.rs index 0771fa8..f87cae8 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,4 +1,4 @@ -use crate::state::{GameState, Event}; +use crate::{state::{GameState, Event}, entity::EntityId}; /** * This is the main game struct. @@ -18,7 +18,7 @@ impl Game { pub fn step(&mut self) { // get list of all people ids - let ids: Vec = self.state.creatures.keys().map(|id| *id).collect(); + let ids: Vec = self.state.creatures.keys().map(|id| *id).collect(); // step each person for id in ids { @@ -74,13 +74,13 @@ mod tests { crate::creature::Profession::Adventurer, ); creature.set_agenda(Agenda::Traveling(Location { x: 2, y: 2 })); - state.add_person(creature); + let id = state.add_person(creature); let mut game = Game::new(state); game.step(); assert_eq!(game.state.creatures.len(), 1); - assert_eq!(game.state.creatures[&1].entity.loc, Location { x: 1, y: 1 }); + assert_eq!(game.state.creatures[&id].loc, Location { x: 1, y: 1 }); } diff --git a/src/item.rs b/src/item.rs index 9020548..c575415 100644 --- a/src/item.rs +++ b/src/item.rs @@ -8,10 +8,18 @@ pub enum ItemType { Armor(Armor), } + +#[derive(Clone)] +pub enum ItemOwner { + Held(EntityId), + Dropped(Location), + Lost, +} + #[derive(Clone)] pub struct Item { pub entity: Entity, - pub owner: Option, + pub owner: ItemOwner, pub name: String, pub item_type: ItemType, } @@ -32,14 +40,14 @@ pub struct ItemGenerator; impl ItemGenerator { pub fn generate_item() -> Item { Item { - entity: Entity { id: 0, loc: Location{ x: 0, y: 0 } }, + entity: Entity::new_item(), name: "Sword".to_string(), item_type: ItemType::Weapon(Weapon { damage_base: 0, damage_dice: 1, damage_sides: 6, }), - owner: None, + owner: ItemOwner::Lost, } } } @@ -51,4 +59,14 @@ impl fmt::Display for ItemType { ItemType::Armor(armor) => write!(f, "Armor: {}", armor.armor_class), } } +} + +impl fmt::Display for ItemOwner { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ItemOwner::Held(entity_id) => write!(f, "Held by {:?}", entity_id), + ItemOwner::Dropped(location) => write!(f, "Dropped at {}", location), + ItemOwner::Lost => write!(f, "Lost"), + } + } } \ No newline at end of file diff --git a/src/site.rs b/src/site.rs index ef821a7..7afaa04 100644 --- a/src/site.rs +++ b/src/site.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::{entity::Entity, generators::TownNameGenerator}; +use crate::{entity::{Entity, Location}, generators::TownNameGenerator}; #[derive(Clone)] pub struct Town { @@ -20,6 +20,7 @@ pub enum Structure { pub struct Site { pub entity: Entity, + pub loc: Location, pub structure: Structure, } diff --git a/src/state.rs b/src/state.rs index 775e147..5b513ff 100644 --- a/src/state.rs +++ b/src/state.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use rand::prelude::*; use crate::entity::{Location, EntityId, Entity}; use crate::creature::{Creature, Profession, CreatureGenerator}; -use crate::item::Item; +use crate::item::{Item, ItemOwner}; use crate::site::{Town, Tavern}; use crate::time::Time; use crate::world::{World, Terrain}; @@ -12,8 +12,8 @@ use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt}; pub struct GameState { pub time: Time, pub world: World, - pub creatures: HashMap, - pub items: HashMap, + pub creatures: HashMap, + pub items: HashMap, pub events: Vec>, pub tavern: Option, } @@ -80,7 +80,7 @@ impl GameState { Some(tavern) => { let loc = self.world.get_site_location(*tavern); self.creatures.values().filter(|c| { - c.entity.loc == loc + c.loc == loc }).map(|p| p.entity.id).collect::>() // Vec::new() }, @@ -88,7 +88,7 @@ impl GameState { } } - pub fn get_creature(&self, id: u32) -> Option<&Creature> { + pub fn get_creature(&self, id: EntityId) -> Option<&Creature> { self.creatures.get(&id) } @@ -134,17 +134,20 @@ impl GameState { } } - pub fn add_person(&mut self, mut creature: Creature) { + pub fn add_person(&mut self, mut creature: Creature) -> EntityId { let id = (self.creatures.len() + 1) as u32; // avoid 0 id - creature.entity.id = id; + creature.entity.id.1 = id; + let id = creature.entity.id; self.creatures.insert(id, creature); + id } pub(crate) fn add_item(&mut self, mut item: Item) -> EntityId { let id = (self.items.len() + 1) as u32; // avoid 0 id - item.entity.id = id; + item.entity.id.1 = id; + let id = item.entity.id; self.items.insert(id, item); - id + id } pub fn build_tavern(&mut self) { @@ -170,7 +173,7 @@ impl GameState { pub fn claim_item(&mut self, new_owner_id: EntityId, item_id: EntityId) { let mut item = self.items.get_mut(&item_id).unwrap(); - item.owner = Some(new_owner_id.clone()); + item.owner = ItemOwner::Held(new_owner_id.clone()); } } diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 9f260dc..c357b6c 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -4,7 +4,7 @@ mod controls; use crossterm::event::{read, Event, KeyCode}; use tui::{backend::Backend, Frame, layout::Layout}; -use crate::{game::Game, entity::EntityId, world::Terrain}; +use crate::{game::Game, entity::{EntityId, EntityType}, world::Terrain}; use self::{chat::{Chat, ChatLine}, controls::Controls}; @@ -20,7 +20,7 @@ use self::{chat::{Chat, ChatLine}, controls::Controls}; enum AppStatus { Initial, GuestSelection, - TalkToGuest(Option), + TalkToGuest(Option), Debug, } @@ -240,16 +240,16 @@ impl<'a> App<'a> { let mut item_list = vec![]; for (id, creature) in self.game.state.creatures.iter() { list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", - id, creature.name, + id.1, creature.name, creature.profession, - creature.entity.loc, + creature.loc, ))); } for (id, item) in self.game.state.items.iter() { item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}", - id, item.name, + id.1, item.name, item.item_type, - item.entity.loc, + item.owner, ))); } @@ -319,7 +319,7 @@ impl<'a> App<'a> { f.render_widget(controls, chunks[1]); } - fn draw_talk_to_guest(&self, f: &mut Frame, guest: Option) { + fn draw_talk_to_guest(&self, f: &mut Frame, guest: Option) { let chunks = self.default_layout().split(f.size()); let guest = self.game.state.get_creature(guest.unwrap()).unwrap(); @@ -435,7 +435,7 @@ impl<'a> App<'a> { fn greet_guest(&mut self, guest_id: Option) { let guest = self.game.state.get_creature(guest_id.unwrap()).unwrap(); self.conversation.add_line(ChatLine::new( - 0, + (EntityType::Creature, 0), "You".to_owned(), "Greetings traveller!".to_owned(), false @@ -453,7 +453,7 @@ impl<'a> App<'a> { fn ask_business(&mut self, guest: Option) { let guest = self.game.state.get_creature(guest.unwrap()).unwrap(); self.conversation.add_line(ChatLine::new( - 0, + (EntityType::Creature, 0), "You".to_owned(), "What's your business?".to_owned(), false diff --git a/src/world.rs b/src/world.rs index 58e7cde..60870d6 100644 --- a/src/world.rs +++ b/src/world.rs @@ -50,10 +50,11 @@ impl World { } pub fn add_site(&mut self, mut site: Site) -> EntityId{ - let id = self.sites.len() as EntityId; - site.entity.id = id; - self.sites.insert(site.entity.loc, site); - return id; + let id = self.sites.len() as u32; + site.entity.id.1 = id; + let id = site.entity.id.clone(); + self.sites.insert(site.loc, site); + id }