Add PathFinder trait
This commit is contained in:
parent
5c8010c23b
commit
08eb0a8e11
8 changed files with 688 additions and 373 deletions
|
|
@ -1,7 +1,10 @@
|
|||
use crate::graph::wheighted_graph::shortest_path::dijkstra;
|
||||
use crate::examples::HashMapMap;
|
||||
use crate::graph::wheighted_graph::WheightedGraph;
|
||||
use crate::misc::Map;
|
||||
use crate::priority_queue::BinaryHeap;
|
||||
use crate::Connection;
|
||||
use crate::Map as _;
|
||||
use crate::{graph::wheighted_graph::shortest_path::dijkstra, SinglePathfinder};
|
||||
use factorio_core::{prelude::*, visualize::Visualize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -9,6 +12,45 @@ pub mod brute_force;
|
|||
|
||||
pub mod conflict_avoidance;
|
||||
|
||||
pub struct ConflictAvoidance {
|
||||
timeout: Option<std::time::Duration>,
|
||||
}
|
||||
|
||||
impl SinglePathfinder for ConflictAvoidance {
|
||||
fn find_paths(
|
||||
&self,
|
||||
input: &[crate::SingleConnection],
|
||||
map: impl crate::Map,
|
||||
) -> Option<Vec<Vec<factorio_core::pathfield::PathField>>> {
|
||||
let (pos, size) = map.area();
|
||||
let mut p = Problem::new(size.x as usize, size.y as usize);
|
||||
|
||||
for x in 0..size.x {
|
||||
for y in 0..size.y {
|
||||
if !map.get_position(Position::new(x - pos.x, y - pos.y)) {
|
||||
p.set_blocked(x as usize, y as usize, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in input {
|
||||
p.add_connection((i.start_pos, i.start_dir), (i.end_pos, i.end_dir));
|
||||
}
|
||||
|
||||
if p.find_path() {
|
||||
let mut c = conflict_avoidance::ConflictAvoidance::new(&p);
|
||||
|
||||
if c.remove_all_conflicts(self.timeout) {
|
||||
Some(c.get_paths().to_vec())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)]
|
||||
pub struct Field {
|
||||
pub blocked: bool,
|
||||
|
|
@ -33,45 +75,6 @@ impl Problem {
|
|||
}
|
||||
}
|
||||
|
||||
// pub fn from_layout(l: &Layout) -> Self {
|
||||
// let mut p = Self::new(l.problem.size.x as usize, l.problem.size.y as usize);
|
||||
|
||||
// for b in &l.blocks {
|
||||
// let aabb = b.get_aabb();
|
||||
|
||||
// p.set_blocked_range(
|
||||
// aabb.min().x as usize,
|
||||
// aabb.min().y as usize,
|
||||
// aabb.max().x as usize,
|
||||
// aabb.max().y as usize,
|
||||
// true,
|
||||
// );
|
||||
// }
|
||||
|
||||
// for c in &l.problem.connections {
|
||||
// let start_transform = l.blocks[c.startblock].block_to_world();
|
||||
// let startpos = l.problem.blocks[c.startblock].output[c.startpoint]
|
||||
// .offset
|
||||
// .transform(start_transform);
|
||||
// let startdir = l.problem.blocks[c.startblock].output[c.startpoint]
|
||||
// .dir
|
||||
// .transform(start_transform);
|
||||
// let end_transform = l.blocks[c.endblock].block_to_world();
|
||||
// let endpos = l.problem.blocks[c.endblock].input[c.endpoint]
|
||||
// .offset
|
||||
// .transform(end_transform);
|
||||
// let enddir = l.problem.blocks[c.endblock].input[c.endpoint]
|
||||
// .dir
|
||||
// .transform(end_transform);
|
||||
// p.add_connection(
|
||||
// (startpos, startdir),
|
||||
// (endpos.in_direction(&enddir, -1), enddir),
|
||||
// );
|
||||
// }
|
||||
|
||||
// p
|
||||
// }
|
||||
|
||||
pub fn add_connection(&mut self, start: (Position, Direction), end: (Position, Direction)) {
|
||||
self.start.push(start);
|
||||
self.end.push(end);
|
||||
|
|
@ -125,6 +128,27 @@ impl Problem {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<(Vec<Connection>, HashMapMap)> for Problem {
|
||||
fn from((input, map): (Vec<Connection>, HashMapMap)) -> Self {
|
||||
let (pos, size) = map.area();
|
||||
let mut p = Problem::new(size.x as usize, size.y as usize);
|
||||
|
||||
for x in 0..size.x {
|
||||
for y in 0..size.y {
|
||||
if !map.get_position(Position::new(x - pos.x, y - pos.y)) {
|
||||
p.set_blocked(x as usize, y as usize, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i in input {
|
||||
p.add_connection((i.start_pos, i.start_dir), (i.end_pos, i.end_dir));
|
||||
}
|
||||
|
||||
p
|
||||
}
|
||||
}
|
||||
|
||||
impl Visualize for Problem {
|
||||
fn visualize(&self) -> factorio_core::visualize::Visualization {
|
||||
let mut v = factorio_core::visualize::Visualization::new(Position::new(
|
||||
|
|
@ -247,321 +271,3 @@ impl Problem {
|
|||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub mod problems {
|
||||
use super::Problem;
|
||||
use factorio_core::prelude::*;
|
||||
|
||||
pub fn simple() -> Problem {
|
||||
let mut p = Problem::new(5, 3);
|
||||
|
||||
p.set_blocked_range(2, 0, 2, 2, true);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(0, 1), Direction::Right),
|
||||
(Position::new(4, 1), Direction::Right),
|
||||
);
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_1() -> Problem {
|
||||
let mut p = Problem::new(17, 13);
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
|
||||
p.set_blocked(1, 4, true);
|
||||
p.set_blocked(2, 4, true);
|
||||
p.set_blocked(1, 5, true);
|
||||
p.set_blocked(2, 5, true);
|
||||
|
||||
p.set_blocked(1, 7, true);
|
||||
p.set_blocked(2, 7, true);
|
||||
p.set_blocked(1, 8, true);
|
||||
p.set_blocked(2, 8, true);
|
||||
|
||||
p.set_blocked(0, 9, true);
|
||||
|
||||
p.set_blocked(16, 3, true);
|
||||
|
||||
p.set_blocked(14, 4, true);
|
||||
p.set_blocked(15, 4, true);
|
||||
p.set_blocked(14, 5, true);
|
||||
p.set_blocked(15, 5, true);
|
||||
|
||||
p.set_blocked(14, 7, true);
|
||||
p.set_blocked(15, 7, true);
|
||||
p.set_blocked(14, 8, true);
|
||||
p.set_blocked(15, 8, true);
|
||||
|
||||
p.set_blocked(16, 9, true);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 7), Direction::Right),
|
||||
(Position::new(13, 4), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 8), Direction::Right),
|
||||
(Position::new(13, 5), Direction::Right),
|
||||
);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 4), Direction::Right),
|
||||
(Position::new(13, 8), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 5), Direction::Right),
|
||||
(Position::new(13, 7), Direction::Right),
|
||||
);
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_2() -> Problem {
|
||||
let mut p = Problem::new(17, 13);
|
||||
p.set_blocked(0, 3, true);
|
||||
|
||||
p.set_blocked_range(1, 2, 2, 5, true);
|
||||
p.set_blocked_range(1, 7, 2, 10, true);
|
||||
|
||||
p.set_blocked(0, 9, true);
|
||||
|
||||
p.set_blocked(16, 3, true);
|
||||
|
||||
p.set_blocked_range(14, 2, 15, 5, true);
|
||||
p.set_blocked_range(14, 7, 15, 10, true);
|
||||
|
||||
p.set_blocked(16, 9, true);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 4), Direction::Right),
|
||||
(Position::new(13, 2), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 7), Direction::Right),
|
||||
(Position::new(13, 3), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 10), Direction::Right),
|
||||
(Position::new(13, 4), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 9), Direction::Right),
|
||||
(Position::new(13, 5), Direction::Right),
|
||||
);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 2), Direction::Right),
|
||||
(Position::new(13, 7), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 3), Direction::Right),
|
||||
(Position::new(13, 8), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 5), Direction::Right),
|
||||
(Position::new(13, 9), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 8), Direction::Right),
|
||||
(Position::new(13, 10), Direction::Right),
|
||||
);
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_3() -> Problem {
|
||||
let mut p = Problem::new(33, 13);
|
||||
|
||||
p.set_blocked_range(1, 3, 2, 5, true);
|
||||
p.set_blocked_range(1, 7, 2, 9, true);
|
||||
|
||||
p.set_blocked(0, 3, true);
|
||||
p.set_blocked(0, 8, true);
|
||||
|
||||
p.set_blocked_range(10, 0, 21, 2, true);
|
||||
p.set_blocked_range(10, 5, 21, 7, true);
|
||||
p.set_blocked_range(10, 10, 21, 12, true);
|
||||
|
||||
p.set_blocked_range(30, 3, 31, 5, true);
|
||||
p.set_blocked_range(30, 7, 31, 9, true);
|
||||
p.set_blocked(32, 3, true);
|
||||
p.set_blocked(32, 9, true);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 3), Direction::Right),
|
||||
(Position::new(29, 7), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 4), Direction::Right),
|
||||
(Position::new(29, 9), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 5), Direction::Right),
|
||||
(Position::new(29, 8), Direction::Right),
|
||||
);
|
||||
|
||||
p.add_connection(
|
||||
(Position::new(2, 7), Direction::Right),
|
||||
(Position::new(29, 3), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 8), Direction::Right),
|
||||
(Position::new(29, 5), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 9), Direction::Right),
|
||||
(Position::new(29, 4), Direction::Right),
|
||||
);
|
||||
|
||||
p
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_5() -> Problem {
|
||||
let mut p = Problem::new(31, 29);
|
||||
|
||||
// power stations
|
||||
p.set_blocked_range(8, 8, 9, 9, true);
|
||||
p.set_blocked_range(21, 8, 22, 9, true);
|
||||
p.set_blocked_range(8, 19, 9, 20, true);
|
||||
p.set_blocked_range(21, 19, 22, 20, true);
|
||||
|
||||
// solar panels
|
||||
p.set_blocked_range(12, 11, 14, 13, true);
|
||||
p.set_blocked_range(16, 11, 18, 13, true);
|
||||
p.set_blocked_range(12, 15, 14, 17, true);
|
||||
p.set_blocked_range(16, 15, 18, 17, true);
|
||||
|
||||
// Top
|
||||
p.set_blocked_range(7, 0, 8, 2, true);
|
||||
p.set_blocked(8, 3, true);
|
||||
p.set_blocked(9, 4, true);
|
||||
p.set_blocked_range(10, 5, 20, 5, true);
|
||||
p.set_blocked(21, 4, true);
|
||||
p.set_blocked(22, 3, true);
|
||||
p.set_blocked_range(22, 0, 23, 2, true);
|
||||
|
||||
p.set_blocked_range(2, 1, 2, 2, true);
|
||||
p.set_blocked_range(4, 1, 4, 2, true);
|
||||
p.set_blocked_range(1, 4, 2, 4, true);
|
||||
|
||||
p.set_blocked_range(12, 1, 12, 2, true);
|
||||
p.set_blocked_range(14, 1, 14, 2, true);
|
||||
p.set_blocked_range(16, 1, 16, 2, true);
|
||||
p.set_blocked_range(18, 1, 18, 2, true);
|
||||
|
||||
p.set_blocked_range(28, 4, 29, 4, true);
|
||||
p.set_blocked_range(26, 1, 26, 2, true);
|
||||
p.set_blocked_range(28, 1, 28, 2, true);
|
||||
|
||||
// Bottom
|
||||
p.set_blocked_range(7, 26, 8, 28, true);
|
||||
p.set_blocked(8, 25, true);
|
||||
p.set_blocked(9, 24, true);
|
||||
p.set_blocked_range(10, 23, 20, 23, true);
|
||||
p.set_blocked(21, 24, true);
|
||||
p.set_blocked(22, 25, true);
|
||||
p.set_blocked_range(22, 26, 23, 28, true);
|
||||
|
||||
p.set_blocked_range(1, 26, 2, 26, true);
|
||||
p.set_blocked_range(4, 26, 4, 27, true);
|
||||
p.set_blocked_range(1, 24, 2, 24, true);
|
||||
|
||||
p.set_blocked_range(12, 26, 12, 27, true);
|
||||
p.set_blocked_range(14, 26, 14, 27, true);
|
||||
p.set_blocked_range(16, 26, 16, 27, true);
|
||||
p.set_blocked_range(18, 26, 18, 27, true);
|
||||
|
||||
p.set_blocked_range(28, 24, 29, 24, true);
|
||||
p.set_blocked_range(26, 26, 26, 27, true);
|
||||
p.set_blocked_range(28, 26, 29, 26, true);
|
||||
|
||||
// Left
|
||||
p.set_blocked_range(0, 7, 2, 8, true);
|
||||
p.set_blocked(3, 8, true);
|
||||
p.set_blocked(4, 9, true);
|
||||
p.set_blocked_range(5, 10, 5, 18, true);
|
||||
p.set_blocked(4, 19, true);
|
||||
p.set_blocked(3, 20, true);
|
||||
p.set_blocked_range(0, 20, 2, 21, true);
|
||||
|
||||
p.set_blocked_range(1, 11, 2, 11, true);
|
||||
p.set_blocked_range(1, 13, 2, 13, true);
|
||||
p.set_blocked_range(1, 15, 2, 15, true);
|
||||
p.set_blocked_range(1, 17, 2, 17, true);
|
||||
|
||||
// Right
|
||||
p.set_blocked_range(28, 7, 30, 8, true);
|
||||
p.set_blocked(27, 8, true);
|
||||
p.set_blocked(26, 9, true);
|
||||
p.set_blocked_range(25, 10, 25, 18, true);
|
||||
p.set_blocked(26, 19, true);
|
||||
p.set_blocked(27, 20, true);
|
||||
p.set_blocked_range(28, 20, 30, 21, true);
|
||||
|
||||
p.set_blocked_range(28, 11, 29, 11, true);
|
||||
p.set_blocked_range(28, 13, 29, 13, true);
|
||||
p.set_blocked_range(28, 15, 29, 15, true);
|
||||
p.set_blocked_range(28, 17, 29, 17, true);
|
||||
|
||||
// Path
|
||||
p.add_connection(
|
||||
(Position::new(4, 2), Direction::Down),
|
||||
(Position::new(26, 25), Direction::Down),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(12, 2), Direction::Down),
|
||||
(Position::new(18, 25), Direction::Down),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(14, 2), Direction::Down),
|
||||
(Position::new(3, 26), Direction::Left),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(16, 2), Direction::Down),
|
||||
(Position::new(14, 25), Direction::Down),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 4), Direction::Right),
|
||||
(Position::new(27, 24), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 11), Direction::Right),
|
||||
(Position::new(27, 17), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 13), Direction::Right),
|
||||
(Position::new(27, 26), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 15), Direction::Right),
|
||||
(Position::new(27, 13), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(28, 15), Direction::Left),
|
||||
(Position::new(2, 3), Direction::Up),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 17), Direction::Right),
|
||||
(Position::new(18, 3), Direction::Up),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(2, 24), Direction::Right),
|
||||
(Position::new(26, 3), Direction::Up),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(4, 26), Direction::Up),
|
||||
(Position::new(27, 4), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(12, 26), Direction::Up),
|
||||
(Position::new(27, 11), Direction::Right),
|
||||
);
|
||||
p.add_connection(
|
||||
(Position::new(16, 26), Direction::Up),
|
||||
(Position::new(28, 3), Direction::Up),
|
||||
);
|
||||
|
||||
p
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use factorio_blueprint::{encode, Blueprint, BlueprintString};
|
||||
use factorio_core::{beltoptions::Beltspeed, visualize::Visualize};
|
||||
use factorio_pathfinding::belt_finding::{
|
||||
conflict_avoidance::ConflictAvoidance, problems, Problem,
|
||||
use factorio_pathfinding::{
|
||||
belt_finding::{conflict_avoidance::ConflictAvoidance, Problem},
|
||||
examples,
|
||||
};
|
||||
use std::{io, path::PathBuf};
|
||||
|
||||
|
|
@ -26,11 +27,11 @@ enum ProblemCase {
|
|||
impl ProblemCase {
|
||||
fn get_problem(&self) -> Problem {
|
||||
match self {
|
||||
ProblemCase::Simple => problems::simple(),
|
||||
ProblemCase::Level1 => problems::belt_madness_level_1(),
|
||||
ProblemCase::Level2 => problems::belt_madness_level_2(),
|
||||
ProblemCase::Level3 => problems::belt_madness_level_3(),
|
||||
ProblemCase::Level5 => problems::belt_madness_level_5(),
|
||||
ProblemCase::Simple => examples::simple().into(),
|
||||
ProblemCase::Level1 => examples::belt_madness_level_1().into(),
|
||||
ProblemCase::Level2 => examples::belt_madness_level_2().into(),
|
||||
ProblemCase::Level3 => examples::belt_madness_level_3().into(),
|
||||
ProblemCase::Level5 => examples::belt_madness_level_5().into(),
|
||||
ProblemCase::File { filename } => {
|
||||
let file = std::fs::File::open(filename).unwrap();
|
||||
serde_json::from_reader(file).unwrap()
|
||||
|
|
|
|||
527
factorio-pathfinding/src/examples.rs
Normal file
527
factorio-pathfinding/src/examples.rs
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
use crate::{Connection, Map};
|
||||
use factorio_core::{
|
||||
beltoptions::Beltspeed,
|
||||
prelude::*,
|
||||
visualize::{Visualization, Visualize},
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub struct HashMapMap {
|
||||
map: HashSet<Position>,
|
||||
size: Position,
|
||||
}
|
||||
|
||||
impl HashMapMap {
|
||||
fn new(size: impl Into<Position>) -> Self {
|
||||
Self {
|
||||
map: HashSet::new(),
|
||||
size: size.into(),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_blocked_range(
|
||||
&mut self,
|
||||
min_pos: impl Into<Position>,
|
||||
max_pos: impl Into<Position>,
|
||||
block: bool,
|
||||
) {
|
||||
let min_pos = min_pos.into();
|
||||
let max_pos = max_pos.into();
|
||||
|
||||
for x in min_pos.x..=max_pos.x {
|
||||
for y in min_pos.y..=max_pos.y {
|
||||
self.set_blocked(Position::new(x, y), block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_blocked(&mut self, pos: impl Into<Position>, block: bool) {
|
||||
let pos = pos.into();
|
||||
if block {
|
||||
self.map.insert(pos);
|
||||
} else {
|
||||
self.map.remove(&pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visualize for HashMapMap {
|
||||
fn visualize(&self) -> factorio_core::visualize::Visualization {
|
||||
let mut v = Visualization::new(self.size);
|
||||
|
||||
for &p in &self.map {
|
||||
v.add_symbol(p, factorio_core::visualize::Symbol::Block, None, None);
|
||||
}
|
||||
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
impl Map for HashMapMap {
|
||||
fn get_position(&self, pos: Position) -> bool {
|
||||
if pos.x < 0 || pos.y < 0 || pos.x >= self.size.x || pos.y >= self.size.y {
|
||||
false
|
||||
} else {
|
||||
!self.map.contains(&pos)
|
||||
}
|
||||
}
|
||||
|
||||
fn area(&self) -> (Position, Position) {
|
||||
(Position::new(0, 0), self.size)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn simple() -> (Vec<Connection>, HashMapMap) {
|
||||
let mut m = HashMapMap::new((5, 3));
|
||||
|
||||
m.set_blocked_range((2, 0), (2, 2), true);
|
||||
|
||||
(
|
||||
vec![Connection {
|
||||
start_pos: Position::new(0, 1),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(4, 1),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
}],
|
||||
m,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_1() -> (Vec<Connection>, HashMapMap) {
|
||||
let mut m = HashMapMap::new((17, 13));
|
||||
|
||||
m.set_blocked((0, 3), true);
|
||||
|
||||
m.set_blocked((1, 4), true);
|
||||
m.set_blocked((2, 4), true);
|
||||
m.set_blocked((1, 5), true);
|
||||
m.set_blocked((2, 5), true);
|
||||
|
||||
m.set_blocked((1, 7), true);
|
||||
m.set_blocked((2, 7), true);
|
||||
m.set_blocked((1, 8), true);
|
||||
m.set_blocked((2, 8), true);
|
||||
|
||||
m.set_blocked((0, 9), true);
|
||||
|
||||
m.set_blocked((16, 3), true);
|
||||
|
||||
m.set_blocked((14, 4), true);
|
||||
m.set_blocked((15, 4), true);
|
||||
m.set_blocked((14, 5), true);
|
||||
m.set_blocked((15, 5), true);
|
||||
|
||||
m.set_blocked((14, 7), true);
|
||||
m.set_blocked((15, 7), true);
|
||||
m.set_blocked((14, 8), true);
|
||||
m.set_blocked((15, 8), true);
|
||||
|
||||
m.set_blocked((16, 9), true);
|
||||
|
||||
(
|
||||
vec![
|
||||
Connection {
|
||||
start_pos: Position::new(2, 7),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 4),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 8),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 5),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 4),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 8),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 5),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 7),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
],
|
||||
m,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_2() -> (Vec<Connection>, HashMapMap) {
|
||||
let mut m = HashMapMap::new((17, 13));
|
||||
m.set_blocked((0, 3), true);
|
||||
|
||||
m.set_blocked_range((1, 2), (2, 5), true);
|
||||
m.set_blocked_range((1, 7), (2, 10), true);
|
||||
|
||||
m.set_blocked((0, 9), true);
|
||||
|
||||
m.set_blocked((16, 3), true);
|
||||
|
||||
m.set_blocked_range((14, 2), (15, 5), true);
|
||||
m.set_blocked_range((14, 7), (15, 10), true);
|
||||
|
||||
m.set_blocked((16, 9), true);
|
||||
|
||||
(
|
||||
vec![
|
||||
Connection {
|
||||
start_pos: Position::new(2, 4),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 2),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 7),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 3),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 10),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 4),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 9),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 5),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 2),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 7),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 3),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 8),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 5),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 9),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 8),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(13, 10),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
],
|
||||
m,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_3() -> (Vec<Connection>, HashMapMap) {
|
||||
let mut m = HashMapMap::new((33, 13));
|
||||
|
||||
m.set_blocked_range((1, 3), (2, 5), true);
|
||||
m.set_blocked_range((1, 7), (2, 9), true);
|
||||
|
||||
m.set_blocked((0, 3), true);
|
||||
m.set_blocked((0, 8), true);
|
||||
|
||||
m.set_blocked_range((10, 0), (21, 2), true);
|
||||
m.set_blocked_range((10, 5), (21, 7), true);
|
||||
m.set_blocked_range((10, 10), (21, 12), true);
|
||||
|
||||
m.set_blocked_range((30, 3), (31, 5), true);
|
||||
m.set_blocked_range((30, 7), (31, 9), true);
|
||||
m.set_blocked((32, 3), true);
|
||||
m.set_blocked((32, 9), true);
|
||||
|
||||
(
|
||||
vec![
|
||||
Connection {
|
||||
start_pos: Position::new(2, 3),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 7),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 4),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 9),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 5),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 8),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 7),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 3),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 8),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 5),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 9),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(29, 4),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
],
|
||||
m,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn belt_madness_level_5() -> (Vec<Connection>, HashMapMap) {
|
||||
let mut m = HashMapMap::new((31, 29));
|
||||
|
||||
// power stations
|
||||
m.set_blocked_range((8, 8), (9, 9), true);
|
||||
m.set_blocked_range((21, 8), (22, 9), true);
|
||||
m.set_blocked_range((8, 19), (9, 20), true);
|
||||
m.set_blocked_range((21, 19), (22, 20), true);
|
||||
|
||||
// solar panels
|
||||
m.set_blocked_range((12, 11), (14, 13), true);
|
||||
m.set_blocked_range((16, 11), (18, 13), true);
|
||||
m.set_blocked_range((12, 15), (14, 17), true);
|
||||
m.set_blocked_range((16, 15), (18, 17), true);
|
||||
|
||||
// Top
|
||||
m.set_blocked_range((7, 0), (8, 2), true);
|
||||
m.set_blocked((8, 3), true);
|
||||
m.set_blocked((9, 4), true);
|
||||
m.set_blocked_range((10, 5), (20, 5), true);
|
||||
m.set_blocked((21, 4), true);
|
||||
m.set_blocked((22, 3), true);
|
||||
m.set_blocked_range((22, 0), (23, 2), true);
|
||||
|
||||
m.set_blocked_range((2, 1), (2, 2), true);
|
||||
m.set_blocked_range((4, 1), (4, 2), true);
|
||||
m.set_blocked_range((1, 4), (2, 4), true);
|
||||
|
||||
m.set_blocked_range((12, 1), (12, 2), true);
|
||||
m.set_blocked_range((14, 1), (14, 2), true);
|
||||
m.set_blocked_range((16, 1), (16, 2), true);
|
||||
m.set_blocked_range((18, 1), (18, 2), true);
|
||||
|
||||
m.set_blocked_range((28, 4), (29, 4), true);
|
||||
m.set_blocked_range((26, 1), (26, 2), true);
|
||||
m.set_blocked_range((28, 1), (28, 2), true);
|
||||
|
||||
// Bottom
|
||||
m.set_blocked_range((7, 26), (8, 28), true);
|
||||
m.set_blocked((8, 25), true);
|
||||
m.set_blocked((9, 24), true);
|
||||
m.set_blocked_range((10, 23), (20, 23), true);
|
||||
m.set_blocked((21, 24), true);
|
||||
m.set_blocked((22, 25), true);
|
||||
m.set_blocked_range((22, 26), (23, 28), true);
|
||||
|
||||
m.set_blocked_range((1, 26), (2, 26), true);
|
||||
m.set_blocked_range((4, 26), (4, 27), true);
|
||||
m.set_blocked_range((1, 24), (2, 24), true);
|
||||
|
||||
m.set_blocked_range((12, 26), (12, 27), true);
|
||||
m.set_blocked_range((14, 26), (14, 27), true);
|
||||
m.set_blocked_range((16, 26), (16, 27), true);
|
||||
m.set_blocked_range((18, 26), (18, 27), true);
|
||||
|
||||
m.set_blocked_range((28, 24), (29, 24), true);
|
||||
m.set_blocked_range((26, 26), (26, 27), true);
|
||||
m.set_blocked_range((28, 26), (29, 26), true);
|
||||
|
||||
// Left
|
||||
m.set_blocked_range((0, 7), (2, 8), true);
|
||||
m.set_blocked((3, 8), true);
|
||||
m.set_blocked((4, 9), true);
|
||||
m.set_blocked_range((5, 10), (5, 18), true);
|
||||
m.set_blocked((4, 19), true);
|
||||
m.set_blocked((3, 20), true);
|
||||
m.set_blocked_range((0, 20), (2, 21), true);
|
||||
|
||||
m.set_blocked_range((1, 11), (2, 11), true);
|
||||
m.set_blocked_range((1, 13), (2, 13), true);
|
||||
m.set_blocked_range((1, 15), (2, 15), true);
|
||||
m.set_blocked_range((1, 17), (2, 17), true);
|
||||
|
||||
// Right
|
||||
m.set_blocked_range((28, 7), (30, 8), true);
|
||||
m.set_blocked((27, 8), true);
|
||||
m.set_blocked((26, 9), true);
|
||||
m.set_blocked_range((25, 10), (25, 18), true);
|
||||
m.set_blocked((26, 19), true);
|
||||
m.set_blocked((27, 20), true);
|
||||
m.set_blocked_range((28, 20), (30, 21), true);
|
||||
|
||||
m.set_blocked_range((28, 11), (29, 11), true);
|
||||
m.set_blocked_range((28, 13), (29, 13), true);
|
||||
m.set_blocked_range((28, 15), (29, 15), true);
|
||||
m.set_blocked_range((28, 17), (29, 17), true);
|
||||
|
||||
// Path
|
||||
(
|
||||
vec![
|
||||
Connection {
|
||||
start_pos: Position::new(4, 2),
|
||||
start_dir: Direction::Down,
|
||||
end_pos: Position::new(26, 25),
|
||||
end_dir: Direction::Down,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(12, 2),
|
||||
start_dir: Direction::Down,
|
||||
end_pos: Position::new(18, 25),
|
||||
end_dir: Direction::Down,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(14, 2),
|
||||
start_dir: Direction::Down,
|
||||
end_pos: Position::new(3, 26),
|
||||
end_dir: Direction::Left,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(16, 2),
|
||||
start_dir: Direction::Down,
|
||||
end_pos: Position::new(14, 25),
|
||||
end_dir: Direction::Down,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 4),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(27, 24),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 11),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(27, 17),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 13),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(27, 26),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 15),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(27, 13),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(28, 15),
|
||||
start_dir: Direction::Left,
|
||||
end_pos: Position::new(2, 3),
|
||||
end_dir: Direction::Up,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 17),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(18, 3),
|
||||
end_dir: Direction::Up,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(2, 24),
|
||||
start_dir: Direction::Right,
|
||||
end_pos: Position::new(26, 3),
|
||||
end_dir: Direction::Up,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(4, 26),
|
||||
start_dir: Direction::Up,
|
||||
end_pos: Position::new(27, 4),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(12, 26),
|
||||
start_dir: Direction::Up,
|
||||
end_pos: Position::new(27, 11),
|
||||
end_dir: Direction::Right,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
Connection {
|
||||
start_pos: Position::new(16, 26),
|
||||
start_dir: Direction::Up,
|
||||
end_pos: Position::new(28, 3),
|
||||
end_dir: Direction::Up,
|
||||
beltspeed: Beltspeed::Normal,
|
||||
lanes: 1,
|
||||
},
|
||||
],
|
||||
m,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,4 +1,74 @@
|
|||
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 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(&self, input: &[Connection], map: impl Map) -> Option<Vec<Vec<PathField>>>;
|
||||
}
|
||||
|
||||
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(&self, input: &[SingleConnection], map: impl Map) -> Option<Vec<Vec<PathField>>>;
|
||||
}
|
||||
|
||||
impl<P> Pathfinder for P
|
||||
where
|
||||
P: SinglePathfinder,
|
||||
{
|
||||
fn find_paths(&self, input: &[Connection], map: impl Map) -> Option<Vec<Vec<PathField>>> {
|
||||
let inner_input = input
|
||||
.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(&inner_input, map)?;
|
||||
|
||||
let mut inner_iterator = inner_result.into_iter();
|
||||
|
||||
Some(
|
||||
input
|
||||
.iter()
|
||||
.map(|i| inner_iterator.by_ref().take(i.lanes).flatten().collect())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue