Update formatting to use 4‑space indentation
Nix package / build (push) Successful in 8m44s
Linux package builds (test) / linux (push) Successful in 2m25s
Linux package builds (test) / aur (push) Successful in 7m41s
Rust checks / check (push) Successful in 3m39s

- Adjust rustfmt.toml to set tab_spaces = 4.
- Reformat imports, struct definitions, function bodies, and match arms
  across the project to match the new style (aligned fields, added
  spacing, etc.).
- Ensure all code complies with the updated rustfmt settings.
This commit is contained in:
GarandPLG committed 2026-10-19 17:43:43 +02:00
1 parent a981663152
commit 73f544d5d6
66 files changed
+5378 -5373

No files matched your search

File diff suppressed because it is too large. Load diff
+41 -41
View File
@@ -1,53 +1,53 @@
pub enum MoveFocusedCell {
Up,
Down,
Left,
Right,
Up,
Down,
Left,
Right,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FocusedCell {
row: usize,
col: usize,
max_row: usize,
max_col: usize,
row: usize,
col: usize,
max_row: usize,
max_col: usize,
}
impl FocusedCell {
pub fn new(row: usize, col: usize, max_row: usize, max_col: usize) -> Self {
Self {
row,
col,
max_row,
max_col,
}
}
pub fn get_coords(&self) -> (usize, usize) {
(self.row, self.col)
}
pub fn move_focused_cell(&mut self, direction: MoveFocusedCell) -> (usize, usize) {
match direction {
MoveFocusedCell::Up => {
self.row = self.row.saturating_sub(1).max(0);
}
MoveFocusedCell::Down => {
self.row = self.row.saturating_add(1).min(self.max_row - 1);
}
MoveFocusedCell::Left => {
self.col = self.col.saturating_sub(1).max(0);
}
MoveFocusedCell::Right => {
self.col = self.col.saturating_add(1).min(self.max_col - 1);
}
pub fn new(row: usize, col: usize, max_row: usize, max_col: usize) -> Self {
Self {
row,
col,
max_row,
max_col,
}
}
(self.row, self.col)
}
pub fn get_coords(&self) -> (usize, usize) {
(self.row, self.col)
}
pub fn set_focused_cell(&mut self, cell: (usize, usize)) {
self.row = cell.0.max(0).min(self.max_row - 1);
self.col = cell.1.max(0).min(self.max_col - 1);
}
pub fn move_focused_cell(&mut self, direction: MoveFocusedCell) -> (usize, usize) {
match direction {
MoveFocusedCell::Up => {
self.row = self.row.saturating_sub(1).max(0);
}
MoveFocusedCell::Down => {
self.row = self.row.saturating_add(1).min(self.max_row - 1);
}
MoveFocusedCell::Left => {
self.col = self.col.saturating_sub(1).max(0);
}
MoveFocusedCell::Right => {
self.col = self.col.saturating_add(1).min(self.max_col - 1);
}
}
(self.row, self.col)
}
pub fn set_focused_cell(&mut self, cell: (usize, usize)) {
self.row = cell.0.max(0).min(self.max_row - 1);
self.col = cell.1.max(0).min(self.max_col - 1);
}
}
+2 -2
View File
@@ -2,6 +2,6 @@ use clap::ValueEnum;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
pub enum GameMode {
LastManStanding,
FrontLines,
LastManStanding,
FrontLines,
}
@@ -3,17 +3,17 @@ use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub struct MarkedCells {
pub marking_cells: bool,
pub marked_cells: VecDeque<(usize, usize)>,
pub selected_unit: Option<Units>,
pub marking_cells: bool,
pub marked_cells: VecDeque<(usize, usize)>,
pub selected_unit: Option<Units>,
}
impl MarkedCells {
pub fn new() -> Self {
Self {
marking_cells: false,
marked_cells: VecDeque::new(),
selected_unit: None,
pub fn new() -> Self {
Self {
marking_cells: false,
marked_cells: VecDeque::new(),
selected_unit: None,
}
}
}
}
+23 -23
View File
@@ -1,35 +1,35 @@
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Offset {
value: usize,
max: usize,
value: usize,
max: usize,
}
impl Offset {
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
Self {
value: initial_value.unwrap_or(0).min(initial_max.unwrap_or(0)),
max: initial_max.unwrap_or(0),
pub fn new(initial_value: Option<usize>, initial_max: Option<usize>) -> Self {
Self {
value: initial_value.unwrap_or(0).min(initial_max.unwrap_or(0)),
max: initial_max.unwrap_or(0),
}
}
}
pub fn get_value(&self) -> usize {
self.value
}
pub fn get_value(&self) -> usize {
self.value
}
pub fn set_value(&mut self, value: usize) {
self.value = value.min(self.max);
}
pub fn set_value(&mut self, value: usize) {
self.value = value.min(self.max);
}
pub fn set_max(&mut self, max: usize) {
self.max = max;
self.value = self.value.min(max);
}
pub fn set_max(&mut self, max: usize) {
self.max = max;
self.value = self.value.min(max);
}
pub fn next(&mut self) {
self.value = self.value.saturating_add(1).min(self.max);
}
pub fn next(&mut self) {
self.value = self.value.saturating_add(1).min(self.max);
}
pub fn prev(&mut self) {
self.value = self.value.saturating_sub(1).max(0)
}
pub fn prev(&mut self) {
self.value = self.value.saturating_sub(1).max(0)
}
}
+23 -23
View File
@@ -1,37 +1,37 @@
use ratatui::{
style::{Color, Stylize},
text::Span,
style::{Color, Stylize},
text::Span,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Players {
Player,
Enemy,
Unclaimed,
Player,
Enemy,
Unclaimed,
}
impl Players {
pub fn get_text(&self) -> &'static str {
match self {
Self::Player => "Player",
Self::Enemy => "Enemy",
Self::Unclaimed => "Unclaimed",
pub fn get_text(&self) -> &'static str {
match self {
Self::Player => "Player",
Self::Enemy => "Enemy",
Self::Unclaimed => "Unclaimed",
}
}
}
pub fn get_color(&self) -> Color {
match self {
Self::Player => Color::LightBlue,
Self::Enemy => Color::LightRed,
Self::Unclaimed => Color::White,
pub fn get_color(&self) -> Color {
match self {
Self::Player => Color::LightBlue,
Self::Enemy => Color::LightRed,
Self::Unclaimed => Color::White,
}
}
}
pub fn get_span(&self) -> Span<'static> {
match self {
Self::Player => self.get_text().fg(self.get_color()),
Self::Enemy => self.get_text().fg(self.get_color()),
Self::Unclaimed => self.get_text().fg(self.get_color()),
pub fn get_span(&self) -> Span<'static> {
match self {
Self::Player => self.get_text().fg(self.get_color()),
Self::Enemy => self.get_text().fg(self.get_color()),
Self::Unclaimed => self.get_text().fg(self.get_color()),
}
}
}
}
+24 -24
View File
@@ -7,35 +7,35 @@ pub const MINE_PRODUCTION_TICKS: u64 = 1000_u64.div_ceil(TICK_MS as u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Resources {
pub wood: u32,
pub metal: u32,
pub wood: u32,
pub metal: u32,
}
impl Resources {
pub fn can_afford(&self, cost: Self) -> bool {
self.wood >= cost.wood && self.metal >= cost.metal
}
pub fn spend(&mut self, cost: Self) -> bool {
if !self.can_afford(cost) {
return false;
pub fn can_afford(&self, cost: Self) -> bool {
self.wood >= cost.wood && self.metal >= cost.metal
}
self.wood -= cost.wood;
self.metal -= cost.metal;
true
}
pub fn new(wood: u16, metal: u16) -> Self {
Self {
wood: u32::from(wood),
metal: u32::from(metal),
pub fn spend(&mut self, cost: Self) -> bool {
if !self.can_afford(cost) {
return false;
}
self.wood -= cost.wood;
self.metal -= cost.metal;
true
}
pub fn new(wood: u16, metal: u16) -> Self {
Self {
wood: u32::from(wood),
metal: u32::from(metal),
}
}
}
pub fn add_wood(&mut self, amount: u32) -> () {
self.wood = self.wood.saturating_add(amount);
}
pub fn add_wood(&mut self, amount: u32) -> () {
self.wood = self.wood.saturating_add(amount);
}
pub fn add_metal(&mut self, amount: u32) -> () {
self.metal = self.metal.saturating_add(amount);
}
pub fn add_metal(&mut self, amount: u32) -> () {
self.metal = self.metal.saturating_add(amount);
}
}
+108 -108
View File
@@ -4,135 +4,135 @@ use ratatui::{style::Color, text::Line};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BaseBuilding {
durability: u16,
stress: u8,
owner: Players,
level: u8,
queued_miners: u32,
recruitment_ticks: u16,
waiting_for_departure: bool,
durability: u16,
stress: u8,
owner: Players,
level: u8,
queued_miners: u32,
recruitment_ticks: u16,
waiting_for_departure: bool,
}
impl BaseBuilding {
pub const RECRUITMENT_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
pub const RECRUITMENT_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
pub fn queued_miners(&self) -> u32 {
self.queued_miners
}
pub fn recruitment_progress(&self) -> u16 {
(u32::from(self.recruitment_ticks) * 100 / u32::from(Self::RECRUITMENT_TICKS)) as u16
}
pub fn can_queue_miner(&self) -> bool {
self.owner != Players::Unclaimed && self.queued_miners < u32::MAX
}
pub fn queue_miner(&mut self) -> bool {
if !self.can_queue_miner() {
return false;
pub fn queued_miners(&self) -> u32 {
self.queued_miners
}
self.queued_miners += 1;
true
}
pub fn advance_recruitment(&mut self, occupied: bool) -> bool {
if self.waiting_for_departure {
if occupied {
return false;
}
self.waiting_for_departure = false;
pub fn recruitment_progress(&self) -> u16 {
(u32::from(self.recruitment_ticks) * 100 / u32::from(Self::RECRUITMENT_TICKS)) as u16
}
if self.queued_miners == 0 {
return false;
}
self.recruitment_ticks = self
.recruitment_ticks
.saturating_add(1)
.min(Self::RECRUITMENT_TICKS);
if self.recruitment_ticks < Self::RECRUITMENT_TICKS || occupied {
return false;
}
self.queued_miners -= 1;
self.recruitment_ticks = 0;
self.waiting_for_departure = true;
true
}
pub fn recruitment_status(&self, occupied: bool) -> &'static str {
if self.queued_miners == 0 {
"Queue empty"
} else if self.waiting_for_departure && occupied {
"Paused: waiting for Miner to leave base"
} else if self.recruitment_ticks == Self::RECRUITMENT_TICKS && occupied {
"Ready: waiting for free base cell"
} else {
"Recruiting"
pub fn can_queue_miner(&self) -> bool {
self.owner != Players::Unclaimed && self.queued_miners < u32::MAX
}
}
pub fn new(owner: Players) -> Self {
Self {
durability: 1500,
stress: 0,
owner,
level: 1,
queued_miners: 0,
recruitment_ticks: 0,
waiting_for_departure: false,
pub fn queue_miner(&mut self) -> bool {
if !self.can_queue_miner() {
return false;
}
self.queued_miners += 1;
true
}
pub fn advance_recruitment(&mut self, occupied: bool) -> bool {
if self.waiting_for_departure {
if occupied {
return false;
}
self.waiting_for_departure = false;
}
if self.queued_miners == 0 {
return false;
}
self.recruitment_ticks = self
.recruitment_ticks
.saturating_add(1)
.min(Self::RECRUITMENT_TICKS);
if self.recruitment_ticks < Self::RECRUITMENT_TICKS || occupied {
return false;
}
self.queued_miners -= 1;
self.recruitment_ticks = 0;
self.waiting_for_departure = true;
true
}
pub fn recruitment_status(&self, occupied: bool) -> &'static str {
if self.queued_miners == 0 {
"Queue empty"
} else if self.waiting_for_departure && occupied {
"Paused: waiting for Miner to leave base"
} else if self.recruitment_ticks == Self::RECRUITMENT_TICKS && occupied {
"Ready: waiting for free base cell"
} else {
"Recruiting"
}
}
pub fn new(owner: Players) -> Self {
Self {
durability: 1500,
stress: 0,
owner,
level: 1,
queued_miners: 0,
recruitment_ticks: 0,
waiting_for_departure: false,
}
}
}
}
impl Structure for BaseBuilding {
fn get_tag(&self) -> char {
'B'
}
fn get_color(&self) -> Color {
match self.owner {
Players::Player => Color::LightBlue,
Players::Enemy => Color::LightRed,
Players::Unclaimed => Color::LightGreen,
fn get_tag(&self) -> char {
'B'
}
}
fn get_level(&self) -> char {
(self.level + b'0') as char
}
fn get_color(&self) -> Color {
match self.owner {
Players::Player => Color::LightBlue,
Players::Enemy => Color::LightRed,
Players::Unclaimed => Color::LightGreen,
}
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_level(&self) -> char {
(self.level + b'0') as char
}
fn get_max_durability(&self) -> u16 {
1500
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_max_durability(&self) -> u16 {
1500
}
fn get_name(&self) -> &'static str {
"Base"
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_owner(&self) -> Players {
self.owner
}
fn get_name(&self) -> &'static str {
"Base"
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = self.base_text();
lines.push(Line::from(format!(
"Recruitment queue: {}",
self.queued_miners
)));
if self.queued_miners > 0 {
lines.push(Line::from(format!(
"Miner progress: {}%",
self.recruitment_progress()
)));
fn get_owner(&self) -> Players {
self.owner
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = self.base_text();
lines.push(Line::from(format!(
"Recruitment queue: {}",
self.queued_miners
)));
if self.queued_miners > 0 {
lines.push(Line::from(format!(
"Miner progress: {}%",
self.recruitment_progress()
)));
}
lines
}
lines
}
}
@@ -1,96 +1,96 @@
use crate::app::states::skirmish_states::{
Players, Resources,
structures::{Ore, Structure},
units::{Unit, Units},
Players, Resources,
structures::{Ore, Structure},
units::{Unit, Units},
};
use ratatui::{
style::{Color, Stylize},
text::Line,
style::{Color, Stylize},
text::Line,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Mine {
owner: Players,
ore: Ore,
owner: Players,
ore: Ore,
}
impl Mine {
pub const COST: Resources = Resources {
wood: 20,
metal: 10,
};
pub const METAL_PER_CYCLE: u16 = 1;
pub const STAFFED_METAL_PER_CYCLE: u16 = 2;
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
if owner == Players::Unclaimed || ore.get_owner() != Players::Unclaimed {
return None;
}
Some(Self { owner, ore })
}
pub fn get_ore_amount(&self) -> u16 {
self.ore.get_ore_amount()
}
pub fn into_ore(self) -> Ore {
self.ore
}
pub fn produce(&mut self) -> u16 {
self.produce_with_miner(false)
}
pub fn accepts_unit(&self, unit: &Units) -> bool {
matches!(unit, Units::Miner(_)) && unit.get_owner() == self.owner
}
pub fn production_per_cycle(&self, staffed: bool) -> u16 {
let rate: u16 = if staffed {
Self::STAFFED_METAL_PER_CYCLE
} else {
Self::METAL_PER_CYCLE
pub const COST: Resources = Resources {
wood: 20,
metal: 10,
};
rate.min(self.get_ore_amount())
}
pub const METAL_PER_CYCLE: u16 = 1;
pub const STAFFED_METAL_PER_CYCLE: u16 = 2;
pub fn produce_with_miner(&mut self, staffed: bool) -> u16 {
self.ore.extract(self.production_per_cycle(staffed))
}
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
if owner == Players::Unclaimed || ore.get_owner() != Players::Unclaimed {
return None;
}
Some(Self { owner, ore })
}
pub fn get_ore_amount(&self) -> u16 {
self.ore.get_ore_amount()
}
pub fn into_ore(self) -> Ore {
self.ore
}
pub fn produce(&mut self) -> u16 {
self.produce_with_miner(false)
}
pub fn accepts_unit(&self, unit: &Units) -> bool {
matches!(unit, Units::Miner(_)) && unit.get_owner() == self.owner
}
pub fn production_per_cycle(&self, staffed: bool) -> u16 {
let rate: u16 = if staffed {
Self::STAFFED_METAL_PER_CYCLE
} else {
Self::METAL_PER_CYCLE
};
rate.min(self.get_ore_amount())
}
pub fn produce_with_miner(&mut self, staffed: bool) -> u16 {
self.ore.extract(self.production_per_cycle(staffed))
}
}
impl Structure for Mine {
fn get_tag(&self) -> char {
'M'
}
fn get_color(&self) -> Color {
self.owner.get_color()
}
fn get_level(&self) -> char {
self.ore.get_level()
}
fn get_stress(&self) -> u8 {
self.ore.get_stress()
}
fn get_durability(&self) -> u16 {
self.ore.get_durability()
}
fn get_max_durability(&self) -> u16 {
self.ore.get_max_durability()
}
fn get_name(&self) -> &'static str {
"Mine"
}
fn get_owner(&self) -> Players {
self.owner
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = self.base_text();
lines.push(Line::from_iter([
"Ore: ".gray(),
self.get_ore_amount().to_string().cyan(),
format!("/{}", self.ore.get_max_ore_amount()).gray(),
]));
lines
}
fn get_tag(&self) -> char {
'M'
}
fn get_color(&self) -> Color {
self.owner.get_color()
}
fn get_level(&self) -> char {
self.ore.get_level()
}
fn get_stress(&self) -> u8 {
self.ore.get_stress()
}
fn get_durability(&self) -> u16 {
self.ore.get_durability()
}
fn get_max_durability(&self) -> u16 {
self.ore.get_max_durability()
}
fn get_name(&self) -> &'static str {
"Mine"
}
fn get_owner(&self) -> Players {
self.owner
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = self.base_text();
lines.push(Line::from_iter([
"Ore: ".gray(),
self.get_ore_amount().to_string().cyan(),
format!("/{}", self.ore.get_max_ore_amount()).gray(),
]));
lines
}
}
@@ -1,75 +1,75 @@
use crate::app::{
states::skirmish_states::{
Players,
structures::{Mine, Ore, Structure},
},
threads::TICK_MS,
states::skirmish_states::{
Players,
structures::{Mine, Ore, Structure},
},
threads::TICK_MS,
};
use ratatui::{style::Color, text::Line};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MineConstruction {
mine: Mine,
ticks: u16,
mine: Mine,
ticks: u16,
}
impl MineConstruction {
pub const BUILD_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
pub const BUILD_TICKS: u16 = 10000_u16.div_ceil(TICK_MS as u16);
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
Mine::new(owner, ore).map(|mine: Mine| -> Self { Self { mine, ticks: 0 } })
}
pub fn new(owner: Players, ore: Ore) -> Option<Self> {
Mine::new(owner, ore).map(|mine: Mine| -> Self { Self { mine, ticks: 0 } })
}
pub fn advance(&mut self) -> () {
self.ticks = self.ticks.saturating_add(1).min(Self::BUILD_TICKS);
}
pub fn advance(&mut self) -> () {
self.ticks = self.ticks.saturating_add(1).min(Self::BUILD_TICKS);
}
pub fn is_finished(&self) -> bool {
self.ticks == Self::BUILD_TICKS
}
pub fn is_finished(&self) -> bool {
self.ticks == Self::BUILD_TICKS
}
pub fn progress_percent(&self) -> u16 {
(u32::from(self.ticks) * 100 / u32::from(Self::BUILD_TICKS)) as u16
}
pub fn progress_percent(&self) -> u16 {
(u32::from(self.ticks) * 100 / u32::from(Self::BUILD_TICKS)) as u16
}
pub fn into_mine(self) -> Option<Mine> {
self.is_finished().then_some(self.mine)
}
pub fn into_mine(self) -> Option<Mine> {
self.is_finished().then_some(self.mine)
}
pub fn cancel(self) -> Ore {
self.mine.into_ore()
}
pub fn cancel(self) -> Ore {
self.mine.into_ore()
}
}
impl Structure for MineConstruction {
fn get_tag(&self) -> char {
'C'
}
fn get_color(&self) -> Color {
self.mine.get_color()
}
fn get_level(&self) -> char {
self.mine.get_level()
}
fn get_stress(&self) -> u8 {
self.mine.get_stress()
}
fn get_durability(&self) -> u16 {
self.mine.get_durability()
}
fn get_max_durability(&self) -> u16 {
self.mine.get_max_durability()
}
fn get_name(&self) -> &'static str {
"Mine construction"
}
fn get_owner(&self) -> Players {
self.mine.get_owner()
}
fn text(&self) -> Vec<Line<'_>> {
vec![
Line::from(format!("Construction: {}%", self.progress_percent())),
Line::from(format!("Ore: {}", self.mine.get_ore_amount())),
]
}
fn get_tag(&self) -> char {
'C'
}
fn get_color(&self) -> Color {
self.mine.get_color()
}
fn get_level(&self) -> char {
self.mine.get_level()
}
fn get_stress(&self) -> u8 {
self.mine.get_stress()
}
fn get_durability(&self) -> u16 {
self.mine.get_durability()
}
fn get_max_durability(&self) -> u16 {
self.mine.get_max_durability()
}
fn get_name(&self) -> &'static str {
"Mine construction"
}
fn get_owner(&self) -> Players {
self.mine.get_owner()
}
fn text(&self) -> Vec<Line<'_>> {
vec![
Line::from(format!("Construction: {}%", self.progress_percent())),
Line::from(format!("Ore: {}", self.mine.get_ore_amount())),
]
}
}
@@ -18,6 +18,6 @@ pub use tunnel::Tunnel;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BuildingTerrain {
Stone,
Ore,
Stone,
Ore,
}
@@ -1,100 +1,100 @@
use crate::app::states::skirmish_states::{Players, structures::Structure};
use ratatui::{
style::{Color, Stylize},
text::Line,
style::{Color, Stylize},
text::Line,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Ore {
owner: Players,
ore_amount: u16,
durability: u16,
stress: u8,
level: u8,
owner: Players,
ore_amount: u16,
durability: u16,
stress: u8,
level: u8,
}
impl Ore {
pub fn new(owner: Players, level: u8) -> Self {
Self {
owner,
ore_amount: 5000,
durability: 1000,
stress: 0,
level,
pub fn new(owner: Players, level: u8) -> Self {
Self {
owner,
ore_amount: 5000,
durability: 1000,
stress: 0,
level,
}
}
}
pub fn get_ore_amount(&self) -> u16 {
self.ore_amount
}
pub fn get_ore_amount(&self) -> u16 {
self.ore_amount
}
pub fn get_max_ore_amount(&self) -> u16 {
5000
}
pub fn get_max_ore_amount(&self) -> u16 {
5000
}
pub fn extract(&mut self, amount: u16) -> u16 {
let extracted: u16 = amount.min(self.ore_amount);
self.ore_amount -= extracted;
extracted
}
pub fn extract(&mut self, amount: u16) -> u16 {
let extracted: u16 = amount.min(self.ore_amount);
self.ore_amount -= extracted;
extracted
}
pub fn set_owner(&mut self, new_owner: Players) -> &mut Self {
self.owner = new_owner;
self
}
pub fn set_owner(&mut self, new_owner: Players) -> &mut Self {
self.owner = new_owner;
self
}
}
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_tag(&self) -> char {
'O'
}
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_level(&self) -> char {
if self.level != 0 {
(self.level + b'0') as char
} else {
' '
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_max_durability(&self) -> u16 {
1000
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_name(&self) -> &'static str {
"Ore"
}
fn get_level(&self) -> char {
if self.level != 0 {
(self.level + b'0') as char
} else {
' '
}
}
fn get_owner(&self) -> Players {
self.owner
}
fn get_max_durability(&self) -> u16 {
1000
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_name(&self) -> &'static str {
"Ore"
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = Structure::base_text(self);
fn get_owner(&self) -> Players {
self.owner
}
lines.push(Line::from_iter([
"Ore: ".gray(),
self.get_ore_amount().to_string().cyan(),
"/".gray(),
self.get_max_ore_amount().to_string().cyan(),
]));
fn get_stress(&self) -> u8 {
self.stress
}
lines
}
fn text(&self) -> Vec<Line<'_>> {
let mut lines: Vec<Line<'_>> = Structure::base_text(self);
lines.push(Line::from_iter([
"Ore: ".gray(),
self.get_ore_amount().to_string().cyan(),
"/".gray(),
self.get_max_ore_amount().to_string().cyan(),
]));
lines
}
}
@@ -3,53 +3,53 @@ use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Stone {
durability: u16,
stress: u8,
durability: u16,
stress: u8,
}
impl Stone {
pub fn take_damage(&mut self, damage: u16) {
self.durability = self.durability.saturating_sub(damage);
}
pub fn take_damage(&mut self, damage: u16) {
self.durability = self.durability.saturating_sub(damage);
}
pub fn new() -> Self {
Self {
durability: 1000,
stress: 0,
pub fn new() -> Self {
Self {
durability: 1000,
stress: 0,
}
}
}
}
impl Structure for Stone {
fn get_tag(&self) -> char {
' '
}
fn get_tag(&self) -> char {
' '
}
fn get_color(&self) -> Color {
Color::White
}
fn get_color(&self) -> Color {
Color::White
}
fn get_level(&self) -> char {
' '
}
fn get_level(&self) -> char {
' '
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_max_durability(&self) -> u16 {
1000
}
fn get_max_durability(&self) -> u16 {
1000
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_name(&self) -> &'static str {
"Stone"
}
fn get_name(&self) -> &'static str {
"Stone"
}
fn get_owner(&self) -> Players {
Players::Unclaimed
}
fn get_owner(&self) -> Players {
Players::Unclaimed
}
}
@@ -1,57 +1,57 @@
use crate::app::states::skirmish_states::Players;
use ratatui::{
style::{Color, Stylize},
text::Line,
style::{Color, Stylize},
text::Line,
};
pub trait Structure {
fn get_tag(&self) -> char;
fn get_tag(&self) -> char;
fn get_color(&self) -> Color;
fn get_color(&self) -> Color;
fn get_level(&self) -> char;
fn get_level(&self) -> char;
fn get_stress(&self) -> u8;
fn get_stress(&self) -> u8;
fn get_durability(&self) -> u16;
fn get_durability(&self) -> u16;
fn get_max_durability(&self) -> u16;
fn get_max_durability(&self) -> u16;
fn get_name(&self) -> &'static str;
fn get_name(&self) -> &'static str;
fn get_owner(&self) -> Players;
fn get_owner(&self) -> Players;
fn base_text(&self) -> Vec<Line<'_>> {
let durability: u16 = self.get_durability();
let max_durability: u16 = self.get_max_durability();
let durability_percent: u32 = durability as u32 * 100 / max_durability as u32;
let stress: u8 = self.get_stress();
let level: char = self.get_level();
fn base_text(&self) -> Vec<Line<'_>> {
let durability: u16 = self.get_durability();
let max_durability: u16 = self.get_max_durability();
let durability_percent: u32 = durability as u32 * 100 / max_durability as u32;
let stress: u8 = self.get_stress();
let level: char = self.get_level();
let mut lines: Vec<Line<'_>> = vec![
Line::from_iter([
"Durability: ".gray(),
durability.to_string().cyan(),
"/".gray(),
max_durability.to_string().cyan(),
" ( ".gray(),
durability_percent.to_string().cyan(),
"% )".gray(),
]),
Line::from_iter(["Stress: ".gray(), stress.to_string().cyan(), "%".gray()]),
];
let mut lines: Vec<Line<'_>> = vec![
Line::from_iter([
"Durability: ".gray(),
durability.to_string().cyan(),
"/".gray(),
max_durability.to_string().cyan(),
" ( ".gray(),
durability_percent.to_string().cyan(),
"% )".gray(),
]),
Line::from_iter(["Stress: ".gray(), stress.to_string().cyan(), "%".gray()]),
];
if level != ' ' {
lines.push(Line::from_iter([
"Level: ".gray(),
level.to_string().cyan(),
]));
if level != ' ' {
lines.push(Line::from_iter([
"Level: ".gray(),
level.to_string().cyan(),
]));
}
lines
}
lines
}
fn text(&self) -> Vec<Line<'_>> {
self.base_text()
}
fn text(&self) -> Vec<Line<'_>> {
self.base_text()
}
}
@@ -1,100 +1,100 @@
use crate::app::states::skirmish_states::{
Players,
structures::{BaseBuilding, Mine, MineConstruction, Ore, Stone, Structure, Tunnel},
units::Units,
Players,
structures::{BaseBuilding, Mine, MineConstruction, Ore, Stone, Structure, Tunnel},
units::Units,
};
use ratatui::{
style::{Color, Stylize},
text::Line,
style::{Color, Stylize},
text::Line,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Structures {
Base(BaseBuilding),
Tunnel(Tunnel),
Stone(Stone),
Ore(Ore),
Mine(Mine),
MineConstruction(MineConstruction),
Base(BaseBuilding),
Tunnel(Tunnel),
Stone(Stone),
Ore(Ore),
Mine(Mine),
MineConstruction(MineConstruction),
}
impl Structures {
pub fn can_enter(&self, unit: &Units) -> bool {
match self {
Self::Base(_) | Self::Tunnel(_) => true,
Self::Mine(mine) => mine.accepts_unit(unit),
_ => false,
pub fn can_enter(&self, unit: &Units) -> bool {
match self {
Self::Base(_) | Self::Tunnel(_) => true,
Self::Mine(mine) => mine.accepts_unit(unit),
_ => false,
}
}
}
pub fn build_mine(&mut self, owner: Players) -> bool {
if let Self::Ore(ore) = *self
&& let Some(mine) = Mine::new(owner, ore)
{
*self = Self::Mine(mine);
return true;
pub fn build_mine(&mut self, owner: Players) -> bool {
if let Self::Ore(ore) = *self
&& let Some(mine) = Mine::new(owner, ore)
{
*self = Self::Mine(mine);
return true;
}
false
}
false
}
#[inline]
fn s(&self) -> &dyn Structure {
match self {
Self::Base(b) => b,
Self::Tunnel(t) => t,
Self::Stone(s) => s,
Self::Ore(o) => o,
Self::Mine(mine) => mine,
Self::MineConstruction(site) => site,
#[inline]
fn s(&self) -> &dyn Structure {
match self {
Self::Base(b) => b,
Self::Tunnel(t) => t,
Self::Stone(s) => s,
Self::Ore(o) => o,
Self::Mine(mine) => mine,
Self::MineConstruction(site) => site,
}
}
}
}
impl Structure for Structures {
fn get_color(&self) -> Color {
self.s().get_color()
}
fn get_tag(&self) -> char {
self.s().get_tag()
}
fn get_level(&self) -> char {
self.s().get_level()
}
fn get_name(&self) -> &'static str {
self.s().get_name()
}
fn get_durability(&self) -> u16 {
self.s().get_durability()
}
fn get_max_durability(&self) -> u16 {
self.s().get_max_durability()
}
fn get_stress(&self) -> u8 {
self.s().get_stress()
}
fn get_owner(&self) -> Players {
self.s().get_owner()
}
fn text(&self) -> Vec<Line<'_>> {
match self.s().get_owner() {
Players::Unclaimed => self.s().text(),
Players::Player | Players::Enemy => {
let mut lines: Vec<Line<'_>> = self.s().text();
lines.push(Line::from_iter([
"Owner: ".gray(),
self.s().get_owner().get_span(),
]));
lines
}
fn get_color(&self) -> Color {
self.s().get_color()
}
fn get_tag(&self) -> char {
self.s().get_tag()
}
fn get_level(&self) -> char {
self.s().get_level()
}
fn get_name(&self) -> &'static str {
self.s().get_name()
}
fn get_durability(&self) -> u16 {
self.s().get_durability()
}
fn get_max_durability(&self) -> u16 {
self.s().get_max_durability()
}
fn get_stress(&self) -> u8 {
self.s().get_stress()
}
fn get_owner(&self) -> Players {
self.s().get_owner()
}
fn text(&self) -> Vec<Line<'_>> {
match self.s().get_owner() {
Players::Unclaimed => self.s().text(),
Players::Player | Players::Enemy => {
let mut lines: Vec<Line<'_>> = self.s().text();
lines.push(Line::from_iter([
"Owner: ".gray(),
self.s().get_owner().get_span(),
]));
lines
}
}
}
}
}
@@ -3,55 +3,55 @@ use ratatui::style::Color;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Tunnel {
durability: u16,
stress: u8,
roof_support: bool,
rail: bool,
lamp: bool,
durability: u16,
stress: u8,
roof_support: bool,
rail: bool,
lamp: bool,
}
impl Tunnel {
pub fn new() -> Self {
Self {
durability: 500,
stress: 25,
roof_support: false,
rail: false,
lamp: false,
pub fn new() -> Self {
Self {
durability: 500,
stress: 25,
roof_support: false,
rail: false,
lamp: false,
}
}
}
}
impl Structure for Tunnel {
fn get_tag(&self) -> char {
'T'
}
fn get_tag(&self) -> char {
'T'
}
fn get_color(&self) -> Color {
Color::Gray
}
fn get_color(&self) -> Color {
Color::Gray
}
fn get_level(&self) -> char {
' '
}
fn get_level(&self) -> char {
' '
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_durability(&self) -> u16 {
self.durability
}
fn get_max_durability(&self) -> u16 {
500
}
fn get_max_durability(&self) -> u16 {
500
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_stress(&self) -> u8 {
self.stress
}
fn get_name(&self) -> &'static str {
"Tunnel"
}
fn get_name(&self) -> &'static str {
"Tunnel"
}
fn get_owner(&self) -> Players {
Players::Unclaimed
}
fn get_owner(&self) -> Players {
Players::Unclaimed
}
}
+50 -50
View File
@@ -3,71 +3,71 @@ use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub struct DiggingTask {
path: VecDeque<(usize, usize)>,
progress: f32,
tick_increase: f32,
total_steps: usize,
path: VecDeque<(usize, usize)>,
progress: f32,
tick_increase: f32,
total_steps: usize,
}
impl DiggingTask {
pub fn new(path: VecDeque<(usize, usize)>, tick_increase: f32) -> Self {
Self {
total_steps: path.len(),
path,
progress: 0.0,
tick_increase,
pub fn new(path: VecDeque<(usize, usize)>, tick_increase: f32) -> Self {
Self {
total_steps: path.len(),
path,
progress: 0.0,
tick_increase,
}
}
}
pub fn pop_front(&mut self) {
self.path.pop_front();
self.progress = 0.0;
}
pub fn from_moving(task: MovingTask, tick_increase: f32) -> Self {
Self {
path: task.get_path().clone(),
progress: 0.0,
tick_increase,
total_steps: task.get_total_steps(),
pub fn pop_front(&mut self) {
self.path.pop_front();
self.progress = 0.0;
}
}
pub fn current_target(&self) -> Option<(usize, usize)> {
self.path.front().copied()
}
pub fn from_moving(task: MovingTask, tick_increase: f32) -> Self {
Self {
path: task.get_path().clone(),
progress: 0.0,
tick_increase,
total_steps: task.get_total_steps(),
}
}
pub fn current_target(&self) -> Option<(usize, usize)> {
self.path.front().copied()
}
}
impl Task for DiggingTask {
fn get_icon(&self) -> char {
'⛏'
}
fn get_icon(&self) -> char {
'⛏'
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
&self.path
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
&self.path
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.path.front().map_or(&(0, 0), |c| c)
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.path.front().map_or(&(0, 0), |c| c)
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.path.back().map_or(&(0, 0), |c| c)
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.path.back().map_or(&(0, 0), |c| c)
}
fn get_progress(&self) -> f32 {
self.progress
}
fn get_progress(&self) -> f32 {
self.progress
}
fn get_total_steps(&self) -> usize {
self.total_steps
}
fn get_total_steps(&self) -> usize {
self.total_steps
}
fn progress(&mut self) {
self.progress = (self.progress + self.tick_increase).clamp(0.0, 100.0);
}
fn progress(&mut self) {
self.progress = (self.progress + self.tick_increase).clamp(0.0, 100.0);
}
fn is_finished(&self) -> bool {
self.progress >= 100.0
}
fn is_finished(&self) -> bool {
self.progress >= 100.0
}
}
+48 -48
View File
@@ -1,6 +1,6 @@
use crate::app::{
states::skirmish_states::tasks::{DiggingTask, Task},
threads::TICK_MS,
states::skirmish_states::tasks::{DiggingTask, Task},
threads::TICK_MS,
};
use std::collections::VecDeque;
@@ -8,68 +8,68 @@ const MOVEMENT_TICKS: u16 = 3000_u16.div_ceil(TICK_MS as u16);
#[derive(Debug, Clone, PartialEq)]
pub struct MovingTask {
path: VecDeque<(usize, usize)>,
ticks: u16,
total_steps: usize,
path: VecDeque<(usize, usize)>,
ticks: u16,
total_steps: usize,
}
impl MovingTask {
pub fn new(path: VecDeque<(usize, usize)>) -> Self {
Self {
total_steps: path.len(),
path,
ticks: 0,
pub fn new(path: VecDeque<(usize, usize)>) -> Self {
Self {
total_steps: path.len(),
path,
ticks: 0,
}
}
}
pub fn from_digging(task: DiggingTask) -> Self {
Self {
total_steps: task.get_total_steps(),
path: task.get_path().clone(),
ticks: 0,
pub fn from_digging(task: DiggingTask) -> Self {
Self {
total_steps: task.get_total_steps(),
path: task.get_path().clone(),
ticks: 0,
}
}
}
pub fn pop_front(&mut self) {
self.path.pop_front();
self.ticks = 0;
}
pub fn pop_front(&mut self) {
self.path.pop_front();
self.ticks = 0;
}
pub fn get_movement_progress(&self) -> Option<u16> {
(self.ticks > 0).then(|| self.ticks * 100 / MOVEMENT_TICKS)
}
pub fn get_movement_progress(&self) -> Option<u16> {
(self.ticks > 0).then(|| self.ticks * 100 / MOVEMENT_TICKS)
}
}
impl Task for MovingTask {
fn get_icon(&self) -> char {
'→'
}
fn get_icon(&self) -> char {
'→'
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
&self.path
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
&self.path
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.path.front().unwrap_or(&(0, 0))
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.path.front().unwrap_or(&(0, 0))
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.path.back().unwrap_or(&(0, 0))
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.path.back().unwrap_or(&(0, 0))
}
fn get_progress(&self) -> f32 {
f32::from(self.ticks) * 100.0 / f32::from(MOVEMENT_TICKS)
}
fn get_progress(&self) -> f32 {
f32::from(self.ticks) * 100.0 / f32::from(MOVEMENT_TICKS)
}
fn get_total_steps(&self) -> usize {
self.total_steps
}
fn get_total_steps(&self) -> usize {
self.total_steps
}
fn progress(&mut self) {
self.ticks = (self.ticks + 1).min(MOVEMENT_TICKS);
}
fn progress(&mut self) {
self.ticks = (self.ticks + 1).min(MOVEMENT_TICKS);
}
fn is_finished(&self) -> bool {
self.ticks == MOVEMENT_TICKS
}
fn is_finished(&self) -> bool {
self.ticks == MOVEMENT_TICKS
}
}
@@ -1,28 +1,28 @@
use std::collections::VecDeque;
pub trait Task {
fn get_icon(&self) -> char;
fn get_icon(&self) -> char;
fn get_path(&self) -> &VecDeque<(usize, usize)>;
fn get_path(&self) -> &VecDeque<(usize, usize)>;
fn get_path_front_coords(&self) -> &(usize, usize);
fn get_path_front_coords(&self) -> &(usize, usize);
fn get_path_back_coords(&self) -> &(usize, usize);
fn get_path_back_coords(&self) -> &(usize, usize);
fn get_progress(&self) -> f32;
fn get_progress(&self) -> f32;
fn get_total_steps(&self) -> usize;
fn get_total_steps(&self) -> usize;
fn get_total_progress(&self) -> f32 {
let total: usize = self.get_total_steps();
if total == 0 {
return 100.0;
fn get_total_progress(&self) -> f32 {
let total: usize = self.get_total_steps();
if total == 0 {
return 100.0;
}
let completed: usize = total.saturating_sub(self.get_path().len());
((completed as f32 * 100.0 + self.get_progress()) / total as f32).clamp(0.0, 100.0)
}
let completed: usize = total.saturating_sub(self.get_path().len());
((completed as f32 * 100.0 + self.get_progress()) / total as f32).clamp(0.0, 100.0)
}
fn progress(&mut self);
fn progress(&mut self);
fn is_finished(&self) -> bool;
fn is_finished(&self) -> bool;
}
@@ -3,58 +3,58 @@ use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub enum Tasks {
Digging(DiggingTask),
Moving(MovingTask),
Digging(DiggingTask),
Moving(MovingTask),
}
impl Tasks {
#[inline]
fn t(&self) -> &dyn Task {
match self {
Self::Digging(d) => d,
Self::Moving(m) => m,
#[inline]
fn t(&self) -> &dyn Task {
match self {
Self::Digging(d) => d,
Self::Moving(m) => m,
}
}
}
#[inline]
fn t_mut(&mut self) -> &mut dyn Task {
match self {
Self::Digging(d) => d,
Self::Moving(m) => m,
#[inline]
fn t_mut(&mut self) -> &mut dyn Task {
match self {
Self::Digging(d) => d,
Self::Moving(m) => m,
}
}
}
}
impl Task for Tasks {
fn get_icon(&self) -> char {
self.t().get_icon()
}
fn get_icon(&self) -> char {
self.t().get_icon()
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
self.t().get_path()
}
fn get_path(&self) -> &VecDeque<(usize, usize)> {
self.t().get_path()
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.t().get_path_front_coords()
}
fn get_path_front_coords(&self) -> &(usize, usize) {
self.t().get_path_front_coords()
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.t().get_path_back_coords()
}
fn get_path_back_coords(&self) -> &(usize, usize) {
self.t().get_path_back_coords()
}
fn get_progress(&self) -> f32 {
self.t().get_progress()
}
fn get_progress(&self) -> f32 {
self.t().get_progress()
}
fn get_total_steps(&self) -> usize {
self.t().get_total_steps()
}
fn get_total_steps(&self) -> usize {
self.t().get_total_steps()
}
fn is_finished(&self) -> bool {
self.t().is_finished()
}
fn is_finished(&self) -> bool {
self.t().is_finished()
}
fn progress(&mut self) {
self.t_mut().progress();
}
fn progress(&mut self) {
self.t_mut().progress();
}
}
+101 -102
View File
@@ -1,133 +1,132 @@
use ratatui::{style::Stylize, text::Line};
use crate::app::states::skirmish_states::{
Players, Resources,
tasks::{Task, Tasks},
units::Unit,
Players, Resources,
tasks::{Task, Tasks},
units::Unit,
};
use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub struct MinerUnit {
owner: Players,
hp: u16,
can_dig: bool,
digging_power: f32,
coords: (usize, usize),
tasks: VecDeque<Tasks>,
owner: Players,
hp: u16,
can_dig: bool,
digging_power: f32,
coords: (usize, usize),
tasks: VecDeque<Tasks>,
}
impl MinerUnit {
pub const RECRUIT_COST: Resources = Resources {
wood: 10,
metal: 15,
};
pub fn new(owner: Players, coords: (usize, usize)) -> Self {
Self {
owner,
hp: 100,
can_dig: true,
digging_power: 0.55,
coords,
tasks: VecDeque::new(),
}
}
fn col_to_letters(&self, col: usize) -> String {
let mut col: usize = col + 1;
let mut letters: Vec<char> = Vec::new();
while col > 0 {
letters.push((b'A' + ((col - 1) % 26) as u8) as char);
col = (col - 1) / 26;
pub const RECRUIT_COST: Resources = Resources {
wood: 10,
metal: 15,
};
pub fn new(owner: Players, coords: (usize, usize)) -> Self {
Self {
owner,
hp: 100,
can_dig: true,
digging_power: 0.55,
coords,
tasks: VecDeque::new(),
}
}
letters.iter().rev().collect()
}
fn col_to_letters(&self, col: usize) -> String {
let mut col: usize = col + 1;
let mut letters: Vec<char> = Vec::new();
fn display_coords(&self, coords: &(usize, usize)) -> String {
format!("{}{}", self.col_to_letters(coords.0), coords.1)
}
while col > 0 {
letters.push((b'A' + ((col - 1) % 26) as u8) as char);
col = (col - 1) / 26;
}
letters.iter().rev().collect()
}
fn display_coords(&self, coords: &(usize, usize)) -> String {
format!("{}{}", self.col_to_letters(coords.0), coords.1)
}
}
impl Unit for MinerUnit {
fn get_owner(&self) -> Players {
self.owner
}
fn get_owner(&self) -> Players {
self.owner
}
fn get_tag(&self) -> char {
'M'
}
fn get_tag(&self) -> char {
'M'
}
fn get_name(&self) -> &'static str {
"Miner"
}
fn get_name(&self) -> &'static str {
"Miner"
}
fn get_hp(&self) -> u16 {
self.hp
}
fn get_hp(&self) -> u16 {
self.hp
}
fn get_max_hp(&self) -> u16 {
100
}
fn get_max_hp(&self) -> u16 {
100
}
fn get_can_dig(&self) -> bool {
self.can_dig
}
fn get_can_dig(&self) -> bool {
self.can_dig
}
fn get_can_build(&self) -> bool {
true
}
fn get_can_build(&self) -> bool {
true
}
fn get_digging_power(&self) -> f32 {
self.digging_power
}
fn get_digging_power(&self) -> f32 {
self.digging_power
}
fn get_coords(&self) -> (usize, usize) {
self.coords
}
fn get_coords(&self) -> (usize, usize) {
self.coords
}
fn set_coords(&mut self, coords: (usize, usize)) {
self.coords = coords;
}
fn set_coords(&mut self, coords: (usize, usize)) {
self.coords = coords;
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
&self.tasks
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
&self.tasks
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
&mut self.tasks
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
&mut self.tasks
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
Vec::from(
self
.tasks
.iter()
.enumerate()
.flat_map(|(i, task): (usize, &Tasks)| -> [Line<'_>; 2] {
[
Line::from_iter([
format!("{}. ", i + 1).gray(),
task.get_icon().gray(),
" ".gray(),
self.display_coords(task.get_path_front_coords()).green(),
" -> ".gray(),
self.display_coords(task.get_path_back_coords()).yellow(),
]),
Line::from(format!(
" Step: {}% | Total: {}%",
task.get_progress() as u16,
task.get_total_progress() as u16,
))
.cyan(),
]
})
.collect::<Vec<Line<'_>>>(),
)
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
Vec::from(
self.tasks
.iter()
.enumerate()
.flat_map(|(i, task): (usize, &Tasks)| -> [Line<'_>; 2] {
[
Line::from_iter([
format!("{}. ", i + 1).gray(),
task.get_icon().gray(),
" ".gray(),
self.display_coords(task.get_path_front_coords()).green(),
" -> ".gray(),
self.display_coords(task.get_path_back_coords()).yellow(),
]),
Line::from(format!(
" Step: {}% | Total: {}%",
task.get_progress() as u16,
task.get_total_progress() as u16,
))
.cyan(),
]
})
.collect::<Vec<Line<'_>>>(),
)
}
fn set_task(&mut self, task: Tasks) {
self.tasks.push_back(task);
}
fn set_task(&mut self, task: Tasks) {
self.tasks.push_back(task);
}
}
@@ -1,90 +1,90 @@
use crate::app::states::skirmish_states::{Players, tasks::Tasks};
use ratatui::{
style::Stylize,
text::{Line, Span},
style::Stylize,
text::{Line, Span},
};
use std::collections::VecDeque;
pub trait Unit {
fn is_unit(&self) -> bool {
true
}
fn get_owner(&self) -> Players;
fn get_tag(&self) -> char;
fn get_name(&self) -> &'static str;
fn get_hp(&self) -> u16;
fn get_max_hp(&self) -> u16;
fn get_can_dig(&self) -> bool;
fn get_can_build(&self) -> bool {
false
}
fn get_digging_power(&self) -> f32;
fn get_coords(&self) -> (usize, usize);
fn set_coords(&mut self, coords: (usize, usize));
fn get_ref_tasks(&self) -> &VecDeque<Tasks>;
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks>;
fn set_task(&mut self, task: Tasks);
fn get_tasks_formatted(&self) -> Vec<Line<'_>>;
fn base_text(&self) -> Vec<Line<'_>> {
let owner: Span<'_> = self.get_owner().get_span();
let hp: u16 = self.get_hp();
let max_hp: u16 = self.get_max_hp();
let hp_percent: u16 = hp * 100 / max_hp;
let can_dig: bool = self.get_can_dig();
let digging_power: f32 = self.get_digging_power();
let have_any_tasks: bool = self.get_ref_tasks().is_empty();
let tasks: Vec<Line<'_>> = self.get_tasks_formatted();
let mut lines: Vec<Line<'_>> = Vec::from([
Line::from_iter(["Owner: ".gray(), owner]),
Line::from_iter([
"HP: ".gray(),
hp.green(),
"/".gray(),
max_hp.green(),
" ( ".gray(),
hp_percent.green(),
"% )".gray(),
]),
]);
if can_dig {
lines.push(Line::from_iter([
"Digging power: ".gray(),
digging_power.green(),
]));
fn is_unit(&self) -> bool {
true
}
if self.get_can_build() {
lines.push(Line::from("Can build: Yes").green());
fn get_owner(&self) -> Players;
fn get_tag(&self) -> char;
fn get_name(&self) -> &'static str;
fn get_hp(&self) -> u16;
fn get_max_hp(&self) -> u16;
fn get_can_dig(&self) -> bool;
fn get_can_build(&self) -> bool {
false
}
if !have_any_tasks {
lines.push(Line::from("Tasks Queue: ".gray()));
for task in tasks {
lines.push(task);
}
fn get_digging_power(&self) -> f32;
fn get_coords(&self) -> (usize, usize);
fn set_coords(&mut self, coords: (usize, usize));
fn get_ref_tasks(&self) -> &VecDeque<Tasks>;
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks>;
fn set_task(&mut self, task: Tasks);
fn get_tasks_formatted(&self) -> Vec<Line<'_>>;
fn base_text(&self) -> Vec<Line<'_>> {
let owner: Span<'_> = self.get_owner().get_span();
let hp: u16 = self.get_hp();
let max_hp: u16 = self.get_max_hp();
let hp_percent: u16 = hp * 100 / max_hp;
let can_dig: bool = self.get_can_dig();
let digging_power: f32 = self.get_digging_power();
let have_any_tasks: bool = self.get_ref_tasks().is_empty();
let tasks: Vec<Line<'_>> = self.get_tasks_formatted();
let mut lines: Vec<Line<'_>> = Vec::from([
Line::from_iter(["Owner: ".gray(), owner]),
Line::from_iter([
"HP: ".gray(),
hp.green(),
"/".gray(),
max_hp.green(),
" ( ".gray(),
hp_percent.green(),
"% )".gray(),
]),
]);
if can_dig {
lines.push(Line::from_iter([
"Digging power: ".gray(),
digging_power.green(),
]));
}
if self.get_can_build() {
lines.push(Line::from("Can build: Yes").green());
}
if !have_any_tasks {
lines.push(Line::from("Tasks Queue: ".gray()));
for task in tasks {
lines.push(task);
}
}
lines
}
lines
}
fn text(&self) -> Vec<Line<'_>> {
self.base_text()
}
fn text(&self) -> Vec<Line<'_>> {
self.base_text()
}
}
+117 -121
View File
@@ -1,158 +1,154 @@
use crate::app::states::skirmish_states::{
Players,
tasks::Tasks,
units::{MinerUnit, Unit},
Players,
tasks::Tasks,
units::{MinerUnit, Unit},
};
use ratatui::text::Line;
use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub enum Units {
Miner(MinerUnit),
Miner(MinerUnit),
}
impl Units {
#[inline]
pub fn u(&self) -> &dyn Unit {
match self {
Self::Miner(m) => m,
#[inline]
pub fn u(&self) -> &dyn Unit {
match self {
Self::Miner(m) => m,
}
}
}
#[inline]
pub fn u_mut(&mut self) -> &mut dyn Unit {
match self {
Self::Miner(m) => m,
#[inline]
pub fn u_mut(&mut self) -> &mut dyn Unit {
match self {
Self::Miner(m) => m,
}
}
}
}
impl Unit for Units {
fn get_can_build(&self) -> bool {
self.u().get_can_build()
}
fn get_tag(&self) -> char {
self.u().get_tag()
}
fn get_can_build(&self) -> bool {
self.u().get_can_build()
}
fn get_tag(&self) -> char {
self.u().get_tag()
}
fn get_name(&self) -> &'static str {
self.u().get_name()
}
fn get_name(&self) -> &'static str {
self.u().get_name()
}
fn get_owner(&self) -> Players {
self.u().get_owner()
}
fn get_owner(&self) -> Players {
self.u().get_owner()
}
fn get_hp(&self) -> u16 {
self.u().get_hp()
}
fn get_hp(&self) -> u16 {
self.u().get_hp()
}
fn get_max_hp(&self) -> u16 {
self.u().get_max_hp()
}
fn get_max_hp(&self) -> u16 {
self.u().get_max_hp()
}
fn get_can_dig(&self) -> bool {
self.u().get_can_dig()
}
fn get_can_dig(&self) -> bool {
self.u().get_can_dig()
}
fn get_digging_power(&self) -> f32 {
self.u().get_digging_power()
}
fn get_digging_power(&self) -> f32 {
self.u().get_digging_power()
}
fn get_coords(&self) -> (usize, usize) {
self.u().get_coords()
}
fn get_coords(&self) -> (usize, usize) {
self.u().get_coords()
}
fn set_coords(&mut self, coords: (usize, usize)) {
self.u_mut().set_coords(coords);
}
fn set_coords(&mut self, coords: (usize, usize)) {
self.u_mut().set_coords(coords);
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
self.u().get_ref_tasks()
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
self.u().get_ref_tasks()
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
self.u_mut().get_mut_tasks()
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
self.u_mut().get_mut_tasks()
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
self.u().get_tasks_formatted()
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
self.u().get_tasks_formatted()
}
fn set_task(&mut self, task: Tasks) {
self.u_mut().set_task(task);
}
fn set_task(&mut self, task: Tasks) {
self.u_mut().set_task(task);
}
}
impl Unit for Option<Units> {
fn get_can_build(&self) -> bool {
self
.as_ref()
.is_some_and(|unit: &Units| -> bool { unit.get_can_build() })
}
fn is_unit(&self) -> bool {
self.as_ref().map_or(false, |u| u.is_unit())
}
fn get_tag(&self) -> char {
self.as_ref().map_or(' ', |u| u.get_tag())
}
fn get_name(&self) -> &'static str {
self.as_ref().map_or("", |u| u.get_name())
}
fn get_owner(&self) -> Players {
self.as_ref().map_or(Players::Unclaimed, |u| u.get_owner())
}
fn get_hp(&self) -> u16 {
self.as_ref().map_or(0, |u| u.get_hp())
}
fn get_max_hp(&self) -> u16 {
self.as_ref().map_or(0, |u| u.get_max_hp())
}
fn get_can_dig(&self) -> bool {
self.as_ref().map_or(false, |u| u.get_can_dig())
}
fn get_digging_power(&self) -> f32 {
self.as_ref().map_or(0.0, |u| u.get_digging_power())
}
fn get_coords(&self) -> (usize, usize) {
self.as_ref().map_or((0, 0), |u| u.get_coords())
}
fn set_coords(&mut self, coords: (usize, usize)) {
if let Some(unit) = self.as_mut() {
unit.set_coords(coords);
fn get_can_build(&self) -> bool {
self.as_ref()
.is_some_and(|unit: &Units| -> bool { unit.get_can_build() })
}
fn is_unit(&self) -> bool {
self.as_ref().map_or(false, |u| u.is_unit())
}
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
self
.as_ref()
.expect("attempted to get referenced tasks from `None`")
.get_ref_tasks()
}
fn get_tag(&self) -> char {
self.as_ref().map_or(' ', |u| u.get_tag())
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
self
.as_mut()
.expect("attempted to get mutable tasks from `None`")
.get_mut_tasks()
}
fn get_name(&self) -> &'static str {
self.as_ref().map_or("", |u| u.get_name())
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
self
.as_ref()
.map_or(Vec::new(), |u| u.get_tasks_formatted())
}
fn get_owner(&self) -> Players {
self.as_ref().map_or(Players::Unclaimed, |u| u.get_owner())
}
fn set_task(&mut self, task: Tasks) {
self.as_mut().map_or((), |u| u.set_task(task))
}
fn get_hp(&self) -> u16 {
self.as_ref().map_or(0, |u| u.get_hp())
}
fn get_max_hp(&self) -> u16 {
self.as_ref().map_or(0, |u| u.get_max_hp())
}
fn get_can_dig(&self) -> bool {
self.as_ref().map_or(false, |u| u.get_can_dig())
}
fn get_digging_power(&self) -> f32 {
self.as_ref().map_or(0.0, |u| u.get_digging_power())
}
fn get_coords(&self) -> (usize, usize) {
self.as_ref().map_or((0, 0), |u| u.get_coords())
}
fn set_coords(&mut self, coords: (usize, usize)) {
if let Some(unit) = self.as_mut() {
unit.set_coords(coords);
}
}
fn get_ref_tasks(&self) -> &VecDeque<Tasks> {
self.as_ref()
.expect("attempted to get referenced tasks from `None`")
.get_ref_tasks()
}
fn get_mut_tasks(&mut self) -> &mut VecDeque<Tasks> {
self.as_mut()
.expect("attempted to get mutable tasks from `None`")
.get_mut_tasks()
}
fn get_tasks_formatted(&self) -> Vec<Line<'_>> {
self.as_ref()
.map_or(Vec::new(), |u| u.get_tasks_formatted())
}
fn set_task(&mut self, task: Tasks) {
self.as_mut().map_or((), |u| u.set_task(task))
}
}
+43 -43
View File
@@ -3,56 +3,56 @@ use ratatui::text::{Line, Span};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, ValueEnum)]
pub enum ZoomLevel {
ZoomedIn,
Default,
ZoomedOut,
ZoomedIn,
Default,
ZoomedOut,
}
pub enum CellSizes {
Width,
Height,
Width,
Height,
}
impl ZoomLevel {
pub fn get_cell_size(&self, cell_size: CellSizes) -> usize {
match (cell_size, self) {
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
(CellSizes::Width, ZoomLevel::Default) => 9,
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
(CellSizes::Height, ZoomLevel::Default) => 5,
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
pub fn get_cell_size(&self, cell_size: CellSizes) -> usize {
match (cell_size, self) {
(CellSizes::Width, ZoomLevel::ZoomedIn) => 13,
(CellSizes::Width, ZoomLevel::Default) => 9,
(CellSizes::Width, ZoomLevel::ZoomedOut) => 5,
(CellSizes::Height, ZoomLevel::ZoomedIn) => 7,
(CellSizes::Height, ZoomLevel::Default) => 5,
(CellSizes::Height, ZoomLevel::ZoomedOut) => 3,
}
}
}
pub fn get_cell_text_area<'a>(
&self,
tag: char,
structure_level: char,
unit: Span<'a>,
) -> Vec<Line<'a>> {
match self {
ZoomLevel::ZoomedIn => vec![
Line::from(vec![
Span::raw(format!(" {} ", structure_level)),
unit,
Span::raw(" "),
]),
Line::from(format!(" ")),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
Line::from(format!(" ")),
],
ZoomLevel::Default => vec![
Line::from(vec![
Span::raw(format!(" {} ", structure_level)),
unit,
Span::raw(" "),
]),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
],
ZoomLevel::ZoomedOut => vec![Line::from(format!(" {} ", tag))],
pub fn get_cell_text_area<'a>(
&self,
tag: char,
structure_level: char,
unit: Span<'a>,
) -> Vec<Line<'a>> {
match self {
ZoomLevel::ZoomedIn => vec![
Line::from(vec![
Span::raw(format!(" {} ", structure_level)),
unit,
Span::raw(" "),
]),
Line::from(format!(" ")),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
Line::from(format!(" ")),
],
ZoomLevel::Default => vec![
Line::from(vec![
Span::raw(format!(" {} ", structure_level)),
unit,
Span::raw(" "),
]),
Line::from(format!(" {} ", tag)),
Line::from(format!(" ")),
],
ZoomLevel::ZoomedOut => vec![Line::from(format!(" {} ", tag))],
}
}
}
}