removing intended_commands
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
use rsbwapi::{Order, Position, Unit, UnitType, UpgradeType};
|
||||
use rsbwapi::{UnitType, UpgradeType};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::state::build_stages::BuildStage;
|
||||
|
||||
pub struct GameState {
|
||||
pub intended_commands: HashMap<usize, IntendedCommand>,
|
||||
pub unit_build_history: Vec<BuildHistoryEntry>,
|
||||
pub build_stages: Vec<BuildStage>,
|
||||
pub current_stage_index: usize,
|
||||
@@ -15,7 +14,6 @@ pub struct GameState {
|
||||
impl Default for GameState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
intended_commands: HashMap::new(),
|
||||
unit_build_history: Vec::new(),
|
||||
build_stages: crate::state::build_stages::get_build_stages(),
|
||||
current_stage_index: 0,
|
||||
@@ -25,13 +23,6 @@ impl Default for GameState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IntendedCommand {
|
||||
pub order: Order,
|
||||
pub target_position: Option<Position>,
|
||||
pub target_unit: Option<Unit>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum BuildStatus {
|
||||
Assigned,
|
||||
|
||||
@@ -1,65 +1,25 @@
|
||||
use rsbwapi::{Game, Order, Player, Unit, UnitType};
|
||||
use rsbwapi::{Game, Player, Unit, UnitType};
|
||||
|
||||
use crate::{
|
||||
state::game_state::{BuildHistoryEntry, GameState, IntendedCommand},
|
||||
state::game_state::{BuildHistoryEntry, GameState},
|
||||
utils::build_location_utils,
|
||||
};
|
||||
|
||||
pub fn on_frame(game: &Game, player: &Player, state: &mut GameState) {
|
||||
cleanup_stale_commands(player, state);
|
||||
// No intended command tracking; directly manage builds and stages.
|
||||
check_and_advance_stage(player, state);
|
||||
state.stage_item_status = get_status_for_stage_items(game, player, state);
|
||||
try_start_next_build(game, player, state);
|
||||
}
|
||||
|
||||
pub fn on_building_create(unit: &Unit, state: &mut GameState) {
|
||||
// When a building is created, clear any intended command for the worker that was assigned to build it.
|
||||
if let Some(entry) = state
|
||||
.unit_build_history
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|e| e.unit_type == Some(unit.get_type()))
|
||||
{
|
||||
if let Some(builder_id) = entry.assigned_unit_id {
|
||||
state.intended_commands.remove(&builder_id);
|
||||
println!(
|
||||
"Building {} started. Removed assignment for worker {}",
|
||||
unit.get_type().name(),
|
||||
builder_id
|
||||
);
|
||||
}
|
||||
}
|
||||
pub fn on_building_create(_unit: &Unit, _state: &mut GameState) {
|
||||
// No intended command tracking needed.
|
||||
}
|
||||
|
||||
/// Called when a non‑building unit (e.g., a trained unit) is created.
|
||||
/// This clears any pending assignment for the building that trained it.
|
||||
pub fn on_unit_create(unit: &Unit, state: &mut GameState) {
|
||||
// Find the most recent history entry for this unit type.
|
||||
if let Some(entry) = state
|
||||
.unit_build_history
|
||||
.iter()
|
||||
.rev()
|
||||
.find(|e| e.unit_type == Some(unit.get_type()))
|
||||
{
|
||||
if let Some(builder_id) = entry.assigned_unit_id {
|
||||
// For training, we didn't store an intended command, but clear just in case.
|
||||
state.intended_commands.remove(&builder_id);
|
||||
println!(
|
||||
"Unit {} created. Cleared assignment for builder {}",
|
||||
unit.get_type().name(),
|
||||
builder_id
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cleanup_stale_commands(player: &Player, state: &mut GameState) {
|
||||
// Retain intended commands as long as the unit still exists.
|
||||
// The command will be cleared when the building/unit is created (on_building_create) or when the unit dies.
|
||||
let unit_ids: Vec<usize> = player.get_units().iter().map(|u| u.get_id()).collect();
|
||||
state
|
||||
.intended_commands
|
||||
.retain(|unit_id, _cmd| unit_ids.contains(unit_id));
|
||||
pub fn on_unit_create(_unit: &Unit, _state: &mut GameState) {
|
||||
// No intended command tracking needed for unit creation.
|
||||
}
|
||||
|
||||
fn try_start_next_build(game: &Game, player: &Player, state: &mut GameState) {
|
||||
@@ -84,7 +44,6 @@ fn try_start_next_build(game: &Game, player: &Player, state: &mut GameState) {
|
||||
tile_position: tile_pos,
|
||||
};
|
||||
state.unit_build_history.push(entry);
|
||||
let current_stage = &state.build_stages[state.current_stage_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,8 +53,6 @@ fn should_start_next_build(_game: &Game, player: &Player, state: &mut GameState)
|
||||
!has_ongoing_constructions(state, player)
|
||||
}
|
||||
|
||||
// Removed: pending assignment tracking now relies on actual unit state via has_ongoing_constructions.
|
||||
|
||||
fn has_ongoing_constructions(state: &GameState, player: &Player) -> bool {
|
||||
state.unit_build_history.iter().any(|entry| {
|
||||
if let Some(unit_id) = entry.assigned_unit_id {
|
||||
@@ -200,7 +157,7 @@ fn check_need_more_supply(_game: &Game, player: &Player, _state: &GameState) ->
|
||||
fn find_builder_for_unit(
|
||||
player: &Player,
|
||||
unit_type: UnitType,
|
||||
state: &GameState,
|
||||
_state: &GameState,
|
||||
) -> Option<rsbwapi::Unit> {
|
||||
let builder_type = unit_type.what_builds().0;
|
||||
player
|
||||
@@ -211,7 +168,6 @@ fn find_builder_for_unit(
|
||||
&& !u.is_constructing()
|
||||
&& !u.is_training()
|
||||
&& (u.is_idle() || u.is_gathering_minerals() || u.is_gathering_gas())
|
||||
&& !state.intended_commands.contains_key(&u.get_id())
|
||||
})
|
||||
.cloned()
|
||||
}
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
use rsbwapi::{Game, Order, Player, Unit};
|
||||
use rsbwapi::{Game, Player, Unit};
|
||||
|
||||
use crate::state::game_state::{GameState, IntendedCommand};
|
||||
use crate::state::game_state::GameState;
|
||||
|
||||
pub fn assign_idle_workers_to_minerals(game: &Game, player: &Player, state: &mut GameState) {
|
||||
let all_units = player.get_units();
|
||||
let workers: Vec<Unit> = all_units
|
||||
.iter()
|
||||
.filter(|u| u.get_type().is_worker() && u.is_completed())
|
||||
.filter(|u| {
|
||||
// Worker must be a completed worker unit
|
||||
u.get_type().is_worker() && u.is_completed()
|
||||
})
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
// Assign idle workers to mining
|
||||
// Assign idle workers that are not already assigned in the build history
|
||||
for worker in workers {
|
||||
// Skip if this worker is already recorded as assigned in any ongoing build history entry
|
||||
let already_assigned = state
|
||||
.unit_build_history
|
||||
.iter()
|
||||
.any(|entry| entry.assigned_unit_id == Some(worker.get_id()));
|
||||
if already_assigned {
|
||||
continue;
|
||||
}
|
||||
assign_worker_to_mineral(game, &worker, state);
|
||||
}
|
||||
}
|
||||
@@ -19,32 +30,26 @@ pub fn assign_idle_workers_to_minerals(game: &Game, player: &Player, state: &mut
|
||||
fn assign_worker_to_mineral(game: &Game, worker: &Unit, state: &mut GameState) {
|
||||
let worker_id = worker.get_id();
|
||||
|
||||
if let Some(cmd) = state.intended_commands.get(&worker_id) {
|
||||
if cmd.order != Order::MiningMinerals {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if !worker.is_idle() {
|
||||
// Skip if the worker is currently assigned to an in‑progress building construction.
|
||||
let has_in_progress_build = state.unit_build_history.iter().any(|entry| {
|
||||
entry.assigned_unit_id == Some(worker_id)
|
||||
&& entry.unit_type.map(|ut| ut.is_building()).unwrap_or(false)
|
||||
});
|
||||
if has_in_progress_build {
|
||||
return;
|
||||
}
|
||||
|
||||
if worker.is_gathering_minerals() || worker.is_gathering_gas() {
|
||||
// Worker must be idle and not already gathering resources.
|
||||
if !worker.is_idle() || worker.is_gathering_minerals() || worker.is_gathering_gas() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find a mineral patch to assign.
|
||||
let Some(mineral) = find_available_mineral(game, worker, state) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let intended_cmd = IntendedCommand {
|
||||
order: Order::MiningMinerals,
|
||||
target_position: None,
|
||||
target_unit: Some(mineral.clone()),
|
||||
};
|
||||
|
||||
state.intended_commands.insert(worker_id, intended_cmd);
|
||||
|
||||
// Assign worker to gather minerals (ignore intended command tracking).
|
||||
if worker.gather(&mineral).is_ok() {
|
||||
println!(
|
||||
"Assigned worker {} to mine from mineral at {:?}",
|
||||
@@ -54,34 +59,17 @@ fn assign_worker_to_mineral(game: &Game, worker: &Unit, state: &mut GameState) {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_available_mineral(game: &Game, worker: &Unit, state: &GameState) -> Option<Unit> {
|
||||
fn find_available_mineral(game: &Game, worker: &Unit, _state: &GameState) -> Option<Unit> {
|
||||
let worker_pos = worker.get_position();
|
||||
let minerals = game.get_static_minerals();
|
||||
let mut mineral_list: Vec<Unit> = minerals.iter().filter(|m| m.exists()).cloned().collect();
|
||||
|
||||
// Sort minerals by distance to the worker.
|
||||
mineral_list.sort_by_key(|m| {
|
||||
let pos = m.get_position();
|
||||
((pos.x - worker_pos.x).pow(2) + (pos.y - worker_pos.y).pow(2)) as i32
|
||||
});
|
||||
|
||||
for mineral in mineral_list.iter() {
|
||||
let mineral_id: usize = mineral.get_id();
|
||||
|
||||
let worker_count = state
|
||||
.intended_commands
|
||||
.values()
|
||||
.filter(|cmd| {
|
||||
if let Some(target) = &cmd.target_unit {
|
||||
target.get_id() == mineral_id
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
.count();
|
||||
|
||||
if worker_count < 2 {
|
||||
return Some(mineral.clone());
|
||||
}
|
||||
}
|
||||
// Return the closest mineral, ignoring any intended command tracking.
|
||||
mineral_list.first().cloned()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user