first conversation

This commit is contained in:
Niko Abeler 2022-12-31 16:04:07 +01:00
parent aa32eaec30
commit 68c12c7f5c
4 changed files with 102 additions and 16 deletions

View File

@ -21,8 +21,9 @@ enum AppStatus {
pub struct App<'a> { pub struct App<'a> {
state: GameState, state: GameState,
guest_list: Vec<tui::widgets::ListItem<'a>>, guest_list: Vec<tui::widgets::ListItem<'a>>,
guest_state: tui::widgets::ListState, guest_list_state: tui::widgets::ListState,
status: AppStatus, status: AppStatus,
conversation: Vec<tui::text::Spans<'a>>,
} }
impl<'a> App<'a> { impl<'a> App<'a> {
@ -30,8 +31,9 @@ impl<'a> App<'a> {
App { App {
state: state, state: state,
guest_list: vec![], guest_list: vec![],
guest_state: tui::widgets::ListState::default(), guest_list_state: tui::widgets::ListState::default(),
status: AppStatus::Initial, status: AppStatus::Initial,
conversation: Vec::new(),
} }
} }
@ -42,8 +44,8 @@ impl<'a> App<'a> {
self.guest_list = self.state.guests().iter().map(|guest| { self.guest_list = self.state.guests().iter().map(|guest| {
tui::widgets::ListItem::new(guest.name.clone()) tui::widgets::ListItem::new(guest.name.clone())
}).collect(); }).collect();
self.guest_state = tui::widgets::ListState::default(); self.guest_list_state = tui::widgets::ListState::default();
self.guest_state.select(Some(0)); self.guest_list_state.select(Some(0));
self.status = AppStatus::GuestSelection; self.status = AppStatus::GuestSelection;
true true
}, },
@ -52,20 +54,22 @@ impl<'a> App<'a> {
Ok(Event::Key(event)) => { Ok(Event::Key(event)) => {
match event.code { match event.code {
KeyCode::Up => { KeyCode::Up => {
let selected = self.guest_state.selected().unwrap(); let selected = self.guest_list_state.selected().unwrap();
if selected > 0 { if selected > 0 {
self.guest_state.select(Some(selected - 1)); self.guest_list_state.select(Some(selected - 1));
} }
}, },
KeyCode::Down => { KeyCode::Down => {
let selected = self.guest_state.selected().unwrap(); let selected = self.guest_list_state.selected().unwrap();
if selected < self.guest_list.len() - 1 { if selected < self.guest_list.len() - 1 {
self.guest_state.select(Some(selected + 1)); self.guest_list_state.select(Some(selected + 1));
} }
}, },
KeyCode::Enter => { KeyCode::Enter => {
let selected = self.guest_state.selected().unwrap(); let selected = self.guest_list_state.selected().unwrap();
let guest = &self.state.guests()[selected]; let guest = &self.state.guests()[selected];
self.conversation = Vec::new();
self.greet_guest(guest);
self.status = AppStatus::TalkToGuest(guest.id()); self.status = AppStatus::TalkToGuest(guest.id());
}, },
KeyCode::Char('.') => { KeyCode::Char('.') => {
@ -89,6 +93,9 @@ impl<'a> App<'a> {
KeyCode::Esc => { KeyCode::Esc => {
self.status = AppStatus::GuestSelection; 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) let controls = tui::widgets::Paragraph::new(control_text)
.style(tui::style::Style::default().fg(tui::style::Color::White)); .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]); 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<u32>) {
let guest = self.state.get_person(guest.unwrap()).unwrap(); 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)); .style(tui::style::Style::default().fg(tui::style::Color::White));
f.render_widget(main_window, f.size()); 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<u32>) {
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"),
])
);
}
} }

View File

@ -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 { impl Display for Person {

View File

@ -6,7 +6,7 @@ use rand::prelude::*;
use crate::entity::Entity; use crate::entity::Entity;
use crate::person::Person; use crate::person::Person;
use crate::time::Time; 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}; use crate::events::{FoundTown, WorldGenesis, PersonGenesis, TavernBuilt};
pub struct GameState { pub struct GameState {
pub time: Time, pub time: Time,
@ -102,6 +102,7 @@ impl GameState {
self.people.get(&id) self.people.get(&id)
} }
/** /**
* Function to populate the world at genesis * Function to populate the world at genesis
*/ */

View File

@ -1,4 +1,4 @@
use std::{rc::Rc, collections::HashMap}; use std::{rc::Rc, collections::HashMap, fmt};
use rand::prelude::*; use rand::prelude::*;
use crate::generators::TownNameGenerator; use crate::generators::TownNameGenerator;
@ -23,6 +23,7 @@ pub struct Tavern {
pub name: String, pub name: String,
} }
#[derive(Clone)]
pub enum Structure { pub enum Structure {
Town(Rc<Town>), Town(Rc<Town>),
Tavern(Rc<Tavern>), Tavern(Rc<Tavern>),
@ -96,6 +97,14 @@ impl World {
panic!("Tavern not found"); panic!("Tavern not found");
} }
pub fn get_structure_at(&self, pos: [usize; 2]) -> Option<Structure> {
match self.structures.get(&pos) {
Some(s) => Some(s.clone()),
None => None,
}
}
} }
impl Terrain { impl Terrain {
@ -146,3 +155,12 @@ impl Tavern {
} }
} }
} }
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),
}
}
}