rocketsim 0.2.4

Simulate Rocket League games at maximum efficiency
Documentation
use glam::{Vec3, Vec3A};

use crate::{Team, consts::dropshot};

pub const TILE_POSITIONS: [Vec3A; dropshot::NUM_TILES_PER_TEAM] = get_tile_positions();
pub const TILE_NEIGHBORS_1: [Varr<7>; dropshot::NUM_TILES_PER_TEAM] = get_tile_neighbors::<1, _>();
pub const TILE_NEIGHBORS_2: [Varr<19>; dropshot::NUM_TILES_PER_TEAM] = get_tile_neighbors::<2, _>();

const fn get_tile_positions() -> [Vec3A; dropshot::NUM_TILES_PER_TEAM] {
    let mut tile_positions = [Vec3A::ZERO; dropshot::NUM_TILES_PER_TEAM];

    let mut cur_idx = 0;
    let mut y = dropshot::TILE_OFFSET_Y;

    let mut i = 0;
    while i < dropshot::NUM_TILE_ROWS {
        let num_tiles = dropshot::TILES_IN_FIRST_ROW - i;
        let row_size_x = dropshot::TILE_WIDTH_X * num_tiles as f32;
        let row_start_x = -(row_size_x / 2.0) + (dropshot::TILE_WIDTH_X / 2.0);

        let mut j = 0;
        while j < num_tiles {
            let x = row_start_x + dropshot::TILE_WIDTH_X * j as f32;
            tile_positions[cur_idx] = Vec3A::new(x, y, 0.0);
            cur_idx += 1;
            j += 1;
        }

        y += dropshot::ROW_OFFSET_Y;
        i += 1;
    }

    assert!(
        cur_idx == dropshot::NUM_TILES_PER_TEAM,
        "Failed to reach tile amount, make sure tile info is correct"
    );

    tile_positions
}

#[derive(Clone, Copy)]
pub struct Varr<const N: usize> {
    arr: [usize; N],
    len: usize,
}

impl<const N: usize> Varr<N> {
    const fn new() -> Self {
        Self {
            arr: [0; N],
            len: 0,
        }
    }

    const fn push(&mut self, value: usize) {
        if self.len >= N {
            panic!("Varr overflow");
        }

        self.arr[self.len] = value;
        self.len += 1;
    }

    pub fn as_slice(&self) -> &[usize] {
        &self.arr[..self.len]
    }
}

const fn get_tile_pos(team: Team, index: usize) -> Vec3 {
    let [x, y, z] = TILE_POSITIONS[index].to_array();
    let team = (team as i8 * 2 - 1) as f32;
    Vec3::new(x * team, y * team, z * team)
}

const fn get_tile_neighbors<const RADIUS: u8, const MAX_NEIGHBORS: usize>()
-> [Varr<MAX_NEIGHBORS>; dropshot::NUM_TILES_PER_TEAM] {
    let neighbor_max_radius = dropshot::TILE_WIDTH_X * 1.2 * RADIUS as f32;
    let neighbor_max_radius_sq = neighbor_max_radius * neighbor_max_radius;

    let mut neighbors = [Varr::new(); dropshot::NUM_TILES_PER_TEAM];

    let mut i = 0;
    while i < dropshot::NUM_TILES_PER_TEAM {
        let pos = get_tile_pos(Team::Blue, i);

        let mut j = 0;
        while j < dropshot::NUM_TILES_PER_TEAM {
            let other_pos = get_tile_pos(Team::Blue, j);
            let diff = Vec3 {
                x: pos.x - other_pos.x,
                y: pos.y - other_pos.y,
                z: pos.z - other_pos.z,
            };

            let dist_sq = diff.x * diff.x + diff.y * diff.y + diff.z * diff.z;
            if dist_sq < neighbor_max_radius_sq {
                neighbors[i].push(j);
            }

            j += 1;
        }

        i += 1;
    }

    neighbors
}