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 { 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])); } } }