factorio_blueprint/factorio-blueprint/src/abstraction/roboports.rs

76 lines
2.1 KiB
Rust

use factorio_core::{misc::PositionMap, prelude::Position};
use factorio_graph::{
graph::Graph,
priority_queue::binary_heap::FastBinaryHeap,
set_cover::{greedy_connected_set_cover_priority_queue, greedy_set_cover_priority_queue},
};
use crate::abstraction::Entity;
use super::Blueprint;
struct RoboportGraph<'a> {
roboports: &'a [Position],
}
impl Graph for RoboportGraph<'_> {
type Node = usize;
fn edge(&self, node: &Self::Node, num: usize) -> Option<Self::Node> {
let p = self.roboports[*node];
self.roboports
.iter()
.enumerate()
.filter(|(_, other)| p.x.abs_diff(other.x) <= 100 && p.y.abs_diff(other.y) <= 100)
.nth(num)
.map(|(i, _)| i)
}
}
impl Blueprint {
pub fn add_roboport_network(&mut self) {
let aabb = self.get_aabb().unwrap();
let universe = self.entities.len();
let map = self.placibility_map();
let mut roboports = Vec::new();
let mut sets = Vec::new();
for (x, y) in (aabb.min().x..=aabb.max().x)
.filter(move |x| x.rem_euclid(2) == 0)
.flat_map(|x| {
(aabb.min().y..=aabb.max().y)
.filter(move |y| y.rem_euclid(2) == 0)
.map(move |y| (x, y))
})
{
if map.placeable(Position::new(x, y), Position::new(8, 8)) {
let mut coverage = Vec::new();
for (i, (_, e)) in self.entities.iter().enumerate() {
if e.position.x.abs_diff(x) <= 110 && e.position.y.abs_diff(y) <= 110 {
coverage.push(i);
}
}
roboports.push(Position::new(x, y));
sets.push(coverage);
}
}
dbg!(universe, sets.len());
let res = greedy_connected_set_cover_priority_queue::<_, _, FastBinaryHeap<_>>(
universe,
&sets,
RoboportGraph {
roboports: &roboports,
},
);
for r in res {
self.add_entity(Entity::new_roboport(roboports[r]));
}
}
}