I have been coding in an external editor, using a rust bundler. After making some changes to my code and increasing it's length, the compiler refuses to compile and just says "Unknown Language." I've verified that the right code is being input, so I'm not sure what the issue is.
pub mod oort_ai_v2 {
use oort_api::prelude::*;
#[cfg(test)]
pub mod test {
use oort_api::prelude::*;
use byteorder::{ByteOrder, ReadBytesExt, BE, LE};
use std::io::{Cursor, Read};
use super::api::comms::*;
#[test]
fn test_serde_vec4() {
let vec = vec2(16.0 * 500.0, 16.0 * 811.0);
let bytes = serialize_vec_i16(vec);
println!("bytes: {:0>8b} {:0>8b}, {:0>8b} {:0>8b}", bytes[0], bytes[1], bytes[2], bytes[3]);
let new_vec = deserialize_vec_i16(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec4");
}
#[test]
fn test_serde_vec8() {
let vec = vec2(500.0, 811.0);
let bytes = serialize_vec_f32(vec);
let new_vec = deserialize_vec_f32(&bytes);
assert_eq!(vec, new_vec, "Data preserved by serde_vec8");
}
}
pub mod api {
pub mod comms {
use std::io::Cursor;
use oort_api::prelude::*;
use byteorder::{ReadBytesExt, WriteBytesExt, ByteOrder, BE};
pub fn serialize_vec_i16(vec: Vec2) -> [u8; 4]{
let x = vec.x.round_ties_even() as i16;
let y = vec.y.round_ties_even() as i16;
[
(y >> 8) as u8,
y as u8,
(x >> 8) as u8,
x as u8,
]
}
pub fn deserialize_vec_i16(data: &[u8; 4]) -> Vec2{
vec2(
((data[2] as i16) << 8 | (data[3] as i16)) as f64,
((data[0] as i16) << 8 | (data[1] as i16)) as f64,
)
}
pub fn serialize_vec_f32(vec: Vec2) -> [u8; 8]{
let mut writer = Cursor::new([0; 8]);
writer.write_f32::<BE>(vec.x as f32).unwrap();
writer.write_f32::<BE>(vec.y as f32).unwrap();
writer.into_inner()
}
pub fn deserialize_vec_f32(data: &[u8; 8]) -> Vec2 {
let mut reader = Cursor::new(data);
let x = reader.read_f32::<BE>().unwrap();
let y = reader.read_f32::<BE>().unwrap();
vec2(x as f64, y as f64)
}
pub enum MessageData {
EnemyArea(Vec2)
} impl MessageData {
pub fn serialize(self) {
match self {
MessageData::EnemyArea(pos) => todo!(),
}
}
}
pub struct Message {
data: MessageData,
sender: u16,
}
}
pub mod targeting {
use oort_api::prelude::*;
#[derive(Clone, Copy, PartialEq)]
pub struct Target {
pub class: Class,
pub position: Vec2,
pub velocity: Vec2,
pub last_seen: f64,
} impl From<ScanResult> for Target {
fn from(value: ScanResult) -> Self {
Target {
class: value.class,
position: value.position,
velocity: value.velocity,
last_seen: current_time(),
}
}
} impl Target {
pub fn vec_to(&self) -> Vec2 {
self.position - position()
}
pub fn angle_to(&self) -> f64 {
self.vec_to().angle()
}
}
#[derive(Clone, Copy, PartialEq)]
pub enum RadarOperation {
Search(f64), //dist
Look(f64), //angle
Track(Target),
}
#[derive(Clone, Copy, PartialEq)]
pub struct RadarStatus {
heading: f64,
width: f64,
min: f64,
max: f64,
ecm: EcmMode,
} impl RadarStatus {
pub fn save() -> Self {
RadarStatus {
heading: radar_heading(),
width: radar_width(),
min: radar_min_distance(),
max: radar_max_distance(),
ecm: radar_ecm_mode(),
}
}
pub fn restore(self) {
set_radar_heading(self.heading);
set_radar_width(self.width);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_ecm_mode(self.ecm);
}
}
pub struct RadarBeamSearcher {
pub width: f64,
pub min: f64,
pub max: f64,
} impl RadarBeamSearcher {
pub fn new() -> Self {
RadarBeamSearcher {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
}
}
pub fn tick(&self) {
set_radar_heading(heading());
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
scan().map(|v| v.into())
}
}
pub struct RadarBeamSweeper {
pub width: f64,
pub min: f64,
pub max: f64,
look_angle: f64,
target: Option<Target>,
} impl RadarBeamSweeper {
pub fn new() -> Self {
RadarBeamSweeper {
width: TAU / 10.0,
min: 2.0,
max: 20000.0,
look_angle: 0.0,
target: None,
}
}
pub fn tick(&mut self) {
if let Some(result) = scan() {
let result = Target::from(result);
self.target = Some(result);
self.look_angle = result.angle_to();
debug!("Sweeper: Active");
} else if let Some(target) = self.target {
let age = current_time() - target.last_seen;
debug!("Sweeper: Last-Seen {age} ago");
if age > 2.5 {
self.target.take();
}
} else {
debug!("Sweeper: Scanning");
self.look_angle += self.width / 5.0;
}
set_radar_heading(self.look_angle);
set_radar_min_distance(self.min);
set_radar_max_distance(self.max);
set_radar_width(self.width);
}
pub fn get_target(&self) -> Option<Target> {
self.target
}
}
pub struct RadarTracker {
operations: Vec<(RadarStatus, RadarOperation)>
}
}
pub mod control {
pub mod movement {
use oort_api::prelude::*;
#[allow(dead_code)]
pub fn lerp(a: f64, b: f64, d: f64) -> f64 {
(1.0 - d) * a + d * b
}
pub fn max_accel(current_heading: f64, target_heading: f64) -> f64 {
let offset = angle_diff(target_heading, current_heading+PI/2.0) + PI;
let quarter = (offset / (TAU / 4.0)) as u32;
let mut quarter_offset = offset;
while quarter_offset > TAU / 4.0 {
quarter_offset -= TAU / 4.0;
}
quarter_offset = quarter_offset * 4.0 / TAU;
match quarter {
0 => lerp(max_lateral_acceleration(), max_backward_acceleration(), quarter_offset),
1 => lerp(max_backward_acceleration(), max_lateral_acceleration(), quarter_offset),
2 => lerp(max_lateral_acceleration(), max_forward_acceleration(), quarter_offset),
3 => lerp(max_forward_acceleration(), max_lateral_acceleration(), quarter_offset),
_ => unreachable!(),
}
}
pub enum ActionControl<T> {
NoControl,
Auto,
Manual(T),
}
pub type AngleControl = ActionControl<f64>;
}
pub mod pid {
#[allow(dead_code)]
pub struct PID {
pub gain_p: f64,
pub gain_i: f64,
pub gain_d: f64,
prev_error: Option<f64>,
idle_time: u32,
} impl PID {
pub fn solve(&mut self, error: f64, dt: f64) -> f64 {
let p = error;
let i = 0.0;
let d;
if let Some(prev_error) = self.prev_error.replace(error) {
d = (error - prev_error) / dt;
self.prev_error.replace(error);
} else {
d = 0.0;
}
let out = p * self.gain_p
+ i * self.gain_i
+ d * self.gain_d;
out
}
pub fn new(gain_p: f64, gain_i: f64, gain_d: f64, output_rate: f64) -> Self {
PID {
gain_p: gain_p * output_rate,
gain_i: gain_i * output_rate,
gain_d: gain_d * output_rate,
prev_error: None,
idle_time: 0,
}
}
pub fn reset(&mut self) {
self.prev_error = None;
}
pub fn idle(&mut self) {
if self.prev_error.is_some() {
self.idle_time += 1;
if self.idle_time > 15 {
self.prev_error.take();
self.idle_time = 0;
}
}
}
}
}
pub mod point {
use oort_api::prelude::*;
use super::super::super::api::{control::{movement::max_accel, pid::PID}, targeting::Target};
#[allow(dead_code)]
pub struct PointAutopilot {
angle_pid: PID,
position_pid: PID,
auto_angle: bool,
infinite_accel: bool,
pub allow_boost: bool,
orbit_distance: f64,
target_angle: Option<f64>,
target_location: Option<Vec2>,
angle_error: Option<f64>,
} impl PointAutopilot {
pub fn new() -> Self {
PointAutopilot {
angle_pid: PID::new(1.0, 0.0, 1.0, max_angular_acceleration()),
position_pid: PID::new(0.5, 0.0, 1.5, 1.0),
auto_angle: true,
infinite_accel: false,
allow_boost: false,
orbit_distance: 0.0,
target_angle: None,
target_location: None,
angle_error: None,
}
}
pub fn tick(&mut self) {
let mut is_at_target = false;
if let Some(target) = self.target_location {
if (target - position()).length() < self.orbit_distance + 3.0 {
is_at_target = true;
}
}
debug!("Point @{} >{} ('{}')", match (self.target_location, self.infinite_accel, is_at_target) {
(Some(_), _, true) => "++",
(Some(_), false, _) => "To",
(Some(_), true, _) => "Cross",
(None, _, _) => "OVERRIDE",
}, match (self.target_angle, self.auto_angle) {
(_, true) => "Auto",
(Some(_), false) => "Specific",
(None, false) => "OVERRIDE",
}, match (self.target_location, self.infinite_accel, self.target_angle, self.auto_angle) {
(Some(location), false, None, true) => {
draw_line(position(), location, 0xFFFF00);
"goto"
},
(Some(location), true, None, true) => {
draw_line(position(), location, 0xFFFF00);
draw_diamond(location, 10.0, 0xFFFF00);
"flyby"
},
(Some(location), _, None, false) => {
draw_line(position(), location, 0xFF0000);
"strafe"
},
(Some(location), _, Some(angle), false) => {
draw_line(position(), location, 0xFF0000);
draw_line(position(), position() + vec2(100.0, 0.0).rotate(angle), 0x00FF00);
"target-strafe"
},
(None, _, Some(angle), _) => {
draw_line(position(), position() + vec2(100.0, 0.0).rotate(angle), 0x00FF00);
"point-at"
},
(None, _, None, _) => "idle",
_ => "?",
});
let mut target_angle = self.target_angle.clone();
if let Some(target) = self.target_location {
let vec_between = target - position();
if self.auto_angle {
target_angle = Some(vec_between.angle());
}
if self.orbit_distance > 0.0 {
draw_polygon(target, self.orbit_distance, 10, current_time(), 0xFF00FF);
}
if !is_at_target && fuel() > 0.0 {
if self.allow_boost {
if self.angle_error.is_some_and(|v| v.abs() < TAU/32.0) && vec_between.length() - self.orbit_distance > 100.0 {
activate_ability(Ability::Boost);
} else if self.angle_error.is_some_and(|v| v.abs() > TAU / 16.0) {
deactivate_ability(Ability::Boost);
}
}
if self.infinite_accel {
accelerate(vec_between.normalize() * max_forward_acceleration());
} else {
let impulse = self.position_pid.solve(vec_between.length() - self.orbit_distance, TICK_LENGTH) * max_accel(heading(), -vec_between.angle());
accelerate(vec_between.normalize() * impulse);
}
} else if is_at_target {
accelerate(-velocity());
deactivate_ability(Ability::Boost);
} else {
debug!("Point ⚠️Not at target, but no fuel!⚠️");
}
}
if self.target_location.is_none() || is_at_target {
self.position_pid.idle();
}
if let Some(angle) = target_angle {
let error = angle_diff(heading(), angle);
self.angle_error = Some(error);
let force = self.angle_pid.solve(error, TICK_LENGTH);
torque(force);
}
if target_angle.is_none() {
self.angle_pid.idle();
}
}
pub fn orbit_distance(&mut self, distance: f64) {
self.orbit_distance = distance;
}
pub fn go_to(&mut self, location: Vec2) {
self.auto_angle = true;
self.infinite_accel = false;
self.target_angle = None;
self.target_location = Some(location);
}
pub fn fly_by(&mut self, location: Vec2) {
self.auto_angle = true;
self.infinite_accel = true;
self.target_angle = None;
self.target_location = Some(location);
}
pub fn point_at(&mut self, location: Vec2) {
self.auto_angle = false;
let vec_between = location - position();
self.target_angle = Some(vec_between.angle());
}
pub fn point_at_angle(&mut self, angle: f64) {
let indicator = position() + vec2(100.0, 0.0).rotate(angle);
self.auto_angle = false;
self.target_angle = Some(angle);
}
pub fn strafe_to(&mut self, location: Vec2) {
self.auto_angle = false;
self.target_location = Some(location);
}
pub fn target_ship(&mut self, ship: Option<Target>) {
}
pub fn angle_error(&self) -> Option<f64> {
self.angle_error
}
pub fn eta(&self) -> Option<f64> {
let target = self.target_location?;
let rel_target = target - position();
let approach = rel_target / velocity();
Some(approach.length())
}
pub fn distance(&self) -> Option<f64> {
Some((self.target_location? - position()).length())
}
pub fn builder() -> PointAutopilotBuilder {
PointAutopilotBuilder::new()
}
}
pub struct PointAutopilotBuilder {
allow_boost: bool,
} impl PointAutopilotBuilder {
pub fn new() -> Self {
PointAutopilotBuilder {
allow_boost: false,
}
}
pub fn build(self) -> PointAutopilot {
let mut out = PointAutopilot::new();
out.allow_boost = self.allow_boost;
out
}
pub fn allow_boost(mut self) -> Self {
self.allow_boost = true;
self
}
pub fn disallow_boost(mut self) -> Self {
self.allow_boost = false;
self
}
}
}