Can change bot type in rules screen

This commit is contained in:
Pierre HUBERT 2022-10-15 15:07:17 +02:00
parent 26d5f85c3c
commit 454dff923b
4 changed files with 64 additions and 29 deletions

View File

@ -13,7 +13,8 @@ use tui::{Frame, Terminal};
use sea_battle_backend::data::GameRules; use sea_battle_backend::data::GameRules;
use crate::constants::TICK_RATE; use crate::constants::{HIGHLIGHT_COLOR, TICK_RATE};
use crate::ui_screens::select_bot_type::SelectBotTypeScreen;
use crate::ui_screens::utils::centered_rect_size; use crate::ui_screens::utils::centered_rect_size;
use crate::ui_screens::ScreenResult; use crate::ui_screens::ScreenResult;
use crate::ui_widgets::button_widget::ButtonWidget; use crate::ui_widgets::button_widget::ButtonWidget;
@ -27,6 +28,7 @@ enum EditingField {
BoatsList, BoatsList,
BoatsCanTouch, BoatsCanTouch,
PlayerContinueOnHit, PlayerContinueOnHit,
BotType,
Cancel, Cancel,
OK, OK,
} }
@ -70,6 +72,14 @@ impl GameRulesConfigurationScreen {
// Submit results // Submit results
KeyCode::Enter => { KeyCode::Enter => {
if self.curr_field == EditingField::BotType {
if let ScreenResult::Ok(t) =
SelectBotTypeScreen::default().show(terminal)?
{
self.rules.bot_type = t;
}
}
if self.curr_field == EditingField::Cancel { if self.curr_field == EditingField::Cancel {
return Ok(ScreenResult::Canceled); return Ok(ScreenResult::Canceled);
} }
@ -143,7 +153,7 @@ impl GameRulesConfigurationScreen {
} }
fn ui<B: Backend>(&mut self, f: &mut Frame<B>) { fn ui<B: Backend>(&mut self, f: &mut Frame<B>) {
let area = centered_rect_size(50, 16, &f.size()); let area = centered_rect_size(50, 20, &f.size());
let block = Block::default().title("Game rules").borders(Borders::ALL); let block = Block::default().title("Game rules").borders(Borders::ALL);
f.render_widget(block, area); f.render_widget(block, area);
@ -156,7 +166,8 @@ impl GameRulesConfigurationScreen {
Constraint::Length(3), Constraint::Length(3),
Constraint::Length(1), Constraint::Length(1),
Constraint::Length(1), Constraint::Length(1),
Constraint::Length(1), Constraint::Length(3), // Bot type
Constraint::Length(1), // Margin
Constraint::Length(1), // Buttons Constraint::Length(1), // Buttons
Constraint::Length(1), // Error message (if any) Constraint::Length(1), // Error message (if any)
]) ])
@ -206,6 +217,22 @@ impl GameRulesConfigurationScreen {
); );
f.render_widget(editor, chunks[EditingField::PlayerContinueOnHit as usize]); f.render_widget(editor, chunks[EditingField::PlayerContinueOnHit as usize]);
// Select bot type
let bot_type_text = format!("Bot type: {}", self.rules.bot_type.description().name);
let text = Paragraph::new(bot_type_text.as_str()).style(
match self.curr_field == EditingField::BotType {
false => Style::default(),
true => Style::default().fg(HIGHLIGHT_COLOR),
},
);
f.render_widget(
text,
chunks[EditingField::BotType as usize].inner(&Margin {
horizontal: 0,
vertical: 1,
}),
);
// Buttons // Buttons
let buttons_chunk = Layout::default() let buttons_chunk = Layout::default()
.direction(Direction::Horizontal) .direction(Direction::Horizontal)

View File

@ -27,7 +27,7 @@ impl Default for SelectBotTypeScreen {
Self { Self {
state: Default::default(), state: Default::default(),
curr_selection: types.len() - 1, curr_selection: types.len() - 1,
types, types: types.to_vec(),
} }
} }
} }

View File

@ -36,7 +36,7 @@ impl GameRules {
.join(","), .join(","),
boats_can_touch: MULTI_PLAYER_BOATS_CAN_TOUCH, boats_can_touch: MULTI_PLAYER_BOATS_CAN_TOUCH,
player_continue_on_hit: MULTI_PLAYER_PLAYER_CAN_CONTINUE_AFTER_HIT, player_continue_on_hit: MULTI_PLAYER_PLAYER_CAN_CONTINUE_AFTER_HIT,
bot_type: BotType::Random, bot_type: BotType::Smart,
} }
} }

View File

@ -9,13 +9,42 @@ pub enum BotType {
Smart, Smart,
} }
#[derive(serde::Serialize)] impl BotType {
pub fn description(&self) -> &'static BotDescription {
BOTS_TYPES.iter().find(|d| d.r#type == *self).unwrap()
}
}
#[derive(serde::Serialize, Clone)]
pub struct BotDescription { pub struct BotDescription {
pub r#type: BotType, pub r#type: BotType,
pub name: &'static str, pub name: &'static str,
pub description: &'static str, pub description: &'static str,
} }
const BOTS_TYPES: [BotDescription; 4] = [
BotDescription {
r#type: BotType::Linear,
name: "Linear",
description: "Linear strike. Shoot A1, A2, A3, ..., B1, B2, ...",
},
BotDescription {
r#type: BotType::Random,
name: "Random",
description: "Random search. Random strike.",
},
BotDescription {
r#type: BotType::Intermediate,
name: "Intermediate",
description: "Random search. Intelligent strike.",
},
BotDescription {
r#type: BotType::Smart,
name: "Smart",
description: "Smart search. Smart strike.",
},
];
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
pub struct PlayConfiguration { pub struct PlayConfiguration {
pub min_boat_len: usize, pub min_boat_len: usize,
@ -26,7 +55,7 @@ pub struct PlayConfiguration {
pub max_map_height: usize, pub max_map_height: usize,
pub min_boats_number: usize, pub min_boats_number: usize,
pub max_boats_number: usize, pub max_boats_number: usize,
pub bot_types: Vec<BotDescription>, pub bot_types: &'static [BotDescription],
pub ordinate_alphabet: &'static str, pub ordinate_alphabet: &'static str,
} }
@ -41,28 +70,7 @@ impl Default for PlayConfiguration {
max_map_height: MAX_MAP_HEIGHT, max_map_height: MAX_MAP_HEIGHT,
min_boats_number: MIN_BOATS_NUMBER, min_boats_number: MIN_BOATS_NUMBER,
max_boats_number: MAX_BOATS_NUMBER, max_boats_number: MAX_BOATS_NUMBER,
bot_types: vec![ bot_types: &BOTS_TYPES,
BotDescription {
r#type: BotType::Linear,
name: "Linear",
description: "Linear strike. Shoot A1, A2, A3, ..., B1, B2, ...",
},
BotDescription {
r#type: BotType::Random,
name: "Ranom",
description: "Random search. Random strike.",
},
BotDescription {
r#type: BotType::Intermediate,
name: "Intermediate",
description: "Random search. Intelligent strike.",
},
BotDescription {
r#type: BotType::Smart,
name: "Smart",
description: "Smart search. Smart strike.",
},
],
ordinate_alphabet: ALPHABET, ordinate_alphabet: ALPHABET,
} }
} }