refactoring EntityId
This commit is contained in:
parent
a1050c1440
commit
427595edb1
|
@ -1,7 +1,7 @@
|
||||||
use std::{fmt::Display};
|
use std::{fmt::Display};
|
||||||
use rand::prelude::*;
|
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)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum Profession {
|
pub enum Profession {
|
||||||
|
@ -20,6 +20,7 @@ pub enum Agenda {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Creature {
|
pub struct Creature {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
pub loc: Location,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub birth_date: Time,
|
pub birth_date: Time,
|
||||||
pub profession: Profession,
|
pub profession: Profession,
|
||||||
|
@ -44,7 +45,8 @@ impl Display for Profession {
|
||||||
impl Creature {
|
impl Creature {
|
||||||
pub fn new(birth_date: Time, location: Location, profession: Profession) -> Creature {
|
pub fn new(birth_date: Time, location: Location, profession: Profession) -> Creature {
|
||||||
Creature {
|
Creature {
|
||||||
entity: Entity { id: 0, loc: location },
|
entity: Entity::new_creature(),
|
||||||
|
loc: location,
|
||||||
name: PersonNameGenerator::name(),
|
name: PersonNameGenerator::name(),
|
||||||
birth_date: birth_date,
|
birth_date: birth_date,
|
||||||
profession: profession,
|
profession: profession,
|
||||||
|
@ -109,17 +111,17 @@ impl Creature {
|
||||||
Agenda::Traveling(destination) => {
|
Agenda::Traveling(destination) => {
|
||||||
// TDOO: A* pathfinding with terrain costs
|
// TDOO: A* pathfinding with terrain costs
|
||||||
// move towards destination
|
// move towards destination
|
||||||
if self.entity.loc.x < destination.x {
|
if self.loc.x < destination.x {
|
||||||
self.entity.loc.x += 1;
|
self.loc.x += 1;
|
||||||
} else if self.entity.loc.x > destination.x {
|
} else if self.loc.x > destination.x {
|
||||||
self.entity.loc.x -= 1;
|
self.loc.x -= 1;
|
||||||
}
|
}
|
||||||
if self.entity.loc.y < destination.y {
|
if self.loc.y < destination.y {
|
||||||
self.entity.loc.y += 1;
|
self.loc.y += 1;
|
||||||
} else if self.entity.loc.y > destination.y {
|
} else if self.loc.y > destination.y {
|
||||||
self.entity.loc.y -= 1;
|
self.loc.y -= 1;
|
||||||
}
|
}
|
||||||
if self.entity.loc == *destination {
|
if self.loc == *destination {
|
||||||
self.agenda = Agenda::Idle(10);
|
self.agenda = Agenda::Idle(10);
|
||||||
}
|
}
|
||||||
Vec::new()
|
Vec::new()
|
||||||
|
@ -199,7 +201,7 @@ mod tests {
|
||||||
let mut person = Creature::new(Time { time: 0 }, Location{x: 0, y: 0}, Profession::Peasant);
|
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.agenda = Agenda::Traveling(Location{x: 10, y: 0});
|
||||||
person.step(&World::new(32));
|
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]
|
#[test]
|
||||||
|
@ -208,7 +210,8 @@ mod tests {
|
||||||
person.agenda = Agenda::Idle(0);
|
person.agenda = Agenda::Idle(0);
|
||||||
let mut world = World::new(32);
|
let mut world = World::new(32);
|
||||||
world.add_site(Site{
|
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()),
|
structure: Structure::Town(Town::new()),
|
||||||
});
|
});
|
||||||
person.step(&world);
|
person.step(&world);
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
use std::fmt;
|
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
|
@ -12,9 +21,23 @@ pub struct Location {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Entity {
|
pub struct Entity {
|
||||||
pub id: EntityId,
|
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 {
|
impl fmt::Display for Location {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "({}, {})", self.x, self.y)
|
write!(f, "({}, {})", self.x, self.y)
|
||||||
|
|
|
@ -9,10 +9,8 @@ impl Action for FoundTown {
|
||||||
fn apply(&self, state: &mut GameState) {
|
fn apply(&self, state: &mut GameState) {
|
||||||
state.world.add_site(
|
state.world.add_site(
|
||||||
Site{
|
Site{
|
||||||
entity: Entity{
|
entity: Entity::new_site(),
|
||||||
loc: self.loc,
|
loc: self.loc,
|
||||||
id: 0,
|
|
||||||
},
|
|
||||||
structure: Structure::Town(self.town.clone()),
|
structure: Structure::Town(self.town.clone()),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -9,7 +9,8 @@ pub struct TavernBuilt {
|
||||||
impl Action for TavernBuilt {
|
impl Action for TavernBuilt {
|
||||||
fn apply(&self, state: &mut GameState) {
|
fn apply(&self, state: &mut GameState) {
|
||||||
let tavern_id = state.world.add_site(Site{
|
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()),
|
structure: Structure::Tavern(self.tavern.clone()),
|
||||||
});
|
});
|
||||||
state.set_tavern(tavern_id);
|
state.set_tavern(tavern_id);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::state::{GameState, Event};
|
use crate::{state::{GameState, Event}, entity::EntityId};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main game struct.
|
* This is the main game struct.
|
||||||
|
@ -18,7 +18,7 @@ impl Game {
|
||||||
|
|
||||||
pub fn step(&mut self) {
|
pub fn step(&mut self) {
|
||||||
// get list of all people ids
|
// 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
|
// step each person
|
||||||
for id in ids {
|
for id in ids {
|
||||||
|
@ -74,13 +74,13 @@ mod tests {
|
||||||
crate::creature::Profession::Adventurer,
|
crate::creature::Profession::Adventurer,
|
||||||
);
|
);
|
||||||
creature.set_agenda(Agenda::Traveling(Location { x: 2, y: 2 }));
|
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);
|
let mut game = Game::new(state);
|
||||||
game.step();
|
game.step();
|
||||||
|
|
||||||
assert_eq!(game.state.creatures.len(), 1);
|
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 });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/item.rs
24
src/item.rs
|
@ -8,10 +8,18 @@ pub enum ItemType {
|
||||||
Armor(Armor),
|
Armor(Armor),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum ItemOwner {
|
||||||
|
Held(EntityId),
|
||||||
|
Dropped(Location),
|
||||||
|
Lost,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Item {
|
pub struct Item {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub owner: Option<EntityId>,
|
pub owner: ItemOwner,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub item_type: ItemType,
|
pub item_type: ItemType,
|
||||||
}
|
}
|
||||||
|
@ -32,14 +40,14 @@ pub struct ItemGenerator;
|
||||||
impl ItemGenerator {
|
impl ItemGenerator {
|
||||||
pub fn generate_item() -> Item {
|
pub fn generate_item() -> Item {
|
||||||
Item {
|
Item {
|
||||||
entity: Entity { id: 0, loc: Location{ x: 0, y: 0 } },
|
entity: Entity::new_item(),
|
||||||
name: "Sword".to_string(),
|
name: "Sword".to_string(),
|
||||||
item_type: ItemType::Weapon(Weapon {
|
item_type: ItemType::Weapon(Weapon {
|
||||||
damage_base: 0,
|
damage_base: 0,
|
||||||
damage_dice: 1,
|
damage_dice: 1,
|
||||||
damage_sides: 6,
|
damage_sides: 6,
|
||||||
}),
|
}),
|
||||||
owner: None,
|
owner: ItemOwner::Lost,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,3 +60,13 @@ impl fmt::Display for ItemType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{entity::Entity, generators::TownNameGenerator};
|
use crate::{entity::{Entity, Location}, generators::TownNameGenerator};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Town {
|
pub struct Town {
|
||||||
|
@ -20,6 +20,7 @@ pub enum Structure {
|
||||||
|
|
||||||
pub struct Site {
|
pub struct Site {
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
|
pub loc: Location,
|
||||||
pub structure: Structure,
|
pub structure: Structure,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
src/state.rs
21
src/state.rs
|
@ -4,7 +4,7 @@ use std::collections::HashMap;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use crate::entity::{Location, EntityId, Entity};
|
use crate::entity::{Location, EntityId, Entity};
|
||||||
use crate::creature::{Creature, Profession, CreatureGenerator};
|
use crate::creature::{Creature, Profession, CreatureGenerator};
|
||||||
use crate::item::Item;
|
use crate::item::{Item, ItemOwner};
|
||||||
use crate::site::{Town, Tavern};
|
use crate::site::{Town, Tavern};
|
||||||
use crate::time::Time;
|
use crate::time::Time;
|
||||||
use crate::world::{World, Terrain};
|
use crate::world::{World, Terrain};
|
||||||
|
@ -12,8 +12,8 @@ use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt};
|
||||||
pub struct GameState {
|
pub struct GameState {
|
||||||
pub time: Time,
|
pub time: Time,
|
||||||
pub world: World,
|
pub world: World,
|
||||||
pub creatures: HashMap<u32, Creature>,
|
pub creatures: HashMap<EntityId, Creature>,
|
||||||
pub items: HashMap<u32, Item>,
|
pub items: HashMap<EntityId, Item>,
|
||||||
pub events: Vec<Box<Event>>,
|
pub events: Vec<Box<Event>>,
|
||||||
pub tavern: Option<EntityId>,
|
pub tavern: Option<EntityId>,
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,7 @@ impl GameState {
|
||||||
Some(tavern) => {
|
Some(tavern) => {
|
||||||
let loc = self.world.get_site_location(*tavern);
|
let loc = self.world.get_site_location(*tavern);
|
||||||
self.creatures.values().filter(|c| {
|
self.creatures.values().filter(|c| {
|
||||||
c.entity.loc == loc
|
c.loc == loc
|
||||||
}).map(|p| p.entity.id).collect::<Vec<_>>()
|
}).map(|p| p.entity.id).collect::<Vec<_>>()
|
||||||
// Vec::new()
|
// 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)
|
self.creatures.get(&id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,15 +134,18 @@ 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
|
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);
|
self.creatures.insert(id, creature);
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_item(&mut self, mut item: Item) -> EntityId {
|
pub(crate) fn add_item(&mut self, mut item: Item) -> EntityId {
|
||||||
let id = (self.items.len() + 1) as u32; // avoid 0 id
|
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);
|
self.items.insert(id, item);
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
@ -170,7 +173,7 @@ impl GameState {
|
||||||
|
|
||||||
pub fn claim_item(&mut self, new_owner_id: EntityId, item_id: EntityId) {
|
pub fn claim_item(&mut self, new_owner_id: EntityId, item_id: EntityId) {
|
||||||
let mut item = self.items.get_mut(&item_id).unwrap();
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod controls;
|
||||||
use crossterm::event::{read, Event, KeyCode};
|
use crossterm::event::{read, Event, KeyCode};
|
||||||
use tui::{backend::Backend, Frame, layout::Layout};
|
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};
|
use self::{chat::{Chat, ChatLine}, controls::Controls};
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ use self::{chat::{Chat, ChatLine}, controls::Controls};
|
||||||
enum AppStatus {
|
enum AppStatus {
|
||||||
Initial,
|
Initial,
|
||||||
GuestSelection,
|
GuestSelection,
|
||||||
TalkToGuest(Option<u32>),
|
TalkToGuest(Option<EntityId>),
|
||||||
Debug,
|
Debug,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,16 +240,16 @@ impl<'a> App<'a> {
|
||||||
let mut item_list = vec![];
|
let mut item_list = vec![];
|
||||||
for (id, creature) in self.game.state.creatures.iter() {
|
for (id, creature) in self.game.state.creatures.iter() {
|
||||||
list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}",
|
list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}",
|
||||||
id, creature.name,
|
id.1, creature.name,
|
||||||
creature.profession,
|
creature.profession,
|
||||||
creature.entity.loc,
|
creature.loc,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
for (id, item) in self.game.state.items.iter() {
|
for (id, item) in self.game.state.items.iter() {
|
||||||
item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}",
|
item_list.push(tui::widgets::ListItem::new(format!("{}: {} ({}) at {}",
|
||||||
id, item.name,
|
id.1, item.name,
|
||||||
item.item_type,
|
item.item_type,
|
||||||
item.entity.loc,
|
item.owner,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ impl<'a> App<'a> {
|
||||||
f.render_widget(controls, chunks[1]);
|
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 chunks = self.default_layout().split(f.size());
|
||||||
|
|
||||||
let guest = self.game.state.get_creature(guest.unwrap()).unwrap();
|
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>) {
|
fn greet_guest(&mut self, guest_id: Option<EntityId>) {
|
||||||
let guest = self.game.state.get_creature(guest_id.unwrap()).unwrap();
|
let guest = self.game.state.get_creature(guest_id.unwrap()).unwrap();
|
||||||
self.conversation.add_line(ChatLine::new(
|
self.conversation.add_line(ChatLine::new(
|
||||||
0,
|
(EntityType::Creature, 0),
|
||||||
"You".to_owned(),
|
"You".to_owned(),
|
||||||
"Greetings traveller!".to_owned(),
|
"Greetings traveller!".to_owned(),
|
||||||
false
|
false
|
||||||
|
@ -453,7 +453,7 @@ impl<'a> App<'a> {
|
||||||
fn ask_business(&mut self, guest: Option<EntityId>) {
|
fn ask_business(&mut self, guest: Option<EntityId>) {
|
||||||
let guest = self.game.state.get_creature(guest.unwrap()).unwrap();
|
let guest = self.game.state.get_creature(guest.unwrap()).unwrap();
|
||||||
self.conversation.add_line(ChatLine::new(
|
self.conversation.add_line(ChatLine::new(
|
||||||
0,
|
(EntityType::Creature, 0),
|
||||||
"You".to_owned(),
|
"You".to_owned(),
|
||||||
"What's your business?".to_owned(),
|
"What's your business?".to_owned(),
|
||||||
false
|
false
|
||||||
|
|
|
@ -50,10 +50,11 @@ impl World {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_site(&mut self, mut site: Site) -> EntityId{
|
pub fn add_site(&mut self, mut site: Site) -> EntityId{
|
||||||
let id = self.sites.len() as EntityId;
|
let id = self.sites.len() as u32;
|
||||||
site.entity.id = id;
|
site.entity.id.1 = id;
|
||||||
self.sites.insert(site.entity.loc, site);
|
let id = site.entity.id.clone();
|
||||||
return id;
|
self.sites.insert(site.loc, site);
|
||||||
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue