refactoring EntityId

This commit is contained in:
Niko Abeler 2023-01-07 10:08:42 +01:00
parent a1050c1440
commit 427595edb1
10 changed files with 100 additions and 52 deletions

View File

@ -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);

View File

@ -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)
}
}
}

View File

@ -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()),
}
);

View File

@ -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);

View File

@ -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<u32> = self.state.creatures.keys().map(|id| *id).collect();
let ids: Vec<EntityId> = 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 });
}

View File

@ -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<EntityId>,
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"),
}
}
}

View File

@ -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,
}

View File

@ -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<u32, Creature>,
pub items: HashMap<u32, Item>,
pub creatures: HashMap<EntityId, Creature>,
pub items: HashMap<EntityId, Item>,
pub events: Vec<Box<Event>>,
pub tavern: Option<EntityId>,
}
@ -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<_>>()
// 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());
}
}

View File

@ -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<u32>),
TalkToGuest(Option<EntityId>),
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<B: Backend>(&self, f: &mut Frame<B>, guest: Option<u32>) {
fn draw_talk_to_guest<B: Backend>(&self, f: &mut Frame<B>, guest: Option<EntityId>) {
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<EntityId>) {
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<EntityId>) {
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

View File

@ -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
}