first conversation
This commit is contained in:
parent
aa32eaec30
commit
68c12c7f5c
78
src/app.rs
78
src/app.rs
|
@ -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"),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
20
src/world.rs
20
src/world.rs
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue