WIP traveling persons
This commit is contained in:
parent
556c6a869f
commit
6318767e32
13
src/app.rs
13
src/app.rs
|
@ -1,4 +1,4 @@
|
|||
use std::rc::Rc;
|
||||
use std::{rc::Rc};
|
||||
|
||||
use crossterm::event::{read, Event, KeyCode};
|
||||
use tui::{Terminal, backend::Backend, Frame, layout::Layout};
|
||||
|
@ -41,7 +41,7 @@ impl<'a> App<'a> {
|
|||
match &self.status {
|
||||
AppStatus::Initial => {
|
||||
// determine guests
|
||||
self.guest_list = self.state.people.iter().map(|guest| {
|
||||
self.guest_list = self.state.guests().iter().map(|guest| {
|
||||
tui::widgets::ListItem::new(guest.name.clone())
|
||||
}).collect();
|
||||
self.guest_state = tui::widgets::ListState::default();
|
||||
|
@ -67,9 +67,13 @@ impl<'a> App<'a> {
|
|||
},
|
||||
KeyCode::Enter => {
|
||||
let selected = self.guest_state.selected().unwrap();
|
||||
let guest = &self.state.people[selected];
|
||||
let guest = &self.state.guests()[selected];
|
||||
self.status = AppStatus::TalkToGuest(guest.clone());
|
||||
},
|
||||
KeyCode::Char('.') => {
|
||||
self.state.step();
|
||||
self.status = AppStatus::Initial;
|
||||
},
|
||||
KeyCode::Esc => {
|
||||
return false;
|
||||
},
|
||||
|
@ -143,6 +147,9 @@ impl<'a> App<'a> {
|
|||
tui::text::Span::styled("⏎", key_style),
|
||||
tui::text::Span::raw(" talk to guest"),
|
||||
tui::text::Span::raw(" "),
|
||||
tui::text::Span::styled(".", key_style),
|
||||
tui::text::Span::raw(" pass one day"),
|
||||
tui::text::Span::raw(" "),
|
||||
tui::text::Span::styled("Esc", key_style),
|
||||
tui::text::Span::raw(" quit"),
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
mod found_town;
|
||||
mod world_genesis;
|
||||
mod person_genesis;
|
||||
mod tavern_built;
|
||||
|
||||
pub use found_town::FoundTown;
|
||||
pub use world_genesis::WorldGenesis;
|
||||
pub use person_genesis::PersonGenesis;
|
||||
pub use person_genesis::PersonGenesis;
|
||||
pub use tavern_built::TavernBuilt;
|
|
@ -0,0 +1,20 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use crate::{state::{GameState, Effect}, world::{Structure, Tavern}};
|
||||
|
||||
pub struct TavernBuilt {
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
pub tavern: Rc<Tavern>,
|
||||
}
|
||||
|
||||
impl Effect for TavernBuilt {
|
||||
fn apply(&self, state: &mut GameState) {
|
||||
state.world.add_structure(self.x, self.y, Structure::Tavern(self.tavern.clone()));
|
||||
state.set_tavern(self.tavern.clone());
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
format!("{} was built", self.tavern.name)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
use std::{rc::Rc, fmt::Display};
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::prelude::*;
|
||||
|
||||
use crate::{time::Time, world::Town, generators::PersonNameGenerator};
|
||||
use crate::{time::Time, world::Town, generators::PersonNameGenerator, state::GameState};
|
||||
|
||||
pub enum Profession {
|
||||
Peasant,
|
||||
|
@ -8,12 +10,18 @@ pub enum Profession {
|
|||
Blacksmith,
|
||||
}
|
||||
|
||||
pub enum Agenda {
|
||||
Idle,
|
||||
Traveling([usize; 2]),
|
||||
}
|
||||
|
||||
pub struct Person {
|
||||
pub name: String,
|
||||
pub birth_date: Time,
|
||||
pub birth_location: Rc<Town>,
|
||||
pub profession: Profession,
|
||||
pub location: [usize; 2],
|
||||
pub agenda: Agenda,
|
||||
}
|
||||
|
||||
impl Person {
|
||||
|
@ -24,6 +32,36 @@ impl Person {
|
|||
birth_location: birth_location,
|
||||
profession: Profession::Peasant,
|
||||
location: [0, 0],
|
||||
agenda: Agenda::Idle,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self, state: &mut GameState) {
|
||||
match &self.agenda {
|
||||
Agenda::Idle => {
|
||||
// do nothing
|
||||
// pick random destination
|
||||
let mut rng = rand::thread_rng();
|
||||
let dest = state.world.structures.keys().choose(&mut rng);
|
||||
self.agenda = Agenda::Traveling(*dest.unwrap());
|
||||
},
|
||||
Agenda::Traveling(destination) => {
|
||||
// TDOO: A* pathfinding with terrain costs
|
||||
// move towards destination
|
||||
if self.location[0] < destination[0] {
|
||||
self.location[0] += 1;
|
||||
} else if self.location[0] > destination[0] {
|
||||
self.location[0] -= 1;
|
||||
}
|
||||
if self.location[1] < destination[1] {
|
||||
self.location[1] += 1;
|
||||
} else if self.location[1] > destination[1] {
|
||||
self.location[1] -= 1;
|
||||
}
|
||||
if self.location == *destination {
|
||||
self.agenda = Agenda::Idle;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
58
src/state.rs
58
src/state.rs
|
@ -4,13 +4,14 @@ use std::rc::Rc;
|
|||
use rand::prelude::*;
|
||||
use crate::person::Person;
|
||||
use crate::time::Time;
|
||||
use crate::world::{World, Terrain, Town};
|
||||
use crate::events::{FoundTown, WorldGenesis, PersonGenesis};
|
||||
use crate::world::{World, Terrain, Town, Tavern, Structure};
|
||||
use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt};
|
||||
pub struct GameState {
|
||||
pub time: Time,
|
||||
pub world: World,
|
||||
pub people: Vec<Rc<Person>>,
|
||||
pub events: Vec<Box<Event>>
|
||||
pub events: Vec<Box<Event>>,
|
||||
pub tavern: Option<Rc<Tavern>>,
|
||||
}
|
||||
|
||||
pub struct Event {
|
||||
|
@ -43,15 +44,23 @@ impl GameState {
|
|||
people: Vec::new(),
|
||||
world: world,
|
||||
events: events,
|
||||
tavern: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_tavern(&mut self, tavern: Rc<Tavern>) {
|
||||
self.tavern = Some(tavern);
|
||||
}
|
||||
|
||||
pub fn add_event(&mut self, event: Event) {
|
||||
event.effect.apply(self);
|
||||
self.events.push(Box::new(event));
|
||||
}
|
||||
|
||||
pub fn step(&mut self) {
|
||||
// for p in self.people.iter() {
|
||||
// p.step(self);
|
||||
// }
|
||||
self.time.time += 1;
|
||||
}
|
||||
|
||||
|
@ -67,6 +76,28 @@ impl GameState {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Getters
|
||||
*/
|
||||
|
||||
pub fn guests(&self) -> Vec<Rc<Person>> {
|
||||
match &self.tavern {
|
||||
Some(tavern) => {
|
||||
let loc = self.world.get_tavern_location(tavern);
|
||||
self.people.iter().filter(|person| {
|
||||
person.location == loc
|
||||
}).map(|p| p.clone()).collect()
|
||||
},
|
||||
None => Vec::new(),
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to populate the world at genesis
|
||||
*/
|
||||
|
||||
pub fn found_town(&mut self) {
|
||||
let mut rng = rand::thread_rng();
|
||||
loop {
|
||||
|
@ -109,4 +140,25 @@ impl GameState {
|
|||
pub fn add_person(&mut self, person: Rc<Person>) {
|
||||
self.people.push(person);
|
||||
}
|
||||
|
||||
pub fn build_tavern(&mut self) {
|
||||
let mut rng = rand::thread_rng();
|
||||
loop {
|
||||
let x = rng.gen_range(0..self.world.size);
|
||||
let y = rng.gen_range(0..self.world.size);
|
||||
if
|
||||
self.world.map[x][y].terrain == Terrain::Flats ||
|
||||
self.world.map[x][y].terrain == Terrain::Hills
|
||||
{
|
||||
self.add_event(Event {
|
||||
time: self.time,
|
||||
effect: Box::new(TavernBuilt {
|
||||
x: x,
|
||||
y: y,
|
||||
tavern: Rc::new(Tavern::new()),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
src/world.rs
47
src/world.rs
|
@ -1,4 +1,4 @@
|
|||
use std::rc::Rc;
|
||||
use std::{rc::Rc, collections::HashMap};
|
||||
use rand::prelude::*;
|
||||
|
||||
use crate::generators::TownNameGenerator;
|
||||
|
@ -19,25 +19,29 @@ pub struct Town {
|
|||
pub name: String,
|
||||
}
|
||||
|
||||
pub struct Tavern {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub enum Structure {
|
||||
Town(Rc<Town>),
|
||||
Tavern(Rc<Tavern>),
|
||||
}
|
||||
|
||||
pub struct WorldCell {
|
||||
pub terrain: Terrain,
|
||||
pub structure: Option<Structure>,
|
||||
}
|
||||
|
||||
pub struct World {
|
||||
pub map: Vec<Vec<WorldCell>>,
|
||||
pub size: usize,
|
||||
pub structures: HashMap<[usize; 2], Structure>
|
||||
}
|
||||
|
||||
impl WorldCell {
|
||||
pub fn new(terrain: Terrain) -> WorldCell {
|
||||
WorldCell {
|
||||
terrain: terrain,
|
||||
structure: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,26 +59,43 @@ impl World {
|
|||
World {
|
||||
map: map,
|
||||
size: size,
|
||||
structures: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_structure(&mut self, x: usize, y: usize, structure: Structure) {
|
||||
self.map[x][y].structure = Some(structure);
|
||||
self.structures.insert([x, y], structure);
|
||||
}
|
||||
|
||||
|
||||
pub fn get_town_location(&self, town: &Rc<Town>) -> [usize; 2] {
|
||||
for x in 0..self.size {
|
||||
for y in 0..self.size {
|
||||
if let Some(Structure::Town(t)) = &self.map[x][y].structure {
|
||||
if Rc::ptr_eq(&t, town) {
|
||||
return [x, y];
|
||||
for (location, structure) in self.structures.iter() {
|
||||
match structure {
|
||||
Structure::Town(t) => {
|
||||
if Rc::ptr_eq(t, town) {
|
||||
return *location;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
panic!("Town not found");
|
||||
}
|
||||
|
||||
pub fn get_tavern_location(&self, tavern: &Rc<Tavern>) -> [usize; 2] {
|
||||
for (location, structure) in self.structures.iter() {
|
||||
match structure {
|
||||
Structure::Tavern(t) => {
|
||||
if Rc::ptr_eq(t, tavern) {
|
||||
return *location;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
panic!("Tavern not found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Terrain {
|
||||
|
@ -117,3 +138,11 @@ impl Town {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Tavern {
|
||||
pub fn new() -> Tavern {
|
||||
Tavern {
|
||||
name: TownNameGenerator::name(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue