diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/constants.rs | 6 | ||||
-rw-r--r-- | src/mass.rs | 11 | ||||
-rw-r--r-- | src/math.rs | 55 | ||||
-rw-r--r-- | src/modules/navigation.rs | 15 | ||||
-rw-r--r-- | src/modules/tractorbeam.rs | 120 |
5 files changed, 141 insertions, 66 deletions
diff --git a/src/constants.rs b/src/constants.rs index 4c48cac..6f2cf6f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -15,7 +15,11 @@ pub const SHIP_NAVIGATION_RANGE: f64 = 100.0; pub const SHIP_REFINERY_TIME: u64 = 5; pub const SHIP_TRACTORBEAM_STRENGTH: f64 = 0.1; pub const SHIP_TRACTORBEAM_RANGE: f64 = 50.0; -pub const SHIP_TRACTORBEAM_BRING_TO_DISTANCE: f64 = 5.0; +pub const SHIP_TRACTORBEAM_ACQUIRE_RANGE: f64 = 1.0; +pub const SHIP_TRACTORBEAM_CONTROLSYSTEM_KP: f64 = 1.0; +pub const SHIP_TRACTORBEAM_CONTROLSYSTEM_KI: f64 = 0.01; +pub const SHIP_TRACTORBEAM_CONTROLSYSTEM_KD: f64 = 0.001; +pub const SHIP_TRACTORBEAM_CONTROLSYSTEM_DT: f64 = 0.0001; pub const SHIP_ENGINES_FUEL_START: f64 = 100.0; pub const SHIP_ENGINES_ACCELERATION: f64 = 0.1; diff --git a/src/mass.rs b/src/mass.rs index a307295..820173f 100644 --- a/src/mass.rs +++ b/src/mass.rs @@ -179,8 +179,15 @@ impl Mass { if let Some(target_name) = &navigation.target_name { let mut target = masses.remove(target_name).unwrap(); mining.process(self.position.clone(), masses, &mut target, storage); - tractorbeam.process(self.position.clone(), &mut target); - masses.insert(target_name.to_string(), target); + let acquired = tractorbeam.process(self.position.clone(), &mut target); + + if acquired { + if let MassType::Item { item } = target.mass_type { + storage.give_item(item); + } + } else { + masses.insert(target_name.to_string(), target); + } } let target = match &navigation.target_name { diff --git a/src/math.rs b/src/math.rs index e266a88..4f0558c 100644 --- a/src/math.rs +++ b/src/math.rs @@ -2,6 +2,8 @@ extern crate rand; use self::rand::distributions::Alphanumeric; use self::rand::Rng; +use crate::constants; +use crate::modules::types::ModuleType; use std::iter::repeat; pub fn rand_name() -> String { @@ -11,6 +13,59 @@ pub fn rand_name() -> String { .collect() } +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct ControlSystem { + previous_error: f64, + integral: f64, + kp: f64, + ki: f64, + kd: f64, + dt: f64, +} + +impl ControlSystem { + pub fn new(module: ModuleType) -> ControlSystem { + let previous_error = 0.0; + let integral = 0.0; + match module { + ModuleType::Tractorbeam => ControlSystem { + kp: constants::SHIP_TRACTORBEAM_CONTROLSYSTEM_KP, + ki: constants::SHIP_TRACTORBEAM_CONTROLSYSTEM_KI, + kd: constants::SHIP_TRACTORBEAM_CONTROLSYSTEM_KD, + dt: constants::SHIP_TRACTORBEAM_CONTROLSYSTEM_DT, + previous_error, + integral, + }, + _ => ControlSystem { + kp: 1.0, + ki: 1.0, + kd: 1.0, + dt: 1.0, + previous_error, + integral, + }, + } + } + + pub fn compute(&mut self, strength: f64, distance: f64, desired_distance: f64) -> f64 { + let error = desired_distance - distance; + self.integral += error * self.dt; + let derivative = (error - self.previous_error) / self.dt; + let output = self.kp * error + self.ki * self.integral + self.kd * derivative; + self.previous_error = error; + + if output.abs() > strength { + if output.is_sign_positive() { + strength + } else { + strength * -1.0 + } + } else { + output + } + } +} + #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] pub struct Vector { pub x: f64, diff --git a/src/modules/navigation.rs b/src/modules/navigation.rs index c931338..6df3327 100644 --- a/src/modules/navigation.rs +++ b/src/modules/navigation.rs @@ -1,3 +1,4 @@ +use std::cmp::Ordering; use std::collections::HashMap; use std::time::SystemTime; @@ -60,8 +61,18 @@ impl Navigation { fn verify_target(&mut self, ship_position: Vector, masses: &HashMap<String, Mass>) { if let Some(name) = self.target_name.clone() { - let target = masses.get(&name).unwrap(); - if target.position.distance_from(ship_position) > self.range { + let good = match masses.get(&name) { + Some(target) => { + target + .position + .distance_from(ship_position) + .partial_cmp(&self.range) + == Some(Ordering::Less) + } + None => false, + }; + + if !good { self.target_name = None; self.status = Status::None; } diff --git a/src/modules/tractorbeam.rs b/src/modules/tractorbeam.rs index 28aa181..726c8b1 100644 --- a/src/modules/tractorbeam.rs +++ b/src/modules/tractorbeam.rs @@ -1,6 +1,8 @@ use crate::constants; -use crate::mass::Mass; +use crate::mass::{Mass, MassType}; +use crate::math::ControlSystem; use crate::math::Vector; +use crate::modules::types::ModuleType; #[derive(Serialize, Deserialize, Debug, Clone, Default)] pub struct Tractorbeam { @@ -11,47 +13,6 @@ pub struct Tractorbeam { control_system: ControlSystem, } -#[derive(Serialize, Deserialize, Debug, Clone, Default)] -struct ControlSystem { - previous_error: f64, - integral: f64, - kp: f64, - ki: f64, - kd: f64, - dt: f64, -} - -impl ControlSystem { - pub fn new() -> ControlSystem { - ControlSystem { - previous_error: 0.0, - integral: 0.0, - kp: 1.0, - ki: 0.01, - kd: 0.001, - dt: 0.0001, - } - } - - pub fn compute(&mut self, strength: f64, distance: f64, desired_distance: f64) -> f64 { - let error = desired_distance - distance; - self.integral += error * self.dt; - let derivative = (error - self.previous_error) / self.dt; - let output = self.kp * error + self.ki * self.integral + self.kd * derivative; - self.previous_error = error; - - if output.abs() > strength { - if output.is_sign_positive() { - strength - } else { - strength * -1.0 - } - } else { - output - } - } -} - impl Tractorbeam { pub fn new() -> Tractorbeam { Tractorbeam { @@ -59,11 +20,11 @@ impl Tractorbeam { status: Status::None, strength: constants::SHIP_TRACTORBEAM_STRENGTH, desired_distance: None, - control_system: ControlSystem::new(), + control_system: ControlSystem::new(ModuleType::Tractorbeam), } } - pub fn process(&mut self, ship_position: Vector, target: &mut Mass) { + pub fn process(&mut self, ship_position: Vector, target: &mut Mass) -> bool { let distance = ship_position.distance_from(target.position.clone()); if self.range < distance { self.off() @@ -81,15 +42,37 @@ impl Tractorbeam { } None => Vector::default(), }, + Status::Acquire => { + match target.mass_type { + MassType::Item { .. } => (), + _ => { + self.status = Status::None; + Vector::default(); + } + } + if distance > constants::SHIP_TRACTORBEAM_ACQUIRE_RANGE { + direction.unitize() + * self.control_system.compute( + self.strength, + distance, + constants::SHIP_TRACTORBEAM_ACQUIRE_RANGE, + ) + } else { + self.status = Status::None; + return true; + } + } Status::None => Vector::default(), }; target.effects.give_acceleration(acceleration); } + false } pub fn get_client_data(&self, target: Option<&Mass>) -> String { let client_data = ClientData { + desired_distance: self.desired_distance, has_target: target.is_some(), status: self.status.clone(), }; @@ -98,40 +81,47 @@ impl Tractorbeam { } pub fn give_received_data(&mut self, recv: String) { - match recv.as_str() { - "o" => self.toggle_pull(), - "p" => self.toggle_push(), - "b" => self.toggle_bring(constants::SHIP_TRACTORBEAM_BRING_TO_DISTANCE), - _ => (), + let server_recv_data: Result<ServerRecvData, serde_json::Error> = + serde_json::from_str(&recv); + if let Ok(server_recv_data) = server_recv_data { + match server_recv_data.key.as_ref() { + "o" => self.toggle_pull(), + "p" => self.toggle_push(), + "b" => self.toggle_bring(server_recv_data.desired_distance), + "a" => self.toggle_acquire(), + _ => (), + } } } fn toggle_pull(&mut self) { self.status = match self.status { - Status::None => Status::Pull, - Status::Push => Status::Pull, - Status::Bring => Status::Pull, Status::Pull => Status::None, + _ => Status::Pull, } } fn toggle_push(&mut self) { self.status = match self.status { - Status::None => Status::Push, - Status::Pull => Status::Push, - Status::Bring => Status::Push, Status::Push => Status::None, + _ => Status::Push, } } - fn toggle_bring(&mut self, desired_distance: f64) { - self.desired_distance = Some(desired_distance); - self.control_system = ControlSystem::new(); + fn toggle_bring(&mut self, desired_distance: Option<f64>) { + self.desired_distance = desired_distance; + self.control_system = ControlSystem::new(ModuleType::Tractorbeam); self.status = match self.status { - Status::None => Status::Bring, - Status::Pull => Status::Bring, - Status::Push => Status::Bring, Status::Bring => Status::None, + _ => Status::Bring, + } + } + + fn toggle_acquire(&mut self) { + self.control_system = ControlSystem::new(ModuleType::Tractorbeam); + self.status = match self.status { + Status::Acquire => Status::None, + _ => Status::Acquire, } } @@ -143,15 +133,23 @@ impl Tractorbeam { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct ClientData { pub has_target: bool, + pub desired_distance: Option<f64>, pub status: Status, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ServerRecvData { + pub key: String, + pub desired_distance: Option<f64>, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] pub enum Status { None, Push, Pull, Bring, + Acquire, } impl Default for Status { |