summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/constants.rs6
-rw-r--r--src/mass.rs11
-rw-r--r--src/math.rs55
-rw-r--r--src/modules/navigation.rs15
-rw-r--r--src/modules/tractorbeam.rs120
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 {