2022-12-31 10:44:42 +00:00
|
|
|
use std::{rc::Rc, fmt::Display};
|
2022-12-31 13:03:24 +00:00
|
|
|
use rand::prelude::*;
|
2022-12-31 08:38:01 +00:00
|
|
|
|
2023-01-04 13:54:57 +00:00
|
|
|
use crate::{time::Time, world::{World}, generators::PersonNameGenerator, state::{GameState, Action}, entity::{Entity, Location, EntityId}};
|
2022-12-31 08:38:01 +00:00
|
|
|
|
2022-12-31 14:22:44 +00:00
|
|
|
#[derive(Clone, Copy)]
|
2022-12-31 07:54:18 +00:00
|
|
|
pub enum Profession {
|
|
|
|
Peasant,
|
|
|
|
}
|
|
|
|
|
2022-12-31 14:22:44 +00:00
|
|
|
#[derive(Clone, Copy)]
|
2022-12-31 13:03:24 +00:00
|
|
|
pub enum Agenda {
|
2022-12-31 14:22:44 +00:00
|
|
|
Idle(u32),
|
2023-01-04 13:37:25 +00:00
|
|
|
Traveling(Location),
|
2022-12-31 13:03:24 +00:00
|
|
|
}
|
|
|
|
|
2022-12-31 14:22:44 +00:00
|
|
|
#[derive(Clone)]
|
2023-01-04 13:37:25 +00:00
|
|
|
pub struct Creature {
|
|
|
|
pub entity: Entity,
|
2022-12-31 07:54:18 +00:00
|
|
|
pub name: String,
|
2022-12-31 08:38:01 +00:00
|
|
|
pub birth_date: Time,
|
2022-12-31 07:54:18 +00:00
|
|
|
pub profession: Profession,
|
2022-12-31 13:03:24 +00:00
|
|
|
pub agenda: Agenda,
|
2022-12-31 08:38:01 +00:00
|
|
|
}
|
|
|
|
|
2023-01-04 13:37:25 +00:00
|
|
|
impl Creature {
|
2023-01-04 13:54:57 +00:00
|
|
|
pub fn new(birth_date: Time, location: Location) -> Creature {
|
2023-01-04 13:37:25 +00:00
|
|
|
Creature {
|
|
|
|
entity: Entity { id: 0, loc: location },
|
2022-12-31 08:38:01 +00:00
|
|
|
name: PersonNameGenerator::name(),
|
|
|
|
birth_date: birth_date,
|
|
|
|
profession: Profession::Peasant,
|
2022-12-31 14:22:44 +00:00
|
|
|
agenda: Agenda::Idle(0),
|
2022-12-31 13:03:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-04 13:37:25 +00:00
|
|
|
pub fn step(&mut self, world: &World) -> Vec<Box<dyn Action>> {
|
2022-12-31 13:03:24 +00:00
|
|
|
match &self.agenda {
|
2022-12-31 14:22:44 +00:00
|
|
|
Agenda::Idle(days) => {
|
2022-12-31 13:03:24 +00:00
|
|
|
// do nothing
|
2022-12-31 14:22:44 +00:00
|
|
|
if *days <= 0 {
|
|
|
|
// pick random destination
|
|
|
|
let mut rng = rand::thread_rng();
|
2023-01-04 13:37:25 +00:00
|
|
|
let dest = world.structures.keys().choose(&mut rng);
|
2022-12-31 14:22:44 +00:00
|
|
|
self.agenda = Agenda::Traveling(*dest.unwrap());
|
|
|
|
} else {
|
|
|
|
self.agenda = Agenda::Idle(days - 1);
|
|
|
|
}
|
2023-01-04 13:37:25 +00:00
|
|
|
Vec::new()
|
2022-12-31 13:03:24 +00:00
|
|
|
},
|
|
|
|
Agenda::Traveling(destination) => {
|
|
|
|
// TDOO: A* pathfinding with terrain costs
|
|
|
|
// move towards destination
|
2023-01-04 13:37:25 +00:00
|
|
|
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;
|
2022-12-31 13:03:24 +00:00
|
|
|
}
|
2023-01-04 13:37:25 +00:00
|
|
|
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;
|
2022-12-31 13:03:24 +00:00
|
|
|
}
|
2023-01-04 13:37:25 +00:00
|
|
|
if self.entity.loc == *destination {
|
2022-12-31 14:22:44 +00:00
|
|
|
self.agenda = Agenda::Idle(10);
|
2022-12-31 13:03:24 +00:00
|
|
|
}
|
2023-01-04 13:37:25 +00:00
|
|
|
Vec::new()
|
2022-12-31 13:03:24 +00:00
|
|
|
},
|
2022-12-31 08:38:01 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-31 15:04:07 +00:00
|
|
|
|
2023-01-04 13:37:25 +00:00
|
|
|
pub fn set_agenda(&mut self, agenda: Agenda) {
|
|
|
|
self.agenda = agenda;
|
|
|
|
}
|
|
|
|
|
2022-12-31 15:04:07 +00:00
|
|
|
pub fn say_agenda(&self, state: & GameState) -> String {
|
|
|
|
match &self.agenda {
|
|
|
|
Agenda::Idle(days) => format!("I'll stay here for {} days", days),
|
|
|
|
Agenda::Traveling(destination) => {
|
|
|
|
let dest_struct = state.world.get_structure_at(*destination);
|
|
|
|
match dest_struct {
|
|
|
|
Some(dest) => {
|
|
|
|
return format!("I'm traveling to {}", dest);
|
|
|
|
},
|
|
|
|
None => return format!("I'm traveling to an unknown location"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-12-31 10:44:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-04 13:37:25 +00:00
|
|
|
impl Display for Creature {
|
2022-12-31 10:44:42 +00:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "{}", self.name)
|
|
|
|
}
|
2022-12-31 14:22:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
2023-01-04 13:54:57 +00:00
|
|
|
use crate::world::{World, Structure, Town};
|
2022-12-31 14:22:44 +00:00
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_person_creation() {
|
2023-01-04 13:54:57 +00:00
|
|
|
let person = Creature::new(Time { time: 0 }, Location{x: 0, y: 0});
|
2022-12-31 14:22:44 +00:00
|
|
|
assert_ne!(person.name, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_traveling() {
|
2023-01-04 13:54:57 +00:00
|
|
|
let mut person = Creature::new(Time { time: 0 }, Location{x: 0, y: 0});
|
2023-01-04 13:37:25 +00:00
|
|
|
person.agenda = Agenda::Traveling(Location{x: 10, y: 0});
|
|
|
|
person.step(&World::new(32));
|
|
|
|
assert_eq!(person.entity.loc, Location{x: 1, y: 0});
|
2022-12-31 14:22:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_start_traveling() {
|
2023-01-04 13:54:57 +00:00
|
|
|
let mut person = Creature::new(Time { time: 0 }, Location{x: 0, y: 0});
|
2022-12-31 14:22:44 +00:00
|
|
|
person.agenda = Agenda::Idle(0);
|
2023-01-04 13:37:25 +00:00
|
|
|
let mut world = World::new(32);
|
|
|
|
world.add_structure(Location{x: 10, y: 10}, Structure::Town(Rc::new(Town::new())));
|
|
|
|
person.step(&world);
|
2022-12-31 14:22:44 +00:00
|
|
|
match &person.agenda {
|
|
|
|
Agenda::Traveling(_) => {},
|
|
|
|
_ => { panic!("Person should be traveling") },
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2022-12-31 07:54:18 +00:00
|
|
|
}
|