Introduce Ore structure and simplify durability fields

Add a new Ore structure with ownership, amount, and durability, and
extend the
Structures enum to include it. Update board generation to place ore
cells next
to player and enemy bases and adjust base coordinates accordingly.
Remove the
redundant `max_durability` field from BaseBuilding, Stone, and Tunnel,
fixing
their `get_max_durability` implementations to return constant values.
Rename the
tick handling parameter from `interval_ms` to `tick_ms`. Minor clean‑ups
include
re‑exporting the Ore module, adding TODO comments in the side panel
widget, and
simplifying the audio thread spawn in `main.rs`.
This commit is contained in:
2026-05-04 16:14:54 +02:00
parent 1daa9802ed
commit 766b65b2fc
10 changed files with 92 additions and 19 deletions
+11 -4
View File
@@ -4,7 +4,7 @@ use crate::app::{
FocusedCell, Offset, FocusedCell, Offset,
skirmish_states::{ skirmish_states::{
CellSizes, MoveFocusedCell, Players, ZoomLevel, CellSizes, MoveFocusedCell, Players, ZoomLevel,
structures::{BaseBuilding, Stone, Structures}, structures::{BaseBuilding, Ore, Stone, Structures},
units::{MinerUnit, Units}, units::{MinerUnit, Units},
}, },
}, },
@@ -58,12 +58,12 @@ impl BoardState {
let horizontal_offset: Offset = Offset::new(None, Some(h_max_offset)); let horizontal_offset: Offset = Offset::new(None, Some(h_max_offset));
let focused_cell: FocusedCell = let focused_cell: FocusedCell =
FocusedCell::new((map_height) / 2, 2, map_height, map_width); FocusedCell::new((map_height) / 2, 3, map_height, map_width);
let mut cells: Vec<Vec<CellWidget>> = Vec::new(); let mut cells: Vec<Vec<CellWidget>> = Vec::new();
let player_base_coords: (usize, usize) = ((map_height) / 2, 1); let player_base_coords: (usize, usize) = ((map_height) / 2, 2);
let enemy_base_coords: (usize, usize) = ((map_height) / 2, map_width - 2); let enemy_base_coords: (usize, usize) = ((map_height) / 2, map_width - 3);
for row in 0..map_height { for row in 0..map_height {
let mut rows: Vec<CellWidget> = Vec::new(); let mut rows: Vec<CellWidget> = Vec::new();
@@ -71,12 +71,19 @@ impl BoardState {
for col in 0..map_width { for col in 0..map_width {
let selected: bool = row == focused_cell.get_row() && col == focused_cell.get_col(); let selected: bool = row == focused_cell.get_row() && col == focused_cell.get_col();
let player_base: bool = row == player_base_coords.0 && col == player_base_coords.1; let player_base: bool = row == player_base_coords.0 && col == player_base_coords.1;
let player_ore: bool =
row == player_base_coords.0 && col == player_base_coords.1 - 1;
let enemy_base: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1; let enemy_base: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1;
let enemy_ore: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1 + 1;
let structure: Structures = if player_base { let structure: Structures = if player_base {
Structures::Base(BaseBuilding::new(Players::Player)) Structures::Base(BaseBuilding::new(Players::Player))
} else if enemy_base { } else if enemy_base {
Structures::Base(BaseBuilding::new(Players::Enemy)) Structures::Base(BaseBuilding::new(Players::Enemy))
} else if player_ore {
Structures::Ore(Ore::new(Players::Player))
} else if enemy_ore {
Structures::Ore(Ore::new(Players::Enemy))
} else { } else {
Structures::Stone(Stone::new()) Structures::Stone(Stone::new())
}; };
@@ -4,7 +4,6 @@ use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BaseBuilding { pub struct BaseBuilding {
durability: u16, durability: u16,
max_durability: u16,
stress: u8, stress: u8,
owner: Players, owner: Players,
level: u8, level: u8,
@@ -14,7 +13,6 @@ impl BaseBuilding {
pub fn new(owner: Players) -> Self { pub fn new(owner: Players) -> Self {
Self { Self {
durability: 1500, durability: 1500,
max_durability: 1500,
stress: 0, stress: 0,
owner, owner,
level: b'1', level: b'1',
@@ -44,7 +42,7 @@ impl Structure for BaseBuilding {
} }
fn get_max_durability(&self) -> u16 { fn get_max_durability(&self) -> u16 {
self.max_durability 1500
} }
fn get_stress(&self) -> u8 { fn get_stress(&self) -> u8 {
@@ -1,10 +1,12 @@
mod base; mod base;
mod ore;
mod stone; mod stone;
mod structures_enum; mod structures_enum;
mod structures_trait; mod structures_trait;
mod tunnel; mod tunnel;
pub use base::BaseBuilding; pub use base::BaseBuilding;
pub use ore::Ore;
pub use stone::Stone; pub use stone::Stone;
pub use structures_enum::Structures; pub use structures_enum::Structures;
pub use structures_trait::Structure; pub use structures_trait::Structure;
@@ -0,0 +1,68 @@
use crate::app::states::skirmish_states::{Players, structures::Structure};
use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Ore {
owner: Players,
ore_amount: u16,
// ore_max_amount: u16,
durability: u16,
stress: u8,
}
impl Ore {
pub fn new(owner: Players) -> Self {
Self {
owner,
ore_amount: 1000,
durability: 1000,
stress: 0,
}
}
pub fn get_ore_amount(&self) -> u16 {
self.ore_amount
}
pub fn get_max_ore_amount(&self) -> u16 {
1000
}
}
impl Structure for Ore {
fn get_tag(&self) -> char {
'O'
}
fn get_color(&self) -> Color {
match self.owner {
Players::Player => self.owner.get_color(),
Players::Enemy => self.owner.get_color(),
Players::Unclaimed => Color::Indexed(217),
}
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_level(&self) -> char {
' '
}
fn get_max_durability(&self) -> u16 {
1000
}
fn get_name(&self) -> &'static str {
"Ore"
}
fn get_owner(&self) -> Players {
self.owner
}
fn get_stress(&self) -> u8 {
self.stress
}
}
@@ -4,7 +4,6 @@ use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Stone { pub struct Stone {
durability: u16, durability: u16,
max_durability: u16,
stress: u8, stress: u8,
} }
@@ -12,7 +11,6 @@ impl Stone {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
durability: 1000, durability: 1000,
max_durability: 1000,
stress: 0, stress: 0,
} }
} }
@@ -36,7 +34,7 @@ impl Structure for Stone {
} }
fn get_max_durability(&self) -> u16 { fn get_max_durability(&self) -> u16 {
self.max_durability 1000
} }
fn get_stress(&self) -> u8 { fn get_stress(&self) -> u8 {
@@ -1,6 +1,6 @@
use crate::app::states::skirmish_states::{ use crate::app::states::skirmish_states::{
Players, Players,
structures::{BaseBuilding, Stone, Structure, Tunnel}, structures::{BaseBuilding, Ore, Stone, Structure, Tunnel},
}; };
use ratatui::style::Color; use ratatui::style::Color;
@@ -9,6 +9,7 @@ pub enum Structures {
Base(BaseBuilding), Base(BaseBuilding),
Tunnel(Tunnel), Tunnel(Tunnel),
Stone(Stone), Stone(Stone),
Ore(Ore),
} }
impl Structures { impl Structures {
@@ -18,6 +19,7 @@ impl Structures {
Self::Base(b) => b, Self::Base(b) => b,
Self::Tunnel(t) => t, Self::Tunnel(t) => t,
Self::Stone(s) => s, Self::Stone(s) => s,
Self::Ore(o) => o,
} }
} }
} }
@@ -4,7 +4,6 @@ use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Tunnel { pub struct Tunnel {
durability: u16, durability: u16,
max_durability: u16,
stress: u8, stress: u8,
roof_support: bool, roof_support: bool,
rail: bool, rail: bool,
@@ -15,7 +14,6 @@ impl Tunnel {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
durability: 500, durability: 500,
max_durability: 500,
stress: 25, stress: 25,
roof_support: false, roof_support: false,
rail: false, rail: false,
@@ -42,7 +40,7 @@ impl Structure for Tunnel {
} }
fn get_max_durability(&self) -> u16 { fn get_max_durability(&self) -> u16 {
self.max_durability 500
} }
fn get_stress(&self) -> u8 { fn get_stress(&self) -> u8 {
+2 -2
View File
@@ -4,8 +4,8 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
pub fn handle_tick_event(tx: Sender<()>, interval_ms: u8) { pub fn handle_tick_event(tx: Sender<()>, tick_ms: u8) {
let interval: Duration = Duration::from_millis(interval_ms as u64); let interval: Duration = Duration::from_millis(tick_ms as u64);
loop { loop {
if tx.send(()).is_err() { if tx.send(()).is_err() {
break; break;
+2
View File
@@ -68,6 +68,7 @@ impl<'a> SidePanelWidget<'a> {
} }
} }
// TODO: Relocate this to Structure trait implementations
fn structure_text(&self) -> Vec<Line<'_>> { fn structure_text(&self) -> Vec<Line<'_>> {
let s: &Structures = self.structure; let s: &Structures = self.structure;
let durability: u16 = s.get_durability(); let durability: u16 = s.get_durability();
@@ -99,6 +100,7 @@ impl<'a> SidePanelWidget<'a> {
lines lines
} }
// TODO: Relocate this to Unit trait implementations
fn unit_text(&self) -> Vec<Line<'_>> { fn unit_text(&self) -> Vec<Line<'_>> {
let u: &Option<Units> = self.unit; let u: &Option<Units> = self.unit;
let owner: Span<'_> = u.get_owner().get_span(); let owner: Span<'_> = u.get_owner().get_span();
+1 -3
View File
@@ -29,9 +29,7 @@ fn main() -> Result<()> {
thread::spawn(move || handle_ct_events(input_tx, resize_tx)); thread::spawn(move || handle_ct_events(input_tx, resize_tx));
thread::spawn(move || handle_tick_event(tick_tx, TICK_MS)); thread::spawn(move || handle_tick_event(tick_tx, TICK_MS));
thread::spawn(move || { thread::spawn(move || handle_audio(audio_rx, args.mute, args.soundtrack));
handle_audio(audio_rx, args.mute, args.soundtrack);
});
let mut terminal: Terminal<CrosstermBackend<Stdout>> = ratatui::init(); let mut terminal: Terminal<CrosstermBackend<Stdout>> = ratatui::init();
let mut app: App = App::new(args, audio_tx); let mut app: App = App::new(args, audio_tx);