factorio_blueprint/factorio-pathfinding/src/lib.rs
2025-01-30 23:22:37 +01:00

89 lines
2.3 KiB
Rust

use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*};
pub mod belt_finding;
pub mod examples;
pub mod graph;
pub mod misc;
pub mod priority_queue;
pub struct PathInput<'c, M> {
pub connections: &'c [Connection],
pub map: M,
}
pub struct Connection {
pub start_pos: Position,
pub start_dir: Direction,
pub end_pos: Position,
pub end_dir: Direction,
pub beltspeed: Beltspeed,
pub lanes: usize,
}
pub trait Map {
/// Returns true if the position is useable
fn get_position(&self, pos: Position) -> bool;
/// Returns the relevant area as (pos, size)
fn area(&self) -> (Position, Position);
}
pub trait Pathfinder {
fn find_paths<M: Map>(&self, input: PathInput<'_, M>) -> Option<Vec<Vec<PathField>>>;
}
pub struct SinglePathInput<'c, M> {
connections: &'c [SingleConnection],
map: M,
}
struct SingleConnection {
pub start_pos: Position,
pub start_dir: Direction,
pub end_pos: Position,
pub end_dir: Direction,
pub beltspeed: Beltspeed,
}
trait SinglePathfinder {
fn find_paths<M: Map>(&self, input: SinglePathInput<'_, M>) -> Option<Vec<Vec<PathField>>>;
}
impl<P> Pathfinder for P
where
P: SinglePathfinder,
{
fn find_paths<M: Map>(&self, input: PathInput<'_, M>) -> Option<Vec<Vec<PathField>>> {
let inner_input = input
.connections
.iter()
.flat_map(|c| {
(0..c.lanes).map(|i| SingleConnection {
start_pos: c
.start_pos
.in_direction(&c.start_dir.clockwise(), i as PositionType),
start_dir: c.start_dir,
end_pos: c
.end_pos
.in_direction(&c.start_dir.clockwise(), i as PositionType),
end_dir: c.end_dir,
beltspeed: c.beltspeed,
})
})
.collect::<Vec<_>>();
let inner_result = self.find_paths(SinglePathInput {
connections: &inner_input,
map: input.map,
})?;
let mut inner_iterator = inner_result.into_iter();
Some(
input
.connections
.iter()
.map(|i| inner_iterator.by_ref().take(i.lanes).flatten().collect())
.collect(),
)
}
}