222 lines
5.9 KiB
Rust
222 lines
5.9 KiB
Rust
|
|
use std::collections::HashMap;
|
|
use std::rc::Rc;
|
|
|
|
use rand::prelude::*;
|
|
use crate::entity::Entity;
|
|
use crate::person::Person;
|
|
use crate::time::Time;
|
|
use crate::world::{World, Terrain, Town, Tavern};
|
|
use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt};
|
|
pub struct GameState {
|
|
pub time: Time,
|
|
pub world: World,
|
|
pub people: HashMap<u32, Person>,
|
|
pub events: Vec<Box<Event>>,
|
|
pub tavern: Option<Rc<Tavern>>,
|
|
}
|
|
|
|
pub struct Event {
|
|
pub time: Time,
|
|
pub effect: Box<dyn Effect>,
|
|
}
|
|
|
|
pub trait Effect {
|
|
fn apply(&self, state: &mut GameState);
|
|
fn description(&self) -> String;
|
|
}
|
|
|
|
impl Event {
|
|
pub fn description(&self) -> String {
|
|
format!("{}: {}", self.time, self.effect.description())
|
|
}
|
|
}
|
|
|
|
|
|
impl GameState {
|
|
pub fn new(world: World) -> GameState {
|
|
let mut events = Vec::new();
|
|
events.push(Box::new(Event {
|
|
time: Time { time: 0 },
|
|
effect: Box::new(WorldGenesis),
|
|
}));
|
|
|
|
GameState {
|
|
time: Time { time: 0 },
|
|
people: HashMap::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) {
|
|
let ids: Vec<u32> = self.people.keys().map(|id| *id).collect();
|
|
for id in ids {
|
|
let mut person = self.people.get_mut(&id).unwrap().clone();
|
|
person.step(self);
|
|
self.people.insert(id, person);
|
|
}
|
|
self.time.time += 1;
|
|
}
|
|
|
|
pub fn step_n(&mut self, n: u32) {
|
|
for _ in 0..n {
|
|
self.step();
|
|
}
|
|
}
|
|
|
|
pub fn step_year(&mut self) {
|
|
for _ in 0..360 {
|
|
self.step();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Getters
|
|
*/
|
|
|
|
pub fn guests(&self) -> Vec<Person> {
|
|
match &self.tavern {
|
|
Some(tavern) => {
|
|
let loc = self.world.get_tavern_location(tavern);
|
|
self.people.values().filter(|person| {
|
|
person.location == loc
|
|
}).map(|p| p.clone()).collect()
|
|
},
|
|
None => Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn get_person(&self, id: u32) -> Option<&Person> {
|
|
self.people.get(&id)
|
|
}
|
|
|
|
/**
|
|
* Function to populate the world at genesis
|
|
*/
|
|
|
|
pub fn found_town(&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
|
|
{
|
|
let town = Rc::new(Town::new());
|
|
self.add_event(Event {
|
|
time: self.time,
|
|
effect: Box::new(FoundTown {
|
|
x: x,
|
|
y: y,
|
|
town: town.clone(),
|
|
})
|
|
});
|
|
|
|
let pop_size = rng.gen_range(20..200);
|
|
|
|
for _ in 0..pop_size {
|
|
self.add_event(Event {
|
|
time: self.time,
|
|
effect: Box::new(PersonGenesis {
|
|
town: town.clone(),
|
|
person: Person::new(
|
|
self.time.substract_years(rng.gen_range(18..30)),
|
|
town.clone(),
|
|
self.world.get_town_location(&town)
|
|
),
|
|
})
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn add_person(&mut self, person: &mut Person) {
|
|
let id = (self.people.len() + 1) as u32; // avoid 0 id
|
|
person.set_id(id);
|
|
self.people.insert(id, person.clone());
|
|
}
|
|
|
|
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()),
|
|
})
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_step() {
|
|
let mut state = GameState::new(World::new(100));
|
|
state.step();
|
|
assert_eq!(state.time.time, 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_step_n() {
|
|
let mut state = GameState::new(World::new(100));
|
|
state.step_n(10);
|
|
assert_eq!(state.time.time, 10);
|
|
}
|
|
|
|
#[test]
|
|
fn test_step_year() {
|
|
let mut state = GameState::new(World::new(100));
|
|
state.step_year();
|
|
assert_eq!(state.time.time, 360);
|
|
}
|
|
|
|
#[test]
|
|
fn test_found_town() {
|
|
let mut state = GameState::new(World::new(1));
|
|
state.world.map[0][0].terrain = Terrain::Flats;
|
|
state.time = Time { time: 1e6 as u32 };
|
|
state.found_town();
|
|
assert_ne!(state.people.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_build_tavern() {
|
|
let mut state = GameState::new(World::new(2));
|
|
state.world.map[0][0].terrain = Terrain::Flats;
|
|
state.world.map[0][1].terrain = Terrain::Flats;
|
|
state.world.map[1][0].terrain = Terrain::Hills;
|
|
state.world.map[1][1].terrain = Terrain::Hills;
|
|
state.build_tavern();
|
|
assert_eq!(state.tavern.is_some(), true);
|
|
}
|
|
} |