diff --git a/src/app.rs b/src/app.rs index 8e31bd1..b95092d 100644 --- a/src/app.rs +++ b/src/app.rs @@ -21,8 +21,9 @@ enum AppStatus { pub struct App<'a> { state: GameState, guest_list: Vec>, - guest_state: tui::widgets::ListState, + guest_list_state: tui::widgets::ListState, status: AppStatus, + conversation: Vec>, } impl<'a> App<'a> { @@ -30,8 +31,9 @@ impl<'a> App<'a> { App { state: state, guest_list: vec![], - guest_state: tui::widgets::ListState::default(), + guest_list_state: tui::widgets::ListState::default(), status: AppStatus::Initial, + conversation: Vec::new(), } } @@ -42,8 +44,8 @@ impl<'a> App<'a> { self.guest_list = self.state.guests().iter().map(|guest| { tui::widgets::ListItem::new(guest.name.clone()) }).collect(); - self.guest_state = tui::widgets::ListState::default(); - self.guest_state.select(Some(0)); + self.guest_list_state = tui::widgets::ListState::default(); + self.guest_list_state.select(Some(0)); self.status = AppStatus::GuestSelection; true }, @@ -52,20 +54,22 @@ impl<'a> App<'a> { Ok(Event::Key(event)) => { match event.code { KeyCode::Up => { - let selected = self.guest_state.selected().unwrap(); + let selected = self.guest_list_state.selected().unwrap(); if selected > 0 { - self.guest_state.select(Some(selected - 1)); + self.guest_list_state.select(Some(selected - 1)); } }, KeyCode::Down => { - let selected = self.guest_state.selected().unwrap(); + let selected = self.guest_list_state.selected().unwrap(); if selected < self.guest_list.len() - 1 { - self.guest_state.select(Some(selected + 1)); + self.guest_list_state.select(Some(selected + 1)); } }, KeyCode::Enter => { - let selected = self.guest_state.selected().unwrap(); + let selected = self.guest_list_state.selected().unwrap(); let guest = &self.state.guests()[selected]; + self.conversation = Vec::new(); + self.greet_guest(guest); self.status = AppStatus::TalkToGuest(guest.id()); }, KeyCode::Char('.') => { @@ -89,6 +93,9 @@ impl<'a> App<'a> { KeyCode::Esc => { self.status = AppStatus::GuestSelection; }, + KeyCode::Char('a') => { + self.ask_business(*guest); + }, _ => {} } }, @@ -155,15 +162,60 @@ impl<'a> App<'a> { let controls = tui::widgets::Paragraph::new(control_text) .style(tui::style::Style::default().fg(tui::style::Color::White)); - f.render_stateful_widget(main_window, chunks[0], &mut self.guest_state); + f.render_stateful_widget(main_window, chunks[0], &mut self.guest_list_state); f.render_widget(controls, chunks[1]); } - fn draw_talk_to_guest(&self, f: &mut Frame, guest: Option) { let guest = self.state.get_person(guest.unwrap()).unwrap(); - let main_window = tui::widgets::Paragraph::new(guest.name.clone()) - .block(tui::widgets::Block::default().title("Guests").borders(tui::widgets::Borders::ALL)) + + let key_style = tui::style::Style::default() + .add_modifier(tui::style::Modifier::BOLD) + .fg(tui::style::Color::Green) + .bg(tui::style::Color::Black); + + let mut full_text = self.conversation.clone(); + full_text.push(tui::text::Spans::from(vec![ + tui::text::Span::styled("(a) ", key_style), + tui::text::Span::raw("What's your business?"), + ])); + let text = tui::text::Text::from(full_text); + + let main_window = tui::widgets::Paragraph::new(text) + .block(tui::widgets::Block::default().title(guest.name.clone()).borders(tui::widgets::Borders::ALL)) .style(tui::style::Style::default().fg(tui::style::Color::White)); f.render_widget(main_window, f.size()); } + + /** + * Conversation + */ + fn greet_guest(&mut self, guest: &Person) { + self.conversation.push( + tui::text::Spans::from(vec![ + tui::text::Span::styled("Greetings traveller?\n", tui::style::Style::default().fg(tui::style::Color::Yellow)), + ]) + ); + self.conversation.push( + tui::text::Spans::from(vec![ + tui::text::Span::raw("Hello, I'm "), + tui::text::Span::styled(guest.name.clone(), tui::style::Style::default().add_modifier(tui::style::Modifier::BOLD)), + tui::text::Span::raw(".\n"), + ]) + ); + } + + fn ask_business(&mut self, guest: Option) { + let guest = self.state.get_person(guest.unwrap()).unwrap(); + self.conversation.push( + tui::text::Spans::from(vec![ + tui::text::Span::styled("What's your business?\n", tui::style::Style::default().fg(tui::style::Color::Yellow)) + ]) + ); + self.conversation.push( + tui::text::Spans::from(vec![ + tui::text::Span::raw(guest.say_agenda(& self.state)), + tui::text::Span::raw("\n"), + ]) + ); + } } \ No newline at end of file diff --git a/src/person.rs b/src/person.rs index c84dcd7..967a506 100644 --- a/src/person.rs +++ b/src/person.rs @@ -72,6 +72,21 @@ impl Person { }, } } + + 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"), + } + } + } + } } impl Display for Person { diff --git a/src/state.rs b/src/state.rs index d572377..504089c 100644 --- a/src/state.rs +++ b/src/state.rs @@ -6,7 +6,7 @@ use rand::prelude::*; use crate::entity::Entity; use crate::person::Person; use crate::time::Time; -use crate::world::{World, Terrain, Town, Tavern}; +use crate::world::{World, Terrain, Town, Tavern, Structure}; use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt}; pub struct GameState { pub time: Time, @@ -102,6 +102,7 @@ impl GameState { self.people.get(&id) } + /** * Function to populate the world at genesis */ diff --git a/src/world.rs b/src/world.rs index 26184c5..7a41e73 100644 --- a/src/world.rs +++ b/src/world.rs @@ -1,4 +1,4 @@ -use std::{rc::Rc, collections::HashMap}; +use std::{rc::Rc, collections::HashMap, fmt}; use rand::prelude::*; use crate::generators::TownNameGenerator; @@ -23,6 +23,7 @@ pub struct Tavern { pub name: String, } +#[derive(Clone)] pub enum Structure { Town(Rc), Tavern(Rc), @@ -96,6 +97,14 @@ impl World { panic!("Tavern not found"); } + + pub fn get_structure_at(&self, pos: [usize; 2]) -> Option { + match self.structures.get(&pos) { + Some(s) => Some(s.clone()), + None => None, + } + } + } impl Terrain { @@ -145,4 +154,13 @@ impl Tavern { name: TownNameGenerator::name(), } } -} \ No newline at end of file +} + +impl fmt::Display for Structure { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Structure::Town(t) => write!(f, "Town: {}", t.name), + Structure::Tavern(t) => write!(f, "Tavern: {}", t.name), + } + } +}