Files
war-in-tunnels/src/app/states/skirmish_states/board.rs
T
GarandPLG 7c9e3d28f0 Refactor task handling to use VecDeque references
- Change `get_tasks` to return `&VecDeque<Tasks>` instead of a formatted
  `String`.
- Introduce `get_tasks_formatted` for display purposes.
- Update `MinerUnit`, `Unit` trait, `Units` enum, and its `Option`
  implementation accordingly.
- Add `EMPTY_TASKS` lazy static for handling empty task lists.
- Adjust `BoardState` to use the new task API (commented out
  conditional).
2026-05-18 14:48:07 +02:00

323 lines
11 KiB
Rust

use crate::app::{
helpers::cells_area_helper,
states::{
FocusedCell, Offset,
skirmish_states::{
CellSizes, MarkedCells, MoveFocusedCell, Players, ZoomLevel,
structures::{BaseBuilding, Ore, Stone, Structures},
tasks::{DiggingTask, Tasks},
units::{MinerUnit, Unit, Units},
},
},
widgets::CellWidget,
};
use log::info;
use ratatui::layout::Rect;
use std::collections::VecDeque;
#[derive(Debug, Clone, PartialEq)]
pub struct BoardState {
cells_area: Rect,
pub cell_width: usize,
pub cell_height: usize,
pub map_width: usize,
pub map_height: usize,
pub cols: usize,
pub rows: usize,
pub vertical_offset: Offset,
pub horizontal_offset: Offset,
pub cells: Vec<Vec<CellWidget>>,
pub zoom_level: ZoomLevel,
focused_cell: FocusedCell,
pub marked_cells: MarkedCells,
}
impl BoardState {
pub fn new(
area: &Rect,
map_width: usize,
map_height: usize,
zoom_level: ZoomLevel,
side_panel: bool,
) -> Self {
let cells_area: Rect = cells_area_helper(area, side_panel);
let cell_width: usize = zoom_level.get_cell_size(CellSizes::Width);
let cell_height: usize = zoom_level.get_cell_size(CellSizes::Height);
let cols: usize = (cells_area.width / cell_width as u16) as usize;
let rows: usize = (cells_area.height / cell_height as u16) as usize;
let v_max_offset: usize = Self::max_offset(map_height, rows);
let h_max_offset: usize = Self::max_offset(map_width, cols);
let vertical_offset: Offset = Offset::new(
Some((map_height - rows as usize + 1) / 2),
Some(v_max_offset),
);
let horizontal_offset: Offset = Offset::new(None, Some(h_max_offset));
let focused_cell: FocusedCell =
FocusedCell::new((map_height) / 2, 3, map_height, map_width);
let mut cells: Vec<Vec<CellWidget>> = Vec::new();
let player_base_coords: (usize, usize) = ((map_height) / 2, 2);
let enemy_base_coords: (usize, usize) = ((map_height) / 2, map_width - 3);
for row in 0..map_height {
let mut rows: Vec<CellWidget> = Vec::new();
for col in 0..map_width {
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_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_ore: bool = row == enemy_base_coords.0 && col == enemy_base_coords.1 + 1;
let structure: Structures = if player_base {
Structures::Base(BaseBuilding::new(Players::Player))
} else if enemy_base {
Structures::Base(BaseBuilding::new(Players::Enemy))
} else if player_ore {
Structures::Ore(Ore::new(Players::Player, 1))
} else if enemy_ore {
Structures::Ore(Ore::new(Players::Enemy, 1))
} else {
Structures::Stone(Stone::new())
};
let unit: Option<Units> = if player_base {
Some(Units::Miner(MinerUnit::new(
Players::Player,
player_base_coords,
)))
} else if enemy_base {
Some(Units::Miner(MinerUnit::new(
Players::Enemy,
enemy_base_coords,
)))
} else {
None
};
rows.push(CellWidget::new(
row, col, zoom_level, selected, structure, unit,
));
}
cells.push(rows);
}
let marked_cells: MarkedCells = MarkedCells::new();
Self {
cells_area,
cell_width,
cell_height,
map_width,
map_height,
cols,
rows,
vertical_offset,
horizontal_offset,
cells,
zoom_level,
focused_cell,
marked_cells,
}
}
pub fn get_ref_cell(&self, row: usize, col: usize) -> &CellWidget {
&self.cells[row][col]
}
fn get_mut_cell(&mut self, row: usize, col: usize) -> &mut CellWidget {
&mut self.cells[row][col]
}
pub fn get_marked_cells_widgets(&self) -> VecDeque<&CellWidget> {
self.marked_cells
.marked_cells
.iter()
.map(move |&(row, col)| &self.cells[row][col])
.collect()
}
pub fn get_marked_cells(&self) -> VecDeque<(usize, usize)> {
self.marked_cells.marked_cells.clone()
}
pub fn toggle_marking(&mut self) {
self.marked_cells.marking_cells = !self.marked_cells.marking_cells;
if self.marked_cells.marking_cells {
self.start_marking_cells();
} else {
self.clear_marked_cells();
}
}
pub fn set_marked_cell(&mut self, new_cell: (usize, usize)) {
let cell: &mut CellWidget = self.get_mut_cell(new_cell.0, new_cell.1);
if !cell.get_marked() {
cell.set_marked(true);
}
self.marked_cells
.marked_cells
.push_back((new_cell.0, new_cell.1));
info!("{:?}", self.marked_cells);
}
pub fn undo_marked_cell(&mut self) {
if self.marked_cells.marked_cells.len() < 2 {
return;
}
let old: (usize, usize) =
self.marked_cells.marked_cells[self.marked_cells.marked_cells.len() - 1];
let new: (usize, usize) =
self.marked_cells.marked_cells[self.marked_cells.marked_cells.len() - 2];
let old_is_unique: bool = self
.marked_cells
.marked_cells
.iter()
.filter(|x| **x == old)
.count()
== 1;
let old_cell: &mut CellWidget = self.get_mut_cell(old.0, old.1).set_selected(false);
if old_is_unique {
old_cell.set_marked(false);
}
self.get_mut_cell(new.0, new.1).set_selected(true);
self.marked_cells.marked_cells.pop_back();
self.focused_cell.set_focused_cell(new);
}
pub fn start_marking_cells(&mut self) {
let row: usize = self.focused_cell.get_row();
let col: usize = self.focused_cell.get_col();
let cell: &mut CellWidget = self.get_mut_cell(row, col);
cell.set_marked(true);
self.marked_cells.selected_unit = cell.get_option_unit();
self.marked_cells.marked_cells.push_back((row, col));
}
pub fn clear_marked_cells(&mut self) {
for (row, col) in self.marked_cells.marked_cells.clone() {
self.get_mut_cell(row, col).set_marked(false);
}
let (row, col) = self.marked_cells.selected_unit.get_coords();
// if !self.marked_cells.marked_cells.len() == 1 {
let task: Tasks = Tasks::Digging(DiggingTask::new(self.marked_cells.marked_cells.clone()));
self.get_mut_cell(row, col)
.get_mut_option_unit()
.set_task(task);
// }
self.marked_cells.selected_unit = None;
self.marked_cells.marked_cells.clear();
}
fn max_offset(map_size: usize, size: usize) -> usize {
if map_size > size { map_size - size } else { 0 }
}
pub fn get_focused_cell(&self) -> &FocusedCell {
&self.focused_cell
}
pub fn is_focused_cell_visible(&self) -> bool {
let vertical_offset: usize = self.vertical_offset.get_value();
let horizontal_offset: usize = self.horizontal_offset.get_value();
let row: usize = self.focused_cell.get_row();
let col: usize = self.focused_cell.get_col();
if 0usize.saturating_add(vertical_offset) > row
|| row >= self.rows.saturating_add(vertical_offset)
{
return false;
}
if 0usize.saturating_add(horizontal_offset) > col
|| col >= self.cols.saturating_add(horizontal_offset)
{
return false;
}
true
}
pub fn change_resize(&mut self, area: &Rect, side_panel: bool) {
self.cells_area = cells_area_helper(area, side_panel);
self.cols = (self.cells_area.width / self.cell_width as u16) as usize;
self.rows = (self.cells_area.height / self.cell_height as u16) as usize;
let v_max_offset: usize = Self::max_offset(self.map_height, self.rows);
let h_max_offset: usize = Self::max_offset(self.map_width, self.cols);
self.horizontal_offset =
Offset::new(Some(self.horizontal_offset.get_value()), Some(h_max_offset));
self.vertical_offset =
Offset::new(Some(self.vertical_offset.get_value()), Some(v_max_offset));
}
pub fn change_zoom(&mut self, new_zoom_level: ZoomLevel) {
self.zoom_level = new_zoom_level;
self.cell_width = new_zoom_level.get_cell_size(CellSizes::Width);
self.cell_height = new_zoom_level.get_cell_size(CellSizes::Height);
self.cols = (self.cells_area.width / self.cell_width as u16) as usize;
self.rows = (self.cells_area.height / self.cell_height as u16) as usize;
let v_max_offset: usize = Self::max_offset(self.map_height, self.rows);
let h_max_offset: usize = Self::max_offset(self.map_width, self.cols);
self.vertical_offset =
Offset::new(Some(self.vertical_offset.get_value()), Some(v_max_offset));
self.horizontal_offset =
Offset::new(Some(self.horizontal_offset.get_value()), Some(h_max_offset));
self.focused_cell = FocusedCell::new(
self.focused_cell.get_row(),
self.focused_cell.get_col(),
self.map_height,
self.map_width,
);
for row in 0..self.map_height {
for col in 0..self.map_width {
self.get_mut_cell(row, col).set_zoom_level(new_zoom_level);
}
}
}
pub fn change_focused_cell(&mut self, direction: MoveFocusedCell) {
let old_cell: (usize, usize) = (self.focused_cell.get_row(), self.focused_cell.get_col());
let new_cell: (usize, usize) = self.focused_cell.move_focused_cell(direction);
self.get_mut_cell(old_cell.0, old_cell.1)
.set_selected(false);
self.get_mut_cell(new_cell.0, new_cell.1).set_selected(true);
if self.marked_cells.marking_cells {
self.set_marked_cell(new_cell);
}
}
}